[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Explicitly declare code/VS files as CRLF\n*.cpp eol=crlf\n*.h eol=crlf\n*.hlsl eol=crlf\n*.vcxproj eol=crlf\n*.filters eol=crlf\n*.sln eol=crlf\n\n# Explicitly declare resource files as binary\n*.bin binary"
  },
  {
    "path": ".gitignore",
    "content": "\n*.opendb\n.vs\nMiniEngine/ModelViewer/imgui.ini\n/teaser_panning1x.anim\n/teaser_panning2x.anim\n/testexe/ModelViewer.exe\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Microsoft\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "Libraries/D3DX12/d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#ifndef __D3DX12_H__\r\n#define __D3DX12_H__\r\n\r\n#include \"d3d12.h\"\r\n\r\n#if defined( __cplusplus )\r\n\r\nstruct CD3DX12_DEFAULT {};\r\nextern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT;\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{\r\n    return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width &&\r\n        l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RECT : public D3D12_RECT\r\n{\r\n    CD3DX12_RECT()\r\n    {}\r\n    explicit CD3DX12_RECT( const D3D12_RECT& o ) :\r\n        D3D12_RECT( o )\r\n    {}\r\n    explicit CD3DX12_RECT(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        right = Right;\r\n        bottom = Bottom;\r\n    }\r\n    ~CD3DX12_RECT() {}\r\n    operator const D3D12_RECT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VIEWPORT : public D3D12_VIEWPORT\r\n{\r\n    CD3DX12_VIEWPORT()\r\n    {}\r\n    explicit CD3DX12_VIEWPORT( const D3D12_VIEWPORT& o ) :\r\n        D3D12_VIEWPORT( o )\r\n    {}\r\n    explicit CD3DX12_VIEWPORT(\r\n        FLOAT topLeftX,\r\n        FLOAT topLeftY,\r\n        FLOAT width,\r\n        FLOAT height,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        TopLeftX = topLeftX;\r\n        TopLeftY = topLeftY;\r\n        Width = width;\r\n        Height = height;\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    explicit CD3DX12_VIEWPORT(\r\n        _In_ ID3D12Resource* pResource,\r\n        UINT mipSlice = 0,\r\n        FLOAT topLeftX = 0.0f,\r\n        FLOAT topLeftY = 0.0f,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        D3D12_RESOURCE_DESC Desc = pResource->GetDesc();\r\n        const UINT64 SubresourceWidth = Desc.Width >> mipSlice;\r\n        const UINT64 SubresourceHeight = Desc.Height >> mipSlice;\r\n        switch (Desc.Dimension)\r\n        {\r\n        case D3D12_RESOURCE_DIMENSION_BUFFER:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = Desc.Width - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = topLeftY;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = (SubresourceHeight ? SubresourceHeight: 1.0f) - topLeftY;\r\n            break;\r\n        default: break;\r\n        }\r\n\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    ~CD3DX12_VIEWPORT() {}\r\n    operator const D3D12_VIEWPORT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BOX : public D3D12_BOX\r\n{\r\n    CD3DX12_BOX()\r\n    {}\r\n    explicit CD3DX12_BOX( const D3D12_BOX& o ) :\r\n        D3D12_BOX( o )\r\n    {}\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Right )\r\n    {\r\n        left = Left;\r\n        top = 0;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = 1;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Front,\r\n        LONG Right,\r\n        LONG Bottom,\r\n        LONG Back )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = Front;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = Back;\r\n    }\r\n    ~CD3DX12_BOX() {}\r\n    operator const D3D12_BOX&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{\r\n    return l.left == r.left && l.top == r.top && l.front == r.front &&\r\n        l.right == r.right && l.bottom == r.bottom && l.back == r.back;\r\n}\r\ninline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC1 : public D3D12_DEPTH_STENCIL_DESC1\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC1()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC1& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC1( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC& o )\r\n    {\r\n        DepthEnable                  = o.DepthEnable;\r\n        DepthWriteMask               = o.DepthWriteMask;\r\n        DepthFunc                    = o.DepthFunc;\r\n        StencilEnable                = o.StencilEnable;\r\n        StencilReadMask              = o.StencilReadMask;\r\n        StencilWriteMask             = o.StencilWriteMask;\r\n        FrontFace.StencilFailOp      = o.FrontFace.StencilFailOp;\r\n        FrontFace.StencilDepthFailOp = o.FrontFace.StencilDepthFailOp;\r\n        FrontFace.StencilPassOp      = o.FrontFace.StencilPassOp;\r\n        FrontFace.StencilFunc        = o.FrontFace.StencilFunc;\r\n        BackFace.StencilFailOp       = o.BackFace.StencilFailOp;\r\n        BackFace.StencilDepthFailOp  = o.BackFace.StencilDepthFailOp;\r\n        BackFace.StencilPassOp       = o.BackFace.StencilPassOp;\r\n        BackFace.StencilFunc         = o.BackFace.StencilFunc;\r\n        DepthBoundsTestEnable        = FALSE;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n        DepthBoundsTestEnable = FALSE;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc,\r\n        BOOL depthBoundsTestEnable )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n        DepthBoundsTestEnable = depthBoundsTestEnable;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC1() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC1&() const { return *this; }\r\n    operator const D3D12_DEPTH_STENCIL_DESC() const\r\n    {\r\n        D3D12_DEPTH_STENCIL_DESC D;\r\n        D.DepthEnable                  = DepthEnable;\r\n        D.DepthWriteMask               = DepthWriteMask;\r\n        D.DepthFunc                    = DepthFunc;\r\n        D.StencilEnable                = StencilEnable;\r\n        D.StencilReadMask              = StencilReadMask;\r\n        D.StencilWriteMask             = StencilWriteMask;\r\n        D.FrontFace.StencilFailOp      = FrontFace.StencilFailOp;\r\n        D.FrontFace.StencilDepthFailOp = FrontFace.StencilDepthFailOp;\r\n        D.FrontFace.StencilPassOp      = FrontFace.StencilPassOp;\r\n        D.FrontFace.StencilFunc        = FrontFace.StencilFunc;\r\n        D.BackFace.StencilFailOp       = BackFace.StencilFailOp;\r\n        D.BackFace.StencilDepthFailOp  = BackFace.StencilDepthFailOp;\r\n        D.BackFace.StencilPassOp       = BackFace.StencilPassOp;\r\n        D.BackFace.StencilFunc         = BackFace.StencilFunc;\r\n        return D;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC\r\n{\r\n    CD3DX12_BLEND_DESC()\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) :\r\n        D3D12_BLEND_DESC( o )\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        AlphaToCoverageEnable = FALSE;\r\n        IndependentBlendEnable = FALSE;\r\n        const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =\r\n        {\r\n            FALSE,FALSE,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_LOGIC_OP_NOOP,\r\n            D3D12_COLOR_WRITE_ENABLE_ALL,\r\n        };\r\n        for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)\r\n            RenderTarget[ i ] = defaultRenderTargetBlendDesc;\r\n    }\r\n    ~CD3DX12_BLEND_DESC() {}\r\n    operator const D3D12_BLEND_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC\r\n{\r\n    CD3DX12_RASTERIZER_DESC()\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) :\r\n        D3D12_RASTERIZER_DESC( o )\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        FillMode = D3D12_FILL_MODE_SOLID;\r\n        CullMode = D3D12_CULL_MODE_BACK;\r\n        FrontCounterClockwise = FALSE;\r\n        DepthBias = D3D12_DEFAULT_DEPTH_BIAS;\r\n        DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;\r\n        SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;\r\n        DepthClipEnable = TRUE;\r\n        MultisampleEnable = FALSE;\r\n        AntialiasedLineEnable = FALSE;\r\n        ForcedSampleCount = 0;\r\n        ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;\r\n    }\r\n    explicit CD3DX12_RASTERIZER_DESC(\r\n        D3D12_FILL_MODE fillMode,\r\n        D3D12_CULL_MODE cullMode,\r\n        BOOL frontCounterClockwise,\r\n        INT depthBias,\r\n        FLOAT depthBiasClamp,\r\n        FLOAT slopeScaledDepthBias,\r\n        BOOL depthClipEnable,\r\n        BOOL multisampleEnable,\r\n        BOOL antialiasedLineEnable, \r\n        UINT forcedSampleCount, \r\n        D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster)\r\n    {\r\n        FillMode = fillMode;\r\n        CullMode = cullMode;\r\n        FrontCounterClockwise = frontCounterClockwise;\r\n        DepthBias = depthBias;\r\n        DepthBiasClamp = depthBiasClamp;\r\n        SlopeScaledDepthBias = slopeScaledDepthBias;\r\n        DepthClipEnable = depthClipEnable;\r\n        MultisampleEnable = multisampleEnable;\r\n        AntialiasedLineEnable = antialiasedLineEnable;\r\n        ForcedSampleCount = forcedSampleCount;\r\n        ConservativeRaster = conservativeRaster;\r\n    }\r\n    ~CD3DX12_RASTERIZER_DESC() {}\r\n    operator const D3D12_RASTERIZER_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO\r\n{\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) :\r\n        D3D12_RESOURCE_ALLOCATION_INFO( o )\r\n    {}\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO(\r\n        UINT64 size,\r\n        UINT64 alignment )\r\n    {\r\n        SizeInBytes = size;\r\n        Alignment = alignment;\r\n    }\r\n    operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES\r\n{\r\n    CD3DX12_HEAP_PROPERTIES()\r\n    {}\r\n    explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) :\r\n        D3D12_HEAP_PROPERTIES(o)\r\n    {}\r\n    CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference,\r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = D3D12_HEAP_TYPE_CUSTOM;\r\n        CPUPageProperty = cpuPageProperty;\r\n        MemoryPoolPreference = memoryPoolPreference;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    explicit CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_HEAP_TYPE type, \r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = type;\r\n        CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n        MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    operator const D3D12_HEAP_PROPERTIES&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    {\r\n        return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&\r\n            (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));\r\n    }\r\n};\r\ninline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{\r\n    return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && \r\n        l.MemoryPoolPreference == r.MemoryPoolPreference &&\r\n        l.CreationNodeMask == r.CreationNodeMask &&\r\n        l.VisibleNodeMask == r.VisibleNodeMask;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC\r\n{\r\n    CD3DX12_HEAP_DESC()\r\n    {}\r\n    explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) :\r\n        D3D12_HEAP_DESC(o)\r\n    {}\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_PROPERTIES properties, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = properties;\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_TYPE type, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_PROPERTIES properties, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = properties;\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_TYPE type, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    operator const D3D12_HEAP_DESC&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }\r\n};\r\ninline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{\r\n    return l.SizeInBytes == r.SizeInBytes &&\r\n        l.Properties == r.Properties && \r\n        l.Alignment == r.Alignment &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE\r\n{\r\n    CD3DX12_CLEAR_VALUE()\r\n    {}\r\n    explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) :\r\n        D3D12_CLEAR_VALUE(o)\r\n    {}\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        const FLOAT color[4] )\r\n    {\r\n        Format = format;\r\n        memcpy( Color, color, sizeof( Color ) );\r\n    }\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        FLOAT depth,\r\n        UINT8 stencil )\r\n    {\r\n        Format = format;\r\n        /* Use memcpy to preserve NAN values */\r\n        memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );\r\n        DepthStencil.Stencil = stencil;\r\n    }\r\n    operator const D3D12_CLEAR_VALUE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE : public D3D12_RANGE\r\n{\r\n    CD3DX12_RANGE()\r\n    {}\r\n    explicit CD3DX12_RANGE(const D3D12_RANGE &o) :\r\n        D3D12_RANGE(o)\r\n    {}\r\n    CD3DX12_RANGE( \r\n        SIZE_T begin, \r\n        SIZE_T end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE_UINT64 : public D3D12_RANGE_UINT64\r\n{\r\n    CD3DX12_RANGE_UINT64()\r\n    {}\r\n    explicit CD3DX12_RANGE_UINT64(const D3D12_RANGE_UINT64 &o) :\r\n        D3D12_RANGE_UINT64(o)\r\n    {}\r\n    CD3DX12_RANGE_UINT64( \r\n        UINT64 begin, \r\n        UINT64 end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE_UINT64&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_RANGE_UINT64 : public D3D12_SUBRESOURCE_RANGE_UINT64\r\n{\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_RANGE_UINT64(const D3D12_SUBRESOURCE_RANGE_UINT64 &o) :\r\n        D3D12_SUBRESOURCE_RANGE_UINT64(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64( \r\n        UINT subresource,\r\n        const D3D12_RANGE_UINT64& range )\r\n    {\r\n        Subresource = subresource;\r\n        Range = range;\r\n    }\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64( \r\n        UINT subresource,\r\n        UINT64 begin, \r\n        UINT64 end )\r\n    {\r\n        Subresource = subresource;\r\n        Range.Begin = begin;\r\n        Range.End = end;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_RANGE_UINT64&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE\r\n{\r\n    CD3DX12_SHADER_BYTECODE()\r\n    {}\r\n    explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) :\r\n        D3D12_SHADER_BYTECODE(o)\r\n    {}\r\n    CD3DX12_SHADER_BYTECODE(\r\n        _In_ ID3DBlob* pShaderBlob )\r\n    {\r\n        pShaderBytecode = pShaderBlob->GetBufferPointer();\r\n        BytecodeLength = pShaderBlob->GetBufferSize();\r\n    }\r\n    CD3DX12_SHADER_BYTECODE(\r\n        const void* _pShaderBytecode,\r\n        SIZE_T bytecodeLength )\r\n    {\r\n        pShaderBytecode = _pShaderBytecode;\r\n        BytecodeLength = bytecodeLength;\r\n    }\r\n    operator const D3D12_SHADER_BYTECODE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE\r\n{\r\n    CD3DX12_TILED_RESOURCE_COORDINATE()\r\n    {}\r\n    explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) :\r\n        D3D12_TILED_RESOURCE_COORDINATE(o)\r\n    {}\r\n    CD3DX12_TILED_RESOURCE_COORDINATE( \r\n        UINT x, \r\n        UINT y, \r\n        UINT z, \r\n        UINT subresource ) \r\n    {\r\n        X = x;\r\n        Y = y;\r\n        Z = z;\r\n        Subresource = subresource;\r\n    }\r\n    operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE\r\n{\r\n    CD3DX12_TILE_REGION_SIZE()\r\n    {}\r\n    explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) :\r\n        D3D12_TILE_REGION_SIZE(o)\r\n    {}\r\n    CD3DX12_TILE_REGION_SIZE( \r\n        UINT numTiles, \r\n        BOOL useBox, \r\n        UINT width, \r\n        UINT16 height, \r\n        UINT16 depth ) \r\n    {\r\n        NumTiles = numTiles;\r\n        UseBox = useBox;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n    }\r\n    operator const D3D12_TILE_REGION_SIZE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING\r\n{\r\n    CD3DX12_SUBRESOURCE_TILING()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) :\r\n        D3D12_SUBRESOURCE_TILING(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_TILING( \r\n        UINT widthInTiles, \r\n        UINT16 heightInTiles, \r\n        UINT16 depthInTiles, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        WidthInTiles = widthInTiles;\r\n        HeightInTiles = heightInTiles;\r\n        DepthInTiles = depthInTiles;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE\r\n{\r\n    CD3DX12_TILE_SHAPE()\r\n    {}\r\n    explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) :\r\n        D3D12_TILE_SHAPE(o)\r\n    {}\r\n    CD3DX12_TILE_SHAPE( \r\n        UINT widthInTexels, \r\n        UINT heightInTexels, \r\n        UINT depthInTexels ) \r\n    {\r\n        WidthInTexels = widthInTexels;\r\n        HeightInTexels = heightInTexels;\r\n        DepthInTexels = depthInTexels;\r\n    }\r\n    operator const D3D12_TILE_SHAPE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) :\r\n        D3D12_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_RESOURCE_BARRIER Transition(\r\n        _In_ ID3D12Resource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER Aliasing(\r\n        _In_ ID3D12Resource* pResourceBefore,\r\n        _In_ ID3D12Resource* pResourceAfter)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER UAV(\r\n        _In_ ID3D12Resource* pResource)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3D12_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO\r\n{\r\n    CD3DX12_PACKED_MIP_INFO()\r\n    {}\r\n    explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) :\r\n        D3D12_PACKED_MIP_INFO(o)\r\n    {}\r\n    CD3DX12_PACKED_MIP_INFO( \r\n        UINT8 numStandardMips, \r\n        UINT8 numPackedMips, \r\n        UINT numTilesForPackedMips, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        NumStandardMips = numStandardMips;\r\n        NumPackedMips = numPackedMips;\r\n        NumTilesForPackedMips = numTilesForPackedMips;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_PACKED_MIP_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT\r\n{\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) :\r\n        D3D12_SUBRESOURCE_FOOTPRINT(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        DXGI_FORMAT format, \r\n        UINT width, \r\n        UINT height, \r\n        UINT depth, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = format;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n        RowPitch = rowPitch;\r\n    }\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        const D3D12_RESOURCE_DESC& resDesc, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = resDesc.Format;\r\n        Width = UINT( resDesc.Width );\r\n        Height = resDesc.Height;\r\n        Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);\r\n        RowPitch = rowPitch;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION\r\n{ \r\n    CD3DX12_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) :\r\n        D3D12_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n}; \r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) :\r\n        D3D12_DESCRIPTOR_RANGE(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS\r\n{\r\n    CD3DX12_ROOT_CONSTANTS() {}\r\n    explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) :\r\n        D3D12_ROOT_CONSTANTS(o)\r\n    {}\r\n    CD3DX12_ROOT_CONSTANTS(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_CONSTANTS &rootConstants,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        rootConstants.Num32BitValues = num32BitValues;\r\n        rootConstants.ShaderRegister = shaderRegister;\r\n        rootConstants.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) :\r\n        D3D12_ROOT_DESCRIPTOR(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER\r\n{\r\n    CD3DX12_ROOT_PARAMETER() {}\r\n    explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) :\r\n        D3D12_ROOT_PARAMETER(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC\r\n{\r\n    CD3DX12_STATIC_SAMPLER_DESC() {}\r\n    explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) :\r\n        D3D12_STATIC_SAMPLER_DESC(o)\r\n    {}\r\n    CD3DX12_STATIC_SAMPLER_DESC(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc,\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        samplerDesc.ShaderRegister = shaderRegister;\r\n        samplerDesc.Filter = filter;\r\n        samplerDesc.AddressU = addressU;\r\n        samplerDesc.AddressV = addressV;\r\n        samplerDesc.AddressW = addressW;\r\n        samplerDesc.MipLODBias = mipLODBias;\r\n        samplerDesc.MaxAnisotropy = maxAnisotropy;\r\n        samplerDesc.ComparisonFunc = comparisonFunc;\r\n        samplerDesc.BorderColor = borderColor;\r\n        samplerDesc.MinLOD = minLOD;\r\n        samplerDesc.MaxLOD = maxLOD;\r\n        samplerDesc.ShaderVisibility = shaderVisibility;\r\n        samplerDesc.RegisterSpace = registerSpace;\r\n    }\r\n    inline void Init(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            *this,\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    CD3DX12_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.NumParameters = numParameters;\r\n        desc.pParameters = _pParameters;\r\n        desc.NumStaticSamplers = numStaticSamplers;\r\n        desc.pStaticSamplers = _pStaticSamplers;\r\n        desc.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE1 : public D3D12_DESCRIPTOR_RANGE1\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE1() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE1(const D3D12_DESCRIPTOR_RANGE1 &o) :\r\n        D3D12_DESCRIPTOR_RANGE1(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE1(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE1 &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.Flags = flags;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE1 : public D3D12_ROOT_DESCRIPTOR_TABLE1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE1(const D3D12_ROOT_DESCRIPTOR_TABLE1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE1 &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR1 : public D3D12_ROOT_DESCRIPTOR1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR1(const D3D12_ROOT_DESCRIPTOR1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR1(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR1 &table, \r\n        UINT shaderRegister, \r\n        UINT registerSpace = 0, \r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n        table.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER1 : public D3D12_ROOT_PARAMETER1\r\n{\r\n    CD3DX12_ROOT_PARAMETER1() {}\r\n    explicit CD3DX12_ROOT_PARAMETER1(const D3D12_ROOT_PARAMETER1 &o) :\r\n        D3D12_ROOT_PARAMETER1(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE1::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_VERSIONED_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        Desc_1_0 = o;\r\n    }\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC1 &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        Desc_1_1 = o;\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init_1_1(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init_1_0(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_0(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        desc.Desc_1_0.NumParameters = numParameters;\r\n        desc.Desc_1_0.pParameters = _pParameters;\r\n        desc.Desc_1_0.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_0.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_0.Flags = flags;\r\n    }\r\n\r\n    inline void Init_1_1(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_1(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        desc.Desc_1_1.NumParameters = numParameters;\r\n        desc.Desc_1_1.pParameters = _pParameters;\r\n        desc.Desc_1_1.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_1.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_1.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_CPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_GPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )\r\n{ \r\n    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; \r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename T, typename U, typename V>\r\ninline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )\r\n{\r\n    MipSlice = static_cast<T>(Subresource % MipLevels);\r\n    ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);\r\n    PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ ID3D12Device* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format};\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo))))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) :\r\n        D3D12_RESOURCE_DESC( o )\r\n    {}\r\n    CD3DX12_RESOURCE_DESC( \r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags )\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, \r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, \r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex1D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex2D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, \r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex3D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    inline UINT16 Depth() const\r\n    { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT16 ArraySize() const\r\n    { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const\r\n    { return D3D12GetFormatPlaneCount(pDevice, Format); }\r\n    inline UINT Subresources(_In_ ID3D12Device* pDevice) const\r\n    { return MipLevels * ArraySize() * PlaneCount(pDevice); }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Row-by-row memcpy\r\ninline void MemcpySubresource(\r\n    _In_ const D3D12_MEMCPY_DEST* pDest,\r\n    _In_ const D3D12_SUBRESOURCE_DATA* pSrc,\r\n    SIZE_T RowSizeInBytes,\r\n    UINT NumRows,\r\n    UINT NumSlices)\r\n{\r\n    for (UINT z = 0; z < NumSlices; ++z)\r\n    {\r\n        BYTE* pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;\r\n        const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * z;\r\n        for (UINT y = 0; y < NumRows; ++y)\r\n        {\r\n            memcpy(pDestSlice + pDest->RowPitch * y,\r\n                   pSrcSlice + pSrc->RowPitch * y,\r\n                   RowSizeInBytes);\r\n        }\r\n    }\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    UINT64 RequiredSize = 0;\r\n    \r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || \r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || \r\n        RequiredSize > (SIZE_T)-1 || \r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && \r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n    \r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n       return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n       return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout )\r\n{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename t_CommandListType>\r\ninline ID3D12CommandList * const * CommandListCast(t_CommandListType * const * pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<ID3D12CommandList * const *>(pp);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// D3D12 exports a new method for serializing root signatures in the Windows 10 Anniversary Update.\r\n// To help enable root signature 1.1 features when they are available and not require maintaining\r\n// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when\r\n// 1.1 is not supported.\r\ninline HRESULT D3DX12SerializeVersionedRootSignature(\r\n    _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n    D3D_ROOT_SIGNATURE_VERSION MaxVersion,\r\n    _Outptr_ ID3DBlob** ppBlob,\r\n    _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob)\r\n{\r\n    if (ppErrorBlob != NULL)\r\n    {\r\n        *ppErrorBlob = NULL;\r\n    }\r\n\r\n    switch (MaxVersion)\r\n    {\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n            switch (pRootSignatureDesc->Version)\r\n            {\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n                    return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n                {\r\n                    HRESULT hr = S_OK;\r\n                    const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1;\r\n\r\n                    const SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters;\r\n                    void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL;\r\n                    if (ParametersSize > 0 && pParameters == NULL)\r\n                    {\r\n                        hr = E_OUTOFMEMORY;\r\n                    }\r\n                    D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast<D3D12_ROOT_PARAMETER*>(pParameters);\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            __analysis_assume(ParametersSize == sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters);\r\n                            pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType;\r\n                            pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility;\r\n\r\n                            switch (desc_1_1.pParameters[n].ParameterType)\r\n                            {\r\n                            case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:\r\n                                pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues;\r\n                                pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace;\r\n                                pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_CBV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_SRV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_UAV:\r\n                                pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace;\r\n                                pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:\r\n                                const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable;\r\n\r\n                                const SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges;\r\n                                void* pDescriptorRanges = (DescriptorRangesSize > 0 && SUCCEEDED(hr)) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL;\r\n                                if (DescriptorRangesSize > 0 && pDescriptorRanges == NULL)\r\n                                {\r\n                                    hr = E_OUTOFMEMORY;\r\n                                }\r\n                                D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pDescriptorRanges);\r\n\r\n                                if (SUCCEEDED(hr))\r\n                                {\r\n                                    for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++)\r\n                                    {\r\n                                        __analysis_assume(DescriptorRangesSize == sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges);\r\n                                        pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister;\r\n                                        pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors;\r\n                                        pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart;\r\n                                        pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType;\r\n                                        pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace;\r\n                                    }\r\n                                }\r\n\r\n                                D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable;\r\n                                table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges;\r\n                                table_1_0.pDescriptorRanges = pDescriptorRanges_1_0;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags);\r\n                        hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n                    }\r\n\r\n                    if (pParameters)\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            if (desc_1_1.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n                            {\r\n                                HeapFree(GetProcessHeap(), 0, reinterpret_cast<void*>(const_cast<D3D12_DESCRIPTOR_RANGE*>(pParameters_1_0[n].DescriptorTable.pDescriptorRanges)));\r\n                            }\r\n                        }\r\n                        HeapFree(GetProcessHeap(), 0, pParameters);\r\n                    }\r\n                    return hr;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n            return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);\r\n    }\r\n\r\n    return E_INVALIDARG;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RT_FORMAT_ARRAY : public D3D12_RT_FORMAT_ARRAY\r\n{\r\n    CD3DX12_RT_FORMAT_ARRAY() {}\r\n    explicit CD3DX12_RT_FORMAT_ARRAY(const D3D12_RT_FORMAT_ARRAY& o)\r\n        : D3D12_RT_FORMAT_ARRAY(o)\r\n    {}\r\n    explicit CD3DX12_RT_FORMAT_ARRAY(const DXGI_FORMAT* pFormats, UINT NumFormats)\r\n    {\r\n        NumRenderTargets = NumFormats;\r\n        memcpy(RTFormats, pFormats, sizeof(RTFormats));\r\n        // assumes ARRAY_SIZE(pFormats) == ARRAY_SIZE(RTFormats)\r\n    }\r\n    operator const D3D12_RT_FORMAT_ARRAY&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Pipeline State Stream Helpers\r\n//------------------------------------------------------------------------------------------------\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stream Subobjects, i.e. elements of a stream\r\n\r\ntemplate <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type, typename DefaultArg = InnerStructType>\r\nclass alignas(void*) CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT\r\n{\r\nprivate:\r\n    D3D12_PIPELINE_STATE_SUBOBJECT_TYPE _Type;\r\n    InnerStructType _Inner;\r\npublic:\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT() : _Type(Type), _Inner(DefaultArg()) {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT(InnerStructType const& i) : _Type(Type), _Inner(i) {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT& operator=(InnerStructType const& i) { _Inner = i; return *this; }\r\n    operator InnerStructType() const { return _Inner; }\r\n};\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PIPELINE_STATE_FLAGS,         D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS>                           CD3DX12_PIPELINE_STATE_STREAM_FLAGS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT,                               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK>                       CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< ID3D12RootSignature*,               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE>                  CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INPUT_LAYOUT_DESC,            D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT>                    CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INDEX_BUFFER_STRIP_CUT_VALUE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE>              CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PRIMITIVE_TOPOLOGY_TYPE,      D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY>              CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS>                              CD3DX12_PIPELINE_STATE_STREAM_VS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS>                              CD3DX12_PIPELINE_STATE_STREAM_GS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_STREAM_OUTPUT_DESC,           D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT>                   CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS>                              CD3DX12_PIPELINE_STATE_STREAM_HS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS>                              CD3DX12_PIPELINE_STATE_STREAM_DS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS>                              CD3DX12_PIPELINE_STATE_STREAM_PS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS>                              CD3DX12_PIPELINE_STATE_STREAM_CS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_BLEND_DESC,                 D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND,          CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC,         D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL,  CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC1,        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_FORMAT,                        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT>            CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC,            D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER,     CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_RT_FORMAT_ARRAY,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS>           CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_SAMPLE_DESC,                   D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC>                     CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT,                               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK>                     CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_CACHED_PIPELINE_STATE,        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO>                      CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO;\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stream Parser Helpers\r\n\r\nstruct ID3DX12PipelineParserCallbacks\r\n{\r\n    // Subobject Callbacks\r\n    virtual void FlagsCb(D3D12_PIPELINE_STATE_FLAGS) {}\r\n    virtual void NodeMaskCb(UINT) {}\r\n    virtual void RootSignatureCb(ID3D12RootSignature*) {}\r\n    virtual void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC&) {}\r\n    virtual void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE) {}\r\n    virtual void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE) {}\r\n    virtual void VSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void GSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC&) {}\r\n    virtual void HSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void DSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void PSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void CSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void BlendStateCb(const D3D12_BLEND_DESC&) {}\r\n    virtual void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC&) {}\r\n    virtual void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1&) {}\r\n    virtual void DSVFormatCb(DXGI_FORMAT) {}\r\n    virtual void RasterizerStateCb(const D3D12_RASTERIZER_DESC&) {}\r\n    virtual void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY&) {}\r\n    virtual void SampleDescCb(const DXGI_SAMPLE_DESC&) {}\r\n    virtual void SampleMaskCb(UINT) {}\r\n    virtual void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE&) {}\r\n\r\n    // Error Callbacks\r\n    virtual void ErrorBadInputParameter(UINT /*ParameterIndex*/) {}\r\n    virtual void ErrorDuplicateSubobject(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE /*DuplicateType*/) {}\r\n    virtual void ErrorUnknownSubobject(UINT /*UnknownTypeValue*/) {}\r\n\r\n};\r\n\r\nstruct CD3DX12_PIPELINE_STATE_STREAM\r\n{\r\n    CD3DX12_PIPELINE_STATE_STREAM() {}\r\n    CD3DX12_PIPELINE_STATE_STREAM(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& Desc)\r\n        : Flags(Desc.Flags)\r\n        , NodeMask(Desc.NodeMask)\r\n        , pRootSignature(Desc.pRootSignature)\r\n        , InputLayout(Desc.InputLayout)\r\n        , IBStripCutValue(Desc.IBStripCutValue)\r\n        , PrimitiveTopologyType(Desc.PrimitiveTopologyType)\r\n        , VS(Desc.VS)\r\n        , GS(Desc.GS)\r\n        , StreamOutput(Desc.StreamOutput)\r\n        , HS(Desc.HS)\r\n        , DS(Desc.DS)\r\n        , PS(Desc.PS)\r\n        , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState))\r\n        , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC1(Desc.DepthStencilState))\r\n        , DSVFormat(Desc.DSVFormat)\r\n        , RasterizerState(CD3DX12_RASTERIZER_DESC(Desc.RasterizerState))\r\n        , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets))\r\n        , SampleDesc(Desc.SampleDesc)\r\n        , SampleMask(Desc.SampleMask)\r\n        , CachedPSO(Desc.CachedPSO)\r\n    {}\r\n    CD3DX12_PIPELINE_STATE_STREAM(const D3D12_COMPUTE_PIPELINE_STATE_DESC& Desc)\r\n        : Flags(Desc.Flags)\r\n        , NodeMask(Desc.NodeMask)\r\n        , pRootSignature(Desc.pRootSignature)\r\n        , CS(CD3DX12_SHADER_BYTECODE(Desc.CS))\r\n        , CachedPSO(Desc.CachedPSO)\r\n    {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_FLAGS Flags;\r\n    CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK NodeMask;\r\n    CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE pRootSignature;\r\n    CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT InputLayout;\r\n    CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE IBStripCutValue;\r\n    CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY PrimitiveTopologyType;\r\n    CD3DX12_PIPELINE_STATE_STREAM_VS VS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_GS GS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT StreamOutput;\r\n    CD3DX12_PIPELINE_STATE_STREAM_HS HS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DS DS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_PS PS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_CS CS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC BlendState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1 DepthStencilState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT DSVFormat;\r\n    CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER RasterizerState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS RTVFormats;\r\n    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC SampleDesc;\r\n    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK SampleMask;\r\n    CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO CachedPSO;\r\n    D3D12_GRAPHICS_PIPELINE_STATE_DESC GraphicsDescV0() const\r\n    {\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC D;\r\n        D.Flags                 = this->Flags;\r\n        D.NodeMask              = this->NodeMask;\r\n        D.pRootSignature        = this->pRootSignature;\r\n        D.InputLayout           = this->InputLayout;\r\n        D.IBStripCutValue       = this->IBStripCutValue;\r\n        D.PrimitiveTopologyType = this->PrimitiveTopologyType;\r\n        D.VS                    = this->VS;\r\n        D.GS                    = this->GS;\r\n        D.StreamOutput          = this->StreamOutput;\r\n        D.HS                    = this->HS;\r\n        D.DS                    = this->DS;\r\n        D.PS                    = this->PS;\r\n        D.BlendState            = this->BlendState;\r\n        D.DepthStencilState     = CD3DX12_DEPTH_STENCIL_DESC1(D3D12_DEPTH_STENCIL_DESC1(this->DepthStencilState));\r\n        D.DSVFormat             = this->DSVFormat;\r\n        D.RasterizerState       = this->RasterizerState;\r\n        D.NumRenderTargets      = D3D12_RT_FORMAT_ARRAY(this->RTVFormats).NumRenderTargets;\r\n        memcpy(D.RTVFormats, D3D12_RT_FORMAT_ARRAY(this->RTVFormats).RTFormats, sizeof(D.RTVFormats));\r\n        D.SampleDesc            = this->SampleDesc;\r\n        D.SampleMask            = this->SampleMask;\r\n        D.CachedPSO             = this->CachedPSO;\r\n        return D;\r\n    }\r\n    D3D12_COMPUTE_PIPELINE_STATE_DESC ComputeDescV0() const\r\n    {\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC D;\r\n        D.Flags                 = this->Flags;\r\n        D.NodeMask              = this->NodeMask;\r\n        D.pRootSignature        = this->pRootSignature;\r\n        D.CS                    = this->CS;\r\n        D.CachedPSO             = this->CachedPSO;\r\n        return D;\r\n    }\r\n};\r\n\r\nstruct CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER : public ID3DX12PipelineParserCallbacks\r\n{\r\n    CD3DX12_PIPELINE_STATE_STREAM PipelineStream;\r\n\r\n    // ID3DX12PipelineParserCallbacks\r\n    void FlagsCb(D3D12_PIPELINE_STATE_FLAGS Flags) {PipelineStream.Flags = Flags;}\r\n    void NodeMaskCb(UINT NodeMask) {PipelineStream.NodeMask = NodeMask;}\r\n    void RootSignatureCb(ID3D12RootSignature* pRootSignature) {PipelineStream.pRootSignature = pRootSignature;}\r\n    void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC& InputLayout) {PipelineStream.InputLayout = InputLayout;}\r\n    void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue) {PipelineStream.IBStripCutValue = IBStripCutValue;}\r\n    void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType) {PipelineStream.PrimitiveTopologyType = PrimitiveTopologyType;}\r\n    void VSCb(const D3D12_SHADER_BYTECODE& VS) {PipelineStream.VS = VS;}\r\n    void GSCb(const D3D12_SHADER_BYTECODE& GS) {PipelineStream.GS = GS;}\r\n    void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC& StreamOutput) {PipelineStream.StreamOutput = StreamOutput;}\r\n    void HSCb(const D3D12_SHADER_BYTECODE& HS) {PipelineStream.HS = HS;}\r\n    void DSCb(const D3D12_SHADER_BYTECODE& DS) {PipelineStream.DS = DS;}\r\n    void PSCb(const D3D12_SHADER_BYTECODE& PS) {PipelineStream.PS = PS;}\r\n    void CSCb(const D3D12_SHADER_BYTECODE& CS) {PipelineStream.CS = CS;}\r\n    void BlendStateCb(const D3D12_BLEND_DESC& BlendState) {PipelineStream.BlendState = CD3DX12_BLEND_DESC(BlendState);}\r\n    void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC& DepthStencilState) {PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(DepthStencilState);}\r\n    void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1& DepthStencilState) {PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(DepthStencilState);}\r\n    void DSVFormatCb(DXGI_FORMAT DSVFormat) {PipelineStream.DSVFormat = DSVFormat;}\r\n    void RasterizerStateCb(const D3D12_RASTERIZER_DESC& RasterizerState) {PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC(RasterizerState);}\r\n    void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY& RTVFormats) {PipelineStream.RTVFormats = RTVFormats;}\r\n    void SampleDescCb(const DXGI_SAMPLE_DESC& SampleDesc) {PipelineStream.SampleDesc = SampleDesc;}\r\n    void SampleMaskCb(UINT SampleMask) {PipelineStream.SampleMask = SampleMask;}\r\n    void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE& CachedPSO) {PipelineStream.CachedPSO = CachedPSO;}\r\n    void ErrorBadInputParameter(UINT) {}\r\n    void ErrorDuplicateSubobject(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE) {}\r\n    void ErrorUnknownSubobject(UINT) {}\r\n};\r\n\r\ninline D3D12_PIPELINE_STATE_SUBOBJECT_TYPE D3DX12GetBaseSubobjectType(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE SubobjectType)\r\n{\r\n    switch (SubobjectType)\r\n    {\r\n    case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1: \r\n        return D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL;\r\n    default:\r\n        return SubobjectType;\r\n    }\r\n}\r\n\r\ninline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& Desc, ID3DX12PipelineParserCallbacks* pCallbacks)\r\n{\r\n    if (Desc.SizeInBytes == 0 || Desc.pPipelineStateSubobjectStream == nullptr)\r\n    {\r\n        pCallbacks->ErrorBadInputParameter(1); // first parameter issue\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    if (pCallbacks == nullptr)\r\n    {\r\n        pCallbacks->ErrorBadInputParameter(2); // second parameter issue\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    bool SubobjectSeen[D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID] = {0};\r\n    for (SIZE_T CurOffset = 0, SizeOfSubobject = 0; CurOffset < Desc.SizeInBytes; CurOffset += SizeOfSubobject)\r\n    {\r\n        BYTE* pStream = static_cast<BYTE*>(Desc.pPipelineStateSubobjectStream)+CurOffset;\r\n        auto SubobjectType = *reinterpret_cast<D3D12_PIPELINE_STATE_SUBOBJECT_TYPE*>(pStream);\r\n        if (SubobjectType >= D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID)\r\n        {\r\n            pCallbacks->ErrorUnknownSubobject(SubobjectType);\r\n            return E_INVALIDARG;\r\n        }\r\n        if (SubobjectSeen[D3DX12GetBaseSubobjectType(SubobjectType)])\r\n        {\r\n            pCallbacks->ErrorDuplicateSubobject(SubobjectType);\r\n            return E_INVALIDARG; // disallow subobject duplicates in a stream\r\n        }\r\n        SubobjectSeen[SubobjectType] = true;\r\n        switch (SubobjectType)\r\n        {\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE: \r\n            pCallbacks->RootSignatureCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::pRootSignature)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::pRootSignature);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS:\r\n            pCallbacks->VSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::VS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::VS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS: \r\n            pCallbacks->PSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::PS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::PS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS: \r\n            pCallbacks->DSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS: \r\n            pCallbacks->HSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::HS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::HS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS: \r\n            pCallbacks->GSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::GS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::GS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS:\r\n            pCallbacks->CSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::CS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT: \r\n            pCallbacks->StreamOutputCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND: \r\n            pCallbacks->BlendStateCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::BlendState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::BlendState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK: \r\n            pCallbacks->SampleMaskCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::SampleMask)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::SampleMask);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER: \r\n            pCallbacks->RasterizerStateCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::RasterizerState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::RasterizerState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL: \r\n            pCallbacks->DepthStencilStateCb(*reinterpret_cast<CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1: \r\n            pCallbacks->DepthStencilState1Cb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DepthStencilState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DepthStencilState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT: \r\n            pCallbacks->InputLayoutCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::InputLayout)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::InputLayout);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE: \r\n            pCallbacks->IBStripCutValueCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::IBStripCutValue)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::IBStripCutValue);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY: \r\n            pCallbacks->PrimitiveTopologyTypeCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::PrimitiveTopologyType)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::PrimitiveTopologyType);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS: \r\n            pCallbacks->RTVFormatsCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::RTVFormats)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::RTVFormats);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT: \r\n            pCallbacks->DSVFormatCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DSVFormat)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DSVFormat);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC: \r\n            pCallbacks->SampleDescCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::SampleDesc)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::SampleDesc);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK: \r\n            pCallbacks->NodeMaskCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::NodeMask)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::NodeMask);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO: \r\n            pCallbacks->CachedPSOCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::CachedPSO)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CachedPSO);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS:\r\n            pCallbacks->FlagsCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::Flags)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::Flags);\r\n            break;\r\n        default:\r\n            pCallbacks->ErrorUnknownSubobject(SubobjectType);\r\n            return E_INVALIDARG;\r\n            break;\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n#endif // defined( __cplusplus )\r\n\r\n#endif //__D3DX12_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Libraries/D3DX12/readme.md",
    "content": "# The D3D12 Helper Library\n\nThis library provides helper functions and structs to make certain common operations less verbose in your code.\n\nDocumentation of the helper functions and structures can he found on [MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/dn708058(v=vs.85).aspx)\n\nNote that Windows 10 Creator Update and Visual Studio 2017 are required for the latest version of D3D12 Helper Library. Visual Studio 2015 compatible version can be found from https://github.com/Microsoft/DirectX-Graphics-Samples/releases/tag/v10.0.14393.4.\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandAllocator.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityCommandAllocator::CD3DX12AffinityCommandAllocator(CD3DX12AffinityDevice* device, ID3D12CommandAllocator** commandAllocators, UINT Count, bool UseDeviceActiveMaskOnReset)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(commandAllocators), Count)\r\n    , mUseDeviceActiveMaskOnReset(UseDeviceActiveMaskOnReset)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandAllocators[i] = commandAllocators[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandAllocators[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandAllocator\";\r\n#endif\r\n\r\n#if !ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    if (UseDeviceActiveMaskOnReset)\r\n    {\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n#endif\r\n}\r\n\r\nHRESULT CD3DX12AffinityCommandAllocator::Reset(void)\r\n{\r\n#if !ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    if (mUseDeviceActiveMaskOnReset)\r\n    {\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n#endif\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandAllocator* Allocator = mCommandAllocators[i];\r\n            HRESULT const hr = Allocator->Reset();\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nID3D12CommandAllocator* CD3DX12AffinityCommandAllocator::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandAllocators[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandAllocator.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandAllocator : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityCommandAllocator(CD3DX12AffinityDevice* device, ID3D12CommandAllocator** commandAllocators, UINT Count, bool UseDeviceActiveMaskOnReset);\r\n\r\n    HRESULT STDMETHODCALLTYPE Reset(void);\r\n    ID3D12CommandAllocator* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    ID3D12CommandAllocator* mCommandAllocators[D3DX12_MAX_ACTIVE_NODES];\r\n    bool mUseDeviceActiveMaskOnReset;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandList.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nCD3DX12AffinityCommandList::CD3DX12AffinityCommandList(CD3DX12AffinityDevice* device, ID3D12CommandList** commandLists, UINT Count)\r\n    : CD3DX12AffinityDeviceChild(device, reinterpret_cast<ID3D12DeviceChild**>(commandLists), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandLists[i] = commandLists[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandLists[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandList\";\r\n#endif\r\n}\r\n\r\nD3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE CD3DX12AffinityCommandList::GetType(UINT AffinityIndex)\r\n{\r\n    return mCommandLists[AffinityIndex]->GetType();\r\n}\r\n\r\nBOOL STDMETHODCALLTYPE CD3DX12AffinityCommandList::AssertResourceState(\r\n    CD3DX12AffinityResource* pResource,\r\n    UINT Subresource,\r\n    UINT State)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    ID3D12CommandList* CommandList = mCommandLists[i];\r\n    ID3D12DebugCommandList* DebugCommandList = nullptr;\r\n\r\n    HRESULT const hr = CommandList->QueryInterface(IID_PPV_ARGS(&DebugCommandList));\r\n    if (S_OK != hr)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    if (false == DebugCommandList->AssertResourceState(pResource->mResources[i], Subresource, State))\r\n    {\r\n        return false;\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandList::SetFeatureMask(\r\n    D3D12_DEBUG_FEATURE Mask)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandList* CommandList = mCommandLists[i];\r\n            ID3D12DebugCommandList* DebugCommandList = nullptr;\r\n\r\n            HRESULT hr = CommandList->QueryInterface(IID_PPV_ARGS(&DebugCommandList));\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n\r\n            hr = DebugCommandList->SetFeatureMask(Mask);\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nID3D12CommandList* CD3DX12AffinityCommandList::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandLists[AffinityIndex];\r\n}\r\n\r\nbool CD3DX12AffinityCommandList::IsReady()\r\n{\r\n    return mPendingBroadcast == 0;\r\n}\r\n\r\nvoid CD3DX12AffinityCommandList::RegisterPendingBroadcast()\r\n{\r\n    std::lock_guard<std::mutex> lock(mMutexPendingBroadcast);\r\n    mPendingBroadcast++;\r\n}\r\n\r\nvoid CD3DX12AffinityCommandList::UnRegisterPendingBroadcast()\r\n{\r\n    std::lock_guard<std::mutex> lock(mMutexPendingBroadcast);\r\n    mPendingBroadcast--;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandList.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandList : public CD3DX12AffinityDeviceChild\r\n{\r\npublic:\r\n    CD3DX12AffinityCommandList(CD3DX12AffinityDevice* device, ID3D12CommandList** commandLists, UINT Count);\r\n\r\n    D3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE GetType(UINT AffinityIndex = 0);\r\n\r\n    BOOL STDMETHODCALLTYPE AssertResourceState(\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        UINT Subresource,\r\n        UINT State);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetFeatureMask(\r\n        D3D12_DEBUG_FEATURE Mask);\r\n\r\n    ID3D12CommandList* GetChildObject(UINT AffinityIndex);\r\n\r\n    bool IsReady();\r\n    void RegisterPendingBroadcast();\r\n    void UnRegisterPendingBroadcast();\r\n\r\nprivate:\r\n    ID3D12CommandList* mCommandLists[D3DX12_MAX_ACTIVE_NODES];\r\n    std::mutex mMutexPendingBroadcast;\r\n    UINT mPendingBroadcast = 0;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandQueue.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::UpdateTileMappings(\r\n    CD3DX12AffinityResource* pResource,\r\n    UINT NumResourceRegions,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pResourceRegionStartCoordinates,\r\n    const D3D12_TILE_REGION_SIZE* pResourceRegionSizes,\r\n    CD3DX12AffinityHeap* pHeap,\r\n    UINT NumRanges,\r\n    const D3D12_TILE_RANGE_FLAGS* pRangeFlags,\r\n    const UINT* pHeapRangeStartOffsets,\r\n    const UINT* pRangeTileCounts,\r\n    D3D12_TILE_MAPPING_FLAGS Flags,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            {\r\n                ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n                Queue->UpdateTileMappings(\r\n                    pResource->mResources[i],\r\n                    NumResourceRegions,\r\n                    pResourceRegionStartCoordinates,\r\n                    pResourceRegionSizes,\r\n                    pHeap->GetChildObject(i),\r\n                    NumRanges,\r\n                    pRangeFlags,\r\n                    pHeapRangeStartOffsets,\r\n                    pRangeTileCounts,\r\n                    Flags);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::CopyTileMappings(\r\n    CD3DX12AffinityResource* pDstResource,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pDstRegionStartCoordinate,\r\n    CD3DX12AffinityResource* pSrcResource,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pSrcRegionStartCoordinate,\r\n    const D3D12_TILE_REGION_SIZE* pRegionSize,\r\n    D3D12_TILE_MAPPING_FLAGS Flags,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n            Queue->CopyTileMappings(\r\n                pDstResource->mResources[i],\r\n                pDstRegionStartCoordinate,\r\n                pSrcResource->mResources[i],\r\n                pSrcRegionStartCoordinate,\r\n                pRegionSize,\r\n                Flags);\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::ExecuteCommandLists(\r\n    UINT NumCommandLists,\r\n    CD3DX12AffinityCommandList* const* ppCommandLists,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12CommandList*> mCachedCommandLists;\r\n    mCachedCommandLists.resize(NumCommandLists);\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            {\r\n                ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n                UINT index = 0;\r\n                for (UINT c = 0; c < NumCommandLists; ++c)\r\n                {\r\n                    CD3DX12AffinityGraphicsCommandList* AffinityCommandList = static_cast<CD3DX12AffinityGraphicsCommandList*>(ppCommandLists[c]);\r\n                    if (AffinityCommandList->GetActiveAffinityMask() & (1 << i))\r\n                    {\r\n                        mCachedCommandLists[index++] = AffinityCommandList->GetChildObject(i);\r\n                    }\r\n                }\r\n\r\n                Queue->ExecuteCommandLists(index, mCachedCommandLists.data());\r\n\r\n#ifdef SERIALIZE_COMMNANDLIST_EXECUTION\r\n                ID3D12Fence* pFence;\r\n                GetParentDevice()->mDevices[0]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n                Queue->Signal(pFence, 1);\r\n                HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n                pFence->SetEventOnCompletion(1, hEvent);\r\n                WaitForSingleObject(hEvent, INFINITE);\r\n                CloseHandle(hEvent);\r\n                pFence->Release();\r\n                if (FAILED(GetParentDevice()->mDevices[0]->GetDeviceRemovedReason()))\r\n                {\r\n                    __debugbreak();\r\n                }\r\n#endif\r\n            }\r\n        }\r\n    }\r\n    ReleaseLog(L\"D3DX12AffinityLayer: [event] ExecuteCommandLists\\n\");\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::SetMarker(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size,\r\n    UINT AffinityMask)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    {\r\n        ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n        Queue->SetMarker(Metadata, pData, Size);\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::BeginEvent(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size,\r\n    UINT AffinityMask)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    {\r\n        ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n        Queue->BeginEvent(Metadata, pData, Size);\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::EndEvent(UINT AffinityMask)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    {\r\n        ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n        Queue->EndEvent();\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::Signal(\r\n    CD3DX12AffinityFence* pFence,\r\n    UINT64 Value,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            {\r\n                ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n                HRESULT const hr = Queue->Signal(pFence->mFences[i], Value);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::Wait(\r\n    CD3DX12AffinityFence* pFence,\r\n    UINT64 Value,\r\n    bool UseActiveQueueOnly,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandQueue* Queue = UseActiveQueueOnly ? mCommandQueues[ActiveNodeIndex] : mCommandQueues[i];\r\n\r\n            HRESULT const hr = Queue->Wait(pFence->mFences[i], Value);\r\n\r\n            if (hr != S_OK)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::GetTimestampFrequency(\r\n    UINT64* pFrequency,\r\n    UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex]->GetTimestampFrequency(pFrequency);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::GetClockCalibration(\r\n    UINT64* pGpuTimestamp,\r\n    UINT64* pCpuTimestamp,\r\n    UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex]->GetClockCalibration(pGpuTimestamp, pCpuTimestamp);\r\n}\r\n\r\nD3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::GetDesc(UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex]->GetDesc();\r\n}\r\n\r\nID3D12CommandQueue* CD3DX12AffinityCommandQueue::GetQueueForSwapChainCreation(UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex];\r\n}\r\n\r\nCD3DX12AffinityCommandQueue::CD3DX12AffinityCommandQueue(CD3DX12AffinityDevice* device, ID3D12CommandQueue** commandQueues, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(commandQueues), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandQueues[i] = commandQueues[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandQueues[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandQueue\";\r\n#endif\r\n}\r\n\r\nID3D12CommandQueue* CD3DX12AffinityCommandQueue::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex];\r\n}\r\n\r\nvoid CD3DX12AffinityCommandQueue::WaitForCompletion(UINT AffinityMask)\r\n{\r\n    // Very inefficient. Should be used very sparingly.\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            ID3D12Fence* pFence;\r\n            ID3D12Device* pDevice = GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA ?\r\n                GetParentDevice()->GetChildObject(0) : GetParentDevice()->GetChildObject(i);\r\n            pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n            mCommandQueues[i]->Signal(pFence, 1);\r\n            HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n            pFence->SetEventOnCompletion(1, hEvent);\r\n            WaitForSingleObject(hEvent, INFINITE);\r\n            CloseHandle(hEvent);\r\n            pFence->Release();\r\n            if (FAILED(pDevice->GetDeviceRemovedReason()))\r\n            {\r\n                __debugbreak();\r\n            }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandQueue.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandQueue : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    void STDMETHODCALLTYPE UpdateTileMappings(\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        UINT NumResourceRegions,\r\n        _In_reads_opt_(NumResourceRegions)  const D3D12_TILED_RESOURCE_COORDINATE* pResourceRegionStartCoordinates,\r\n        _In_reads_opt_(NumResourceRegions)  const D3D12_TILE_REGION_SIZE* pResourceRegionSizes,\r\n        _In_opt_  CD3DX12AffinityHeap* pHeap,\r\n        UINT NumRanges,\r\n        _In_reads_opt_(NumRanges)  const D3D12_TILE_RANGE_FLAGS* pRangeFlags,\r\n        _In_reads_opt_(NumRanges)  const UINT* pHeapRangeStartOffsets,\r\n        _In_reads_opt_(NumRanges)  const UINT* pRangeTileCounts,\r\n        D3D12_TILE_MAPPING_FLAGS Flags,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyTileMappings(\r\n        _In_  CD3DX12AffinityResource* pDstResource,\r\n        _In_  const D3D12_TILED_RESOURCE_COORDINATE* pDstRegionStartCoordinate,\r\n        _In_  CD3DX12AffinityResource* pSrcResource,\r\n        _In_  const D3D12_TILED_RESOURCE_COORDINATE* pSrcRegionStartCoordinate,\r\n        _In_  const D3D12_TILE_REGION_SIZE* pRegionSize,\r\n        D3D12_TILE_MAPPING_FLAGS Flags,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE ExecuteCommandLists(\r\n        _In_  UINT NumCommandLists,\r\n        _In_reads_(NumCommandLists)  CD3DX12AffinityCommandList* const* ppCommandLists,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE SetMarker(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE BeginEvent(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE EndEvent(_In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE Signal(\r\n        CD3DX12AffinityFence* pFence,\r\n        UINT64 Value,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE Wait(\r\n        CD3DX12AffinityFence* pFence,\r\n        UINT64 Value,\r\n        bool UseActiveQueueOnly = false,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetTimestampFrequency(\r\n        _Out_  UINT64* pFrequency,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetClockCalibration(\r\n        _Out_  UINT64* pGpuTimestamp,\r\n        _Out_  UINT64* pCpuTimestamp,\r\n        UINT AffinityIndex = 0);\r\n\r\n    D3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n\r\n    ID3D12CommandQueue* GetQueueForSwapChainCreation(UINT AffinityIndex);\r\n    ID3D12CommandQueue* GetChildObject(UINT AffinityIndex);\r\n    void WaitForCompletion(UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    CD3DX12AffinityCommandQueue(CD3DX12AffinityDevice* device, ID3D12CommandQueue** commandQueues, UINT Count);\r\n\r\nprivate:\r\n    std::vector<ID3D12CommandList*> mCachedCommandLists;\r\n    ID3D12CommandQueue* mCommandQueues[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandSignature.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityCommandSignature::CD3DX12AffinityCommandSignature(CD3DX12AffinityDevice* device, ID3D12CommandSignature** commandSignatures, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(commandSignatures), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandSignatures[i] = commandSignatures[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandSignatures[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandSignature\";\r\n#endif\r\n}\r\n\r\nID3D12CommandSignature* CD3DX12AffinityCommandSignature::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandSignatures[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityCommandSignature.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandSignature : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityCommandSignature(CD3DX12AffinityDevice* device, ID3D12CommandSignature** commandSignatures, UINT Count);\r\n    ID3D12CommandSignature* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    ID3D12CommandSignature* mCommandSignatures[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityDescriptorHeap.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nD3D12_DESCRIPTOR_HEAP_DESC STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetDesc(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex]->GetDesc();\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetCPUDescriptorHandleForHeapStart(void)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return mDescriptorHeaps[0]->GetCPUDescriptorHandleForHeapStart();\r\n    }\r\n    D3D12_CPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = (SIZE_T)mCPUHeapStart;\r\n    return handle;\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetGPUDescriptorHandleForHeapStart(void)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return mDescriptorHeaps[0]->GetGPUDescriptorHandleForHeapStart();\r\n    }\r\n    D3D12_GPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = (SIZE_T)mGPUHeapStart;\r\n    return handle;\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetActiveCPUDescriptorHandleForHeapStart(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex]->GetCPUDescriptorHandleForHeapStart();\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetActiveGPUDescriptorHandleForHeapStart(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex]->GetGPUDescriptorHandleForHeapStart();\r\n}\r\n\r\nvoid CD3DX12AffinityDescriptorHeap::InitDescriptorHandles(D3D12_DESCRIPTOR_HEAP_TYPE type)\r\n{\r\n    UINT const NodeCount = GetNodeCount();\r\n\r\n    UINT maxindex = 0;\r\n    for (UINT i = 0; i < NodeCount; ++i)\r\n    {\r\n        D3D12_CPU_DESCRIPTOR_HANDLE const CPUBase = mDescriptorHeaps[i]->GetCPUDescriptorHandleForHeapStart();\r\n        D3D12_GPU_DESCRIPTOR_HANDLE const GPUBase = mDescriptorHeaps[i]->GetGPUDescriptorHandleForHeapStart();\r\n        UINT HandleIncrement = 0;\r\n        if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n        {\r\n            HandleIncrement = GetParentDevice()->GetChildObject(0)->GetDescriptorHandleIncrementSize(type);\r\n        }\r\n        for (UINT j = 0; j < mNumDescriptors; ++j)\r\n        {\r\n            mCPUHeapStart[j * NodeCount + i] = CPUBase.ptr + HandleIncrement * j;\r\n            mGPUHeapStart[j * NodeCount + i] = GPUBase.ptr + HandleIncrement * j;\r\n            maxindex = max(maxindex, j * NodeCount + i);\r\n        }\r\n    }\r\n\r\n\r\n    DebugLog(L\"Used up to index %u in heap array\\n\", maxindex);\r\n\r\n    DebugLog(L\"Created a descriptor heap with CPU start at 0x%IX and GPU start a 0x%IX\\n\", mCPUHeapStart, mGPUHeapStart);\r\n    for (UINT i = 0; i < NodeCount; ++i)\r\n    {\r\n        DebugLog(L\"  Device %u CPU starts at 0x%IX and GPU starts at 0x%IX\\n\",\r\n            i, mDescriptorHeaps[i]->GetCPUDescriptorHandleForHeapStart().ptr, mDescriptorHeaps[i]->GetGPUDescriptorHandleForHeapStart().ptr);\r\n    }\r\n\r\n#ifdef D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n    // Validation\r\n    {\r\n        std::lock_guard<std::mutex> lock(GetParentDevice()->MutexPointerRanges);\r\n\r\n        GetParentDevice()->CPUHeapPointerRanges.push_back(std::make_pair((SIZE_T)mCPUHeapStart, (SIZE_T)(mCPUHeapStart + mNumDescriptors * NodeCount)));\r\n        GetParentDevice()->GPUHeapPointerRanges.push_back(std::make_pair((SIZE_T)mGPUHeapStart, (SIZE_T)(mGPUHeapStart + mNumDescriptors * NodeCount)));\r\n    }\r\n#endif\r\n}\r\n\r\nCD3DX12AffinityDescriptorHeap::CD3DX12AffinityDescriptorHeap(CD3DX12AffinityDevice* device, ID3D12DescriptorHeap** descriptorHeaps, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(descriptorHeaps), Count)\r\n    , mCPUHeapStart(nullptr)\r\n    , mGPUHeapStart(nullptr)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mDescriptorHeaps[i] = descriptorHeaps[i];\r\n        }\r\n        else\r\n        {\r\n            mDescriptorHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"DescriptorHeap\";\r\n#endif\r\n}\r\n\r\nCD3DX12AffinityDescriptorHeap::~CD3DX12AffinityDescriptorHeap()\r\n{\r\n    if (mCPUHeapStart != nullptr)\r\n    {\r\n        delete[] mCPUHeapStart;\r\n    }\r\n    if (mGPUHeapStart != nullptr)\r\n    {\r\n        delete[] mGPUHeapStart;\r\n    }\r\n}\r\n\r\nID3D12DescriptorHeap* CD3DX12AffinityDescriptorHeap::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityDescriptorHeap.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityDescriptorHeap : public CD3DX12AffinityPageable\r\n{\r\n    friend class CD3DX12AffinityDevice;\r\n\r\npublic:\r\n    D3D12_DESCRIPTOR_HEAP_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetCPUDescriptorHandleForHeapStart(void);\r\n\r\n    D3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetGPUDescriptorHandleForHeapStart(void);\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetActiveCPUDescriptorHandleForHeapStart(UINT AffinityIndex);\r\n\r\n    D3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetActiveGPUDescriptorHandleForHeapStart(UINT AffinityIndex);\r\n\r\n    void InitDescriptorHandles(D3D12_DESCRIPTOR_HEAP_TYPE type);\r\n\r\n    CD3DX12AffinityDescriptorHeap(CD3DX12AffinityDevice* device, ID3D12DescriptorHeap** descriptorHeaps, UINT Count);\r\n    CD3DX12AffinityDescriptorHeap::~CD3DX12AffinityDescriptorHeap();\r\n\r\n    ID3D12DescriptorHeap* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    UINT mNumDescriptors;\r\n    ID3D12DescriptorHeap* mDescriptorHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n    UINT64* mCPUHeapStart;\r\n    UINT64* mGPUHeapStart;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityDevice.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::SetAffinity(UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityObject::SetAffinity(AffinityMask);\r\n    UpdateActiveDevices();\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::UpdateActiveDevices()\r\n{\r\n    mNumActiveDevices = 0;\r\n    for (int i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (mDevices[i])\r\n        {\r\n            mNumActiveDevices++;\r\n        }\r\n        else\r\n        {\r\n            break;\r\n        }\r\n    }\r\n}\r\n\r\nUINT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetNodeCount(void)\r\n{\r\n    return g_CachedNodeCount;\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::LDAAllNodeMasks()\r\n{\r\n    return (1 << mLDANodeCount) - 1;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandQueue(\r\n    const D3D12_COMMAND_QUEUE_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppCommandQueue,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_COMMAND_QUEUE_DESC Desc = *pDesc;\r\n\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    std::vector<ID3D12CommandQueue*> Queues;\r\n    Queues.resize(GetNodeCount(), nullptr);\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12CommandQueue* Queue = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT hr = Device->CreateCommandQueue(&Desc, IID_PPV_ARGS(&Queue));\r\n                if (S_OK == hr)\r\n                {\r\n                    Queues[i] = Queue;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityCommandQueue* CommandQueue = new CD3DX12AffinityCommandQueue(this, &(Queues[0]), (UINT)Queues.size());\r\n    (*ppCommandQueue) = CommandQueue;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandAllocator(\r\n    D3D12_COMMAND_LIST_TYPE type,\r\n    REFIID riid,\r\n    void** ppCommandAllocator,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12CommandAllocator*> Allocators;\r\n    Allocators.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12CommandAllocator* Allocator = nullptr;\r\n                HRESULT hr = Device->CreateCommandAllocator(type, IID_PPV_ARGS(&Allocator));\r\n                if (S_OK == hr)\r\n                {\r\n                    Allocators[i] = Allocator;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityCommandAllocator* CommandAllocator = new CD3DX12AffinityCommandAllocator(this, &(Allocators[0]), (UINT)Allocators.size(), AffinityMask == 0);\r\n    (*ppCommandAllocator) = CommandAllocator;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateGraphicsPipelineState(\r\n    const D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppPipelineState,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityRootSignature* AffinityRootSignature = static_cast<CD3DX12AffinityRootSignature*>(pDesc->pRootSignature);\r\n\r\n    std::vector<ID3D12PipelineState*> PipelineStates;\r\n    PipelineStates.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        //\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC ActualDescriptor;\r\n        ActualDescriptor = pDesc->ToD3D12();\r\n        ActualDescriptor.pRootSignature = AffinityRootSignature->mRootSignatures[0];\r\n        ActualDescriptor.NodeMask = LDAAllNodeMasks();\r\n\r\n        ID3D12PipelineState* PipelineState = nullptr;\r\n        HRESULT const hr = Device->CreateGraphicsPipelineState(&ActualDescriptor, IID_PPV_ARGS(&PipelineState));\r\n        if (S_OK == hr)\r\n        {\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n                    PipelineState->AddRef();\r\n                    PipelineStates[i] = PipelineState;\r\n\r\n                }\r\n            }\r\n            PipelineState->Release();\r\n        }\r\n        else\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n    CD3DX12AffinityPipelineState* AffinityPipelineState = new CD3DX12AffinityPipelineState(this, &(PipelineStates[0]), (UINT)PipelineStates.size());\r\n    (*ppPipelineState) = AffinityPipelineState;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateComputePipelineState(\r\n    const D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppPipelineState,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityRootSignature* AffinityRootSignature = static_cast<CD3DX12AffinityRootSignature*>(pDesc->pRootSignature);\r\n\r\n    std::vector<ID3D12PipelineState*> PipelineStates;\r\n    PipelineStates.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC ActualDescriptor;\r\n        ActualDescriptor = pDesc->ToD3D12();\r\n        ActualDescriptor.pRootSignature = AffinityRootSignature->mRootSignatures[0];\r\n        ActualDescriptor.NodeMask = LDAAllNodeMasks();\r\n\r\n        ID3D12PipelineState* PipelineState = nullptr;\r\n        HRESULT const hr = Device->CreateComputePipelineState(&ActualDescriptor, IID_PPV_ARGS(&PipelineState));\r\n        if (S_OK == hr)\r\n        {\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n                    PipelineState->AddRef();\r\n                    PipelineStates[i] = PipelineState;\r\n                }\r\n            }\r\n            PipelineState->Release();\r\n        }\r\n        else\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityPipelineState* AffinityPipelineState = new CD3DX12AffinityPipelineState(this, &(PipelineStates[0]), (UINT)PipelineStates.size());\r\n    (*ppPipelineState) = AffinityPipelineState;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandList(\r\n    UINT nodeMask,\r\n    D3D12_COMMAND_LIST_TYPE type,\r\n    CD3DX12AffinityCommandAllocator* pCommandAllocator,\r\n    CD3DX12AffinityPipelineState* pInitialState,\r\n    REFIID riid,\r\n    void** ppCommandList,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12GraphicsCommandList*> CommandLists;\r\n    CommandLists.resize(GetNodeCount(), nullptr);\r\n    CD3DX12AffinityCommandAllocator* WrappedAllocator = static_cast<CD3DX12AffinityCommandAllocator*>(pCommandAllocator);\r\n    CD3DX12AffinityPipelineState* WrappedState = static_cast<CD3DX12AffinityPipelineState*>(pInitialState);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12GraphicsCommandList* CommandList = nullptr;\r\n                HRESULT hr = Device->CreateCommandList(AffinityIndexToNodeMask(i), type,\r\n                    WrappedAllocator->GetChildObject(i),\r\n                    WrappedState ? WrappedState->mPipelineStates[i] : nullptr, IID_PPV_ARGS(&CommandList));\r\n\r\n                if (S_OK == hr)\r\n                {\r\n#if !ALWAYS_RESET_ALL_COMMAND_LISTS\r\n                    //When a new commandlist is created, it is in active state\r\n                    //the next time the active node is changed the commnadlist will be in closed state\r\n                    //So make sure all commandlists on non-active nodes are closed for next reuse\r\n                    if (i != GetActiveNodeIndex() && AffinityMask == 0)\r\n                    {\r\n                        CommandList->Close();\r\n                    }\r\n#endif\r\n                    CommandLists[i] = CommandList;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    CD3DX12AffinityGraphicsCommandList* CommandList = new CD3DX12AffinityGraphicsCommandList(this, &(CommandLists[0]), (UINT)CommandLists.size(), AffinityMask == 0);\r\n    (*ppCommandList) = CommandList;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CheckFeatureSupport(\r\n    D3D12_FEATURE Feature,\r\n    void* pFeatureSupportData,\r\n    UINT FeatureSupportDataSize,\r\n    UINT AffinityIndex)\r\n{\r\n    // Return feature support for device 0 and hope that that's consistent!\r\n    return mDevices[AffinityIndex]->CheckFeatureSupport(Feature, pFeatureSupportData, FeatureSupportDataSize);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateDescriptorHeap(\r\n    const D3D12_DESCRIPTOR_HEAP_DESC* pDescriptorHeapDesc,\r\n    REFIID riid,\r\n    void** ppvHeap,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_DESCRIPTOR_HEAP_DESC Desc = *pDescriptorHeapDesc;\r\n\r\n    std::vector<ID3D12DescriptorHeap*> Heaps;\r\n    Heaps.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12DescriptorHeap* Heap = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT hr = Device->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&Heap));\r\n                if (S_OK == hr)\r\n                {\r\n                    Heaps[i] = Heap;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityDescriptorHeap* DescriptorHeap = new CD3DX12AffinityDescriptorHeap(this, &(Heaps[0]), (UINT)Heaps.size());\r\n    DescriptorHeap->mNumDescriptors = pDescriptorHeapDesc->NumDescriptors;\r\n    if (GetNodeCount() > 1)\r\n    {\r\n        DescriptorHeap->mCPUHeapStart = new UINT64[pDescriptorHeapDesc->NumDescriptors * GetNodeCount()]();\r\n        DescriptorHeap->mGPUHeapStart = new UINT64[pDescriptorHeapDesc->NumDescriptors * GetNodeCount()]();\r\n\r\n        DebugLog(L\"Allocated %u spots in heap array\\n\", pDescriptorHeapDesc->NumDescriptors * GetNodeCount());\r\n\r\n        DescriptorHeap->InitDescriptorHandles(pDescriptorHeapDesc->Type);\r\n    }\r\n    (*ppvHeap) = DescriptorHeap;\r\n\r\n    return S_OK;\r\n}\r\n\r\nUINT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetDescriptorHandleIncrementSize(\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n    UINT AffinityMask)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return mDevices[0]->GetDescriptorHandleIncrementSize(DescriptorHeapType);\r\n    }\r\n    return sizeof(UINT64) * GetNodeCount();\r\n}\r\n\r\nUINT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetActiveDescriptorHandleIncrementSize(\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n    UINT AffinityIndex)\r\n{\r\n    UINT HandleIncrementSize = 0;\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        HandleIncrementSize = mDevices[0]->GetDescriptorHandleIncrementSize(DescriptorHeapType);\r\n    }\r\n    return HandleIncrementSize;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateRootSignature(\r\n    UINT nodeMask,\r\n    const void* pBlobWithRootSignature,\r\n    SIZE_T blobLengthInBytes,\r\n    REFIID riid,\r\n    void** ppvRootSignature,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12RootSignature*> Signatures;\r\n    Signatures.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        ID3D12RootSignature* Signature = nullptr;\r\n        UINT MaskToUse = LDAAllNodeMasks();\r\n        HRESULT hr = Device->CreateRootSignature(MaskToUse, pBlobWithRootSignature, blobLengthInBytes, IID_PPV_ARGS(&Signature));\r\n        if (S_OK == hr)\r\n        {\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n                    Signature->AddRef();\r\n                    Signatures[i] = Signature;\r\n                }\r\n            }\r\n            Signature->Release();\r\n        }\r\n        else\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n    CD3DX12AffinityRootSignature* Signature = new CD3DX12AffinityRootSignature(this, &(Signatures[0]), (UINT)Signatures.size());\r\n    (*ppvRootSignature) = Signature;\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateConstantBufferView(\r\n    const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                D3D12_CONSTANT_BUFFER_VIEW_DESC ActualDesc = *pDesc;\r\n                ActualDesc.BufferLocation = GetGPUVirtualAddress(pDesc->BufferLocation, i);\r\n\r\n                Device->CreateConstantBufferView(&ActualDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateShaderResourceView(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateShaderResourceViewWithAffinity(pResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateShaderResourceViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                Device->CreateShaderResourceView(AffinityResource ? AffinityResource->mResources[i] : nullptr, pDesc, ActualDestDescriptor);\r\n\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateUnorderedAccessView(\r\n    CD3DX12AffinityResource* pResource,\r\n    CD3DX12AffinityResource* pCounterResource,\r\n    const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateUnorderedAccessViewWithAffinity(pResource, pCounterResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateUnorderedAccessViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    CD3DX12AffinityResource* pCounterResource,\r\n    const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n    CD3DX12AffinityResource* AffinityCounterResource = nullptr;\r\n    if (pCounterResource)\r\n    {\r\n        AffinityCounterResource = static_cast<CD3DX12AffinityResource*>(pCounterResource);\r\n    }\r\n\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                Device->CreateUnorderedAccessView(\r\n                    AffinityResource ? AffinityResource->mResources[i] : nullptr,\r\n                    AffinityCounterResource ? AffinityCounterResource->mResources[i] : nullptr,\r\n                    pDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateRenderTargetView(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateRenderTargetViewWithAffinity(pResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateRenderTargetViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                ID3D12Resource* Resource = nullptr;\r\n                if (AffinityResource)\r\n                {\r\n                    Resource = AffinityResource->mResources[i];\r\n                    if (Resource != nullptr)\r\n                    {\r\n                        Device->CreateRenderTargetView(Resource, pDesc, ActualDestDescriptor);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateDepthStencilView(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateDepthStencilViewWithAffinity(pResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateDepthStencilViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                ID3D12Resource* Resource = nullptr;\r\n                if (AffinityResource)\r\n                {\r\n                    Resource = AffinityResource->mResources[i];\r\n                }\r\n                Device->CreateDepthStencilView(Resource, pDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateSampler(\r\n    const D3D12_SAMPLER_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n                Device->CreateSampler(pDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CopyDescriptors(\r\n    UINT NumDestDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n    const UINT* pDestDescriptorRangeSizes,\r\n    UINT NumSrcDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n    const UINT* pSrcDescriptorRangeSizes,\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n    UINT AffinityMask)\r\n{\r\n    if (NumDestDescriptorRanges == 1 && NumSrcDescriptorRanges == 1)\r\n    {\r\n        return CopyDescriptorsOne(NumDestDescriptorRanges, pDestDescriptorRangeStarts, pDestDescriptorRangeSizes, NumSrcDescriptorRanges,\r\n            pSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes, DescriptorHeapsType, AffinityMask);\r\n    }\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* ActualDestDescriptorRangeStarts = new D3D12_CPU_DESCRIPTOR_HANDLE[NumDestDescriptorRanges];\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* ActualSrcDescriptorRangeStarts = new D3D12_CPU_DESCRIPTOR_HANDLE[NumSrcDescriptorRanges];\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n\r\n                {\r\n                    for (UINT t = 0; t < NumDestDescriptorRanges; ++t)\r\n                    {\r\n                        ActualDestDescriptorRangeStarts[t] = GetCPUHeapPointer(pDestDescriptorRangeStarts[t], i);\r\n                    }\r\n                    for (UINT t = 0; t < NumSrcDescriptorRanges; ++t)\r\n                    {\r\n                        ActualSrcDescriptorRangeStarts[t] = GetCPUHeapPointer(pSrcDescriptorRangeStarts[t], i);\r\n                    }\r\n\r\n                    Device->CopyDescriptors(\r\n                        NumDestDescriptorRanges, ActualDestDescriptorRangeStarts, pDestDescriptorRangeSizes,\r\n                        NumSrcDescriptorRanges, ActualSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes,\r\n                        DescriptorHeapsType);\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    delete[] ActualDestDescriptorRangeStarts;\r\n    delete[] ActualSrcDescriptorRangeStarts;\r\n\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CopyDescriptorsOne(\r\n    UINT NumDestDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n    const UINT* pDestDescriptorRangeSizes,\r\n    UINT NumSrcDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n    const UINT* pSrcDescriptorRangeSizes,\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptorRangeStarts[1];\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ActualSrcDescriptorRangeStarts[1];\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                {\r\n                    ActualDestDescriptorRangeStarts[0] = GetCPUHeapPointer(pDestDescriptorRangeStarts[0], i);\r\n                    ActualSrcDescriptorRangeStarts[0] = GetCPUHeapPointer(pSrcDescriptorRangeStarts[0], i);\r\n\r\n                    Device->CopyDescriptors(\r\n                        NumDestDescriptorRanges, ActualDestDescriptorRangeStarts, pDestDescriptorRangeSizes,\r\n                        NumSrcDescriptorRanges, ActualSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes,\r\n                        DescriptorHeapsType);\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CopyDescriptorsSimple(\r\n    UINT NumDescriptors,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptorRangeStart,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRangeStart,\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptorRangeStart, i);\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualSrcDescriptor = GetCPUHeapPointer(SrcDescriptorRangeStart, i);\r\n\r\n                Device->CopyDescriptorsSimple(NumDescriptors, ActualDestDescriptor, ActualSrcDescriptor, DescriptorHeapsType);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nD3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE CD3DX12AffinityDevice::GetResourceAllocationInfo(\r\n    UINT visibleMask,\r\n    UINT numResourceDescs,\r\n    const D3D12_RESOURCE_DESC* pResourceDescs,\r\n    UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetResourceAllocationInfo(visibleMask, numResourceDescs, pResourceDescs);\r\n}\r\n\r\nD3D12_HEAP_PROPERTIES STDMETHODCALLTYPE CD3DX12AffinityDevice::GetCustomHeapProperties(\r\n    UINT nodeMask,\r\n    D3D12_HEAP_TYPE heapType,\r\n    UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetCustomHeapProperties(nodeMask, heapType);\r\n}\r\n\r\nUINT64 GetBufferSizeForResource(\r\n    ID3D12Resource* pResource)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pResource->GetDesc();\r\n    UINT64 Size = 0;\r\n    switch (Desc.Dimension)\r\n    {\r\n    case D3D12_RESOURCE_DIMENSION_BUFFER:\r\n    {\r\n        DEBUG_ASSERT(Desc.Height == 1);\r\n        Size = Desc.Width;\r\n    }\r\n    break;\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n    {\r\n        ID3D12Device* pDevice;\r\n        pResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n        auto info = pDevice->GetResourceAllocationInfo(0, 1, &Desc);\r\n        pDevice->Release();\r\n\r\n        Size = info.SizeInBytes;\r\n    }\r\n    break;\r\n    default:\r\n    case D3D12_RESOURCE_DIMENSION_UNKNOWN:\r\n    {\r\n        DEBUG_ASSERT(false);\r\n    }\r\n    break;\r\n    }\r\n    return Size;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommittedResource(\r\n    const D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n    D3D12_HEAP_FLAGS HeapFlags,\r\n    const D3D12_RESOURCE_DESC* pResourceDesc,\r\n    D3D12_RESOURCE_STATES InitialResourceState,\r\n    const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n    REFIID riid,\r\n    void** ppvResource,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_HEAP_PROPERTIES& Properties = *(const_cast<D3D12_HEAP_PROPERTIES*>(pHeapProperties));\r\n\r\n    ID3D12Resource* Resources[D3DX12_MAX_ACTIVE_NODES] = {};\r\n    ID3D12Heap* Heaps[D3DX12_MAX_ACTIVE_NODES] = {};\r\n    ID3D12Heap** pHeaps = nullptr;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        D3D12_HEAP_PROPERTIES heapProp = Device->GetCustomHeapProperties(0, pHeapProperties->Type);\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                UINT nodeMask = AffinityIndexToNodeMask(i);\r\n                Properties.CreationNodeMask = nodeMask;\r\n                Properties.VisibleNodeMask = LDAAllNodeMasks();\r\n                if (heapProp.MemoryPoolPreference == D3D12_MEMORY_POOL_L0)\r\n                {\r\n                    // System memory, don't create the resource more than once or manager syncronization.\r\n                    if (i == 0)\r\n                    {\r\n                        HRESULT hr = Device->CreateCommittedResource(&Properties, HeapFlags, pResourceDesc, InitialResourceState, pOptimizedClearValue, IID_PPV_ARGS(&Resources[i]));\r\n                        RETURN_IF_FAILED(hr);\r\n                    }\r\n                    else\r\n                    {\r\n                        Resources[i] = Resources[i - 1];\r\n                        Resources[i]->AddRef();\r\n                    }\r\n\r\n                }\r\n                else\r\n                {\r\n                    Properties.VisibleNodeMask = nodeMask;\r\n#if TILE_MAPPING_GPUVA\r\n                    if (GetNodeCount() > 1 &&\r\n                        pResourceDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n                    {\r\n                        UINT64 Width = (pResourceDesc->Width + D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES - 1)\r\n                            & ~(D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES - 1);\r\n                        // Video memory buffers - allocate heaps on each GPU and a single reserved resource so we don't have to remap GPUVA.\r\n                        D3D12_HEAP_DESC HeapDesc = { Width, Properties, pResourceDesc->Alignment, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS };\r\n                        HRESULT hr = Device->CreateHeap(&HeapDesc, IID_PPV_ARGS(&Heaps[i]));\r\n                        RETURN_IF_FAILED(hr);\r\n                    }\r\n                    else\r\n#endif\r\n                    {\r\n                        HRESULT hr = Device->CreateCommittedResource(&Properties, HeapFlags, pResourceDesc, InitialResourceState, pOptimizedClearValue, IID_PPV_ARGS(&Resources[i]));\r\n                        RETURN_IF_FAILED(hr);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n#if TILE_MAPPING_GPUVA\r\n        if (GetNodeCount() > 1 &&\r\n            pResourceDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&\r\n            heapProp.MemoryPoolPreference != D3D12_MEMORY_POOL_L0)\r\n        {\r\n            HRESULT hr = Device->CreateReservedResource(pResourceDesc, InitialResourceState, pOptimizedClearValue, IID_PPV_ARGS(&Resources[0]));\r\n            RETURN_IF_FAILED(hr);\r\n\r\n            pHeaps = Heaps;\r\n\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n\r\n                    if (i > 0)\r\n                    {\r\n                        Resources[i] = Resources[0];\r\n                        Resources[i]->AddRef();\r\n                    }\r\n\r\n                    D3D12_TILED_RESOURCE_COORDINATE Coord = {};\r\n                    D3D12_TILE_REGION_SIZE Region = { (UINT)(((pResourceDesc->Width - 1ull) / D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES) + 1) };\r\n                    D3D12_TILE_RANGE_FLAGS RangeFlags = D3D12_TILE_RANGE_FLAG_NONE;\r\n                    UINT RangeStart = 0;\r\n\r\n                    UINT HeapIndex = i;\r\n#if FORCE_REMOTE_TILE_MAPPING_GPUVA\r\n                    HeapIndex = AffinityIndices[(Counter + 1) % IndicesCount];\r\n#endif\r\n\r\n                    mSyncCommandQueues[i]->UpdateTileMappings(Resources[i], 1, &Coord, &Region, Heaps[HeapIndex], 1, &RangeFlags, &RangeStart, &Region.NumTiles, D3D12_TILE_MAPPING_FLAG_NO_HAZARD);\r\n                }\r\n\r\n                ID3D12Fence* pFence = nullptr;\r\n                RETURN_IF_FAILED(Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence)));\r\n                HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n                for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n                {\r\n                    if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                    {\r\n                        mSyncCommandQueues[i]->Signal(pFence, i + 1);\r\n                        pFence->SetEventOnCompletion(i + 1, hEvent);\r\n                        WaitForSingleObject(hEvent, INFINITE);\r\n                    }\r\n                }\r\n                pFence->Release();\r\n            }\r\n        }\r\n#endif\r\n    }\r\n\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(this, Resources, GetNodeCount(), pHeaps);\r\n    Resource->mReferenceCount = 0;\r\n    Resource->mBufferSize = GetBufferSizeForResource(Resources[0]);\r\n    Resource->mCPUPageProperty = mDevices[0]->GetCustomHeapProperties(0, pHeapProperties->Type).CPUPageProperty;\r\n    {\r\n        ReleaseLog(L\"D3DX12AffinityLayer: Committed resource is not write combine, creating no shadow buffer.\\n\", Resource->mBufferSize);\r\n        Resource->mShadowBuffer = nullptr;\r\n    }\r\n\r\n    (*ppvResource) = Resource;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateHeap(\r\n    const D3D12_HEAP_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppvHeap,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Heap*> Heaps;\r\n    Heaps.resize(GetNodeCount(), nullptr);\r\n    D3D12_HEAP_PROPERTIES& Properties = (const_cast<D3D12_HEAP_DESC*>(pDesc))->Properties;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Heap* Heap = nullptr;\r\n                Properties.CreationNodeMask = AffinityIndexToNodeMask(i);\r\n                Properties.VisibleNodeMask = LDAAllNodeMasks();\r\n\r\n                HRESULT hr = Device->CreateHeap(pDesc, IID_PPV_ARGS(&Heap));\r\n                if (S_OK == hr)\r\n                {\r\n                    Heaps[i] = Heap;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityHeap* Heap = new CD3DX12AffinityHeap(this, &(Heaps[0]), (UINT)Heaps.size());\r\n    (*ppvHeap) = Heap;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreatePlacedResource(\r\n    CD3DX12AffinityHeap* pHeap,\r\n    UINT64 HeapOffset,\r\n    const D3D12_RESOURCE_DESC* pDesc,\r\n    D3D12_RESOURCE_STATES InitialState,\r\n    const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n    REFIID riid,\r\n    void** ppvResource,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Resource*> Resources;\r\n    Resources.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n#if TILE_MAPPING_GPUVA\r\n        if (pDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n        {\r\n            return E_NOTIMPL;\r\n        }\r\n#endif\r\n\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = nullptr;\r\n\r\n                HRESULT hr = Device->CreatePlacedResource(\r\n                    pHeap->GetChildObject(i),\r\n                    HeapOffset,\r\n                    pDesc,\r\n                    InitialState,\r\n                    pOptimizedClearValue,\r\n                    IID_PPV_ARGS(&Resource));\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Resource;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(this, &(Resources[0]), (UINT)Resources.size());\r\n    (*ppvResource) = Resource;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateReservedResource(\r\n    const D3D12_RESOURCE_DESC* pDesc,\r\n    D3D12_RESOURCE_STATES InitialState,\r\n    const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n    REFIID riid,\r\n    void** ppvResource,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Resource*> Resources;\r\n    Resources.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n#if TILE_MAPPING_GPUVA\r\n        if (pDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n        {\r\n            return E_NOTIMPL;\r\n        }\r\n#endif\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = nullptr;\r\n\r\n                HRESULT hr = Device->CreateReservedResource(\r\n                    pDesc,\r\n                    InitialState,\r\n                    pOptimizedClearValue,\r\n                    IID_PPV_ARGS(&Resource));\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Resource;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(this, &(Resources[0]), (UINT)Resources.size());\r\n    (*ppvResource) = Resource;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::MakeResident(\r\n    UINT NumObjects,\r\n    CD3DX12AffinityPageable* const* ppObjects,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Pageable*> Objects(NumObjects);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                for (UINT j = 0; j < NumObjects; ++j)\r\n                {\r\n                    Objects[j] = static_cast<CD3DX12AffinityPageable*>(ppObjects[j])->mPageables[i];\r\n                }\r\n                HRESULT const hr = Device->MakeResident(NumObjects, Objects.data());\r\n                if (S_OK != hr)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::Evict(\r\n    UINT NumObjects,\r\n    CD3DX12AffinityPageable* const* ppObjects,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<CD3DX12AffinityPageable*> AffinityPageables;\r\n    AffinityPageables.resize(NumObjects);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < NumObjects; ++i)\r\n    {\r\n        AffinityPageables[i] = static_cast<CD3DX12AffinityPageable*>(ppObjects[i]);\r\n    }\r\n\r\n    std::vector<ID3D12Pageable*> Pageables;\r\n    Pageables.resize(NumObjects);\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                for (UINT j = 0; j < NumObjects; ++j)\r\n                {\r\n                    Pageables[j] = AffinityPageables[j]->mPageables[i];\r\n                }\r\n\r\n                HRESULT const hr = Device->Evict(NumObjects, Pageables.data());\r\n                if (S_OK != hr)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateFence(\r\n    UINT64 InitialValue,\r\n    D3D12_FENCE_FLAGS Flags,\r\n    REFIID riid,\r\n    void** ppFence,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Fence*> Fences;\r\n    Fences.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        ID3D12Fence* Fence = nullptr;\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                HRESULT const hr = Device->CreateFence(InitialValue, Flags, IID_PPV_ARGS(&Fence));\r\n                if (S_OK == hr)\r\n                {\r\n                    Fences[i] = Fence;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityFence* Fence = new CD3DX12AffinityFence(this, &(Fences[0]), (UINT)Fences.size());\r\n    (*ppFence) = Fence;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetDeviceRemovedReason(UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetDeviceRemovedReason();\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::GetCopyableFootprints(\r\n    const D3D12_RESOURCE_DESC* pResourceDesc,\r\n    UINT FirstSubresource,\r\n    UINT NumSubresources,\r\n    UINT64 BaseOffset,\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    UINT* pNumRows,\r\n    UINT64* pRowSizeInBytes,\r\n    UINT64* pTotalBytes,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        Device->GetCopyableFootprints(\r\n            pResourceDesc,\r\n            FirstSubresource,\r\n            NumSubresources,\r\n            BaseOffset,\r\n            pLayouts,\r\n            pNumRows,\r\n            pRowSizeInBytes,\r\n            pTotalBytes);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateQueryHeap(\r\n    const D3D12_QUERY_HEAP_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppvHeap,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_QUERY_HEAP_DESC Desc = *pDesc;\r\n\r\n    std::vector<ID3D12QueryHeap*> QueryHeaps;\r\n    QueryHeaps.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12QueryHeap* QueryHeap = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT const hr = Device->CreateQueryHeap(&Desc, IID_PPV_ARGS(&QueryHeap));\r\n                if (S_OK == hr)\r\n                {\r\n                    QueryHeaps[i] = QueryHeap;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityQueryHeap* QueryHeap = new CD3DX12AffinityQueryHeap(this, &(QueryHeaps[0]), (UINT)QueryHeaps.size());\r\n    (*ppvHeap) = QueryHeap;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::SetStablePowerState(\r\n    BOOL Enable,\r\n    UINT AffinityMask)\r\n{\r\n    for (UINT ActiveIndex = 0; ActiveIndex < mNumActiveDevices; ++ActiveIndex)\r\n    {\r\n        ID3D12Device* Device = mDevices[ActiveIndex];\r\n        UINT const i = ActiveIndex;\r\n\r\n        HRESULT const hr = Device->SetStablePowerState(Enable);\r\n\r\n        if (S_OK != hr)\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandSignature(\r\n    const D3D12_COMMAND_SIGNATURE_DESC* pDesc,\r\n    CD3DX12AffinityRootSignature* pRootSignature,\r\n    REFIID riid,\r\n    CD3DX12AffinityCommandSignature** ppvCommandSignature,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_COMMAND_SIGNATURE_DESC Desc = *pDesc;\r\n    CD3DX12AffinityRootSignature* RootSignature = static_cast<CD3DX12AffinityRootSignature*>(pRootSignature);\r\n\r\n    std::vector<ID3D12CommandSignature*> CommandSignatures;\r\n    CommandSignatures.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12CommandSignature* CommandSignature = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT const hr = Device->CreateCommandSignature(&Desc, RootSignature ? RootSignature->mRootSignatures[i] : nullptr, IID_PPV_ARGS(&CommandSignature));\r\n                if (S_OK == hr)\r\n                {\r\n                    CommandSignatures[i] = CommandSignature;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityCommandSignature* CommandSignature = new CD3DX12AffinityCommandSignature(this, &(CommandSignatures[0]), (UINT)CommandSignatures.size());\r\n    (*ppvCommandSignature) = CommandSignature;\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::GetResourceTiling(\r\n    CD3DX12AffinityResource* pTiledResource,\r\n    UINT* pNumTilesForEntireResource,\r\n    D3D12_PACKED_MIP_INFO* pPackedMipDesc,\r\n    D3D12_TILE_SHAPE* pStandardTileShapeForNonPackedMips,\r\n    UINT* pNumSubresourceTilings,\r\n    UINT FirstSubresourceTilingToGet,\r\n    D3D12_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips,\r\n    UINT AffinityIndex)\r\n{\r\n    mDevices[AffinityIndex]->GetResourceTiling(\r\n        pTiledResource->mResources[AffinityIndex],\r\n        pNumTilesForEntireResource,\r\n        pPackedMipDesc,\r\n        pStandardTileShapeForNonPackedMips,\r\n        pNumSubresourceTilings,\r\n        FirstSubresourceTilingToGet,\r\n        pSubresourceTilingsForNonPackedMips);\r\n}\r\n\r\nLUID STDMETHODCALLTYPE CD3DX12AffinityDevice::GetAdapterLuid(UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetAdapterLuid();\r\n}\r\n\r\nID3D12Device* CD3DX12AffinityDevice::GetChildObject(UINT AffinityIndex)\r\n{\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        return mDevices[0];\r\n    }\r\n    else\r\n    {\r\n        return mDevices[AffinityIndex];\r\n    }\r\n}\r\n\r\nbool CD3DX12AffinityDevice::IsD3D()\r\n{\r\n    return true;\r\n}\r\n\r\nCD3DX12AffinityDevice::CD3DX12AffinityDevice(ID3D12Device** devices, UINT Count, EAffinityMode::Mask affinitymode)\r\n    : CD3DX12AffinityObject(this, reinterpret_cast<IUnknown**>(devices), Count)\r\n{\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Device\";\r\n#endif\r\n    mAffinityMode = affinitymode;\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mDevices[i] = devices[i];\r\n        }\r\n        else\r\n        {\r\n            mDevices[i] = nullptr;\r\n        }\r\n    }\r\n    if (mAffinityMode == EAffinityMode::LDA)\r\n    {\r\n        mLDANodeCount = min(mDevices[0]->GetNodeCount(), D3DX12_MAX_ACTIVE_NODES);\r\n    }\r\n    else\r\n    {\r\n        mLDANodeCount = 0;\r\n    }\r\n    mDeviceCount = Count;\r\n    if (mAffinityMode == EAffinityMode::LDA)\r\n    {\r\n        g_CachedNodeCount = mLDANodeCount;\r\n        g_CachedNodeMask = (1 << mLDANodeCount) - 1;\r\n\r\n    }\r\n    else\r\n    {\r\n        g_CachedNodeCount = mDeviceCount;\r\n        g_CachedNodeMask = (1 << mDeviceCount) - 1;\r\n\r\n    }\r\n    mAffinityRenderingMode = EAffinityRenderingMode::AFR;\r\n\r\n    mParentDevice = this;\r\n    // Re-calculate the affinity based on the effective affinity node mask.\r\n    SetAffinity(GetNodeMask());\r\n\r\n    UpdateActiveDevices();\r\n\r\n    // Initialize sync queues for cross frame resources.\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        for (UINT i = 0; i < GetNodeCount(); i++)\r\n        {\r\n            D3D12_COMMAND_QUEUE_DESC desc;\r\n            desc.Type = D3D12_COMMAND_LIST_TYPE_COPY;\r\n            desc.Priority = 0;\r\n            desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;\r\n            desc.NodeMask = 1 << i;\r\n\r\n            mDevices[0]->CreateCommandQueue(&desc, IID_PPV_ARGS(&mSyncCommandQueues[i]));\r\n            mDevices[0]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mSyncFences[i]));\r\n        }\r\n    }\r\n}\r\n\r\nCD3DX12AffinityDevice::~CD3DX12AffinityDevice()\r\n{\r\n    for (UINT i = 0; i < GetNodeCount(); i++)\r\n    {\r\n        mSyncCommandQueues[i]->Release();\r\n        mSyncFences[i]->Release();\r\n    }\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::GetDeviceCount()\r\n{\r\n    return mDeviceCount;\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE CD3DX12AffinityDevice::GetCPUHeapPointer(D3D12_CPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return Original;\r\n    }\r\n#ifdef D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n    // Validation\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexPointerRanges);\r\n\r\n        bool IsOK = false;\r\n        for (auto Range : GetParentDevice()->CPUHeapPointerRanges)\r\n        {\r\n            if (Original.ptr >= Range.first && Original.ptr < Range.second)\r\n            {\r\n                IsOK = true;\r\n                break;\r\n            }\r\n        }\r\n\r\n        if (!IsOK)\r\n        {\r\n            DebugLog(L\"Found a pointer outside of expected memory ranges!\\n\");\r\n            DEBUG_FAIL_MESSAGE(L\"Found a pointer outside of expected memory ranges!\\n\");\r\n        }\r\n\r\n    }\r\n#endif\r\n    D3D12_CPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = static_cast<size_t>(((UINT64*)Original.ptr)[NodeIndex]);\r\n    return handle;\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE CD3DX12AffinityDevice::GetGPUHeapPointer(D3D12_GPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return Original;\r\n    }\r\n#ifdef D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n    // Validation\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexPointerRanges);\r\n\r\n        bool IsOK = false;\r\n        for (auto Range : GetParentDevice()->GPUHeapPointerRanges)\r\n        {\r\n            if (Original.ptr >= Range.first && Original.ptr < Range.second)\r\n            {\r\n                IsOK = true;\r\n                break;\r\n            }\r\n        }\r\n\r\n        if (!IsOK)\r\n        {\r\n            DebugLog(L\"Found a pointer outside of expected memory ranges!\\n\");\r\n            DEBUG_FAIL_MESSAGE(\"Found a pointer outside of expected memory ranges!\\n\");\r\n        }\r\n\r\n    }\r\n#endif\r\n    D3D12_GPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = ((UINT64*)Original.ptr)[NodeIndex];\r\n    return handle;\r\n}\r\n\r\nD3D12_GPU_VIRTUAL_ADDRESS CD3DX12AffinityDevice::GetGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS const& Original, UINT const NodeIndex)\r\n{\r\n    if (NodeIndex == 0)\r\n        return Original;\r\n\r\n    if (Original == 0)\r\n        return 0;\r\n\r\n#if TILE_MAPPING_GPUVA\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n        return Original;\r\n#endif\r\n\r\n\r\n    // This function searches through our list of known GPU virtual addresses and finds the next lowest (or equal) address to the Original\r\n    // The Original pointer is then assumed to be an offset into some segment of memory that starts at the next lowest address.\r\n    // We use that offset against the equivalent base addresses across all devices.\r\n\r\n    // TODO: It is inefficient to look through this every time i.e. for each DeviceIndex.\r\n    // Possibly just cache the NextLowest here or change the interface to return a vector of offsetted pointers.\r\n    // Should probably do both, since surely the user will be using heap pointers often and it would be nice\r\n    // to simply save the base pointers for future lookup.\r\n    // Of course this would all go away if we had a way to have consistent virtual addresses across all devices!\r\n    // Also it might be possible to use proxy CPU memory allocated by the affinity layer to make this a simple lookup - see GetGPUHeapPointer.\r\n    D3D12_GPU_VIRTUAL_ADDRESS NextLowest;\r\n    D3D12_GPU_VIRTUAL_ADDRESS Return;\r\n\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexGPUVirtualAddresses);\r\n\r\n        auto NextGreatestIterator = GPUVirtualAddresses.upper_bound(Original);\r\n        auto NextLowestIterator = --NextGreatestIterator;\r\n        NextLowest = NextLowestIterator->first;\r\n        Return = NextLowestIterator->second[NodeIndex];\r\n    }\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS const Offset = Original - NextLowest;\r\n    Return += Offset;\r\n\r\n    return Return;\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::WriteApplicationMessage(D3D12_MESSAGE_SEVERITY const Severity, char const* const Message)\r\n{\r\n    DebugLog(L\"Writing application message: %s\\n\", Message);\r\n    if (InfoQueue)\r\n    {\r\n        InfoQueue->AddApplicationMessage(Severity, Message);\r\n    }\r\n    else\r\n    {\r\n        DebugLog(L\"No InfoQueue to write application message.\\n\");\r\n    }\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::AffinityIndexToNodeMask(UINT const Index)\r\n{\r\n#ifndef D3DX12_SIMULATE_LDA_ON_SINGLE_NODE  \r\n    if (mAffinityMode == EAffinityMode::LDA)\r\n        return 1 << Index;\r\n    else\r\n#endif\r\n        return 0;\r\n}\r\n\r\nEAffinityMode::Mask CD3DX12AffinityDevice::GetAffinityMode()\r\n{\r\n    return mAffinityMode;\r\n}\r\n\r\nEAffinityRenderingMode::Mask CD3DX12AffinityDevice::GetAffinityRenderingMode()\r\n{\r\n    return mAffinityRenderingMode;\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::SetAffinityRenderingMode(EAffinityRenderingMode::Mask renderingmode)\r\n{\r\n    mAffinityRenderingMode = renderingmode;\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::GetActiveNodeMask()\r\n{\r\n    return 1 << g_ActiveNodeIndex;\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::SwitchToNextNode()\r\n{\r\n#ifdef SYNC_CROSS_FRAME_RESOURCES\r\n    // Sync all cross frame resources.\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexSyncResources);\r\n        for (UINT i = 0; i < mSyncResources.size(); i++)\r\n        {\r\n            mSyncResources[i]->BroadcastResourceForCrossGPUSync();\r\n        }\r\n\r\n        //#ifdef SERIALIZE_COMMNANDLIST_EXECUTION\r\n        ID3D12Fence* pFence;\r\n        GetParentDevice()->mDevices[0]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n        mSyncCommandQueues[mActiveNodeIndex]->Signal(pFence, 1);\r\n        HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n        pFence->SetEventOnCompletion(1, hEvent);\r\n        WaitForSingleObject(hEvent, INFINITE);\r\n        CloseHandle(hEvent);\r\n        pFence->Release();\r\n        if (FAILED(mDevices[0]->GetDeviceRemovedReason()))\r\n        {\r\n            __debugbreak();\r\n        }\r\n        //#endif\r\n    }\r\n#endif\r\n\r\n    g_ActiveNodeIndex = (g_ActiveNodeIndex + 1) % GetNodeCount();\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::g_ActiveNodeIndex = 0;\r\nUINT CD3DX12AffinityDevice::g_CachedNodeCount = 0;\r\nUINT CD3DX12AffinityDevice::g_CachedNodeMask = 0;\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityDevice.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"d3dx12affinity_structs.h\"\r\n#include \"CD3DX12AffinityObject.h\"\r\n\r\nstruct D3DX12_CPU_DESCRIPTOR_HANDLE_COMPARATOR\r\n{\r\n    bool operator()(D3D12_CPU_DESCRIPTOR_HANDLE const& Left, D3D12_CPU_DESCRIPTOR_HANDLE const& Right) const\r\n    {\r\n        return Left.ptr < Right.ptr;\r\n    }\r\n};\r\n\r\nstruct D3DX12_GPU_DESCRIPTOR_HANDLE_COMPARATOR\r\n{\r\n    bool operator()(D3D12_GPU_DESCRIPTOR_HANDLE const& Left, D3D12_GPU_DESCRIPTOR_HANDLE const& Right) const\r\n    {\r\n        return Left.ptr < Right.ptr;\r\n    }\r\n};\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityDevice : public CD3DX12AffinityObject\r\n{\r\n    friend class CD3DX12AffinityResource;\r\n\r\npublic:\r\n    virtual void STDMETHODCALLTYPE SetAffinity(\r\n        _In_  UINT AffinityMask);\r\n\r\n    UINT STDMETHODCALLTYPE GetNodeCount(void);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandQueue(\r\n        _In_  const D3D12_COMMAND_QUEUE_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppCommandQueue,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandAllocator(\r\n        _In_  D3D12_COMMAND_LIST_TYPE type,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppCommandAllocator,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateGraphicsPipelineState(\r\n        _In_  const D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppPipelineState,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateComputePipelineState(\r\n        _In_  const D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppPipelineState,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandList(\r\n        _In_  UINT nodeMask,\r\n        _In_  D3D12_COMMAND_LIST_TYPE type,\r\n        _In_  CD3DX12AffinityCommandAllocator* pCommandAllocator,\r\n        _In_opt_  CD3DX12AffinityPipelineState* pInitialState,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppCommandList,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CheckFeatureSupport(\r\n        D3D12_FEATURE Feature,\r\n        _Inout_updates_bytes_(FeatureSupportDataSize)  void* pFeatureSupportData,\r\n        UINT FeatureSupportDataSize,\r\n        _In_ UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateDescriptorHeap(\r\n        _In_  const D3D12_DESCRIPTOR_HEAP_DESC* pDescriptorHeapDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppvHeap,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    UINT STDMETHODCALLTYPE GetDescriptorHandleIncrementSize(\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    UINT STDMETHODCALLTYPE GetActiveDescriptorHandleIncrementSize(\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n        _In_opt_  UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateRootSignature(\r\n        _In_  UINT nodeMask,\r\n        _In_reads_(blobLengthInBytes)  const void* pBlobWithRootSignature,\r\n        _In_  SIZE_T blobLengthInBytes,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppvRootSignature,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateConstantBufferView(\r\n        _In_opt_  const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateShaderResourceView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateShaderResourceViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateUnorderedAccessView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  CD3DX12AffinityResource* pCounterResource,\r\n        _In_opt_  const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateUnorderedAccessViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  CD3DX12AffinityResource* pCounterResource,\r\n        _In_opt_  const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateRenderTargetView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateRenderTargetViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateDepthStencilView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateDepthStencilViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateSampler(\r\n        _In_  const D3D12_SAMPLER_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyDescriptors(\r\n        _In_  UINT NumDestDescriptorRanges,\r\n        _In_reads_(NumDestDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n        _In_reads_opt_(NumDestDescriptorRanges)  const UINT* pDestDescriptorRangeSizes,\r\n        _In_  UINT NumSrcDescriptorRanges,\r\n        _In_reads_(NumSrcDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n        _In_reads_opt_(NumSrcDescriptorRanges)  const UINT* pSrcDescriptorRangeSizes,\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyDescriptorsOne(\r\n        _In_  UINT NumDestDescriptorRanges,\r\n        _In_reads_(NumDestDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n        _In_reads_opt_(NumDestDescriptorRanges)  const UINT* pDestDescriptorRangeSizes,\r\n        _In_  UINT NumSrcDescriptorRanges,\r\n        _In_reads_(NumSrcDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n        _In_reads_opt_(NumSrcDescriptorRanges)  const UINT* pSrcDescriptorRangeSizes,\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyDescriptorsSimple(\r\n        _In_  UINT NumDescriptors,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptorRangeStart,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRangeStart,\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    D3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE GetResourceAllocationInfo(\r\n        _In_  UINT visibleMask,\r\n        _In_  UINT numResourceDescs,\r\n        _In_reads_(numResourceDescs)  const D3D12_RESOURCE_DESC* pResourceDescs,\r\n        UINT AffinityIndex = 0);\r\n\r\n    D3D12_HEAP_PROPERTIES STDMETHODCALLTYPE GetCustomHeapProperties(\r\n        _In_  UINT nodeMask,\r\n        D3D12_HEAP_TYPE heapType,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommittedResource(\r\n        _In_  const D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n        D3D12_HEAP_FLAGS HeapFlags,\r\n        _In_  const D3D12_RESOURCE_DESC* pResourceDesc,\r\n        D3D12_RESOURCE_STATES InitialResourceState,\r\n        _In_opt_  const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n        _In_ REFIID riid,\r\n        _Outptr_opt_  void** ppvResource,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateHeap(\r\n        _In_  const D3D12_HEAP_DESC* pDesc,\r\n        REFIID riid,\r\n        _Outptr_opt_  void** ppvHeap,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreatePlacedResource(\r\n        _In_  CD3DX12AffinityHeap* pHeap,\r\n        UINT64 HeapOffset,\r\n        _In_  const D3D12_RESOURCE_DESC* pDesc,\r\n        D3D12_RESOURCE_STATES InitialState,\r\n        _In_opt_  const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n        REFIID riid,\r\n        _Outptr_opt_  void** ppvResource,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateReservedResource(\r\n        _In_  const D3D12_RESOURCE_DESC* pDesc,\r\n        D3D12_RESOURCE_STATES InitialState,\r\n        _In_opt_  const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n        REFIID riid,\r\n        _Outptr_opt_  void** ppvResource,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE MakeResident(\r\n        UINT NumObjects,\r\n        _In_reads_(NumObjects)  CD3DX12AffinityPageable* const* ppObjects,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE Evict(\r\n        UINT NumObjects,\r\n        _In_reads_(NumObjects)  CD3DX12AffinityPageable* const* ppObjects,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateFence(\r\n        UINT64 InitialValue,\r\n        D3D12_FENCE_FLAGS Flags,\r\n        _In_ REFIID riid,\r\n        _COM_Outptr_  void** ppFence,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(UINT AffinityIndex = 0);\r\n\r\n    void STDMETHODCALLTYPE GetCopyableFootprints(\r\n        _In_  const D3D12_RESOURCE_DESC* pResourceDesc,\r\n        _In_range_(0, D3D12_REQ_SUBRESOURCES)  UINT FirstSubresource,\r\n        _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource)  UINT NumSubresources,\r\n        UINT64 BaseOffset,\r\n        _Out_writes_opt_(NumSubresources)  D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n        _Out_writes_opt_(NumSubresources)  UINT* pNumRows,\r\n        _Out_writes_opt_(NumSubresources)  UINT64* pRowSizeInBytes,\r\n        _Out_opt_  UINT64* pTotalBytes,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateQueryHeap(\r\n        _In_  const D3D12_QUERY_HEAP_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_opt_  void** ppvHeap,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetStablePowerState(\r\n        BOOL Enable,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandSignature(\r\n        _In_  const D3D12_COMMAND_SIGNATURE_DESC* pDesc,\r\n        _In_opt_  CD3DX12AffinityRootSignature* pRootSignature,\r\n        _In_ REFIID riid,\r\n        _Outptr_opt_  CD3DX12AffinityCommandSignature** ppvCommandSignature,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE GetResourceTiling(\r\n        _In_  CD3DX12AffinityResource* pTiledResource,\r\n        _Out_opt_  UINT* pNumTilesForEntireResource,\r\n        _Out_opt_  D3D12_PACKED_MIP_INFO* pPackedMipDesc,\r\n        _Out_opt_  D3D12_TILE_SHAPE* pStandardTileShapeForNonPackedMips,\r\n        _Inout_opt_  UINT* pNumSubresourceTilings,\r\n        _In_  UINT FirstSubresourceTilingToGet,\r\n        _Out_writes_(*pNumSubresourceTilings)  D3D12_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips,\r\n        UINT AffinityIndex = 0);\r\n\r\n    LUID STDMETHODCALLTYPE GetAdapterLuid(UINT AffinityIndex = 0);\r\n    ID3D12Device* GetChildObject(UINT AffinityIndex);\r\n\r\n    CD3DX12AffinityDevice(ID3D12Device** devices, UINT Count, EAffinityMode::Mask affinitymode);\r\n    virtual ~CD3DX12AffinityDevice();\r\n    EAffinityMode::Mask GetAffinityMode();\r\n    EAffinityRenderingMode::Mask GetAffinityRenderingMode();\r\n    void SetAffinityRenderingMode(EAffinityRenderingMode::Mask renderingmode);\r\n    UINT AffinityIndexToNodeMask(UINT const Index);\r\n    UINT GetDeviceCount();\r\n\r\n    UINT LDAAllNodeMasks();\r\n    UINT GetActiveNodeMask();\r\n    void SwitchToNextNode();\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHeapPointer(D3D12_CPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex);\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHeapPointer(D3D12_GPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex);\r\n    D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS const& Original, UINT const NodeIndex);\r\n\r\nprotected:\r\n    virtual bool IsD3D();\r\n\r\nprivate:\r\n    void UpdateActiveDevices();\r\n    ID3D12Device* mDevices[D3DX12_MAX_ACTIVE_NODES];\r\n\r\n    UINT mNumActiveDevices = 0;\r\n    EAffinityMode::Mask mAffinityMode;\r\n    EAffinityRenderingMode::Mask mAffinityRenderingMode;\r\n\r\n    UINT mDeviceCount = 0;\r\n\r\n    std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> DestDescriptorRangeStartsCache;\r\n    std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> SrcDescriptorRangeStartsCache;\r\n\r\n    std::mutex MutexPointerRanges;\r\n    std::vector<std::pair<SIZE_T, SIZE_T>> CPUHeapPointerRanges;\r\n    std::vector<std::pair<SIZE_T, SIZE_T>> GPUHeapPointerRanges;\r\n\r\n    std::map<D3D12_GPU_VIRTUAL_ADDRESS, std::vector<D3D12_GPU_VIRTUAL_ADDRESS>> GPUVirtualAddresses;\r\n    std::mutex MutexGPUVirtualAddresses;\r\n\r\n    std::set<CD3DX12AffinityResource*> StillMappedResources;\r\n    std::mutex MutexStillMappedResources;\r\n\r\n    UINT mLDANodeCount = 0;\r\n\r\n    ID3D12CommandQueue* mSyncCommandQueues[D3DX12_MAX_ACTIVE_NODES];\r\n    ID3D12Fence* mSyncFences[D3DX12_MAX_ACTIVE_NODES];\r\n    std::mutex MutexSyncResources;\r\n    std::vector<CD3DX12AffinityResource*> mSyncResources;\r\n    ID3D12InfoQueue* InfoQueue = nullptr;\r\n\r\npublic:\r\n    void WriteApplicationMessage(D3D12_MESSAGE_SEVERITY const Severity, char const* const Message);\r\n\r\n    // Static Member Variables\r\n\r\n    // Used to do super simple \"device that's doing work in an AFR scenario\" tracking\r\n    // Probably this should be application controlled, but this very simple mechanism\r\n    // is a good starting point and also helps keep the first affinity integration step\r\n    // as minimal as possible.\r\n    static UINT g_ActiveNodeIndex;\r\n    static UINT g_CachedNodeCount;\r\n    static UINT g_CachedNodeMask;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityDeviceChild.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nCD3DX12AffinityDeviceChild::CD3DX12AffinityDeviceChild(CD3DX12AffinityDevice* device, ID3D12DeviceChild** deviceChilds, UINT Count)\r\n    : CD3DX12AffinityObject(device, reinterpret_cast<IUnknown**>(deviceChilds), Count)\r\n{\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"DeviceChild\";\r\n#endif\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDeviceChild::GetDevice(\r\n    REFIID riid,\r\n    void** ppvDevice)\r\n{\r\n    CD3DX12AffinityDevice* pDevice = GetParentDevice();\r\n    pDevice->AddRef();\r\n    *ppvDevice = (void*)pDevice;\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDeviceChild::GetDevice(\r\n    CD3DX12AffinityDevice** ppDevice)\r\n{\r\n    *ppDevice = GetParentDevice();\r\n    (*ppDevice)->AddRef();\r\n    return S_OK;\r\n}\r\n\r\nbool CD3DX12AffinityDeviceChild::IsD3D()\r\n{\r\n    return true;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityDeviceChild.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityObject.h\"\r\n\r\nclass CD3DX12AffinityDevice;\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityDeviceChild : public CD3DX12AffinityObject\r\n{\r\npublic:\r\n    CD3DX12AffinityDeviceChild(CD3DX12AffinityDevice* device, ID3D12DeviceChild* deviceChilds[], UINT Count);\r\n    HRESULT STDMETHODCALLTYPE GetDevice(CD3DX12AffinityDevice** ppDevice);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDevice(\r\n        REFIID riid,\r\n        void** ppvDevice);\r\n\r\nprotected:\r\n    virtual bool IsD3D();\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityFence.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nUINT64 STDMETHODCALLTYPE CD3DX12AffinityFence::GetCompletedValue(void)\r\n{\r\n    UINT64 Minimum = mFences[0]->GetCompletedValue();\r\n    for (UINT i = 1; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n\r\n            UINT64 CompletedValue = mFences[i]->GetCompletedValue();\r\n            Minimum = min(CompletedValue, Minimum);\r\n        }\r\n    }\r\n\r\n    return Minimum;\r\n}\r\n\r\nUINT64 CD3DX12AffinityFence::GetCompletedValue(UINT AffinityMask)\r\n{\r\n    UINT64 Minimum = 0 - 1ull;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            UINT64 CompletedValue = mFences[i]->GetCompletedValue();\r\n            Minimum = min(CompletedValue, Minimum);\r\n        }\r\n    }\r\n    return Minimum;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityFence::SetEventOnCompletion(\r\n    UINT64 Value,\r\n    HANDLE hEvent)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    ID3D12Fence* Fence = mFences[i];\r\n    return Fence->SetEventOnCompletion(Value, hEvent);\r\n}\r\n\r\nHRESULT CD3DX12AffinityFence::SetEventOnCompletion(UINT64 Value, HANDLE hEvent, UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            return mFences[i]->SetEventOnCompletion(Value, hEvent);\r\n        }\r\n    }\r\n    //should never get here, mask is incorrect\r\n    return E_FAIL;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityFence::WaitOnFenceCompletion(\r\n    UINT64 Value)\r\n{\r\n    std::vector<HANDLE> Events;\r\n\r\n    UINT EventCount = 0;\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12Fence* Fence = mFences[i];\r\n            Events.push_back(0);\r\n            Events[EventCount] = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n            HRESULT const hr = Fence->SetEventOnCompletion(Value, Events[EventCount]);\r\n\r\n            if (hr != S_OK)\r\n            {\r\n                return hr;\r\n            }\r\n\r\n            ++EventCount;\r\n        }\r\n    }\r\n    WaitForMultipleObjects((DWORD)EventCount, Events.data(), TRUE, INFINITE);\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityFence::Signal(\r\n    UINT64 Value)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12Fence* Fence = mFences[i];\r\n\r\n            HRESULT const hr = Fence->Signal(Value);\r\n\r\n            if (hr != S_OK)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT CD3DX12AffinityFence::Signal(UINT64 Value, UINT AffinityIndex)\r\n{\r\n    return mFences[AffinityIndex]->Signal(Value);\r\n}\r\n\r\nCD3DX12AffinityFence::CD3DX12AffinityFence(CD3DX12AffinityDevice* device, ID3D12Fence** fences, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(fences), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mFences[i] = fences[i];\r\n        }\r\n        else\r\n        {\r\n            mFences[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Fence\";\r\n#endif\r\n    mDevice = device;\r\n}\r\n\r\nCD3DX12AffinityFence::~CD3DX12AffinityFence()\r\n{\r\n}\r\n\r\nID3D12Fence* CD3DX12AffinityFence::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mFences[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityFence.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityFence : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    UINT64 STDMETHODCALLTYPE GetCompletedValue(void);\r\n\r\n    UINT64 STDMETHODCALLTYPE GetCompletedValue(UINT AffinityMask);\r\n\r\n    // It is not recommended to use this function in multi-GPU scenarios \r\n    // as it operates only on the active GPU fence.\r\n    // Please refactor your engine to use WaitOnFenceCompletion instead.\r\n    HRESULT STDMETHODCALLTYPE SetEventOnCompletion(\r\n        UINT64 Value,\r\n        HANDLE hEvent);\r\n\r\n    // The mask should resolve to a single Node Index.\r\n    HRESULT STDMETHODCALLTYPE SetEventOnCompletion(\r\n        UINT64 Value,\r\n        HANDLE hEvent,\r\n        UINT AffinityMask);\r\n\r\n    HRESULT STDMETHODCALLTYPE WaitOnFenceCompletion(\r\n        UINT64 Value);\r\n\r\n    HRESULT STDMETHODCALLTYPE Signal(\r\n        UINT64 Value);\r\n\r\n    HRESULT STDMETHODCALLTYPE Signal(\r\n        UINT64 Value,\r\n        UINT AffinityIndex);\r\n\r\n    CD3DX12AffinityFence(CD3DX12AffinityDevice* device, ID3D12Fence** fences, UINT Count);\r\n    ~CD3DX12AffinityFence();\r\n    ID3D12Fence* GetChildObject(UINT AffinityIndex);\r\n\r\n    ID3D12Fence* mFences[D3DX12_MAX_ACTIVE_NODES];\r\n    HANDLE mCompletionEvent;\r\n\r\nprivate:\r\n    CD3DX12AffinityDevice* mDevice;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityGraphicsCommandList.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityGraphicsCommandList::SetAffinity(UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityObject::SetAffinity(AffinityMask);\r\n    mAccumulatedAffinityMask |= AffinityMask;\r\n}\r\n\r\nD3D12_COMMAND_LIST_TYPE CD3DX12AffinityGraphicsCommandList::GetType()\r\n{\r\n    return mGraphicsCommandLists[0]->GetType();\r\n}\r\n\r\nHRESULT CD3DX12AffinityGraphicsCommandList::Close()\r\n{\r\n#if ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    for (UINT i = 0; i < GetNodeCount(); ++i)\r\n    {\r\n        ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#else\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#endif\r\n            HRESULT const hr = List->Close();\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n#ifdef ALWAYS_RESET_ALL_COMMAND_LISTS\r\n#else\r\n    }\r\n#endif\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT CD3DX12AffinityGraphicsCommandList::Reset(\r\n    CD3DX12AffinityCommandAllocator* pAllocator,\r\n    CD3DX12AffinityPipelineState* pInitialState)\r\n{\r\n    if (mUseDeviceActiveMaskOnReset)\r\n    {\r\n        mAccumulatedAffinityMask = 0;\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n\r\n#if ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    for (UINT i = 0; i < GetNodeCount(); ++i)\r\n    {\r\n        ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#else\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#endif\r\n\r\n            HRESULT const hr = List->Reset(pAllocator->GetChildObject(i),\r\n                pInitialState ? pInitialState->mPipelineStates[i] : nullptr);\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearState(\r\n    CD3DX12AffinityPipelineState* pPipelineState)\r\n{\r\n    CD3DX12AffinityPipelineState* PipelineState = static_cast<CD3DX12AffinityPipelineState*>(pPipelineState);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->ClearState(PipelineState->mPipelineStates[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::DrawInstanced(\r\n    UINT VertexCountPerInstance,\r\n    UINT InstanceCount,\r\n    UINT StartVertexLocation,\r\n    UINT StartInstanceLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::Dispatch(\r\n    UINT ThreadGroupCountX,\r\n    UINT ThreadGroupCountY,\r\n    UINT ThreadGroupCountZ)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->Dispatch(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyBufferRegion(\r\n    CD3DX12AffinityResource* pDstBuffer,\r\n    UINT64 DstOffset,\r\n    CD3DX12AffinityResource* pSrcBuffer,\r\n    UINT64 SrcOffset,\r\n    UINT64 NumBytes)\r\n{\r\n    CD3DX12AffinityResource* DstBuffer = static_cast<CD3DX12AffinityResource*>(pDstBuffer);\r\n    CD3DX12AffinityResource* SrcBuffer = static_cast<CD3DX12AffinityResource*>(pSrcBuffer);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->CopyBufferRegion(DstBuffer->mResources[i], DstOffset, SrcBuffer->mResources[i], SrcOffset, NumBytes);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyTextureRegion(\r\n    const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pDst,\r\n    UINT DstX,\r\n    UINT DstY,\r\n    UINT DstZ,\r\n    const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pSrc,\r\n    const D3D12_BOX* pSrcBox)\r\n{\r\n    CD3DX12AffinityResource* DstTexture = static_cast<CD3DX12AffinityResource*>(pDst->pResource);\r\n    CD3DX12AffinityResource* SrcTexture = static_cast<CD3DX12AffinityResource*>(pSrc->pResource);\r\n\r\n    D3D12_TEXTURE_COPY_LOCATION Dst = pDst->ToD3D12();\r\n    D3D12_TEXTURE_COPY_LOCATION Src = pSrc->ToD3D12();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            Dst.pResource = DstTexture->mResources[i];\r\n            Src.pResource = SrcTexture->mResources[i];\r\n            List->CopyTextureRegion(&Dst, DstX, DstY, DstZ, &Src, pSrcBox);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyResource(\r\n    CD3DX12AffinityResource* pDstResource,\r\n    CD3DX12AffinityResource* pSrcResource)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->CopyResource(pDstResource->mResources[i], pSrcResource->mResources[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyTiles(\r\n    CD3DX12AffinityResource* pTiledResource,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,\r\n    const D3D12_TILE_REGION_SIZE* pTileRegionSize,\r\n    CD3DX12AffinityResource* pBuffer,\r\n    UINT64 BufferStartOffsetInBytes,\r\n    D3D12_TILE_COPY_FLAGS Flags)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->CopyTiles(\r\n                pTiledResource->mResources[i],\r\n                pTileRegionStartCoordinate,\r\n                pTileRegionSize,\r\n                pBuffer->mResources[i],\r\n                BufferStartOffsetInBytes,\r\n                Flags);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ResolveSubresource(\r\n    CD3DX12AffinityResource* pDstResource,\r\n    UINT DstSubresource,\r\n    CD3DX12AffinityResource* pSrcResource,\r\n    UINT SrcSubresource,\r\n    DXGI_FORMAT Format)\r\n{\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ResolveSubresource(pDstResource->mResources[i], DstSubresource, pSrcResource->mResources[i], SrcSubresource, Format);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::IASetPrimitiveTopology(\r\n    D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->IASetPrimitiveTopology(PrimitiveTopology);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::RSSetViewports(\r\n    UINT NumViewports,\r\n    const D3D12_VIEWPORT* pViewports)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->RSSetViewports(NumViewports, pViewports);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::RSSetScissorRects(\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->RSSetScissorRects(NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::OMSetBlendFactor(\r\n    const FLOAT BlendFactor[4])\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->OMSetBlendFactor(BlendFactor);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::OMSetStencilRef(\r\n    UINT StencilRef)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->OMSetStencilRef(StencilRef);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ResourceBarrier(\r\n    UINT NumBarriers,\r\n    const D3DX12_AFFINITY_RESOURCE_BARRIER* pBarriers)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            mCachedResourceBarriers.resize(NumBarriers);\r\n            for (UINT b = 0; b < NumBarriers; ++b)\r\n            {\r\n                D3D12_RESOURCE_BARRIER Use = pBarriers[b].ToD3D12();\r\n\r\n                switch (pBarriers[b].Type)\r\n                {\r\n                case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:\r\n                {\r\n                    if (pBarriers[b].Transition.pResource)\r\n                    {\r\n                        Use.Transition.pResource = pBarriers[b].Transition.pResource->mResources[i];\r\n                    }\r\n                    break;\r\n                }\r\n                case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:\r\n                {\r\n                    if (pBarriers[b].Aliasing.pResourceAfter)\r\n                    {\r\n                        Use.Aliasing.pResourceAfter = pBarriers[b].Aliasing.pResourceAfter->mResources[i];\r\n                    }\r\n                    if (pBarriers[b].Aliasing.pResourceBefore)\r\n                    {\r\n                        Use.Aliasing.pResourceBefore = pBarriers[b].Aliasing.pResourceBefore->mResources[i];\r\n                    }\r\n                    break;\r\n                }\r\n                case D3D12_RESOURCE_BARRIER_TYPE_UAV:\r\n                {\r\n                    if (pBarriers[b].UAV.pResource)\r\n                    {\r\n                        Use.UAV.pResource = pBarriers[b].UAV.pResource->mResources[i];\r\n                    }\r\n                    break;\r\n                }\r\n                }\r\n\r\n                mCachedResourceBarriers[b] = Use;\r\n            }\r\n\r\n            List->ResourceBarrier(NumBarriers, mCachedResourceBarriers.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ExecuteBundle(\r\n    CD3DX12AffinityGraphicsCommandList* pCommandList)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->ExecuteBundle(pCommandList->mGraphicsCommandLists[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetDescriptorHeaps(\r\n    UINT NumDescriptorHeaps,\r\n    CD3DX12AffinityDescriptorHeap** ppDescriptorHeaps)\r\n{\r\n    mCachedDescriptorHeaps.resize(NumDescriptorHeaps);\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            for (UINT h = 0; h < NumDescriptorHeaps; ++h)\r\n            {\r\n                mCachedDescriptorHeaps[h] = static_cast<CD3DX12AffinityDescriptorHeap*>(ppDescriptorHeaps[h])->GetChildObject(i);\r\n            }\r\n\r\n            List->SetDescriptorHeaps(NumDescriptorHeaps, mCachedDescriptorHeaps.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootSignature(\r\n    CD3DX12AffinityRootSignature* pRootSignature)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootSignature(pRootSignature->mRootSignatures[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootSignature(\r\n    CD3DX12AffinityRootSignature* pRootSignature)\r\n{\r\n    CD3DX12AffinityRootSignature* AffinityRootSignature = static_cast<CD3DX12AffinityRootSignature*>(pRootSignature);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootSignature(AffinityRootSignature->mRootSignatures[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRoot32BitConstant(\r\n    UINT RootParameterIndex,\r\n    UINT SrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRoot32BitConstant(RootParameterIndex, SrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRoot32BitConstant(\r\n    UINT RootParameterIndex,\r\n    UINT SrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRoot32BitConstant(RootParameterIndex, SrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRoot32BitConstants(\r\n    UINT RootParameterIndex,\r\n    UINT Num32BitValuesToSet,\r\n    const void* pSrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n           \r\n            List->SetComputeRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRoot32BitConstants(\r\n    UINT RootParameterIndex,\r\n    UINT Num32BitValuesToSet,\r\n    const void* pSrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootConstantBufferView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootConstantBufferView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootConstantBufferView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootConstantBufferView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootShaderResourceView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootShaderResourceView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootShaderResourceView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootShaderResourceView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootUnorderedAccessView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootUnorderedAccessView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootUnorderedAccessView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootUnorderedAccessView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::IASetVertexBuffers(\r\n    UINT StartSlot,\r\n    UINT NumViews,\r\n    const D3D12_VERTEX_BUFFER_VIEW* pViews)\r\n{\r\n    mCachedBufferViews.resize(NumViews);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            for (UINT v = 0; v < NumViews; ++v)\r\n            {\r\n                mCachedBufferViews[v] = pViews[v];\r\n                mCachedBufferViews[v].BufferLocation = GetParentDevice()->GetGPUVirtualAddress(pViews[v].BufferLocation, i);\r\n            }\r\n\r\n            List->IASetVertexBuffers(StartSlot, NumViews, mCachedBufferViews.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SOSetTargets(\r\n    UINT StartSlot,\r\n    UINT NumViews,\r\n    const D3D12_STREAM_OUTPUT_BUFFER_VIEW* pViews)\r\n{\r\n    mCachedStreamOutBufferViews.resize(NumViews);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            for (UINT v = 0; v < NumViews; ++v)\r\n            {\r\n                mCachedStreamOutBufferViews[v] = pViews[v];\r\n                mCachedStreamOutBufferViews[v].BufferLocation = GetParentDevice()->GetGPUVirtualAddress(pViews[v].BufferLocation, i);\r\n                mCachedStreamOutBufferViews[v].BufferFilledSizeLocation = GetParentDevice()->GetGPUVirtualAddress(pViews[v].BufferFilledSizeLocation, i);\r\n            }\r\n\r\n            List->SOSetTargets(StartSlot, NumViews, mCachedStreamOutBufferViews.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::OMSetRenderTargets(\r\n    UINT NumRenderTargetDescriptors,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pRenderTargetDescriptors,\r\n    BOOL RTsSingleHandleToDescriptorRange,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pDepthStencilDescriptor)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            mCachedRenderTargetViews.resize(NumRenderTargetDescriptors);\r\n            for (UINT r = 0; r < NumRenderTargetDescriptors; ++r)\r\n            {\r\n                mCachedRenderTargetViews[r] = GetParentDevice()->GetCPUHeapPointer(pRenderTargetDescriptors[r], i);\r\n            }\r\n\r\n            if (pDepthStencilDescriptor)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDepthStencilDescriptor = GetParentDevice()->GetCPUHeapPointer(*pDepthStencilDescriptor, i);\r\n                List->OMSetRenderTargets(NumRenderTargetDescriptors, mCachedRenderTargetViews.data(), RTsSingleHandleToDescriptorRange, &ActualDepthStencilDescriptor);\r\n            }\r\n            else\r\n            {\r\n                List->OMSetRenderTargets(NumRenderTargetDescriptors, mCachedRenderTargetViews.data(), RTsSingleHandleToDescriptorRange, nullptr);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearDepthStencilView(\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView,\r\n    D3D12_CLEAR_FLAGS ClearFlags,\r\n    FLOAT Depth,\r\n    UINT8 Stencil,\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ClearDepthStencilView(GetParentDevice()->GetCPUHeapPointer(DepthStencilView, i), ClearFlags, Depth, Stencil, NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearRenderTargetView(\r\n    D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView,\r\n    const FLOAT ColorRGBA[4],\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n#ifdef D3DX12_DEBUG_CLEAR_WHITE\r\n            FLOAT White[4] = { 1, 1, 1, 1 };\r\n            List->ClearRenderTargetView(GetParentDevice()->GetCPUHeapPointer(RenderTargetView, i), White, NumRects, pRects);\r\n#else\r\n            List->ClearRenderTargetView(GetParentDevice()->GetCPUHeapPointer(RenderTargetView, i), ColorRGBA, NumRects, pRects);\r\n#endif\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearUnorderedAccessViewUint(\r\n    D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n    CD3DX12AffinityResource* pResource,\r\n    const UINT Values[4],\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ClearUnorderedAccessViewUint(\r\n                GetParentDevice()->GetGPUHeapPointer(ViewGPUHandleInCurrentHeap, i),\r\n                GetParentDevice()->GetCPUHeapPointer(ViewCPUHandle, i),\r\n                pResource->mResources[i], Values, NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearUnorderedAccessViewFloat(\r\n    D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n    CD3DX12AffinityResource* pResource,\r\n    const FLOAT Values[4],\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ClearUnorderedAccessViewFloat(\r\n                GetParentDevice()->GetGPUHeapPointer(ViewGPUHandleInCurrentHeap, i),\r\n                GetParentDevice()->GetCPUHeapPointer(ViewCPUHandle, i),\r\n                pResource->mResources[i], Values, NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::DiscardResource(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_DISCARD_REGION* pRegion)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->DiscardResource(\r\n                pResource->mResources[i],\r\n                pRegion);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::BeginQuery(\r\n    CD3DX12AffinityQueryHeap* pQueryHeap,\r\n    D3D12_QUERY_TYPE Type,\r\n    UINT Index)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            ID3D12QueryHeap* QueryHeap = pQueryHeap->mQueryHeaps[i];\r\n\r\n            List->BeginQuery(\r\n                QueryHeap,\r\n                Type,\r\n                Index);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::EndQuery(\r\n    CD3DX12AffinityQueryHeap* pQueryHeap,\r\n    D3D12_QUERY_TYPE Type,\r\n    UINT Index)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            ID3D12QueryHeap* QueryHeap = pQueryHeap->mQueryHeaps[i];\r\n\r\n            List->EndQuery(\r\n                QueryHeap,\r\n                Type,\r\n                Index);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ResolveQueryData(\r\n    CD3DX12AffinityQueryHeap* pQueryHeap,\r\n    D3D12_QUERY_TYPE Type,\r\n    UINT StartIndex,\r\n    UINT NumQueries,\r\n    CD3DX12AffinityResource* pDestinationBuffer,\r\n    UINT64 AlignedDestinationBufferOffset)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            ID3D12QueryHeap* QueryHeap = pQueryHeap->mQueryHeaps[i];\r\n            ID3D12Resource* DestinationBuffer = pDestinationBuffer->mResources[i];\r\n\r\n            List->ResolveQueryData(\r\n                QueryHeap,\r\n                Type,\r\n                StartIndex,\r\n                NumQueries,\r\n                DestinationBuffer,\r\n                AlignedDestinationBufferOffset);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetPredication(\r\n    CD3DX12AffinityResource* pBuffer,\r\n    UINT64 AlignedBufferOffset,\r\n    D3D12_PREDICATION_OP Operation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetPredication(\r\n                pBuffer->mResources[i],\r\n                AlignedBufferOffset,\r\n                Operation);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetMarker(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->SetMarker(\r\n                Metadata,\r\n                pData,\r\n                Size);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::BeginEvent(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->BeginEvent(\r\n                Metadata,\r\n                pData,\r\n                Size);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::EndEvent(void)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->EndEvent();\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ExecuteIndirect(\r\n    CD3DX12AffinityCommandSignature* pCommandSignature,\r\n    UINT MaxCommandCount,\r\n    CD3DX12AffinityResource* pArgumentBuffer,\r\n    UINT64 ArgumentBufferOffset,\r\n    CD3DX12AffinityResource* pCountBuffer,\r\n    UINT64 CountBufferOffset)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ExecuteIndirect(\r\n                pCommandSignature->GetChildObject(i),\r\n                MaxCommandCount,\r\n                pArgumentBuffer->mResources[i], ArgumentBufferOffset,\r\n                pCountBuffer ? pCountBuffer->mResources[i] : nullptr, CountBufferOffset);\r\n        }\r\n    }\r\n}\r\n\r\nCD3DX12AffinityGraphicsCommandList::CD3DX12AffinityGraphicsCommandList(CD3DX12AffinityDevice* device, ID3D12GraphicsCommandList** graphicsCommandLists, UINT Count, bool UseDeviceActiveMaskOnReset)\r\n    : CD3DX12AffinityCommandList(device, reinterpret_cast<ID3D12CommandList**>(graphicsCommandLists), Count)\r\n    , mUseDeviceActiveMaskOnReset(UseDeviceActiveMaskOnReset)\r\n    , mAccumulatedAffinityMask(0)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mGraphicsCommandLists[i] = graphicsCommandLists[i];\r\n        }\r\n        else\r\n        {\r\n            mGraphicsCommandLists[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"GraphicsCommandList\";\r\n#endif\r\n\r\n    if (UseDeviceActiveMaskOnReset)\r\n    {\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n    else\r\n    {\r\n        mAccumulatedAffinityMask = GetNodeMask();\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetPipelineState(\r\n    CD3DX12AffinityPipelineState* pPipelineState)\r\n{\r\n    CD3DX12AffinityPipelineState* PipelineState = static_cast<CD3DX12AffinityPipelineState*>(pPipelineState);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetPipelineState(PipelineState->mPipelineStates[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootDescriptorTable(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootDescriptorTable(RootParameterIndex, GetParentDevice()->GetGPUHeapPointer(BaseDescriptor, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootDescriptorTable(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            mGraphicsCommandLists[i]->SetGraphicsRootDescriptorTable(\r\n                RootParameterIndex,\r\n                GetParentDevice()->GetGPUHeapPointer(BaseDescriptor, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::IASetIndexBuffer(\r\n    const D3D12_INDEX_BUFFER_VIEW* pView)\r\n{\r\n    if (pView)\r\n    {\r\n        D3D12_INDEX_BUFFER_VIEW View = *pView;\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n                \r\n                View.BufferLocation = GetParentDevice()->GetGPUVirtualAddress(pView->BufferLocation, i);\r\n                List->IASetIndexBuffer(&View);\r\n            }\r\n        }\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n                List->IASetIndexBuffer(nullptr);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::DrawIndexedInstanced(\r\n    UINT IndexCountPerInstance,\r\n    UINT InstanceCount,\r\n    UINT StartIndexLocation,\r\n    INT BaseVertexLocation,\r\n    UINT StartInstanceLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            mGraphicsCommandLists[i]->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::BroadcastResource(CD3DX12AffinityResource* pResource, UINT NodeIndex, UINT TargetNodeMask)\r\n{\r\n    // The command list affinity must match the supplied source node\r\n    DEBUG_ASSERT(mAffinityMask == (1 << NodeIndex));\r\n\r\n    // Copy is a push operation on the Source node commandlist to a target resource\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & TargetNodeMask) != 0)\r\n        {\r\n            if (NodeIndex != i)\r\n            {\r\n                mGraphicsCommandLists[NodeIndex]->CopyResource(\r\n                    pResource->GetChildObject(i),\r\n                    pResource->GetChildObject(NodeIndex)\r\n                    );\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nID3D12GraphicsCommandList* CD3DX12AffinityGraphicsCommandList::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mGraphicsCommandLists[AffinityIndex];\r\n}\r\n\r\nUINT CD3DX12AffinityGraphicsCommandList::GetActiveAffinityMask()\r\n{\r\n    return mAccumulatedAffinityMask;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityGraphicsCommandList.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityCommandList.h\"\r\n#include \"CD3DX12AffinityQueryHeap.h\"\r\n#include \"CD3DX12AffinityDevice.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityGraphicsCommandList : public CD3DX12AffinityCommandList\r\n{\r\npublic:\r\n    virtual void STDMETHODCALLTYPE SetAffinity(\r\n        _In_  UINT AffinityMask);\r\n\r\n    D3D12_COMMAND_LIST_TYPE GetType();\r\n\r\n    HRESULT Close();\r\n\r\n    HRESULT Reset(\r\n        _In_  CD3DX12AffinityCommandAllocator* pAllocator,\r\n        _In_opt_  CD3DX12AffinityPipelineState* pInitialState);\r\n\r\n    void ClearState(\r\n        _In_opt_  CD3DX12AffinityPipelineState* pPipelineState);\r\n\r\n    void DrawInstanced(\r\n        _In_  UINT VertexCountPerInstance,\r\n        _In_  UINT InstanceCount,\r\n        _In_  UINT StartVertexLocation,\r\n        _In_  UINT StartInstanceLocation);\r\n\r\n    void DrawIndexedInstanced(\r\n        _In_  UINT IndexCountPerInstance,\r\n        _In_  UINT InstanceCount,\r\n        _In_  UINT StartIndexLocation,\r\n        _In_  INT BaseVertexLocation,\r\n        _In_  UINT StartInstanceLocation);\r\n\r\n    void Dispatch(\r\n        _In_  UINT ThreadGroupCountX,\r\n        _In_  UINT ThreadGroupCountY,\r\n        _In_  UINT ThreadGroupCountZ);\r\n\r\n    void CopyBufferRegion(\r\n        _In_  CD3DX12AffinityResource* pDstBuffer,\r\n        UINT64 DstOffset,\r\n        _In_  CD3DX12AffinityResource* pSrcBuffer,\r\n        UINT64 SrcOffset,\r\n        UINT64 NumBytes);\r\n\r\n    void CopyTextureRegion(\r\n        _In_  const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pDst,\r\n        UINT DstX,\r\n        UINT DstY,\r\n        UINT DstZ,\r\n        _In_  const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pSrc,\r\n        _In_opt_  const D3D12_BOX* pSrcBox);\r\n\r\n    void CopyResource(\r\n        _In_  CD3DX12AffinityResource* pDstResource,\r\n        _In_  CD3DX12AffinityResource* pSrcResource);\r\n\r\n    void CopyTiles(\r\n        _In_  CD3DX12AffinityResource* pTiledResource,\r\n        _In_  const D3D12_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,\r\n        _In_  const D3D12_TILE_REGION_SIZE* pTileRegionSize,\r\n        _In_  CD3DX12AffinityResource* pBuffer,\r\n        UINT64 BufferStartOffsetInBytes,\r\n        D3D12_TILE_COPY_FLAGS Flags);\r\n\r\n    void ResolveSubresource(\r\n        _In_  CD3DX12AffinityResource* pDstResource,\r\n        _In_  UINT DstSubresource,\r\n        _In_  CD3DX12AffinityResource* pSrcResource,\r\n        _In_  UINT SrcSubresource,\r\n        _In_  DXGI_FORMAT Format);\r\n\r\n    void IASetPrimitiveTopology(\r\n        _In_  D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology);\r\n\r\n    void RSSetViewports(\r\n        _In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE)  UINT NumViewports,\r\n        _In_reads_(NumViewports)  const D3D12_VIEWPORT* pViewports);\r\n\r\n    void RSSetScissorRects(\r\n        _In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE)  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void OMSetBlendFactor(\r\n        _In_opt_  const FLOAT BlendFactor[4]);\r\n\r\n    void OMSetStencilRef(\r\n        _In_  UINT StencilRef);\r\n\r\n    void SetPipelineState(\r\n        _In_  CD3DX12AffinityPipelineState* pPipelineState);\r\n\r\n    void ResourceBarrier(\r\n        _In_  UINT NumBarriers,\r\n        _In_reads_(NumBarriers)  const D3DX12_AFFINITY_RESOURCE_BARRIER* pBarriers);\r\n\r\n    void ExecuteBundle(\r\n        _In_  CD3DX12AffinityGraphicsCommandList* pCommandList);\r\n\r\n    void SetDescriptorHeaps(\r\n        _In_  UINT NumDescriptorHeaps,\r\n        _In_reads_(NumDescriptorHeaps)  CD3DX12AffinityDescriptorHeap** ppDescriptorHeaps);\r\n\r\n    void SetComputeRootSignature(\r\n        _In_  CD3DX12AffinityRootSignature* pRootSignature);\r\n\r\n    void SetGraphicsRootSignature(\r\n        _In_  CD3DX12AffinityRootSignature* pRootSignature);\r\n\r\n    void SetComputeRootDescriptorTable(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);\r\n\r\n    void SetGraphicsRootDescriptorTable(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);\r\n\r\n    void SetComputeRoot32BitConstant(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT SrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetGraphicsRoot32BitConstant(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT SrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetComputeRoot32BitConstants(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT Num32BitValuesToSet,\r\n        _In_reads_(Num32BitValuesToSet* sizeof(UINT))  const void* pSrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetGraphicsRoot32BitConstants(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT Num32BitValuesToSet,\r\n        _In_reads_(Num32BitValuesToSet* sizeof(UINT))  const void* pSrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetComputeRootConstantBufferView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetGraphicsRootConstantBufferView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetComputeRootShaderResourceView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetGraphicsRootShaderResourceView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetComputeRootUnorderedAccessView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetGraphicsRootUnorderedAccessView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void IASetIndexBuffer(\r\n        _In_opt_  const D3D12_INDEX_BUFFER_VIEW* pView);\r\n\r\n    void IASetVertexBuffers(\r\n        _In_  UINT StartSlot,\r\n        _In_  UINT NumViews,\r\n        _In_reads_opt_(NumViews)  const D3D12_VERTEX_BUFFER_VIEW* pViews);\r\n\r\n    void SOSetTargets(\r\n        _In_  UINT StartSlot,\r\n        _In_  UINT NumViews,\r\n        _In_reads_opt_(NumViews)  const D3D12_STREAM_OUTPUT_BUFFER_VIEW* pViews);\r\n\r\n    void OMSetRenderTargets(\r\n        _In_  UINT NumRenderTargetDescriptors,\r\n        _In_  const D3D12_CPU_DESCRIPTOR_HANDLE* pRenderTargetDescriptors,\r\n        _In_  BOOL RTsSingleHandleToDescriptorRange,\r\n        _In_opt_  const D3D12_CPU_DESCRIPTOR_HANDLE* pDepthStencilDescriptor);\r\n\r\n    void ClearDepthStencilView(\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView,\r\n        _In_  D3D12_CLEAR_FLAGS ClearFlags,\r\n        _In_  FLOAT Depth,\r\n        _In_  UINT8 Stencil,\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void ClearRenderTargetView(\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView,\r\n        _In_  const FLOAT ColorRGBA[4],\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void ClearUnorderedAccessViewUint(\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        _In_  const UINT Values[4],\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void ClearUnorderedAccessViewFloat(\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        _In_  const FLOAT Values[4],\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void DiscardResource(\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_DISCARD_REGION* pRegion);\r\n\r\n    void BeginQuery(\r\n        _In_  CD3DX12AffinityQueryHeap* pQueryHeap,\r\n        _In_  D3D12_QUERY_TYPE Type,\r\n        _In_  UINT Index);\r\n\r\n    void EndQuery(\r\n        _In_  CD3DX12AffinityQueryHeap* pQueryHeap,\r\n        _In_  D3D12_QUERY_TYPE Type,\r\n        _In_  UINT Index);\r\n\r\n    void ResolveQueryData(\r\n        _In_  CD3DX12AffinityQueryHeap* pQueryHeap,\r\n        _In_  D3D12_QUERY_TYPE Type,\r\n        _In_  UINT StartIndex,\r\n        _In_  UINT NumQueries,\r\n        _In_  CD3DX12AffinityResource* pDestinationBuffer,\r\n        _In_  UINT64 AlignedDestinationBufferOffset);\r\n\r\n    void SetPredication(\r\n        _In_opt_  CD3DX12AffinityResource* pBuffer,\r\n        _In_  UINT64 AlignedBufferOffset,\r\n        _In_  D3D12_PREDICATION_OP Operation);\r\n\r\n    void SetMarker(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size);\r\n\r\n    void BeginEvent(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size);\r\n\r\n    void EndEvent(void);\r\n\r\n    void ExecuteIndirect(\r\n        _In_  CD3DX12AffinityCommandSignature* pCommandSignature,\r\n        _In_  UINT MaxCommandCount,\r\n        _In_  CD3DX12AffinityResource* pArgumentBuffer,\r\n        _In_  UINT64 ArgumentBufferOffset,\r\n        _In_opt_  CD3DX12AffinityResource* pCountBuffer,\r\n        _In_  UINT64 CountBufferOffset);\r\n\r\n    void BroadcastResource(CD3DX12AffinityResource* pResource, UINT NodeIndex, UINT TargetNodeMask);\r\n\r\n    CD3DX12AffinityGraphicsCommandList(CD3DX12AffinityDevice* device, ID3D12GraphicsCommandList** graphicsCommandLists, UINT Count, bool UseDeviceActiveMaskOnReset);\r\n\r\n    ID3D12GraphicsCommandList* GetChildObject(UINT AffinityIndex);\r\n    UINT GetActiveAffinityMask();\r\n\r\nprivate:\r\n    ID3D12GraphicsCommandList* mGraphicsCommandLists[D3DX12_MAX_ACTIVE_NODES];\r\n    UINT mAccumulatedAffinityMask;\r\n    bool mUseDeviceActiveMaskOnReset;\r\n    std::vector<D3D12_RESOURCE_BARRIER> mCachedResourceBarriers;\r\n    std::vector<ID3D12DescriptorHeap*> mCachedDescriptorHeaps;\r\n    std::vector<D3D12_VERTEX_BUFFER_VIEW> mCachedBufferViews;\r\n    std::vector<D3D12_STREAM_OUTPUT_BUFFER_VIEW> mCachedStreamOutBufferViews;\r\n    std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> mCachedRenderTargetViews;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityHeap.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nCD3DX12AffinityHeap::CD3DX12AffinityHeap(CD3DX12AffinityDevice* device, ID3D12Heap** heaps, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(heaps), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mHeaps[i] = heaps[i];\r\n        }\r\n        else\r\n        {\r\n            mHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Heap\";\r\n#endif\r\n}\r\n\r\nD3D12_HEAP_DESC STDMETHODCALLTYPE CD3DX12AffinityHeap::GetDesc(UINT AffinityIndex)\r\n{\r\n    return mHeaps[AffinityIndex]->GetDesc();\r\n}\r\n\r\nID3D12Heap* CD3DX12AffinityHeap::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mHeaps[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityHeap.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityHeap : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityHeap(CD3DX12AffinityDevice* device, ID3D12Heap** heaps, UINT Count);\r\n\r\n    D3D12_HEAP_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n    ID3D12Heap* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    ID3D12Heap* mHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityObject.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::GetPrivateData(\r\n    REFGUID guid,\r\n    UINT* pDataSize,\r\n    void* pData,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        return ((ID3D12Object*)mObjects[AffinityIndex])->GetPrivateData(guid, pDataSize, pData);\r\n    }\r\n    else\r\n    {\r\n        return ((IDXGIObject*)mObjects[AffinityIndex])->GetPrivateData(guid, pDataSize, pData);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::SetPrivateData(\r\n    REFGUID guid,\r\n    UINT DataSize,\r\n    const void* pData,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        return ((ID3D12Object*)mObjects[AffinityIndex])->SetPrivateData(guid, DataSize, pData);\r\n    }\r\n    else\r\n    {\r\n        return ((IDXGIObject*)mObjects[AffinityIndex])->SetPrivateData(guid, DataSize, pData);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::SetPrivateDataInterface(\r\n    REFGUID guid,\r\n    const IUnknown* pData,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        return ((ID3D12Object*)mObjects[AffinityIndex])->SetPrivateDataInterface(guid, pData);\r\n    }\r\n    else\r\n    {\r\n        return ((IDXGIObject*)mObjects[AffinityIndex])->SetPrivateDataInterface(guid, pData);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::SetName(\r\n    LPCWSTR Name,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; ++i)\r\n        {\r\n            if (mObjects[i])\r\n            {\r\n                ((ID3D12Object*)mObjects[i])->SetName(Name);\r\n            }\r\n            else\r\n            {\r\n                break;\r\n            }\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectDebugName = Name;\r\n#endif\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityObject::SetAffinity(\r\n    UINT AffinityMask)\r\n{\r\n    mAffinityMask = AffinityMask & GetNodeMask();\r\n}\r\n\r\nUINT CD3DX12AffinityObject::AffinityIndexToMask(UINT const Index)\r\n{\r\n    return 1 << Index;\r\n}\r\n\r\nCD3DX12AffinityObject::CD3DX12AffinityObject(CD3DX12AffinityDevice* device, IUnknown** objects, UINT Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mObjects[i] = objects[i];\r\n        }\r\n        else\r\n        {\r\n            mObjects[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Object\";\r\n#endif\r\n    mReferenceCount = 1;\r\n    mParentDevice = device;\r\n    SetAffinity(mParentDevice->GetNodeMask());\r\n}\r\n\r\nCD3DX12AffinityObject::~CD3DX12AffinityObject()\r\n{\r\n    for (size_t i = 0; i < D3DX12_MAX_ACTIVE_NODES; ++i)\r\n    {\r\n        if (mObjects[i])\r\n        {\r\n            ULONG RefCount = mObjects[i]->Release();\r\n            DebugLog(L\"Releasing handle 0x%p, ref count is now %lu\\n\", mObjects[i], RefCount);\r\n        }\r\n    }\r\n}\r\n\r\nULONG CD3DX12AffinityObject::AddRef()\r\n{\r\n    InterlockedIncrement(&mReferenceCount);\r\n    return mReferenceCount;\r\n}\r\n\r\nULONG CD3DX12AffinityObject::Release()\r\n{\r\n    ULONG currentRefCount = InterlockedDecrement(&mReferenceCount);\r\n#ifdef DEBUG_OBJECT_NAME\r\n    DebugLog(L\"Release() called on an affinity object, reference count now %u [%p] [%s] [%s]\\n\", mReferenceCount, this, mObjectTypeName.c_str(), mObjectDebugName.c_str());\r\n#endif\r\n    if (mReferenceCount == 0)\r\n    {\r\n        delete this;\r\n    }\r\n\r\n    return currentRefCount;\r\n}\r\n\r\nCD3DX12AffinityDevice* CD3DX12AffinityObject::GetParentDevice()\r\n{\r\n    return mParentDevice;\r\n}\r\n\r\nUINT CD3DX12AffinityObject::GetNodeMask()\r\n{\r\n    return CD3DX12AffinityDevice::g_CachedNodeMask;\r\n}\r\n\r\nUINT CD3DX12AffinityObject::GetNodeCount()\r\n{\r\n    return CD3DX12AffinityDevice::g_CachedNodeCount;\r\n}\r\n\r\nUINT CD3DX12AffinityObject::GetActiveNodeIndex()\r\n{\r\n    return CD3DX12AffinityDevice::g_ActiveNodeIndex;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityObject.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityObject : public IUnknown\r\n{\r\npublic:\r\n#pragma region\r\n    // IUnknown\r\n    virtual HRESULT STDMETHODCALLTYPE QueryInterface(\r\n        REFIID riid,\r\n        __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject\r\n    )\r\n    {\r\n        //Simple QueryInterface implementation, Not real COM\r\n        *ppvObject = this;\r\n        AddRef();\r\n        return S_OK;\r\n    }\r\n#pragma endregion\r\n\r\n    HRESULT STDMETHODCALLTYPE GetPrivateData(\r\n        _In_  REFGUID guid,\r\n        _Inout_  UINT* pDataSize,\r\n        _Out_writes_bytes_opt_(*pDataSize)  void* pData,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetPrivateData(\r\n        _In_  REFGUID guid,\r\n        _In_  UINT DataSize,\r\n        _In_reads_bytes_opt_(DataSize)  const void* pData,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(\r\n        _In_  REFGUID guid,\r\n        _In_opt_  const IUnknown* pData,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetName(\r\n        _In_z_  LPCWSTR Name,\r\n        UINT AffinityIndex = 0);\r\n\r\n    virtual void STDMETHODCALLTYPE SetAffinity(\r\n        _In_  UINT AffinityMask);\r\n\r\n    virtual ULONG STDMETHODCALLTYPE AddRef();\r\n    virtual ULONG STDMETHODCALLTYPE Release();\r\n\r\n    CD3DX12AffinityObject(CD3DX12AffinityDevice* device, IUnknown** objects, UINT Count);\r\n    virtual ~CD3DX12AffinityObject();\r\n\r\n    CD3DX12AffinityDevice* GetParentDevice();\r\n\r\n    IUnknown* mObjects[D3DX12_MAX_ACTIVE_NODES];\r\n    UINT mAffinityMask = 0;\r\n    UINT mReferenceCount;\r\n\r\n#ifdef DEBUG_OBJECT_NAME\r\n    std::wstring mObjectTypeName;\r\n    std::wstring mObjectDebugName;\r\n#endif\r\n    CD3DX12AffinityDevice* mParentDevice;\r\n\r\n    static UINT AffinityIndexToMask(UINT const Index);\r\n    UINT GetNodeMask();\r\n\r\n    UINT GetNodeCount();\r\n    UINT GetActiveNodeIndex();\r\n\r\nprotected:\r\n    virtual bool IsD3D() = 0;\r\n\r\nprivate:\r\n    // Non-copyable\r\n    CD3DX12AffinityObject(CD3DX12AffinityObject const&);\r\n    CD3DX12AffinityObject& operator=(CD3DX12AffinityObject const&);\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityPageable.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityPageable::CD3DX12AffinityPageable(CD3DX12AffinityDevice* device, ID3D12Pageable** pageables, UINT Count)\r\n    : CD3DX12AffinityDeviceChild(device, reinterpret_cast<ID3D12DeviceChild**>(pageables), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mPageables[i] = pageables[i];\r\n        }\r\n        else\r\n        {\r\n            mPageables[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Pageable\";\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityPageable.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityPageable : public CD3DX12AffinityDeviceChild\r\n{\r\npublic:\r\n    CD3DX12AffinityPageable(CD3DX12AffinityDevice* device, ID3D12Pageable** pageables, UINT Count);\r\n\r\n    ID3D12Pageable* mPageables[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityPipelineState.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityPipelineState::GetCachedBlob(\r\n    ID3DBlob** ppBlob,\r\n    UINT AffinityIndex)\r\n{\r\n    return mPipelineStates[AffinityIndex]->GetCachedBlob(ppBlob);\r\n}\r\n\r\nCD3DX12AffinityPipelineState::CD3DX12AffinityPipelineState(CD3DX12AffinityDevice* device, ID3D12PipelineState** pipelineStates, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(pipelineStates), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mPipelineStates[i] = pipelineStates[i];\r\n        }\r\n        else\r\n        {\r\n            mPipelineStates[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"PipelineState\";\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityPipelineState.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityPipelineState : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    HRESULT STDMETHODCALLTYPE GetCachedBlob(\r\n        _COM_Outptr_  ID3DBlob** ppBlob,\r\n        UINT AffinityIndex = 0);\r\n\r\n    CD3DX12AffinityPipelineState(CD3DX12AffinityDevice* device, ID3D12PipelineState** pipelineStates, UINT Count);\r\n\r\n    ID3D12PipelineState* mPipelineStates[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityQueryHeap.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityQueryHeap::CD3DX12AffinityQueryHeap(CD3DX12AffinityDevice* device, ID3D12QueryHeap** queryHeaps, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(queryHeaps), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mQueryHeaps[i] = queryHeaps[i];\r\n        }\r\n        else\r\n        {\r\n            mQueryHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"QueryHeap\";\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityQueryHeap.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityQueryHeap : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityQueryHeap(CD3DX12AffinityDevice* device, ID3D12QueryHeap** queryHeaps, UINT Count);\r\n\r\n    ID3D12QueryHeap* mQueryHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityResource.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::Map(\r\n    UINT Subresource,\r\n    const D3D12_RANGE* pReadRange,\r\n    void** ppData)\r\n{\r\n    if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        return mResources[0]->Map(Subresource, pReadRange, ppData);\r\n    }\r\n\r\n    if (++mReferenceCount == 1)\r\n    {\r\n        DEBUG_ASSERT(mMappedAddresses.empty());\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = mResources[i];\r\n                void* MappedAddress = nullptr;\r\n                HRESULT const hr = Resource->Map(Subresource, pReadRange, &MappedAddress);\r\n\r\n                if (S_OK == hr)\r\n                {\r\n                    mMappedAddresses.push_back(MappedAddress);\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n\r\n            {\r\n                std::lock_guard<std::mutex> lock(GetParentDevice()->MutexStillMappedResources);\r\n                GetParentDevice()->StillMappedResources.insert(this);\r\n            }\r\n        }\r\n    }\r\n\r\n    switch (mCPUPageProperty)\r\n    {\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK:\r\n        *ppData = mMappedAddresses[0];\r\n        break;\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE:\r\n        *ppData = mShadowBuffer;\r\n        break;\r\n    default:\r\n    case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE:\r\n    case D3D12_CPU_PAGE_PROPERTY_UNKNOWN:\r\n        DEBUG_ASSERT(false);\r\n        return S_FALSE;\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityResource::Unmap(\r\n    UINT Subresource,\r\n    const D3D12_RANGE* pWrittenRange)\r\n{\r\n    if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        mResources[0]->Unmap(Subresource, pWrittenRange);\r\n        return;\r\n    }\r\n\r\n    if (--mReferenceCount == 0)\r\n    {\r\n        SynchronizeAcrossDevices();\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = mResources[i];\r\n                Resource->Unmap(Subresource, pWrittenRange);\r\n            }\r\n        }\r\n\r\n        {\r\n            std::lock_guard<std::mutex> lock(GetParentDevice()->MutexStillMappedResources);\r\n            GetParentDevice()->StillMappedResources.erase(this);\r\n        }\r\n        mMappedAddresses.clear();\r\n    }\r\n\r\n    DEBUG_ASSERT(mReferenceCount >= 0);\r\n}\r\n\r\nD3D12_RESOURCE_DESC STDMETHODCALLTYPE CD3DX12AffinityResource::GetDesc(UINT AffinityIndex)\r\n{\r\n    while (!mResources[AffinityIndex])\r\n    {\r\n        AffinityIndex++;\r\n    }\r\n    return mResources[AffinityIndex]->GetDesc();\r\n}\r\n\r\nD3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE CD3DX12AffinityResource::GetGPUVirtualAddress(void)\r\n{\r\n    if (GetNodeCount() == 1\r\n#if TILE_MAPPING_GPUVA\r\n        || GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA\r\n#endif\r\n        )\r\n    {\r\n        return mResources[0]->GetGPUVirtualAddress();\r\n    }\r\n    if (0 == mVirtualAddress)\r\n    {\r\n        std::vector<D3D12_GPU_VIRTUAL_ADDRESS> Addresses(GetNodeCount());\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                Addresses[i] = mResources[i]->GetGPUVirtualAddress();\r\n            }\r\n        }\r\n        mVirtualAddress = Addresses[0];\r\n\r\n        GetParentDevice()->MutexGPUVirtualAddresses.lock();\r\n        GetParentDevice()->GPUVirtualAddresses[mVirtualAddress] = std::move(Addresses);\r\n        GetParentDevice()->MutexGPUVirtualAddresses.unlock();\r\n    }\r\n\r\n    return mVirtualAddress;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::WriteToSubresource(\r\n    UINT DstSubresource,\r\n    const D3D12_BOX* pDstBox,\r\n    const void* pSrcData,\r\n    UINT SrcRowPitch,\r\n    UINT SrcDepthPitch)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12Resource* Resource = mResources[i];\r\n            HRESULT const hr = Resource->WriteToSubresource(\r\n                DstSubresource,\r\n                pDstBox,\r\n                pSrcData,\r\n                SrcRowPitch,\r\n                SrcDepthPitch);\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::ReadFromSubresource(\r\n    void* pDstData,\r\n    UINT DstRowPitch,\r\n    UINT DstDepthPitch,\r\n    UINT SrcSubresource,\r\n    const D3D12_BOX* pSrcBox,\r\n    UINT AffinityIndex)\r\n{\r\n    return mResources[AffinityIndex]->ReadFromSubresource(\r\n        pDstData,\r\n        DstRowPitch,\r\n        DstDepthPitch,\r\n        SrcSubresource,\r\n        pSrcBox);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::GetHeapProperties(\r\n    D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n    D3D12_HEAP_FLAGS* pHeapFlags,\r\n    UINT AffinityIndex)\r\n{\r\n    return mResources[AffinityIndex]->GetHeapProperties(pHeapProperties, pHeapFlags);\r\n}\r\n\r\nCD3DX12AffinityResource::CD3DX12AffinityResource(CD3DX12AffinityDevice* device, ID3D12Resource** resources, UINT Count, ID3D12Heap** heaps)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(resources), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mResources[i] = resources[i];\r\n            mHeaps[i] = heaps ? heaps[i] : nullptr;\r\n        }\r\n        else\r\n        {\r\n            mResources[i] = nullptr;\r\n            mHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Resource\";\r\n#endif\r\n    mVirtualAddress = 0;\r\n}\r\n\r\nCD3DX12AffinityResource::~CD3DX12AffinityResource()\r\n{\r\n    std::lock_guard<std::mutex> lock(GetParentDevice()->MutexStillMappedResources);\r\n    GetParentDevice()->StillMappedResources.erase(this);\r\n\r\n    if (0 != mVirtualAddress)\r\n    {\r\n        GetParentDevice()->GPUVirtualAddresses.erase(mVirtualAddress);\r\n    }\r\n\r\n    for (UINT i = 0; i < GetNodeCount(); i++)\r\n    {\r\n        if (mHeaps[i])\r\n        {\r\n            mHeaps[i]->Release();\r\n            mHeaps[i] = nullptr;\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityResource::SynchronizeAcrossDevices()\r\n{\r\n    if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        return;\r\n    }\r\n\r\n    switch (mCPUPageProperty)\r\n    {\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK:\r\n        for (size_t i = 1; i < mMappedAddresses.size(); ++i)\r\n        {\r\n            memcpy(mMappedAddresses[i], mMappedAddresses[0], static_cast<size_t>(mBufferSize));\r\n        }\r\n        ReleaseLog(L\"D3DX12AffinityLayer: [memcpy] Synchronized %lu bytes of WRITE_BACK memory.\\n\", mBufferSize);\r\n        break;\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE:\r\n    {\r\n        static UINT const WrittenAddressBufferSize = 8192;\r\n        UINT NumUpdated = 0;\r\n        UINT64 BytesCopied = 0;\r\n\r\n#ifdef DO_FULL_MAPPED_MEM_COPY\r\n        for (size_t i = 0; i < mMappedAddresses.size(); ++i)\r\n        {\r\n            memcpy(mMappedAddresses[i], mShadowBuffer, static_cast<size_t>(mBufferSize));\r\n            BytesCopied += mBufferSize;\r\n        }\r\n#else\r\n        static thread_local void** WrittenAddresses = nullptr;\r\n        if (nullptr == WrittenAddresses)\r\n        {\r\n            WrittenAddresses = new void*[WrittenAddressBufferSize];\r\n        }\r\n\r\n        ULONG_PTR Count = WrittenAddressBufferSize;\r\n        ULONG Granularity = 0;\r\n        GetWriteWatch(WRITE_WATCH_FLAG_RESET, mShadowBuffer, static_cast<size_t>(mBufferSize), WrittenAddresses, &Count, &Granularity);\r\n\r\n        while (Count)\r\n        {\r\n            for (ULONG_PTR address = 0; address < Count; ++address)\r\n            {\r\n                ULONG_PTR const PageOffsetFromBasePtr = ((byte*)WrittenAddresses[address] - (byte*)mShadowBuffer);\r\n                for (size_t i = 0; i < mMappedAddresses.size(); ++i)\r\n                {\r\n                    memcpy((byte*)mMappedAddresses[i] + PageOffsetFromBasePtr, WrittenAddresses[address], Granularity);\r\n                }\r\n                NumUpdated++;\r\n                BytesCopied += Granularity;\r\n            }\r\n\r\n            Count = WrittenAddressBufferSize;\r\n            GetWriteWatch(WRITE_WATCH_FLAG_RESET, mShadowBuffer, static_cast<size_t>(mBufferSize), WrittenAddresses, &Count, &Granularity);\r\n        }\r\n#endif\r\n\r\n        ReleaseLog(L\"D3DX12AffinityLayer: [memcpy] Synchronized %lu bytes of shadow buffered memory.\\n\", BytesCopied);\r\n        break;\r\n    }\r\n    case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE:\r\n        DEBUG_FAIL_MESSAGE(L\"Property of CPU Page unnavailable while synchronizing.\");\r\n        break;\r\n    case D3D12_CPU_PAGE_PROPERTY_UNKNOWN:\r\n        DEBUG_FAIL_MESSAGE(L\"Property of CPU Page unknown while synchronizing.\");\r\n        break;\r\n    default:\r\n        DebugLog(L\"Unexpected CPU page value: %d\\n\", mCPUPageProperty);\r\n        DEBUG_FAIL_MESSAGE(L\"Property of CPU Page entirely unexpected while synchronizing. Possible corruption.\");\r\n        break;\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityResource::UpdatePersistentMaps(CD3DX12AffinityDevice* pDevice)\r\n{\r\n    std::lock_guard<std::mutex> lock(pDevice->MutexStillMappedResources);\r\n    for (CD3DX12AffinityResource* Resource : pDevice->StillMappedResources)\r\n    {\r\n        Resource->SynchronizeAcrossDevices();\r\n    }\r\n}\r\n\r\nID3D12Resource* CD3DX12AffinityResource::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mResources[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityResource.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityResource : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    HRESULT STDMETHODCALLTYPE Map(\r\n        UINT Subresource,\r\n        _In_opt_  const D3D12_RANGE* pReadRange,\r\n        _Outptr_opt_result_bytebuffer_(_Inexpressible_(\"Dependent on resource\"))  void** ppData);\r\n\r\n    void STDMETHODCALLTYPE Unmap(\r\n        UINT Subresource,\r\n        _In_opt_  const D3D12_RANGE* pWrittenRange);\r\n\r\n    D3D12_RESOURCE_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE GetGPUVirtualAddress(void);\r\n\r\n    HRESULT STDMETHODCALLTYPE WriteToSubresource(\r\n        UINT DstSubresource,\r\n        _In_opt_  const D3D12_BOX* pDstBox,\r\n        _In_  const void* pSrcData,\r\n        UINT SrcRowPitch,\r\n        UINT SrcDepthPitch);\r\n\r\n    HRESULT STDMETHODCALLTYPE ReadFromSubresource(\r\n        _Out_  void* pDstData,\r\n        UINT DstRowPitch,\r\n        UINT DstDepthPitch,\r\n        UINT SrcSubresource,\r\n        _In_opt_  const D3D12_BOX* pSrcBox,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetHeapProperties(\r\n        _Out_opt_  D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n        _Out_opt_  D3D12_HEAP_FLAGS* pHeapFlags,\r\n        UINT AffinityIndex = 0);\r\n\r\n    CD3DX12AffinityResource(CD3DX12AffinityDevice* device, ID3D12Resource** resources, UINT Count, ID3D12Heap** heaps = nullptr);\r\n    ~CD3DX12AffinityResource();\r\n\r\n    ID3D12Resource* GetChildObject(UINT AffinityIndex);\r\n    void SynchronizeAcrossDevices();\r\n\r\n    static void UpdatePersistentMaps(CD3DX12AffinityDevice* pDevice);\r\n\r\n\r\n    ID3D12Resource* mResources[D3DX12_MAX_ACTIVE_NODES];\r\n    ID3D12Heap* mHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n    std::vector<void*> mMappedAddresses;\r\n    int mReferenceCount;\r\n    void* mShadowBuffer;\r\n    UINT64 mBufferSize;\r\n    D3D12_CPU_PAGE_PROPERTY mCPUPageProperty;\r\n    D3D12_GPU_VIRTUAL_ADDRESS mVirtualAddress;\r\n\r\n    ID3D12CommandList* mSyncCommandLists[D3DX12_MAX_ACTIVE_NODES];\r\n    ID3D12CommandAllocator* mSyncCommandAllocators[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityRootSignature.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityRootSignature::CD3DX12AffinityRootSignature(CD3DX12AffinityDevice* device, ID3D12RootSignature** rootSignatures, UINT Count)\r\n    : CD3DX12AffinityDeviceChild(device, reinterpret_cast<ID3D12DeviceChild**>(rootSignatures), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mRootSignatures[i] = rootSignatures[i];\r\n        }\r\n        else\r\n        {\r\n            mRootSignatures[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"RootSignature\";\r\n#endif\r\n}\r\n\r\nID3D12RootSignature* CD3DX12AffinityRootSignature::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mRootSignatures[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CD3DX12AffinityRootSignature.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityRootSignature : public CD3DX12AffinityDeviceChild\r\n{\r\npublic:\r\n    CD3DX12AffinityRootSignature(CD3DX12AffinityDevice* device, ID3D12RootSignature** rootSignatures, UINT Count);\r\n    ID3D12RootSignature* GetChildObject(UINT AffinityIndex);\r\n\r\n    ID3D12RootSignature* mRootSignatures[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CDXGIAffinitySwapChain.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"d3dx12.h\"\r\n#include \"Utils.h\"\r\n\r\n#include <string>\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetParent(\r\n    REFIID riid,\r\n    void** ppParent,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetParent(riid, ppParent);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::Present(\r\n    UINT SyncInterval,\r\n    UINT Flags,\r\n    UINT AffinityMask)\r\n{\r\n    UINT IndicesCount = 0;\r\n    HRESULT hr = S_OK;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    switch (mMode)\r\n    {\r\n    case EAffinitySwapChainMode::MultiWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n                hr = SwapChain->Present(SyncInterval, Flags);\r\n                RETURN_IF_FAILED(hr);\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::LDA:\r\n    {\r\n        hr = mSwapChains[0]->Present(SyncInterval, Flags);\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::SingleWindow:\r\n    {\r\n        UINT const i = 0;\r\n        DebugLog(L\"Presenting contents of backbuffer %d on device %d\", mCurrentBackBufferIndex, i);\r\n\r\n        DebugLog(L\" [marshalled]\\n\");\r\n        SDeviceContext& Context = mDeviceContexts[i];\r\n        ID3D12Resource* RenderTarget = Context.mRenderTargets[mCurrentBackBufferIndex];\r\n        ID3D12Resource* CopyBuffer = Context.mCrossAdapterCopyBuffers[mCurrentBackBufferIndex];\r\n\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(RenderTarget, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_SOURCE));\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBuffer, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));\r\n        Context.mDisplayCommandList->CopyResource(CopyBuffer, RenderTarget);\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON));\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(RenderTarget, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT));\r\n        Context.mDisplayCommandList->Close();\r\n\r\n        if (Context.mFenceValue)\r\n            Context.mDisplayCommandQueue->Wait(Context.mCrossAdapterCopyFence, Context.mFenceValue);\r\n        ID3D12CommandList* ppCommandLists1[] = { Context.mDisplayCommandList };\r\n        Context.mDisplayCommandQueue->ExecuteCommandLists(_countof(ppCommandLists1), ppCommandLists1);\r\n        Context.mDisplayCommandQueue->Signal(Context.mCrossAdapterCopyFence, ++Context.mFenceValue);\r\n\r\n        Context.mDisplayCommandList->Reset(Context.mDisplayCommandAllocator, nullptr);\r\n\r\n        ID3D12Resource* CopyBufferOnHost = Context.mCrossAdapterCopyBuffersOnHost[mCurrentBackBufferIndex];\r\n        ID3D12Resource* TargetBackBufferResource = nullptr;\r\n        mSwapChains[0]->GetBuffer(mCurrentBackBufferIndex, IID_PPV_ARGS(&TargetBackBufferResource));\r\n\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(TargetBackBufferResource, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST));\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBufferOnHost, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE));\r\n        mDeviceContexts[0].mDisplayCommandList->CopyResource(TargetBackBufferResource, CopyBufferOnHost);\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBufferOnHost, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON));\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(TargetBackBufferResource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT));\r\n        mDeviceContexts[0].mDisplayCommandList->Close();\r\n\r\n        mDeviceContexts[0].mDisplayCommandQueue->Wait(Context.mCrossAdapterCopyFenceOnHost, Context.mFenceValue);\r\n        ID3D12CommandList* ppCommandLists2[] = { mDeviceContexts[0].mDisplayCommandList };\r\n        mDeviceContexts[0].mDisplayCommandQueue->ExecuteCommandLists(_countof(ppCommandLists2), ppCommandLists2);\r\n        mDeviceContexts[0].mDisplayCommandQueue->Signal(Context.mCrossAdapterCopyFenceOnHost, ++Context.mFenceValue);\r\n\r\n        mDeviceContexts[0].mDisplayCommandList->Reset(mDeviceContexts[0].mDisplayCommandAllocator, nullptr);\r\n\r\n        hr = mSwapChains[0]->Present(SyncInterval, Flags);\r\n\r\n        TargetBackBufferResource->Release();\r\n\r\n        break;\r\n    }\r\n    }\r\n\r\n    mCurrentBackBufferIndex = mSwapChains[0]->GetCurrentBackBufferIndex();\r\n    return hr;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetBuffer(\r\n    UINT Buffer,\r\n    REFIID riid,\r\n    void** ppSurface,\r\n    UINT AffinityMask)\r\n{\r\n    UINT IndicesCount = 0;\r\n    \r\n    std::vector<ID3D12Resource*> Resources;\r\n    Resources.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    switch (mMode)\r\n    {\r\n    case EAffinitySwapChainMode::MultiWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n                ID3D12Resource* Surface = nullptr;\r\n                HRESULT const hr = SwapChain->GetBuffer(Buffer, IID_PPV_ARGS(&Surface));\r\n\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Surface;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::LDA:\r\n    {\r\n        for (UINT b = 0; b < mNumBackBuffers; ++b)\r\n        {\r\n            UINT bufferIndex = b % mNumRequestedBackBuffers;\r\n            if (bufferIndex == Buffer)\r\n            {\r\n                UINT nodeIndex = b % GetNodeCount();\r\n                HRESULT hr = mSwapChains[0]->GetBuffer(b, IID_PPV_ARGS(&Resources[nodeIndex]));\r\n                if (FAILED(hr))\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::SingleWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Surface = nullptr;\r\n                HRESULT hr = S_OK;\r\n\r\n                Surface = mDeviceContexts[i].mRenderTargets[Buffer];\r\n                Surface->AddRef();\r\n\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Surface;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    }\r\n\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(GetParentDevice(), &(Resources[0]), (UINT)Resources.size());\r\n#ifdef DEBUG_OBJECT_NAME\r\n    Resource->mObjectDebugName = L\"SwapChainBackBuffer\";\r\n#endif\r\n\r\n    *ppSurface = Resource;\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetFullscreenState(\r\n    BOOL Fullscreen,\r\n    IDXGIOutput* pTarget,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetFullscreenState(Fullscreen, pTarget);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetFullscreenState(Fullscreen, pTarget);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetFullscreenState(\r\n    BOOL* pFullscreen,\r\n    IDXGIOutput** ppTarget,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFullscreenState(pFullscreen, ppTarget);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetDesc(\r\n    DXGI_SWAP_CHAIN_DESC* pDesc,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetDesc(pDesc);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::ResizeBuffers(\r\n    UINT BufferCount,\r\n    UINT Width,\r\n    UINT Height,\r\n    DXGI_FORMAT NewFormat,\r\n    UINT SwapChainFlags,\r\n    UINT AffinityMask)\r\n{\r\n    DebugLog(L\"Doing swap chain buffer resize...\\n\");\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    // First free up any existing resources.\r\n\r\n    for (UINT i = 1; i < mDeviceContexts.size(); ++i)\r\n    {\r\n        CDXGIAffinitySwapChain::SDeviceContext& DeviceContext = mDeviceContexts[i];\r\n\r\n        for (size_t i = 0; i < DeviceContext.mRenderTargets.size(); ++i)\r\n        {\r\n            DeviceContext.mRenderTargets[i]->Release();\r\n        }\r\n        DeviceContext.mRenderTargets.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBufferHeaps.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBufferHeaps[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBufferHeaps.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBuffers.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBuffers[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBuffers.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBufferHeapsOnHost.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBufferHeapsOnHost[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBufferHeapsOnHost.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBuffersOnHost.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBuffersOnHost[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBuffersOnHost.clear();\r\n    }\r\n\r\n    // Resize the actual swap buffers.\r\n\r\n    switch (mMode)\r\n    {\r\n    case EAffinitySwapChainMode::MultiWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n                RETURN_IF_FAILED(\r\n                    SwapChain->ResizeBuffers(\r\n                        BufferCount,\r\n                        Width,\r\n                        Height,\r\n                        NewFormat,\r\n                        SwapChainFlags));\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::LDA:\r\n    {\r\n        std::vector<UINT> creationNodeMasks;\r\n        std::vector<IUnknown*> pQueues;\r\n        UINT nodeCount = GetNodeCount();\r\n        if (nodeCount > 1)\r\n        {\r\n            mNumBackBuffers = lcm(BufferCount, nodeCount);\r\n            mNumRequestedBackBuffers = BufferCount;\r\n            creationNodeMasks.resize(mNumBackBuffers);\r\n            pQueues.resize(mNumBackBuffers);\r\n            for (UINT i = 0; i < mNumBackBuffers; i++)\r\n            {\r\n                creationNodeMasks[i] = GetParentDevice()->AffinityIndexToNodeMask(i % nodeCount);\r\n                pQueues[i] = mParentQueue->GetChildObject(i % nodeCount);\r\n            }\r\n            RETURN_IF_FAILED(\r\n                mSwapChains[0]->ResizeBuffers1(\r\n                    mNumBackBuffers,\r\n                    Width,\r\n                    Height,\r\n                    NewFormat,\r\n                    SwapChainFlags,\r\n                    creationNodeMasks.data(),\r\n                    pQueues.data()));\r\n\r\n            GetParentDevice()->g_ActiveNodeIndex = 0;\r\n        }\r\n        else\r\n        {\r\n            RETURN_IF_FAILED(\r\n                mSwapChains[0]->ResizeBuffers(\r\n                    BufferCount,\r\n                    Width,\r\n                    Height,\r\n                    NewFormat,\r\n                    SwapChainFlags));\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::SingleWindow:\r\n        RETURN_IF_FAILED(\r\n            mSwapChains[0]->ResizeBuffers(\r\n                BufferCount,\r\n                Width,\r\n                Height,\r\n                NewFormat,\r\n                SwapChainFlags));\r\n        break;\r\n    }\r\n\r\n    mCurrentBackBufferIndex = 0;\r\n\r\n    // Recreate render targets.\r\n\r\n    if (mMode != EAffinitySwapChainMode::LDA)\r\n    {\r\n        for (UINT i = 0; i < mDeviceContexts.size(); ++i)\r\n        {\r\n            RETURN_IF_FAILED(\r\n                CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n                    i,\r\n                    GetParentDevice(),\r\n                    mHostDevice,\r\n                    mDeviceContexts[i],\r\n                    Width, Height, NewFormat,\r\n                    mNumBackBuffers));\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::ResizeTarget(\r\n    const DXGI_MODE_DESC* pNewTargetParameters,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->ResizeTarget(pNewTargetParameters);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->ResizeTarget(pNewTargetParameters);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetContainingOutput(\r\n    IDXGIOutput** ppOutput,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetContainingOutput(ppOutput);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetFrameStatistics(\r\n    DXGI_FRAME_STATISTICS* pStats,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFrameStatistics(pStats);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetLastPresentCount(\r\n    UINT* pLastPresentCount,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetLastPresentCount(pLastPresentCount);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetDesc1(DXGI_SWAP_CHAIN_DESC1* pDesc, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetDesc1(pDesc);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFullscreenDesc(pDesc);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetHwnd(HWND* pHwnd, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetHwnd(pHwnd);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetCoreWindow(REFIID refiid, void** ppUnk, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetCoreWindow(refiid, ppUnk);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters, UINT AffinityMask)\r\n{\r\n    HRESULT_METHOD_NOT_YET_IMPLEMENTED(CDXGIAffinitySwapChain::Present1);\r\n}\r\n\r\nBOOL CDXGIAffinitySwapChain::IsTemporaryMonoSupported(UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->IsTemporaryMonoSupported();\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetRestrictToOutput(ppRestrictToOutput);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::SetBackgroundColor(const DXGI_RGBA* pColor, UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain1* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetBackgroundColor(pColor);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetBackgroundColor(pColor);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetBackgroundColor(DXGI_RGBA* pColor, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetBackgroundColor(pColor);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::SetRotation(DXGI_MODE_ROTATION Rotation, UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain1* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetRotation(Rotation);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetRotation(Rotation);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetRotation(DXGI_MODE_ROTATION* pRotation, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetRotation(pRotation);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetSourceSize(\r\n    UINT Width,\r\n    UINT Height,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain2* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetSourceSize(Width, Height);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetSourceSize(Width, Height);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetSourceSize(\r\n    UINT* pWidth,\r\n    UINT* pHeight,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetSourceSize(pWidth, pHeight);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetMaximumFrameLatency(\r\n    UINT MaxLatency,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain2* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetMaximumFrameLatency(MaxLatency);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetMaximumFrameLatency(MaxLatency);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetMaximumFrameLatency(\r\n    UINT* pMaxLatency,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetMaximumFrameLatency(pMaxLatency);\r\n}\r\n\r\nHANDLE STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetFrameLatencyWaitableObject(UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFrameLatencyWaitableObject();\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::SetMatrixTransform(\r\n    const DXGI_MATRIX_3X2_F* pMatrix,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain2* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetMatrixTransform(pMatrix);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetMatrixTransform(pMatrix);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetMatrixTransform(\r\n    DXGI_MATRIX_3X2_F* pMatrix,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetMatrixTransform(pMatrix);\r\n}\r\n\r\nUINT CDXGIAffinitySwapChain::GetCurrentBackBufferIndex()\r\n{\r\n    return mCurrentBackBufferIndex;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::CheckColorSpaceSupport(\r\n    DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n    UINT* pColorSpaceSupport,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetColorSpace1(\r\n    DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain3* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetColorSpace1(ColorSpace);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetColorSpace1(ColorSpace);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::ResizeBuffers1(\r\n    UINT BufferCount,\r\n    UINT Width,\r\n    UINT Height,\r\n    DXGI_FORMAT Format,\r\n    UINT SwapChainFlags,\r\n    const UINT* pCreationNodeMask,\r\n    IUnknown* const* ppPresentQueue)\r\n{\r\n    HRESULT_METHOD_NOT_YET_IMPLEMENTED(CDXGIAffinitySwapChain::ResizeBuffers1);\r\n}\r\n\r\nCDXGIAffinitySwapChain::CDXGIAffinitySwapChain(CD3DX12AffinityDevice* device, CD3DX12AffinityCommandQueue* queue, IDXGISwapChain3** swapChains, UINT Count)\r\n    : CD3DX12AffinityObject(device, reinterpret_cast<IUnknown**>(swapChains), Count)\r\n    , mCurrentBackBufferIndex(0)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mSwapChains[i] = swapChains[i];\r\n        }\r\n        else\r\n        {\r\n            mSwapChains[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"SwapChain\";\r\n#endif\r\n    mParentQueue = queue;\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n    UINT const Index,\r\n    CD3DX12AffinityDevice* AffinityDevice,\r\n    ID3D12Device* const HostDevice,\r\n    CDXGIAffinitySwapChain::SDeviceContext& DeviceContext,\r\n    UINT const Width,\r\n    UINT const Height,\r\n    DXGI_FORMAT const Format,\r\n    UINT const NumBackBuffers)\r\n{\r\n    for (UINT b = 0; b < NumBackBuffers; ++b)\r\n    {\r\n        // Create the render target itself.\r\n\r\n        ID3D12Resource* RenderTarget = nullptr;\r\n\r\n        CD3DX12_HEAP_PROPERTIES renderTargetHeapProps(D3D12_HEAP_TYPE_DEFAULT);\r\n        if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA)\r\n        {\r\n            renderTargetHeapProps.CreationNodeMask = AffinityDevice->AffinityIndexToNodeMask(Index);\r\n            renderTargetHeapProps.VisibleNodeMask = AffinityDevice->LDAAllNodeMasks();\r\n        }\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateCommittedResource(\r\n                &renderTargetHeapProps,\r\n                D3D12_HEAP_FLAG_NONE,\r\n                &CD3DX12_RESOURCE_DESC::Tex2D(\r\n                    Format,\r\n                    Width,\r\n                    Height,\r\n                    1, 1,\r\n                    1, 0,\r\n                    D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,\r\n                    D3D12_TEXTURE_LAYOUT_UNKNOWN),\r\n                D3D12_RESOURCE_STATE_COMMON,\r\n                nullptr,\r\n                IID_PPV_ARGS(&RenderTarget)\r\n            ),\r\n            \"Failed to create render target committed resource during affinity swap chain setup.\", AffinityDevice);\r\n        WCHAR name[256] = {};\r\n        swprintf_s(name, L\"SwapChain RenderTarget: %u\", b);\r\n        RenderTarget->SetName(name);\r\n        DeviceContext.mRenderTargets.push_back(RenderTarget);\r\n\r\n        // Next create a heap for the cross adapter copy.\r\n\r\n        ID3D12Resource* CrossAdapterCopyResource = nullptr;\r\n        ID3D12Heap* CrossAdapterCopyBufferHeap = nullptr;\r\n\r\n        CD3DX12_RESOURCE_DESC const ResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(\r\n            Format,\r\n            Width,\r\n            Height,\r\n            1, 1,\r\n            1, 0,\r\n            D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER,\r\n            D3D12_TEXTURE_LAYOUT_ROW_MAJOR);\r\n\r\n        D3D12_RESOURCE_ALLOCATION_INFO const AllocationInfo = DeviceContext.mDevice->GetResourceAllocationInfo(\r\n            0,\r\n            1, &ResourceDesc);\r\n        CD3DX12_HEAP_DESC heapDesc(AllocationInfo.SizeInBytes, D3D12_HEAP_TYPE_DEFAULT, 0, D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER);\r\n        if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA)\r\n        {\r\n            heapDesc.Properties.CreationNodeMask = AffinityDevice->AffinityIndexToNodeMask(Index);\r\n            heapDesc.Properties.VisibleNodeMask = AffinityDevice->LDAAllNodeMasks();\r\n        }\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateHeap(\r\n                &heapDesc,\r\n                IID_PPV_ARGS(&CrossAdapterCopyBufferHeap)),\r\n            \"Failed to create cross-adapter heap during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        DeviceContext.mCrossAdapterCopyBufferHeaps.push_back(CrossAdapterCopyBufferHeap);\r\n\r\n        // Create a placed resource with that heap on the current device.\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreatePlacedResource(\r\n                CrossAdapterCopyBufferHeap, 0,\r\n                &ResourceDesc,\r\n                D3D12_RESOURCE_STATE_COMMON,\r\n                nullptr,\r\n                IID_PPV_ARGS(&CrossAdapterCopyResource)\r\n            ),\r\n            \"Failed to create cross-adapter placed resource during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        std::wstring Name = std::wstring(L\"CrossAdapterCopyBuffer\") + std::to_wstring(Index) + L\"-\" + std::to_wstring(b);\r\n        CrossAdapterCopyResource->SetName(Name.c_str());\r\n        DeviceContext.mCrossAdapterCopyBuffers.push_back(CrossAdapterCopyResource);\r\n\r\n        // Now open the heap up on the host device.\r\n\r\n        HANDLE CrossAdapterCopyBufferSharedHandle = nullptr;\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateSharedHandle(\r\n                CrossAdapterCopyBufferHeap,\r\n                nullptr,\r\n                GENERIC_ALL,\r\n                nullptr,\r\n                &CrossAdapterCopyBufferSharedHandle),\r\n            \"Failed to create shared handle to cross-adapter copy buffer heap during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        CrossAdapterCopyBufferHeap = nullptr;\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            HostDevice->OpenSharedHandle(CrossAdapterCopyBufferSharedHandle, IID_PPV_ARGS(&CrossAdapterCopyBufferHeap)),\r\n            \"Failed to open shared handle to cross-adapter copy buffer heap during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        DeviceContext.mCrossAdapterCopyBufferHeapsOnHost.push_back(CrossAdapterCopyBufferHeap);\r\n\r\n        // And finally use that heap to create placed resource on the host device.\r\n\r\n        CrossAdapterCopyResource = nullptr;\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            HostDevice->CreatePlacedResource(\r\n                CrossAdapterCopyBufferHeap, 0,\r\n                &CD3DX12_RESOURCE_DESC::Tex2D(\r\n                    Format,\r\n                    Width,\r\n                    Height,\r\n                    1, 1,\r\n                    1, 0,\r\n                    D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER,\r\n                    D3D12_TEXTURE_LAYOUT_ROW_MAJOR),\r\n                D3D12_RESOURCE_STATE_COMMON,\r\n                nullptr,\r\n                IID_PPV_ARGS(&CrossAdapterCopyResource)),\r\n            \"Failed to create cross-adapter placed resource on host device during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        CrossAdapterCopyResource->SetName(L\"CrossAdapterCopyBufferOnHost\");\r\n        DeviceContext.mCrossAdapterCopyBuffersOnHost.push_back(CrossAdapterCopyResource);\r\n\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/CDXGIAffinitySwapChain.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityObject.h\"\r\n\r\n#include <dxgi1_4.h>\r\n\r\ninline UINT gcd(UINT a, UINT b)\r\n{\r\n    for (;;)\r\n    {\r\n        if (a == 0) return b;\r\n        b %= a;\r\n        if (b == 0) return a;\r\n        a %= b;\r\n    }\r\n}\r\n\r\ninline UINT lcm(UINT a, UINT b)\r\n{\r\n    UINT temp = gcd(a, b);\r\n\r\n    return temp ? (a / temp * b) : 0;\r\n}\r\n\r\nenum EAffinitySwapChainMode\r\n{\r\n    SingleWindow,\r\n    MultiWindow,\r\n    LDA\r\n};\r\n\r\n// Implements up to IDXGISwapChain3.\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CDXGIAffinitySwapChain : public CD3DX12AffinityObject\r\n{\r\npublic:\r\n    virtual HRESULT QueryInterface(CDXGIAffinitySwapChain** ppvObject)\r\n    {\r\n        *ppvObject = this;\r\n        AddRef();\r\n        return S_OK;\r\n    }\r\n\r\n    HRESULT STDMETHODCALLTYPE GetParent(\r\n        _In_  REFIID riid,\r\n        _COM_Outptr_  void** ppParent,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE Present(\r\n        UINT SyncInterval,\r\n        UINT Flags,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetBuffer(\r\n        UINT Buffer,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppSurface,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetFullscreenState(\r\n        BOOL Fullscreen,\r\n        _In_opt_  IDXGIOutput* pTarget,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetFullscreenState(\r\n        _Out_opt_  BOOL* pFullscreen,\r\n        _COM_Outptr_opt_result_maybenull_  IDXGIOutput** ppTarget,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDesc(\r\n        _Out_  DXGI_SWAP_CHAIN_DESC* pDesc,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE ResizeBuffers(\r\n        UINT BufferCount,\r\n        UINT Width,\r\n        UINT Height,\r\n        DXGI_FORMAT NewFormat,\r\n        UINT SwapChainFlags,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE ResizeTarget(\r\n        _In_  const DXGI_MODE_DESC* pNewTargetParameters,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetContainingOutput(\r\n        _COM_Outptr_  IDXGIOutput** ppOutput,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetFrameStatistics(\r\n        _Out_  DXGI_FRAME_STATISTICS* pStats,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetLastPresentCount(\r\n        _Out_  UINT* pLastPresentCount,\r\n        UINT AffinityIndex = 0);\r\n\r\n    // IDXGISwapChain1\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDesc1(\r\n        _Out_  DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetFullscreenDesc(\r\n        _Out_  DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetHwnd(\r\n        _Out_  HWND* pHwnd,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetCoreWindow(\r\n        _In_  REFIID refiid,\r\n        _COM_Outptr_  void** ppUnk,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE Present1(\r\n        UINT SyncInterval,\r\n        UINT PresentFlags,\r\n        _In_  const DXGI_PRESENT_PARAMETERS* pPresentParameters,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported(UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetRestrictToOutput(\r\n        _Out_  IDXGIOutput** ppRestrictToOutput,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetBackgroundColor(\r\n        _In_  const DXGI_RGBA* pColor,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetBackgroundColor(\r\n        _Out_  DXGI_RGBA* pColor,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetRotation(\r\n        _In_  DXGI_MODE_ROTATION Rotation,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetRotation(\r\n        _Out_  DXGI_MODE_ROTATION* pRotation,\r\n        UINT AffinityIndex = 0);\r\n\r\n    // IDXGISwapChain2\r\n\r\n    HRESULT STDMETHODCALLTYPE SetSourceSize(\r\n        UINT Width,\r\n        UINT Height,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetSourceSize(\r\n        _Out_  UINT* pWidth,\r\n        _Out_  UINT* pHeight,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(\r\n        UINT MaxLatency,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(\r\n        _Out_  UINT* pMaxLatency,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject(\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetMatrixTransform(\r\n        const DXGI_MATRIX_3X2_F* pMatrix,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetMatrixTransform(\r\n        _Out_  DXGI_MATRIX_3X2_F* pMatrix,\r\n        UINT AffinityIndex = 0);\r\n\r\n    // IDXGISwapChain3\r\n\r\n    UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex();\r\n\r\n    HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport(\r\n        _In_  DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n        _Out_  UINT* pColorSpaceSupport,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetColorSpace1(\r\n        _In_  DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE ResizeBuffers1(\r\n        _In_  UINT BufferCount,\r\n        _In_  UINT Width,\r\n        _In_  UINT Height,\r\n        _In_  DXGI_FORMAT Format,\r\n        _In_  UINT SwapChainFlags,\r\n        _In_reads_(BufferCount)  const UINT* pCreationNodeMask,\r\n        _In_reads_(BufferCount)  IUnknown* const* ppPresentQueue);\r\n\r\n    CDXGIAffinitySwapChain(CD3DX12AffinityDevice* device, CD3DX12AffinityCommandQueue* queue, IDXGISwapChain3** swapChains, UINT Count);\r\n\r\n    struct SDeviceContext\r\n    {\r\n        std::vector<ID3D12Resource*> mRenderTargets;\r\n        std::vector<ID3D12Resource*> mCrossAdapterCopyBuffers;\r\n        std::vector<ID3D12Heap*> mCrossAdapterCopyBufferHeaps;\r\n        std::vector<ID3D12Resource*> mCrossAdapterCopyBuffersOnHost;\r\n        std::vector<ID3D12Heap*> mCrossAdapterCopyBufferHeapsOnHost;\r\n        ID3D12Fence* mCrossAdapterCopyFence;\r\n        ID3D12Fence* mCrossAdapterCopyFenceOnHost;\r\n\r\n        ID3D12CommandQueue* mDisplayCommandQueue;\r\n        ID3D12CommandAllocator* mDisplayCommandAllocator;\r\n        ID3D12GraphicsCommandList* mDisplayCommandList;\r\n\r\n        UINT mFenceValue;\r\n        ID3D12Device* mDevice;\r\n\r\n        SDeviceContext()\r\n        {\r\n            mCrossAdapterCopyFence = nullptr;\r\n            mCrossAdapterCopyFenceOnHost = nullptr;\r\n\r\n            mDisplayCommandQueue = nullptr;\r\n            mDisplayCommandAllocator = nullptr;\r\n            mDisplayCommandList = nullptr;\r\n\r\n            mFenceValue = 0;\r\n            mDevice = nullptr;\r\n        }\r\n    };\r\n\r\n    static HRESULT CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n        UINT const Index,\r\n        CD3DX12AffinityDevice* AffinityDevice,\r\n        ID3D12Device* const HostDevice,\r\n        CDXGIAffinitySwapChain::SDeviceContext& DeviceContext,\r\n        UINT const Width,\r\n        UINT const Height,\r\n        DXGI_FORMAT const Format,\r\n        UINT const NumBackBuffers);\r\n\r\n    CD3DX12AffinityCommandQueue* mParentQueue;\r\n    std::vector<SDeviceContext> mDeviceContexts;\r\n\r\n    UINT mCurrentBackBufferIndex;\r\n    UINT mNumBackBuffers;\r\n    UINT mNumRequestedBackBuffers;\r\n    EAffinitySwapChainMode mMode;\r\n\r\n    ID3D12Device* mHostDevice;\r\n\r\nprotected:\r\n    virtual bool IsD3D()\r\n    {\r\n        return false;\r\n    }\r\n\r\nprivate:\r\n    IDXGISwapChain3* mSwapChains[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/D3DX12AffinityCreateMultiDevice.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This is the standard (only) method for creating a D3DX12 Affinity device. It takes\r\n * an array of ID3D12Devices and does some very minimal setup.\r\n */\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT WINAPI D3DX12AffinityCreateLDADevice(\r\n    ID3D12Device* Device,\r\n    CD3DX12AffinityDevice** ppDevice)\r\n{\r\n\r\n    CD3DX12AffinityDevice* Instance = new CD3DX12AffinityDevice(&Device, 1, EAffinityMode::LDA);\r\n    Device->AddRef();\r\n\r\n#ifdef DEBUG\r\n    ID3D12Debug* debugController = nullptr;\r\n    if (!CD3DX12AffinityDevice::InfoQueue && SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))\r\n    {\r\n        ID3D12InfoQueue* infoQueue = nullptr;\r\n        if (SUCCEEDED(debugController->QueryInterface(IID_PPV_ARGS(&infoQueue))))\r\n        {\r\n            CD3DX12AffinityDevice::InfoQueue = infoQueue;\r\n        }\r\n    }\r\n#endif\r\n\r\n    (*ppDevice) = Instance;\r\n    return S_OK;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/D3DX12AffinityLayer.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{B2283BA1-603B-4360-AE99-7A3F5912BC42}</ProjectGuid>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <RootNamespace>D3DX12AffinityLayer</RootNamespace>\r\n    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"Shared\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandAllocator.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityCommandList.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityCommandQueue.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityCommandSignature.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityDescriptorHeap.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityDevice.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityDeviceChild.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityFence.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityGraphicsCommandList.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityHeap.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityObject.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityPageable.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityPipelineState.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityQueryHeap.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityResource.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityRootSignature.h\" />\r\n    <ClInclude Include=\"CDXGIAffinitySwapChain.h\" />\r\n    <ClInclude Include=\"d3dx12.h\" />\r\n    <ClInclude Include=\"d3dx12affinity.h\" />\r\n    <ClInclude Include=\"d3dx12affinity_d3dx12.h\" />\r\n    <ClInclude Include=\"d3dx12affinity_structs.h\" />\r\n    <ClInclude Include=\"Utils.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandAllocator.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityCommandList.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityCommandQueue.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityCommandSignature.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityDescriptorHeap.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityDevice.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityDeviceChild.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityFence.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityGraphicsCommandList.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityHeap.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityObject.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityPageable.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityPipelineState.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityQueryHeap.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityResource.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityRootSignature.cpp\" />\r\n    <ClCompile Include=\"CDXGIAffinitySwapChain.cpp\" />\r\n    <ClCompile Include=\"d3dx12affinity.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3DX12AffinityCreateMultiDevice.cpp\" />\r\n    <ClCompile Include=\"DXGIXAffinityCreateLDASwapChain.cpp\" />\r\n    <ClCompile Include=\"DXGIXAffinityCreateSingleWindowSwapChain.cpp\" />\r\n    <ClCompile Include=\"Utils.cpp\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/D3DX12AffinityLayer.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Header Files\">\r\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandAllocator.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandList.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandQueue.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandSignature.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityDescriptorHeap.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityDevice.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityDeviceChild.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityFence.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityGraphicsCommandList.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityHeap.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityObject.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityPageable.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityPipelineState.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityQueryHeap.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityResource.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityRootSignature.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CDXGIAffinitySwapChain.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3DX12AffinityCreateMultiDevice.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DXGIXAffinityCreateLDASwapChain.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DXGIXAffinityCreateSingleWindowSwapChain.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Utils.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"d3dx12affinity.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandAllocator.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandList.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandQueue.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandSignature.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityDescriptorHeap.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityDevice.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityDeviceChild.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityFence.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityGraphicsCommandList.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityHeap.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityObject.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityPageable.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityPipelineState.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityQueryHeap.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityResource.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityRootSignature.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CDXGIAffinitySwapChain.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12affinity.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12affinity_d3dx12.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12affinity_structs.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Utils.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/DXGIXAffinityCreateLDASwapChain.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include <dxgi1_2.h>\r\n#include <string>\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    IDXGISwapChain* pSwapChain,\r\n    CD3DX12AffinityCommandQueue* pQueue,\r\n    CD3DX12AffinityDevice* pDevice,\r\n    CDXGIAffinitySwapChain** ppSwapChain)\r\n{\r\n    IDXGISwapChain3* pSwapChain3;\r\n    if (SUCCEEDED(pSwapChain->QueryInterface(IID_PPV_ARGS(&pSwapChain3))))\r\n    {\r\n        DXGI_SWAP_CHAIN_DESC1 desc;\r\n        if (SUCCEEDED(pSwapChain3->GetDesc1(&desc)))\r\n        {\r\n            HRESULT hr = DXGIXAffinityCreateLDASwapChain(pSwapChain3, pQueue, pDevice, &desc, ppSwapChain);\r\n            pSwapChain3->Release();\r\n            return hr;\r\n        }\r\n    }\r\n    return E_FAIL;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    IDXGISwapChain3* pSwapChain,\r\n    CD3DX12AffinityCommandQueue* pQueue,\r\n    CD3DX12AffinityDevice* pDevice,\r\n    DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    CDXGIAffinitySwapChain** ppSwapChain)\r\n{\r\n    CD3DX12AffinityCommandQueue* AffinityQueue = static_cast<CD3DX12AffinityCommandQueue*>(pQueue);\r\n    CD3DX12AffinityDevice* AffinityDevice = static_cast<CD3DX12AffinityDevice*>(pDevice);\r\n    ID3D12Device* HostDevice = AffinityDevice->GetChildObject(0);\r\n\r\n    std::vector<CDXGIAffinitySwapChain::SDeviceContext> NodeContexts;\r\n    NodeContexts.reserve(AffinityDevice->GetNodeCount());\r\n\r\n    for (UINT i = 0; i < AffinityDevice->GetNodeCount(); ++i)\r\n    {\r\n        NodeContexts.push_back(CDXGIAffinitySwapChain::SDeviceContext());\r\n        CDXGIAffinitySwapChain::SDeviceContext& NodeContext = NodeContexts.back();\r\n\r\n        NodeContext.mDevice = AffinityDevice->GetChildObject(0); //single device in LDA case\r\n        NodeContext.mDisplayCommandQueue = AffinityQueue->GetChildObject(i);\r\n    }\r\n\r\n    CDXGIAffinitySwapChain* AffinityChain = new CDXGIAffinitySwapChain(AffinityDevice, AffinityQueue, &pSwapChain, 1);\r\n    AffinityChain->mMode = EAffinitySwapChainMode::LDA;\r\n\r\n    AffinityChain->mDeviceContexts = NodeContexts;\r\n    AffinityChain->mNumBackBuffers = lcm(pDesc->BufferCount, AffinityDevice->GetNodeCount());\r\n    AffinityChain->mNumRequestedBackBuffers = pDesc->BufferCount;\r\n    AffinityChain->mHostDevice = HostDevice;\r\n    *ppSwapChain = AffinityChain;\r\n\r\n    std::vector<IUnknown*> ppCommandQueues;\r\n    std::vector<UINT> pCreationNodes;\r\n    for (UINT i = 0; i < AffinityChain->mNumBackBuffers; ++i)\r\n    {\r\n        UINT node = i % AffinityDevice->GetNodeCount();\r\n        ppCommandQueues.push_back(AffinityQueue->GetChildObject(node));\r\n        pCreationNodes.push_back(AffinityDevice->AffinityIndexToNodeMask(node));\r\n    }\r\n\r\n    pSwapChain->AddRef();\r\n    const HRESULT hr = pSwapChain->ResizeBuffers1(AffinityChain->mNumBackBuffers, pDesc->Width, pDesc->Height, pDesc->Format, pDesc->Flags,\r\n        pCreationNodes.data(), ppCommandQueues.data());\r\n\r\n    return hr;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/DXGIXAffinityCreateSingleWindowSwapChain.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This is your standard \"SFR or AFR or SPR (split pipeline rendering)\" scenario where\r\n * there is just ONE actual swapchain and Present()s from any other adapter means we\r\n * have to copy the render target to the adapter which owns the actual swapchain.\r\n *\r\n * As such this method does a lot of the heavy lifting in terms of creating all the\r\n * resources and objects we need to perform that copy.\r\n */\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include <dxgi1_2.h>\r\n#include <string>\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateSingleWindowSwapChain(\r\n    IDXGISwapChain3* pSwapChain,\r\n    CD3DX12AffinityCommandQueue* pQueue,\r\n    CD3DX12AffinityDevice* pDevice,\r\n    DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    CDXGIAffinitySwapChain** ppSwapChain)\r\n{\r\n    CD3DX12AffinityCommandQueue* AffinityQueue = static_cast<CD3DX12AffinityCommandQueue*>(pQueue);\r\n    CD3DX12AffinityDevice* AffinityDevice = static_cast<CD3DX12AffinityDevice*>(pDevice);\r\n    ID3D12Device* HostDevice = AffinityDevice->GetChildObject(0);\r\n\r\n    std::vector<CDXGIAffinitySwapChain::SDeviceContext> DeviceContexts;\r\n    DeviceContexts.reserve(AffinityDevice->GetDeviceCount());\r\n\r\n    for (UINT i = 0; i < AffinityDevice->GetDeviceCount(); ++i)\r\n    {\r\n        DeviceContexts.push_back(CDXGIAffinitySwapChain::SDeviceContext());\r\n        CDXGIAffinitySwapChain::SDeviceContext& DeviceContext = DeviceContexts.back();\r\n\r\n        DeviceContext.mDevice = AffinityDevice->GetChildObject(i);\r\n        DeviceContext.mDisplayCommandQueue = AffinityQueue->GetChildObject(i);\r\n\r\n        // Each device needs a command list and respective command allocator.\r\n        // This list will be used for submitting resource barriers and copies from the \"dummy\" rendertarget.\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&DeviceContext.mDisplayCommandAllocator)),\r\n            \"Failed to create command allocator during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateCommandList(\r\n                0, D3D12_COMMAND_LIST_TYPE_DIRECT, DeviceContext.mDisplayCommandAllocator,\r\n                nullptr, IID_PPV_ARGS(&DeviceContext.mDisplayCommandList)),\r\n            \"Failed to create command list during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        // The device at index 0 is the \"host\" device, it uses it's own actual render targets\r\n        // and presents from this device occur in the usual fashion.\r\n        //\r\n        // For all devices index 1 and up, we need to create some fences and intermediate buffers\r\n        // to facilitate presents.\r\n\r\n        {\r\n            // Create the cross-adapter copy fence, used to control access to the cross-adapter copy buffer\r\n\r\n            RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n                DeviceContext.mDevice->CreateFence(\r\n                    0,\r\n                    D3D12_FENCE_FLAG_SHARED | D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER,\r\n                    IID_PPV_ARGS(&DeviceContext.mCrossAdapterCopyFence)),\r\n                \"Failed to create fence during affinity swap chain setup.\", AffinityDevice);\r\n\r\n            std::wstring Name = std::wstring(L\"CrossAdapterCopyFence\") + std::to_wstring(i);\r\n            RETURN_IF_FAILED(DeviceContext.mCrossAdapterCopyFence->SetName(Name.c_str()));\r\n\r\n            {\r\n                HANDLE CrossAdapterCopyFenceSharedHandle = nullptr;\r\n                RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n                    DeviceContext.mDevice->CreateSharedHandle(\r\n                        DeviceContext.mCrossAdapterCopyFence,\r\n                        nullptr,\r\n                        GENERIC_ALL,\r\n                        Name.c_str(),\r\n                        &CrossAdapterCopyFenceSharedHandle),\r\n                    \"Failed to create shared handle to cross adapter copy fence during affinity swap chain setup.\", AffinityDevice);\r\n\r\n                RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n                    HostDevice->OpenSharedHandle(CrossAdapterCopyFenceSharedHandle, IID_PPV_ARGS(&DeviceContext.mCrossAdapterCopyFenceOnHost)),\r\n                    \"Failed to open shared handle to cross adapter copy fence during affinity swap chain setup.\", AffinityDevice);\r\n\r\n                Name = std::wstring(L\"CrossAdapterCopyFenceOnHost\") + std::to_wstring(i);\r\n                RETURN_IF_FAILED(DeviceContext.mCrossAdapterCopyFenceOnHost->SetName(L\"CrossAdapterCopyFenceOnHost\"));\r\n            }\r\n            // Create the \"dummy\" render targets and cross-adapter copy buffers.\r\n            // For a swap chain with (n) back buffers, we create (n) render targets and (n) cross-adapter copy buffers.\r\n\r\n            DeviceContext.mRenderTargets.reserve(pDesc->BufferCount);\r\n            DeviceContext.mCrossAdapterCopyBuffers.reserve(pDesc->BufferCount);\r\n\r\n            RETURN_IF_FAILED(CDXGIAffinitySwapChain::CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n                i,\r\n                AffinityDevice,\r\n                HostDevice,\r\n                DeviceContext,\r\n                pDesc->Width,\r\n                pDesc->Height,\r\n                pDesc->Format,\r\n                pDesc->BufferCount\r\n            ));\r\n        }\r\n    }\r\n\r\n    pSwapChain->AddRef();\r\n\r\n    CDXGIAffinitySwapChain* AffinityChain = new CDXGIAffinitySwapChain(AffinityDevice, AffinityQueue, &pSwapChain, 1);\r\n    if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        AffinityChain->mMode = EAffinitySwapChainMode::LDA;\r\n    }\r\n    else\r\n    {\r\n        AffinityChain->mMode = EAffinitySwapChainMode::SingleWindow;\r\n    }\r\n\r\n    AffinityChain->mDeviceContexts = DeviceContexts;\r\n    AffinityChain->mNumBackBuffers = pDesc->BufferCount;\r\n    AffinityChain->mHostDevice = HostDevice;\r\n    *ppSwapChain = AffinityChain;\r\n\r\n    return S_OK;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/Utils.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\n#include <locale>\r\n#include <codecvt>\r\n#include <string>\r\n#include <comdef.h>\r\n\r\nvoid WriteHRESULTError(HRESULT const hr)\r\n{\r\n    _com_error err(hr, nullptr);\r\n    DebugLog(L\"HRESULT Failure: %d 0x%08X %s\\n\", hr, hr, std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(err.ErrorMessage()).c_str());\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/Utils.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This is a utility header with:\r\n * - Configuration macros\r\n * - Commonly used (STL) headers\r\n * - Logging/Assertion methods for debugging\r\n */\r\n\r\n#pragma once\r\n\r\n#include <stdio.h>\r\n#include <wtypes.h>\r\n\r\n////////////////////////////\r\n// CONFIG //////////////////\r\n////////////////////////////\r\n\r\n//#define D3DX12_DEBUG_CLEAR_WHITE\r\n\r\n// Max number of nodes(devices or lda nodes) useable by the affinity layer.\r\n// Note that it's fine to have less than this. You don't need to\r\n// recompile anything if you pull a GPU out of your system.\r\n#define D3DX12_MAX_ACTIVE_NODES 2\r\n\r\n// This mode allows catching bugs in the affinity layer itself\r\n// by running the recorder for n GPU nodes but execute on GPU0.\r\n//#define D3DX12_SIMULATE_LDA_ON_SINGLE_NODE 1\r\n\r\n// Insert a fence, wait and a check for device removed after every commandlist\r\n// useful for debugging the source command-list when a TDR occurs.\r\n//#define SERIALIZE_COMMNANDLIST_EXECUTION\r\n\r\n//#define SYNC_CROSS_FRAME_RESOURCES\r\n\r\n//#define DEBUG_OBJECT_NAME\r\n\r\n// On LDA devices, makes all buffers have a single GPUVA by either having a single\r\n// resource in system memory, or having a single reserved buffer mapped to separate\r\n// heaps on each GPU (via unicast page table mappings). Removes any GPUVA translation\r\n// overhead.\r\n#define TILE_MAPPING_GPUVA 1\r\n\r\n// Just a fun experiment to see what happens when all buffers are accessed from remote GPUs.\r\n//#define FORCE_REMOTE_TILE_MAPPING_GPUVA 1\r\n\r\n//#define ALWAYS_RESET_ALL_COMMAND_LISTS 1\r\n\r\n////////////////////////////\r\n// DEBUG CONFIG ////////////\r\n////////////////////////////\r\n\r\n// Logging options. (e.g. memory mapped, every ECL)\r\n//#define ENABLE_DEBUG_LOG 1\r\n//#define ENABLE_RELEASE_LOG 1\r\n//#define D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n\r\n// Instead of using GetWriteWatch, just upload ALL mapped data when unmapped or ECL.\r\n// This is mostly just used to prove how SLOW it is not to use GetWriteWatch.\r\n//#define DO_FULL_MAPPED_MEM_COPY\r\n\r\n////////////////////////////\r\n////////////////////////////\r\n\r\n#include <windows.h>\r\n#include <vector>\r\n#include <map>\r\n#include <set>\r\n#include <mutex>\r\n#include <cstdio>\r\n\r\nstruct EAffinityMask\r\n{\r\n    enum Mask\r\n    {\r\n        AllNodes = 0,\r\n        Node0 = 0x01,\r\n        Node1 = 0x02,\r\n        Node2 = 0x04,\r\n        Node3 = 0x08,\r\n        Node4 = 0x10,\r\n    };\r\n};\r\n\r\nstruct EAffinityMode\r\n{\r\n    enum Mask\r\n    {\r\n        LDA,\r\n    };\r\n};\r\n\r\nstruct EAffinityRenderingMode\r\n{\r\n    enum Mask\r\n    {\r\n        AFR,\r\n    };\r\n};\r\n\r\nvoid WriteHRESULTError(HRESULT const hr);\r\n\r\n#define RETURN_IF_FAILED(x) do { HRESULT const _hr_check = (x); if (S_OK != _hr_check) { WriteHRESULTError(_hr_check); return _hr_check; } } while (false);\r\n#define RETURN_IF_FAILED_WITH_ERROR_LOG(x, y, z) do { HRESULT const _hr_check = (x); if (S_OK != _hr_check) { WriteHRESULTError(_hr_check); z->WriteApplicationMessage(D3D12_MESSAGE_SEVERITY_ERROR, (y)); return _hr_check; } } while (false);\r\n\r\n#ifdef DEBUG\r\n\r\n#include <cassert>\r\n\r\n#define METHOD_NOT_YET_IMPLEMENTED(x) _wassert(L\"Method not yet implemented: \" L ## #x, L\"\", 0);\r\n#define HRESULT_METHOD_NOT_YET_IMPLEMENTED(x) _wassert(L\"Method not yet implemented: \" L ## #x, L\"\", 0); return E_NOTIMPL;\r\n#define DEBUG_ASSERT(x) assert((x));\r\n#define DEBUG_FAIL_MESSAGE(x) _wassert((x), L\"\", 0);\r\n\r\n#else\r\n\r\n#define METHOD_NOT_YET_IMPLEMENTED(x)\r\n#define HRESULT_METHOD_NOT_YET_IMPLEMENTED(x) return S_FALSE;\r\n#define DEBUG_ASSERT(x)\r\n#define DEBUG_FAIL_MESSAGE(x)\r\n\r\n#endif\r\n\r\n// Thread_local is only available in C++11, so if we're compiling under VS 2012 we need\r\n// to define it.\r\n#if _MSC_VER == 1700\r\n#define thread_local __declspec(thread)\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////////////////\r\n// See http://stackoverflow.com/a/8712996\r\n\r\n#if defined(_MSC_VER) && _MSC_VER < 1900\r\n\r\n#define snprintf c99_snprintf\r\n#define vsnprintf c99_vsnprintf\r\n\r\ninline int c99_vsnprintf(char* outBuf, size_t size, const char* format, va_list ap)\r\n{\r\n    int count = -1;\r\n\r\n    if (size != 0)\r\n        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);\r\n    if (count == -1)\r\n        count = _vscprintf(format, ap);\r\n\r\n    return count;\r\n}\r\n\r\ninline int c99_snprintf(char* outBuf, size_t size, const char* format, ...)\r\n{\r\n    int count;\r\n    va_list ap;\r\n\r\n    va_start(ap, format);\r\n    count = c99_vsnprintf(outBuf, size, format, ap);\r\n    va_end(ap);\r\n\r\n    return count;\r\n}\r\n\r\n#endif\r\n\r\n// End code borrowed from StackOverflow\r\n///////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\ninline void DebugLog(wchar_t const* const Format, ...)\r\n{\r\n#ifdef ENABLE_DEBUG_LOG\r\n    static int const BufferSize = 65536;\r\n    static wchar_t* WideBuffer = nullptr;\r\n\r\n    if (!WideBuffer)\r\n    {\r\n        WideBuffer = new wchar_t[BufferSize];\r\n    }\r\n\r\n    va_list Args;\r\n    va_start(Args, Format);\r\n    _vsnwprintf_s(WideBuffer, BufferSize, BufferSize - 1, Format, Args);\r\n    va_end(Args);\r\n\r\n    OutputDebugString(WideBuffer);\r\n#endif\r\n}\r\n\r\ninline void ReleaseLog(wchar_t const* const Format, ...)\r\n{\r\n#ifdef ENABLE_RELEASE_LOG\r\n    static int const BufferSize = 65536;\r\n    static wchar_t* WideBuffer = nullptr;\r\n\r\n    if (!WideBuffer)\r\n    {\r\n        WideBuffer = new wchar_t[BufferSize];\r\n    }\r\n\r\n    va_list Args;\r\n    va_start(Args, Format);\r\n    //_vsnwprintf(WideBuffer, BufferSize, Format, Args);\r\n    _vsnwprintf_s(WideBuffer, BufferSize, BufferSize, Format, Args);\r\n    va_end(Args);\r\n\r\n    OutputDebugString(WideBuffer);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#ifndef __D3DX12_H__\r\n#define __D3DX12_H__\r\n\r\n#include \"d3d12.h\"\r\n\r\n#if defined( __cplusplus )\r\n\r\nstruct CD3DX12_DEFAULT {};\r\nextern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT;\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{\r\n    return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width &&\r\n        l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RECT : public D3D12_RECT\r\n{\r\n    CD3DX12_RECT()\r\n    {}\r\n    explicit CD3DX12_RECT( const D3D12_RECT& o ) :\r\n        D3D12_RECT( o )\r\n    {}\r\n    explicit CD3DX12_RECT(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        right = Right;\r\n        bottom = Bottom;\r\n    }\r\n    ~CD3DX12_RECT() {}\r\n    operator const D3D12_RECT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VIEWPORT : public D3D12_VIEWPORT\r\n{\r\n    CD3DX12_VIEWPORT()\r\n    {}\r\n    explicit CD3DX12_VIEWPORT( const D3D12_VIEWPORT& o ) :\r\n        D3D12_VIEWPORT( o )\r\n    {}\r\n    explicit CD3DX12_VIEWPORT(\r\n        FLOAT topLeftX,\r\n        FLOAT topLeftY,\r\n        FLOAT width,\r\n        FLOAT height,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        TopLeftX = topLeftX;\r\n        TopLeftY = topLeftY;\r\n        Width = width;\r\n        Height = height;\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    explicit CD3DX12_VIEWPORT(\r\n        _In_ ID3D12Resource* pResource,\r\n        UINT mipSlice = 0,\r\n        FLOAT topLeftX = 0.0f,\r\n        FLOAT topLeftY = 0.0f,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        D3D12_RESOURCE_DESC Desc = pResource->GetDesc();\r\n        const UINT64 SubresourceWidth = Desc.Width >> mipSlice;\r\n        const UINT64 SubresourceHeight = Desc.Height >> mipSlice;\r\n        switch (Desc.Dimension)\r\n        {\r\n        case D3D12_RESOURCE_DIMENSION_BUFFER:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = Desc.Width - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = topLeftY;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = (SubresourceHeight ? SubresourceHeight: 1.0f) - topLeftY;\r\n            break;\r\n        default: break;\r\n        }\r\n\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    ~CD3DX12_VIEWPORT() {}\r\n    operator const D3D12_VIEWPORT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BOX : public D3D12_BOX\r\n{\r\n    CD3DX12_BOX()\r\n    {}\r\n    explicit CD3DX12_BOX( const D3D12_BOX& o ) :\r\n        D3D12_BOX( o )\r\n    {}\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Right )\r\n    {\r\n        left = Left;\r\n        top = 0;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = 1;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Front,\r\n        LONG Right,\r\n        LONG Bottom,\r\n        LONG Back )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = Front;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = Back;\r\n    }\r\n    ~CD3DX12_BOX() {}\r\n    operator const D3D12_BOX&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{\r\n    return l.left == r.left && l.top == r.top && l.front == r.front &&\r\n        l.right == r.right && l.bottom == r.bottom && l.back == r.back;\r\n}\r\ninline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC1 : public D3D12_DEPTH_STENCIL_DESC1\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC1()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC1& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC1( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC& o )\r\n    {\r\n        DepthEnable                  = o.DepthEnable;\r\n        DepthWriteMask               = o.DepthWriteMask;\r\n        DepthFunc                    = o.DepthFunc;\r\n        StencilEnable                = o.StencilEnable;\r\n        StencilReadMask              = o.StencilReadMask;\r\n        StencilWriteMask             = o.StencilWriteMask;\r\n        FrontFace.StencilFailOp      = o.FrontFace.StencilFailOp;\r\n        FrontFace.StencilDepthFailOp = o.FrontFace.StencilDepthFailOp;\r\n        FrontFace.StencilPassOp      = o.FrontFace.StencilPassOp;\r\n        FrontFace.StencilFunc        = o.FrontFace.StencilFunc;\r\n        BackFace.StencilFailOp       = o.BackFace.StencilFailOp;\r\n        BackFace.StencilDepthFailOp  = o.BackFace.StencilDepthFailOp;\r\n        BackFace.StencilPassOp       = o.BackFace.StencilPassOp;\r\n        BackFace.StencilFunc         = o.BackFace.StencilFunc;\r\n        DepthBoundsTestEnable        = FALSE;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n        DepthBoundsTestEnable = FALSE;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc,\r\n        BOOL depthBoundsTestEnable )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n        DepthBoundsTestEnable = depthBoundsTestEnable;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC1() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC1&() const { return *this; }\r\n    operator const D3D12_DEPTH_STENCIL_DESC() const\r\n    {\r\n        D3D12_DEPTH_STENCIL_DESC D;\r\n        D.DepthEnable                  = DepthEnable;\r\n        D.DepthWriteMask               = DepthWriteMask;\r\n        D.DepthFunc                    = DepthFunc;\r\n        D.StencilEnable                = StencilEnable;\r\n        D.StencilReadMask              = StencilReadMask;\r\n        D.StencilWriteMask             = StencilWriteMask;\r\n        D.FrontFace.StencilFailOp      = FrontFace.StencilFailOp;\r\n        D.FrontFace.StencilDepthFailOp = FrontFace.StencilDepthFailOp;\r\n        D.FrontFace.StencilPassOp      = FrontFace.StencilPassOp;\r\n        D.FrontFace.StencilFunc        = FrontFace.StencilFunc;\r\n        D.BackFace.StencilFailOp       = BackFace.StencilFailOp;\r\n        D.BackFace.StencilDepthFailOp  = BackFace.StencilDepthFailOp;\r\n        D.BackFace.StencilPassOp       = BackFace.StencilPassOp;\r\n        D.BackFace.StencilFunc         = BackFace.StencilFunc;\r\n        return D;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC\r\n{\r\n    CD3DX12_BLEND_DESC()\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) :\r\n        D3D12_BLEND_DESC( o )\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        AlphaToCoverageEnable = FALSE;\r\n        IndependentBlendEnable = FALSE;\r\n        const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =\r\n        {\r\n            FALSE,FALSE,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_LOGIC_OP_NOOP,\r\n            D3D12_COLOR_WRITE_ENABLE_ALL,\r\n        };\r\n        for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)\r\n            RenderTarget[ i ] = defaultRenderTargetBlendDesc;\r\n    }\r\n    ~CD3DX12_BLEND_DESC() {}\r\n    operator const D3D12_BLEND_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC\r\n{\r\n    CD3DX12_RASTERIZER_DESC()\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) :\r\n        D3D12_RASTERIZER_DESC( o )\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        FillMode = D3D12_FILL_MODE_SOLID;\r\n        CullMode = D3D12_CULL_MODE_BACK;\r\n        FrontCounterClockwise = FALSE;\r\n        DepthBias = D3D12_DEFAULT_DEPTH_BIAS;\r\n        DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;\r\n        SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;\r\n        DepthClipEnable = TRUE;\r\n        MultisampleEnable = FALSE;\r\n        AntialiasedLineEnable = FALSE;\r\n        ForcedSampleCount = 0;\r\n        ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;\r\n    }\r\n    explicit CD3DX12_RASTERIZER_DESC(\r\n        D3D12_FILL_MODE fillMode,\r\n        D3D12_CULL_MODE cullMode,\r\n        BOOL frontCounterClockwise,\r\n        INT depthBias,\r\n        FLOAT depthBiasClamp,\r\n        FLOAT slopeScaledDepthBias,\r\n        BOOL depthClipEnable,\r\n        BOOL multisampleEnable,\r\n        BOOL antialiasedLineEnable, \r\n        UINT forcedSampleCount, \r\n        D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster)\r\n    {\r\n        FillMode = fillMode;\r\n        CullMode = cullMode;\r\n        FrontCounterClockwise = frontCounterClockwise;\r\n        DepthBias = depthBias;\r\n        DepthBiasClamp = depthBiasClamp;\r\n        SlopeScaledDepthBias = slopeScaledDepthBias;\r\n        DepthClipEnable = depthClipEnable;\r\n        MultisampleEnable = multisampleEnable;\r\n        AntialiasedLineEnable = antialiasedLineEnable;\r\n        ForcedSampleCount = forcedSampleCount;\r\n        ConservativeRaster = conservativeRaster;\r\n    }\r\n    ~CD3DX12_RASTERIZER_DESC() {}\r\n    operator const D3D12_RASTERIZER_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO\r\n{\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) :\r\n        D3D12_RESOURCE_ALLOCATION_INFO( o )\r\n    {}\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO(\r\n        UINT64 size,\r\n        UINT64 alignment )\r\n    {\r\n        SizeInBytes = size;\r\n        Alignment = alignment;\r\n    }\r\n    operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES\r\n{\r\n    CD3DX12_HEAP_PROPERTIES()\r\n    {}\r\n    explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) :\r\n        D3D12_HEAP_PROPERTIES(o)\r\n    {}\r\n    CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference,\r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = D3D12_HEAP_TYPE_CUSTOM;\r\n        CPUPageProperty = cpuPageProperty;\r\n        MemoryPoolPreference = memoryPoolPreference;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    explicit CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_HEAP_TYPE type, \r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = type;\r\n        CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n        MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    operator const D3D12_HEAP_PROPERTIES&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    {\r\n        return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&\r\n            (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));\r\n    }\r\n};\r\ninline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{\r\n    return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && \r\n        l.MemoryPoolPreference == r.MemoryPoolPreference &&\r\n        l.CreationNodeMask == r.CreationNodeMask &&\r\n        l.VisibleNodeMask == r.VisibleNodeMask;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC\r\n{\r\n    CD3DX12_HEAP_DESC()\r\n    {}\r\n    explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) :\r\n        D3D12_HEAP_DESC(o)\r\n    {}\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_PROPERTIES properties, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = properties;\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_TYPE type, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_PROPERTIES properties, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = properties;\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_TYPE type, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    operator const D3D12_HEAP_DESC&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }\r\n};\r\ninline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{\r\n    return l.SizeInBytes == r.SizeInBytes &&\r\n        l.Properties == r.Properties && \r\n        l.Alignment == r.Alignment &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE\r\n{\r\n    CD3DX12_CLEAR_VALUE()\r\n    {}\r\n    explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) :\r\n        D3D12_CLEAR_VALUE(o)\r\n    {}\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        const FLOAT color[4] )\r\n    {\r\n        Format = format;\r\n        memcpy( Color, color, sizeof( Color ) );\r\n    }\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        FLOAT depth,\r\n        UINT8 stencil )\r\n    {\r\n        Format = format;\r\n        /* Use memcpy to preserve NAN values */\r\n        memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );\r\n        DepthStencil.Stencil = stencil;\r\n    }\r\n    operator const D3D12_CLEAR_VALUE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE : public D3D12_RANGE\r\n{\r\n    CD3DX12_RANGE()\r\n    {}\r\n    explicit CD3DX12_RANGE(const D3D12_RANGE &o) :\r\n        D3D12_RANGE(o)\r\n    {}\r\n    CD3DX12_RANGE( \r\n        SIZE_T begin, \r\n        SIZE_T end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE_UINT64 : public D3D12_RANGE_UINT64\r\n{\r\n    CD3DX12_RANGE_UINT64()\r\n    {}\r\n    explicit CD3DX12_RANGE_UINT64(const D3D12_RANGE_UINT64 &o) :\r\n        D3D12_RANGE_UINT64(o)\r\n    {}\r\n    CD3DX12_RANGE_UINT64( \r\n        UINT64 begin, \r\n        UINT64 end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE_UINT64&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_RANGE_UINT64 : public D3D12_SUBRESOURCE_RANGE_UINT64\r\n{\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_RANGE_UINT64(const D3D12_SUBRESOURCE_RANGE_UINT64 &o) :\r\n        D3D12_SUBRESOURCE_RANGE_UINT64(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64( \r\n        UINT subresource,\r\n        const D3D12_RANGE_UINT64& range )\r\n    {\r\n        Subresource = subresource;\r\n        Range = range;\r\n    }\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64( \r\n        UINT subresource,\r\n        UINT64 begin, \r\n        UINT64 end )\r\n    {\r\n        Subresource = subresource;\r\n        Range.Begin = begin;\r\n        Range.End = end;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_RANGE_UINT64&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE\r\n{\r\n    CD3DX12_SHADER_BYTECODE()\r\n    {}\r\n    explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) :\r\n        D3D12_SHADER_BYTECODE(o)\r\n    {}\r\n    CD3DX12_SHADER_BYTECODE(\r\n        _In_ ID3DBlob* pShaderBlob )\r\n    {\r\n        pShaderBytecode = pShaderBlob->GetBufferPointer();\r\n        BytecodeLength = pShaderBlob->GetBufferSize();\r\n    }\r\n    CD3DX12_SHADER_BYTECODE(\r\n        const void* _pShaderBytecode,\r\n        SIZE_T bytecodeLength )\r\n    {\r\n        pShaderBytecode = _pShaderBytecode;\r\n        BytecodeLength = bytecodeLength;\r\n    }\r\n    operator const D3D12_SHADER_BYTECODE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE\r\n{\r\n    CD3DX12_TILED_RESOURCE_COORDINATE()\r\n    {}\r\n    explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) :\r\n        D3D12_TILED_RESOURCE_COORDINATE(o)\r\n    {}\r\n    CD3DX12_TILED_RESOURCE_COORDINATE( \r\n        UINT x, \r\n        UINT y, \r\n        UINT z, \r\n        UINT subresource ) \r\n    {\r\n        X = x;\r\n        Y = y;\r\n        Z = z;\r\n        Subresource = subresource;\r\n    }\r\n    operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE\r\n{\r\n    CD3DX12_TILE_REGION_SIZE()\r\n    {}\r\n    explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) :\r\n        D3D12_TILE_REGION_SIZE(o)\r\n    {}\r\n    CD3DX12_TILE_REGION_SIZE( \r\n        UINT numTiles, \r\n        BOOL useBox, \r\n        UINT width, \r\n        UINT16 height, \r\n        UINT16 depth ) \r\n    {\r\n        NumTiles = numTiles;\r\n        UseBox = useBox;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n    }\r\n    operator const D3D12_TILE_REGION_SIZE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING\r\n{\r\n    CD3DX12_SUBRESOURCE_TILING()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) :\r\n        D3D12_SUBRESOURCE_TILING(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_TILING( \r\n        UINT widthInTiles, \r\n        UINT16 heightInTiles, \r\n        UINT16 depthInTiles, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        WidthInTiles = widthInTiles;\r\n        HeightInTiles = heightInTiles;\r\n        DepthInTiles = depthInTiles;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE\r\n{\r\n    CD3DX12_TILE_SHAPE()\r\n    {}\r\n    explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) :\r\n        D3D12_TILE_SHAPE(o)\r\n    {}\r\n    CD3DX12_TILE_SHAPE( \r\n        UINT widthInTexels, \r\n        UINT heightInTexels, \r\n        UINT depthInTexels ) \r\n    {\r\n        WidthInTexels = widthInTexels;\r\n        HeightInTexels = heightInTexels;\r\n        DepthInTexels = depthInTexels;\r\n    }\r\n    operator const D3D12_TILE_SHAPE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) :\r\n        D3D12_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_RESOURCE_BARRIER Transition(\r\n        _In_ ID3D12Resource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER Aliasing(\r\n        _In_ ID3D12Resource* pResourceBefore,\r\n        _In_ ID3D12Resource* pResourceAfter)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER UAV(\r\n        _In_ ID3D12Resource* pResource)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3D12_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO\r\n{\r\n    CD3DX12_PACKED_MIP_INFO()\r\n    {}\r\n    explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) :\r\n        D3D12_PACKED_MIP_INFO(o)\r\n    {}\r\n    CD3DX12_PACKED_MIP_INFO( \r\n        UINT8 numStandardMips, \r\n        UINT8 numPackedMips, \r\n        UINT numTilesForPackedMips, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        NumStandardMips = numStandardMips;\r\n        NumPackedMips = numPackedMips;\r\n        NumTilesForPackedMips = numTilesForPackedMips;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_PACKED_MIP_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT\r\n{\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) :\r\n        D3D12_SUBRESOURCE_FOOTPRINT(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        DXGI_FORMAT format, \r\n        UINT width, \r\n        UINT height, \r\n        UINT depth, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = format;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n        RowPitch = rowPitch;\r\n    }\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        const D3D12_RESOURCE_DESC& resDesc, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = resDesc.Format;\r\n        Width = UINT( resDesc.Width );\r\n        Height = resDesc.Height;\r\n        Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);\r\n        RowPitch = rowPitch;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION\r\n{ \r\n    CD3DX12_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) :\r\n        D3D12_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n}; \r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) :\r\n        D3D12_DESCRIPTOR_RANGE(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS\r\n{\r\n    CD3DX12_ROOT_CONSTANTS() {}\r\n    explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) :\r\n        D3D12_ROOT_CONSTANTS(o)\r\n    {}\r\n    CD3DX12_ROOT_CONSTANTS(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_CONSTANTS &rootConstants,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        rootConstants.Num32BitValues = num32BitValues;\r\n        rootConstants.ShaderRegister = shaderRegister;\r\n        rootConstants.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) :\r\n        D3D12_ROOT_DESCRIPTOR(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER\r\n{\r\n    CD3DX12_ROOT_PARAMETER() {}\r\n    explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) :\r\n        D3D12_ROOT_PARAMETER(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC\r\n{\r\n    CD3DX12_STATIC_SAMPLER_DESC() {}\r\n    explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) :\r\n        D3D12_STATIC_SAMPLER_DESC(o)\r\n    {}\r\n    CD3DX12_STATIC_SAMPLER_DESC(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc,\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        samplerDesc.ShaderRegister = shaderRegister;\r\n        samplerDesc.Filter = filter;\r\n        samplerDesc.AddressU = addressU;\r\n        samplerDesc.AddressV = addressV;\r\n        samplerDesc.AddressW = addressW;\r\n        samplerDesc.MipLODBias = mipLODBias;\r\n        samplerDesc.MaxAnisotropy = maxAnisotropy;\r\n        samplerDesc.ComparisonFunc = comparisonFunc;\r\n        samplerDesc.BorderColor = borderColor;\r\n        samplerDesc.MinLOD = minLOD;\r\n        samplerDesc.MaxLOD = maxLOD;\r\n        samplerDesc.ShaderVisibility = shaderVisibility;\r\n        samplerDesc.RegisterSpace = registerSpace;\r\n    }\r\n    inline void Init(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            *this,\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    CD3DX12_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.NumParameters = numParameters;\r\n        desc.pParameters = _pParameters;\r\n        desc.NumStaticSamplers = numStaticSamplers;\r\n        desc.pStaticSamplers = _pStaticSamplers;\r\n        desc.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE1 : public D3D12_DESCRIPTOR_RANGE1\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE1() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE1(const D3D12_DESCRIPTOR_RANGE1 &o) :\r\n        D3D12_DESCRIPTOR_RANGE1(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE1(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE1 &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.Flags = flags;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE1 : public D3D12_ROOT_DESCRIPTOR_TABLE1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE1(const D3D12_ROOT_DESCRIPTOR_TABLE1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE1 &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR1 : public D3D12_ROOT_DESCRIPTOR1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR1(const D3D12_ROOT_DESCRIPTOR1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR1(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR1 &table, \r\n        UINT shaderRegister, \r\n        UINT registerSpace = 0, \r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n        table.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER1 : public D3D12_ROOT_PARAMETER1\r\n{\r\n    CD3DX12_ROOT_PARAMETER1() {}\r\n    explicit CD3DX12_ROOT_PARAMETER1(const D3D12_ROOT_PARAMETER1 &o) :\r\n        D3D12_ROOT_PARAMETER1(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE1::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_VERSIONED_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        Desc_1_0 = o;\r\n    }\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC1 &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        Desc_1_1 = o;\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init_1_1(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init_1_0(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_0(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        desc.Desc_1_0.NumParameters = numParameters;\r\n        desc.Desc_1_0.pParameters = _pParameters;\r\n        desc.Desc_1_0.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_0.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_0.Flags = flags;\r\n    }\r\n\r\n    inline void Init_1_1(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_1(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        desc.Desc_1_1.NumParameters = numParameters;\r\n        desc.Desc_1_1.pParameters = _pParameters;\r\n        desc.Desc_1_1.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_1.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_1.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_CPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_GPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )\r\n{ \r\n    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; \r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename T, typename U, typename V>\r\ninline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )\r\n{\r\n    MipSlice = static_cast<T>(Subresource % MipLevels);\r\n    ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);\r\n    PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ ID3D12Device* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format};\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo))))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) :\r\n        D3D12_RESOURCE_DESC( o )\r\n    {}\r\n    CD3DX12_RESOURCE_DESC( \r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags )\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, \r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, \r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex1D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex2D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, \r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex3D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    inline UINT16 Depth() const\r\n    { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT16 ArraySize() const\r\n    { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const\r\n    { return D3D12GetFormatPlaneCount(pDevice, Format); }\r\n    inline UINT Subresources(_In_ ID3D12Device* pDevice) const\r\n    { return MipLevels * ArraySize() * PlaneCount(pDevice); }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Row-by-row memcpy\r\ninline void MemcpySubresource(\r\n    _In_ const D3D12_MEMCPY_DEST* pDest,\r\n    _In_ const D3D12_SUBRESOURCE_DATA* pSrc,\r\n    SIZE_T RowSizeInBytes,\r\n    UINT NumRows,\r\n    UINT NumSlices)\r\n{\r\n    for (UINT z = 0; z < NumSlices; ++z)\r\n    {\r\n        BYTE* pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;\r\n        const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * z;\r\n        for (UINT y = 0; y < NumRows; ++y)\r\n        {\r\n            memcpy(pDestSlice + pDest->RowPitch * y,\r\n                   pSrcSlice + pSrc->RowPitch * y,\r\n                   RowSizeInBytes);\r\n        }\r\n    }\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    UINT64 RequiredSize = 0;\r\n    \r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || \r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || \r\n        RequiredSize > (SIZE_T)-1 || \r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && \r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n    \r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n       return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n       return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout )\r\n{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename t_CommandListType>\r\ninline ID3D12CommandList * const * CommandListCast(t_CommandListType * const * pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<ID3D12CommandList * const *>(pp);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// D3D12 exports a new method for serializing root signatures in the Windows 10 Anniversary Update.\r\n// To help enable root signature 1.1 features when they are available and not require maintaining\r\n// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when\r\n// 1.1 is not supported.\r\ninline HRESULT D3DX12SerializeVersionedRootSignature(\r\n    _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n    D3D_ROOT_SIGNATURE_VERSION MaxVersion,\r\n    _Outptr_ ID3DBlob** ppBlob,\r\n    _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob)\r\n{\r\n    if (ppErrorBlob != NULL)\r\n    {\r\n        *ppErrorBlob = NULL;\r\n    }\r\n\r\n    switch (MaxVersion)\r\n    {\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n            switch (pRootSignatureDesc->Version)\r\n            {\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n                    return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n                {\r\n                    HRESULT hr = S_OK;\r\n                    const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1;\r\n\r\n                    const SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters;\r\n                    void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL;\r\n                    if (ParametersSize > 0 && pParameters == NULL)\r\n                    {\r\n                        hr = E_OUTOFMEMORY;\r\n                    }\r\n                    D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast<D3D12_ROOT_PARAMETER*>(pParameters);\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            __analysis_assume(ParametersSize == sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters);\r\n                            pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType;\r\n                            pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility;\r\n\r\n                            switch (desc_1_1.pParameters[n].ParameterType)\r\n                            {\r\n                            case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:\r\n                                pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues;\r\n                                pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace;\r\n                                pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_CBV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_SRV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_UAV:\r\n                                pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace;\r\n                                pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:\r\n                                const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable;\r\n\r\n                                const SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges;\r\n                                void* pDescriptorRanges = (DescriptorRangesSize > 0 && SUCCEEDED(hr)) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL;\r\n                                if (DescriptorRangesSize > 0 && pDescriptorRanges == NULL)\r\n                                {\r\n                                    hr = E_OUTOFMEMORY;\r\n                                }\r\n                                D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pDescriptorRanges);\r\n\r\n                                if (SUCCEEDED(hr))\r\n                                {\r\n                                    for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++)\r\n                                    {\r\n                                        __analysis_assume(DescriptorRangesSize == sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges);\r\n                                        pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister;\r\n                                        pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors;\r\n                                        pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart;\r\n                                        pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType;\r\n                                        pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace;\r\n                                    }\r\n                                }\r\n\r\n                                D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable;\r\n                                table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges;\r\n                                table_1_0.pDescriptorRanges = pDescriptorRanges_1_0;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags);\r\n                        hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n                    }\r\n\r\n                    if (pParameters)\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            if (desc_1_1.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n                            {\r\n                                HeapFree(GetProcessHeap(), 0, reinterpret_cast<void*>(const_cast<D3D12_DESCRIPTOR_RANGE*>(pParameters_1_0[n].DescriptorTable.pDescriptorRanges)));\r\n                            }\r\n                        }\r\n                        HeapFree(GetProcessHeap(), 0, pParameters);\r\n                    }\r\n                    return hr;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n            return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);\r\n    }\r\n\r\n    return E_INVALIDARG;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RT_FORMAT_ARRAY : public D3D12_RT_FORMAT_ARRAY\r\n{\r\n    CD3DX12_RT_FORMAT_ARRAY() {}\r\n    explicit CD3DX12_RT_FORMAT_ARRAY(const D3D12_RT_FORMAT_ARRAY& o)\r\n        : D3D12_RT_FORMAT_ARRAY(o)\r\n    {}\r\n    explicit CD3DX12_RT_FORMAT_ARRAY(const DXGI_FORMAT* pFormats, UINT NumFormats)\r\n    {\r\n        NumRenderTargets = NumFormats;\r\n        memcpy(RTFormats, pFormats, sizeof(RTFormats));\r\n        // assumes ARRAY_SIZE(pFormats) == ARRAY_SIZE(RTFormats)\r\n    }\r\n    operator const D3D12_RT_FORMAT_ARRAY&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Pipeline State Stream Helpers\r\n//------------------------------------------------------------------------------------------------\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stream Subobjects, i.e. elements of a stream\r\n\r\ntemplate <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type, typename DefaultArg = InnerStructType>\r\nclass alignas(void*) CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT\r\n{\r\nprivate:\r\n    D3D12_PIPELINE_STATE_SUBOBJECT_TYPE _Type;\r\n    InnerStructType _Inner;\r\npublic:\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT() : _Type(Type), _Inner(DefaultArg()) {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT(InnerStructType const& i) : _Type(Type), _Inner(i) {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT& operator=(InnerStructType const& i) { _Inner = i; return *this; }\r\n    operator InnerStructType() const { return _Inner; }\r\n};\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PIPELINE_STATE_FLAGS,         D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS>                           CD3DX12_PIPELINE_STATE_STREAM_FLAGS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT,                               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK>                       CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< ID3D12RootSignature*,               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE>                  CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INPUT_LAYOUT_DESC,            D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT>                    CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INDEX_BUFFER_STRIP_CUT_VALUE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE>              CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PRIMITIVE_TOPOLOGY_TYPE,      D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY>              CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS>                              CD3DX12_PIPELINE_STATE_STREAM_VS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS>                              CD3DX12_PIPELINE_STATE_STREAM_GS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_STREAM_OUTPUT_DESC,           D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT>                   CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS>                              CD3DX12_PIPELINE_STATE_STREAM_HS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS>                              CD3DX12_PIPELINE_STATE_STREAM_DS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS>                              CD3DX12_PIPELINE_STATE_STREAM_PS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS>                              CD3DX12_PIPELINE_STATE_STREAM_CS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_BLEND_DESC,                 D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND,          CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC,         D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL,  CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC1,        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_FORMAT,                        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT>            CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC,            D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER,     CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_RT_FORMAT_ARRAY,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS>           CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_SAMPLE_DESC,                   D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC>                     CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT,                               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK>                     CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_CACHED_PIPELINE_STATE,        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO>                      CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO;\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stream Parser Helpers\r\n\r\nstruct ID3DX12PipelineParserCallbacks\r\n{\r\n    // Subobject Callbacks\r\n    virtual void FlagsCb(D3D12_PIPELINE_STATE_FLAGS) {}\r\n    virtual void NodeMaskCb(UINT) {}\r\n    virtual void RootSignatureCb(ID3D12RootSignature*) {}\r\n    virtual void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC&) {}\r\n    virtual void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE) {}\r\n    virtual void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE) {}\r\n    virtual void VSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void GSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC&) {}\r\n    virtual void HSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void DSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void PSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void CSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void BlendStateCb(const D3D12_BLEND_DESC&) {}\r\n    virtual void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC&) {}\r\n    virtual void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1&) {}\r\n    virtual void DSVFormatCb(DXGI_FORMAT) {}\r\n    virtual void RasterizerStateCb(const D3D12_RASTERIZER_DESC&) {}\r\n    virtual void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY&) {}\r\n    virtual void SampleDescCb(const DXGI_SAMPLE_DESC&) {}\r\n    virtual void SampleMaskCb(UINT) {}\r\n    virtual void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE&) {}\r\n\r\n    // Error Callbacks\r\n    virtual void ErrorBadInputParameter(UINT /*ParameterIndex*/) {}\r\n    virtual void ErrorDuplicateSubobject(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE /*DuplicateType*/) {}\r\n    virtual void ErrorUnknownSubobject(UINT /*UnknownTypeValue*/) {}\r\n\r\n};\r\n\r\nstruct CD3DX12_PIPELINE_STATE_STREAM\r\n{\r\n    CD3DX12_PIPELINE_STATE_STREAM() {}\r\n    CD3DX12_PIPELINE_STATE_STREAM(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& Desc)\r\n        : Flags(Desc.Flags)\r\n        , NodeMask(Desc.NodeMask)\r\n        , pRootSignature(Desc.pRootSignature)\r\n        , InputLayout(Desc.InputLayout)\r\n        , IBStripCutValue(Desc.IBStripCutValue)\r\n        , PrimitiveTopologyType(Desc.PrimitiveTopologyType)\r\n        , VS(Desc.VS)\r\n        , GS(Desc.GS)\r\n        , StreamOutput(Desc.StreamOutput)\r\n        , HS(Desc.HS)\r\n        , DS(Desc.DS)\r\n        , PS(Desc.PS)\r\n        , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState))\r\n        , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC1(Desc.DepthStencilState))\r\n        , DSVFormat(Desc.DSVFormat)\r\n        , RasterizerState(CD3DX12_RASTERIZER_DESC(Desc.RasterizerState))\r\n        , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets))\r\n        , SampleDesc(Desc.SampleDesc)\r\n        , SampleMask(Desc.SampleMask)\r\n        , CachedPSO(Desc.CachedPSO)\r\n    {}\r\n    CD3DX12_PIPELINE_STATE_STREAM(const D3D12_COMPUTE_PIPELINE_STATE_DESC& Desc)\r\n        : Flags(Desc.Flags)\r\n        , NodeMask(Desc.NodeMask)\r\n        , pRootSignature(Desc.pRootSignature)\r\n        , CS(CD3DX12_SHADER_BYTECODE(Desc.CS))\r\n        , CachedPSO(Desc.CachedPSO)\r\n    {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_FLAGS Flags;\r\n    CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK NodeMask;\r\n    CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE pRootSignature;\r\n    CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT InputLayout;\r\n    CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE IBStripCutValue;\r\n    CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY PrimitiveTopologyType;\r\n    CD3DX12_PIPELINE_STATE_STREAM_VS VS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_GS GS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT StreamOutput;\r\n    CD3DX12_PIPELINE_STATE_STREAM_HS HS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DS DS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_PS PS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_CS CS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC BlendState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1 DepthStencilState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT DSVFormat;\r\n    CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER RasterizerState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS RTVFormats;\r\n    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC SampleDesc;\r\n    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK SampleMask;\r\n    CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO CachedPSO;\r\n    D3D12_GRAPHICS_PIPELINE_STATE_DESC GraphicsDescV0() const\r\n    {\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC D;\r\n        D.Flags                 = this->Flags;\r\n        D.NodeMask              = this->NodeMask;\r\n        D.pRootSignature        = this->pRootSignature;\r\n        D.InputLayout           = this->InputLayout;\r\n        D.IBStripCutValue       = this->IBStripCutValue;\r\n        D.PrimitiveTopologyType = this->PrimitiveTopologyType;\r\n        D.VS                    = this->VS;\r\n        D.GS                    = this->GS;\r\n        D.StreamOutput          = this->StreamOutput;\r\n        D.HS                    = this->HS;\r\n        D.DS                    = this->DS;\r\n        D.PS                    = this->PS;\r\n        D.BlendState            = this->BlendState;\r\n        D.DepthStencilState     = CD3DX12_DEPTH_STENCIL_DESC1(D3D12_DEPTH_STENCIL_DESC1(this->DepthStencilState));\r\n        D.DSVFormat             = this->DSVFormat;\r\n        D.RasterizerState       = this->RasterizerState;\r\n        D.NumRenderTargets      = D3D12_RT_FORMAT_ARRAY(this->RTVFormats).NumRenderTargets;\r\n        memcpy(D.RTVFormats, D3D12_RT_FORMAT_ARRAY(this->RTVFormats).RTFormats, sizeof(D.RTVFormats));\r\n        D.SampleDesc            = this->SampleDesc;\r\n        D.SampleMask            = this->SampleMask;\r\n        D.CachedPSO             = this->CachedPSO;\r\n        return D;\r\n    }\r\n    D3D12_COMPUTE_PIPELINE_STATE_DESC ComputeDescV0() const\r\n    {\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC D;\r\n        D.Flags                 = this->Flags;\r\n        D.NodeMask              = this->NodeMask;\r\n        D.pRootSignature        = this->pRootSignature;\r\n        D.CS                    = this->CS;\r\n        D.CachedPSO             = this->CachedPSO;\r\n        return D;\r\n    }\r\n};\r\n\r\nstruct CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER : public ID3DX12PipelineParserCallbacks\r\n{\r\n    CD3DX12_PIPELINE_STATE_STREAM PipelineStream;\r\n\r\n    // ID3DX12PipelineParserCallbacks\r\n    void FlagsCb(D3D12_PIPELINE_STATE_FLAGS Flags) {PipelineStream.Flags = Flags;}\r\n    void NodeMaskCb(UINT NodeMask) {PipelineStream.NodeMask = NodeMask;}\r\n    void RootSignatureCb(ID3D12RootSignature* pRootSignature) {PipelineStream.pRootSignature = pRootSignature;}\r\n    void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC& InputLayout) {PipelineStream.InputLayout = InputLayout;}\r\n    void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue) {PipelineStream.IBStripCutValue = IBStripCutValue;}\r\n    void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType) {PipelineStream.PrimitiveTopologyType = PrimitiveTopologyType;}\r\n    void VSCb(const D3D12_SHADER_BYTECODE& VS) {PipelineStream.VS = VS;}\r\n    void GSCb(const D3D12_SHADER_BYTECODE& GS) {PipelineStream.GS = GS;}\r\n    void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC& StreamOutput) {PipelineStream.StreamOutput = StreamOutput;}\r\n    void HSCb(const D3D12_SHADER_BYTECODE& HS) {PipelineStream.HS = HS;}\r\n    void DSCb(const D3D12_SHADER_BYTECODE& DS) {PipelineStream.DS = DS;}\r\n    void PSCb(const D3D12_SHADER_BYTECODE& PS) {PipelineStream.PS = PS;}\r\n    void CSCb(const D3D12_SHADER_BYTECODE& CS) {PipelineStream.CS = CS;}\r\n    void BlendStateCb(const D3D12_BLEND_DESC& BlendState) {PipelineStream.BlendState = CD3DX12_BLEND_DESC(BlendState);}\r\n    void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC& DepthStencilState) {PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(DepthStencilState);}\r\n    void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1& DepthStencilState) {PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(DepthStencilState);}\r\n    void DSVFormatCb(DXGI_FORMAT DSVFormat) {PipelineStream.DSVFormat = DSVFormat;}\r\n    void RasterizerStateCb(const D3D12_RASTERIZER_DESC& RasterizerState) {PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC(RasterizerState);}\r\n    void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY& RTVFormats) {PipelineStream.RTVFormats = RTVFormats;}\r\n    void SampleDescCb(const DXGI_SAMPLE_DESC& SampleDesc) {PipelineStream.SampleDesc = SampleDesc;}\r\n    void SampleMaskCb(UINT SampleMask) {PipelineStream.SampleMask = SampleMask;}\r\n    void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE& CachedPSO) {PipelineStream.CachedPSO = CachedPSO;}\r\n    void ErrorBadInputParameter(UINT) {}\r\n    void ErrorDuplicateSubobject(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE) {}\r\n    void ErrorUnknownSubobject(UINT) {}\r\n};\r\n\r\ninline D3D12_PIPELINE_STATE_SUBOBJECT_TYPE D3DX12GetBaseSubobjectType(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE SubobjectType)\r\n{\r\n    switch (SubobjectType)\r\n    {\r\n    case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1: \r\n        return D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL;\r\n    default:\r\n        return SubobjectType;\r\n    }\r\n}\r\n\r\ninline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& Desc, ID3DX12PipelineParserCallbacks* pCallbacks)\r\n{\r\n    if (Desc.SizeInBytes == 0 || Desc.pPipelineStateSubobjectStream == nullptr)\r\n    {\r\n        pCallbacks->ErrorBadInputParameter(1); // first parameter issue\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    if (pCallbacks == nullptr)\r\n    {\r\n        pCallbacks->ErrorBadInputParameter(2); // second parameter issue\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    bool SubobjectSeen[D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID] = {0};\r\n    for (SIZE_T CurOffset = 0, SizeOfSubobject = 0; CurOffset < Desc.SizeInBytes; CurOffset += SizeOfSubobject)\r\n    {\r\n        BYTE* pStream = static_cast<BYTE*>(Desc.pPipelineStateSubobjectStream)+CurOffset;\r\n        auto SubobjectType = *reinterpret_cast<D3D12_PIPELINE_STATE_SUBOBJECT_TYPE*>(pStream);\r\n        if (SubobjectType >= D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID)\r\n        {\r\n            pCallbacks->ErrorUnknownSubobject(SubobjectType);\r\n            return E_INVALIDARG;\r\n        }\r\n        if (SubobjectSeen[D3DX12GetBaseSubobjectType(SubobjectType)])\r\n        {\r\n            pCallbacks->ErrorDuplicateSubobject(SubobjectType);\r\n            return E_INVALIDARG; // disallow subobject duplicates in a stream\r\n        }\r\n        SubobjectSeen[SubobjectType] = true;\r\n        switch (SubobjectType)\r\n        {\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE: \r\n            pCallbacks->RootSignatureCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::pRootSignature)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::pRootSignature);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS:\r\n            pCallbacks->VSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::VS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::VS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS: \r\n            pCallbacks->PSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::PS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::PS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS: \r\n            pCallbacks->DSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS: \r\n            pCallbacks->HSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::HS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::HS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS: \r\n            pCallbacks->GSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::GS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::GS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS:\r\n            pCallbacks->CSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::CS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT: \r\n            pCallbacks->StreamOutputCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND: \r\n            pCallbacks->BlendStateCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::BlendState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::BlendState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK: \r\n            pCallbacks->SampleMaskCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::SampleMask)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::SampleMask);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER: \r\n            pCallbacks->RasterizerStateCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::RasterizerState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::RasterizerState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL: \r\n            pCallbacks->DepthStencilStateCb(*reinterpret_cast<CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1: \r\n            pCallbacks->DepthStencilState1Cb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DepthStencilState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DepthStencilState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT: \r\n            pCallbacks->InputLayoutCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::InputLayout)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::InputLayout);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE: \r\n            pCallbacks->IBStripCutValueCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::IBStripCutValue)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::IBStripCutValue);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY: \r\n            pCallbacks->PrimitiveTopologyTypeCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::PrimitiveTopologyType)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::PrimitiveTopologyType);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS: \r\n            pCallbacks->RTVFormatsCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::RTVFormats)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::RTVFormats);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT: \r\n            pCallbacks->DSVFormatCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DSVFormat)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DSVFormat);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC: \r\n            pCallbacks->SampleDescCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::SampleDesc)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::SampleDesc);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK: \r\n            pCallbacks->NodeMaskCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::NodeMask)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::NodeMask);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO: \r\n            pCallbacks->CachedPSOCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::CachedPSO)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CachedPSO);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS:\r\n            pCallbacks->FlagsCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::Flags)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::Flags);\r\n            break;\r\n        default:\r\n            pCallbacks->ErrorUnknownSubobject(SubobjectType);\r\n            return E_INVALIDARG;\r\n            break;\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n#endif // defined( __cplusplus )\r\n\r\n#endif //__D3DX12_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/d3dx12affinity.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/d3dx12affinity.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * Primary included header for the affinity layer. You should change all\r\n * #include <d3d12.h> in your engine source to include this file instead.\r\n */\r\n\r\n#pragma once\r\n\r\n#pragma pack(push,16)\r\n\r\n\r\n#include <d3d12.h>\r\n\r\nclass CD3DX12AffinityObject;\r\nclass CD3DX12AffinityDeviceChild;\r\nclass CD3DX12AffinityPageable;\r\nclass CD3DX12AffinityRootSignature;\r\nclass CD3DX12AffinityRootSignatureDeserializer;\r\nclass CD3DX12AffinityHeap;\r\nclass CD3DX12AffinityResource;\r\nclass CD3DX12AffinityCommandAllocator;\r\nclass CD3DX12AffinityFence;\r\nclass CD3DX12AffinityPipelineState;\r\nclass CD3DX12AffinityDescriptorHeap;\r\nclass CD3DX12AffinityQueryHeap;\r\nclass CD3DX12AffinityCommandSignature;\r\nclass CD3DX12AffinityCommandList;\r\nclass CD3DX12AffinityGraphicsCommandList;\r\nclass CD3DX12AffinityCommandQueue;\r\nclass CD3DX12AffinityDevice;\r\nclass CDXGIAffinitySwapChain;\r\n\r\n#include \"CD3DX12AffinityObject.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n#include \"CD3DX12AffinityRootSignature.h\"\r\n#include \"CD3DX12AffinityHeap.h\"\r\n#include \"CD3DX12AffinityResource.h\"\r\n#include \"CD3DX12AffinityCommandAllocator.h\"\r\n#include \"CD3DX12AffinityFence.h\"\r\n#include \"CD3DX12AffinityPipelineState.h\"\r\n#include \"CD3DX12AffinityDescriptorHeap.h\"\r\n#include \"CD3DX12AffinityQueryHeap.h\"\r\n#include \"CD3DX12AffinityCommandSignature.h\"\r\n#include \"CD3DX12AffinityCommandList.h\"\r\n#include \"CD3DX12AffinityGraphicsCommandList.h\"\r\n#include \"CD3DX12AffinityCommandQueue.h\"\r\n#include \"CD3DX12AffinityDevice.h\"\r\n#include \"CDXGIAffinitySwapChain.h\"\r\n#include \"d3dx12affinity_structs.h\"\r\n\r\n\r\nHRESULT WINAPI D3DX12AffinityCreateLDADevice(\r\n    _In_ ID3D12Device* Device,\r\n    _Outptr_  CD3DX12AffinityDevice** ppDevice);\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateSingleWindowSwapChain(\r\n    _In_  IDXGISwapChain3* pSwapChain,\r\n    _In_  CD3DX12AffinityCommandQueue* pQueue,\r\n    _In_  CD3DX12AffinityDevice* pDevice,\r\n    _In_  DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    _Outptr_  CDXGIAffinitySwapChain** ppSwapChain);\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    _In_  IDXGISwapChain* pSwapChain,\r\n    _In_  CD3DX12AffinityCommandQueue* pQueue,\r\n    _In_  CD3DX12AffinityDevice* pDevice,\r\n    _Outptr_  CDXGIAffinitySwapChain** ppSwapChain);\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    _In_  IDXGISwapChain3* pSwapChain,\r\n    _In_  CD3DX12AffinityCommandQueue* pQueue,\r\n    _In_  CD3DX12AffinityDevice* pDevice,\r\n    _In_  DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    _Outptr_  CDXGIAffinitySwapChain** ppSwapChain);\r\n\r\n#pragma pack(pop)\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/d3dx12affinity_d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This header provides \"affinity\" versions of some structs provided by <d3dx12.h>\r\n * Any struct that includes \"ID3D12____\" pointers needs to have an affinity version\r\n * that has a \"CD3DX12____\" pointer instead. AFAIK I haven't modified any of these\r\n * structs so if there are any differences vs. <d3dx12.h> it is probably due to\r\n * API changes.\r\n *\r\n * Very few if any of these have been used extensively, so they are relatively\r\n * untested.\r\n */\r\n\r\n#pragma once\r\n\r\n#include \"d3dx12.h\"\r\n#include \"d3dx12affinity.h\"\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_AFFINITY_RESOURCE_BARRIER : public D3DX12_AFFINITY_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_AFFINITY_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_AFFINITY_RESOURCE_BARRIER(const D3DX12_AFFINITY_RESOURCE_BARRIER &o) :\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_AFFINITY_RESOURCE_BARRIER Transition(\r\n        _In_ CD3DX12AffinityResource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_AFFINITY_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_BARRIER Aliasing(\r\n        _In_ CD3DX12AffinityResource* pResourceBefore,\r\n        _In_ CD3DX12AffinityResource* pResourceAfter)\r\n    {\r\n        CD3DX12_AFFINITY_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_BARRIER UAV(\r\n        _In_ CD3DX12AffinityResource* pResource)\r\n    {\r\n        CD3DX12_AFFINITY_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3DX12_AFFINITY_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION : public D3DX12_AFFINITY_TEXTURE_COPY_LOCATION\r\n{\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION &o) :\r\n        D3DX12_AFFINITY_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(CD3DX12AffinityResource* pRes) { pResource = pRes; }\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(CD3DX12AffinityResource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(CD3DX12AffinityResource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ CD3DX12AffinityDevice* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = { Format };\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo), 0)))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_AFFINITY_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_AFFINITY_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_AFFINITY_RESOURCE_DESC(const D3D12_RESOURCE_DESC& o) :\r\n        D3D12_RESOURCE_DESC(o)\r\n    {}\r\n    CD3DX12_AFFINITY_RESOURCE_DESC(\r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags)\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Buffer(\r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes,\r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Buffer(\r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1,\r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Tex1D(\r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize,\r\n            mipLevels, format, 1, 0, layout, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Tex2D(\r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize,\r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Tex3D(\r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth,\r\n            mipLevels, format, 1, 0, layout, flags);\r\n    }\r\n    inline UINT16 Depth() const\r\n    {\r\n        return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1);\r\n    }\r\n    inline UINT16 ArraySize() const\r\n    {\r\n        return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1);\r\n    }\r\n    inline UINT8 PlaneCount(_In_ CD3DX12AffinityDevice* pDevice) const\r\n    {\r\n        return D3D12GetFormatPlaneCount(pDevice, Format);\r\n    }\r\n    inline UINT Subresources(_In_ CD3DX12AffinityDevice* pDevice) const\r\n    {\r\n        return MipLevels * ArraySize() * PlaneCount(pDevice);\r\n    }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    {\r\n        return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize());\r\n    }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==(const CD3DX12_AFFINITY_RESOURCE_DESC& l, const CD3DX12_AFFINITY_RESOURCE_DESC& r)\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=(const CD3DX12_AFFINITY_RESOURCE_DESC& l, const CD3DX12_AFFINITY_RESOURCE_DESC& r)\r\n{\r\n    return !(l == r);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    UINT64 RequiredSize = 0;\r\n\r\n    CD3DX12AffinityDevice* pDevice;\r\n    pDestinationResource->GetDevice(&pDevice);\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ CD3DX12AffinityGraphicsCommandList* pCmdList,\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_ CD3DX12AffinityResource* pIntermediate,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(/* DeviceIndex */ 0);\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||\r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||\r\n        RequiredSize >(SIZE_T) - 1 ||\r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&\r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n\r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox(UINT(pLayouts[0].Offset), UINT(pLayouts[0].Offset + pLayouts[0].Footprint.Width));\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources(\r\n    _In_ CD3DX12AffinityGraphicsCommandList* pCmdList,\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_ CD3DX12AffinityResource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n        return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n        return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    CD3DX12AffinityDevice* pDevice;\r\n    pDestinationResource->GetDevice(&pDevice);\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n\r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources(\r\n    _In_ CD3DX12AffinityGraphicsCommandList* pCmdList,\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_ CD3DX12AffinityResource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    CD3DX12AffinityDevice* pDevice;\r\n    pDestinationResource->GetDevice(&pDevice);\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n\r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline CD3DX12AffinityCommandList* const* CommandListCast(CD3DX12AffinityGraphicsCommandList* const* pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<CD3DX12AffinityCommandList* const*>(pp);\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/Desktop/d3dx12affinity_structs.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This header provides \"affinity\" versions of the structs provided by <d3d12.h>\r\n * Any struct that includes \"ID3D12____\" pointers needs to have an affinity version\r\n * that has a \"CD3DX12____\" pointer instead. The only modification made to these\r\n * structs is to add ToD3D12() methods that produce copies of the D3D12 structs\r\n * with NULL substituted for the \"ID3D12____\" members, so if there are any differences\r\n * vs. <d3dx12.h> it is probably due to API changes.\r\n */\r\n\r\n#pragma once\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\ntypedef struct D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC\r\n{\r\n    CD3DX12AffinityRootSignature* pRootSignature;\r\n    D3D12_SHADER_BYTECODE VS;\r\n    D3D12_SHADER_BYTECODE PS;\r\n    D3D12_SHADER_BYTECODE DS;\r\n    D3D12_SHADER_BYTECODE HS;\r\n    D3D12_SHADER_BYTECODE GS;\r\n    D3D12_STREAM_OUTPUT_DESC StreamOutput;\r\n    D3D12_BLEND_DESC BlendState;\r\n    UINT SampleMask;\r\n    D3D12_RASTERIZER_DESC RasterizerState;\r\n    D3D12_DEPTH_STENCIL_DESC DepthStencilState;\r\n    D3D12_INPUT_LAYOUT_DESC InputLayout;\r\n    D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;\r\n    D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;\r\n    UINT NumRenderTargets;\r\n    DXGI_FORMAT RTVFormats[8];\r\n    DXGI_FORMAT DSVFormat;\r\n    DXGI_SAMPLE_DESC SampleDesc;\r\n    UINT NodeMask;\r\n    D3D12_CACHED_PIPELINE_STATE CachedPSO;\r\n    D3D12_PIPELINE_STATE_FLAGS Flags;\r\n\r\n    D3D12_GRAPHICS_PIPELINE_STATE_DESC ToD3D12() const\r\n    {\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC Desc;\r\n        Desc.pRootSignature = nullptr;\r\n        Desc.VS = VS;\r\n        Desc.PS = PS;\r\n        Desc.DS = DS;\r\n        Desc.HS = HS;\r\n        Desc.GS = GS;\r\n        Desc.StreamOutput = StreamOutput;\r\n        Desc.BlendState = BlendState;\r\n        Desc.SampleMask = SampleMask;\r\n        Desc.RasterizerState = RasterizerState;\r\n        Desc.DepthStencilState = DepthStencilState;\r\n        Desc.InputLayout = InputLayout;\r\n        Desc.IBStripCutValue = IBStripCutValue;\r\n        Desc.PrimitiveTopologyType = PrimitiveTopologyType;\r\n        Desc.NumRenderTargets = NumRenderTargets;\r\n        for (int i = 0; i < 8; ++i)\r\n            Desc.RTVFormats[i] = RTVFormats[i];\r\n        Desc.DSVFormat = DSVFormat;\r\n        Desc.SampleDesc = SampleDesc;\r\n        Desc.NodeMask = NodeMask;\r\n        Desc.CachedPSO = CachedPSO;\r\n        Desc.Flags = Flags;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC;\r\n\r\ntypedef struct D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC\r\n{\r\n    CD3DX12AffinityRootSignature* pRootSignature;\r\n    D3D12_SHADER_BYTECODE CS;\r\n    UINT NodeMask;\r\n    D3D12_CACHED_PIPELINE_STATE CachedPSO;\r\n    D3D12_PIPELINE_STATE_FLAGS Flags;\r\n\r\n    D3D12_COMPUTE_PIPELINE_STATE_DESC ToD3D12() const\r\n    {\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC Desc;\r\n        Desc.pRootSignature = nullptr;\r\n        Desc.CS = CS;\r\n        Desc.NodeMask = NodeMask;\r\n        Desc.CachedPSO = CachedPSO;\r\n        Desc.Flags = Flags;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_TRANSITION_BARRIER\r\n{\r\n    CD3DX12AffinityResource* pResource;\r\n    UINT Subresource;\r\n    D3D12_RESOURCE_STATES StateBefore;\r\n    D3D12_RESOURCE_STATES StateAfter;\r\n\r\n    D3D12_RESOURCE_TRANSITION_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_TRANSITION_BARRIER Desc;\r\n        Desc.pResource = nullptr;\r\n        Desc.Subresource = Subresource;\r\n        Desc.StateBefore = StateBefore;\r\n        Desc.StateAfter = StateAfter;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_TRANSITION_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_ALIASING_BARRIER\r\n{\r\n    CD3DX12AffinityResource* pResourceBefore;\r\n    CD3DX12AffinityResource* pResourceAfter;\r\n\r\n    D3D12_RESOURCE_ALIASING_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_ALIASING_BARRIER Desc;\r\n        Desc.pResourceBefore = nullptr;\r\n        Desc.pResourceAfter = nullptr;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_ALIASING_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_UAV_BARRIER\r\n{\r\n    CD3DX12AffinityResource* pResource;\r\n\r\n    D3D12_RESOURCE_UAV_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_UAV_BARRIER Desc;\r\n        Desc.pResource = nullptr;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_UAV_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_BARRIER\r\n{\r\n    D3D12_RESOURCE_BARRIER_TYPE Type;\r\n    D3D12_RESOURCE_BARRIER_FLAGS Flags;\r\n    union\r\n    {\r\n        D3DX12_AFFINITY_RESOURCE_TRANSITION_BARRIER Transition;\r\n        D3DX12_AFFINITY_RESOURCE_ALIASING_BARRIER Aliasing;\r\n        D3DX12_AFFINITY_RESOURCE_UAV_BARRIER UAV;\r\n    };\r\n\r\n    D3D12_RESOURCE_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_BARRIER Desc;\r\n        Desc.Type = Type;\r\n        Desc.Flags = Flags;\r\n        switch (Type)\r\n        {\r\n        case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:\r\n            Desc.Transition = Transition.ToD3D12();\r\n            break;\r\n        case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:\r\n            Desc.Aliasing = Aliasing.ToD3D12();\r\n            break;\r\n        case D3D12_RESOURCE_BARRIER_TYPE_UAV:\r\n            Desc.UAV = UAV.ToD3D12();\r\n            break;\r\n        }\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_TEXTURE_COPY_LOCATION\r\n{\r\n    CD3DX12AffinityResource* pResource;\r\n    D3D12_TEXTURE_COPY_TYPE Type;\r\n    union\r\n    {\r\n        D3D12_PLACED_SUBRESOURCE_FOOTPRINT PlacedFootprint;\r\n        UINT SubresourceIndex;\r\n    };\r\n\r\n    D3D12_TEXTURE_COPY_LOCATION ToD3D12() const\r\n    {\r\n        D3D12_TEXTURE_COPY_LOCATION Desc;\r\n        Desc.pResource = nullptr;\r\n        switch (Type)\r\n        {\r\n        case D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT:\r\n            Desc.PlacedFootprint = PlacedFootprint;\r\n            break;\r\n        case D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX:\r\n            Desc.SubresourceIndex = SubresourceIndex;\r\n            break;\r\n        }\r\n        Desc.Type = Type;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_TEXTURE_COPY_LOCATION;\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandAllocator.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityCommandAllocator::CD3DX12AffinityCommandAllocator(CD3DX12AffinityDevice* device, ID3D12CommandAllocator** commandAllocators, UINT Count, bool UseDeviceActiveMaskOnReset)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(commandAllocators), Count)\r\n    , mUseDeviceActiveMaskOnReset(UseDeviceActiveMaskOnReset)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandAllocators[i] = commandAllocators[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandAllocators[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandAllocator\";\r\n#endif\r\n\r\n#if !ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    if (UseDeviceActiveMaskOnReset)\r\n    {\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n#endif\r\n}\r\n\r\nHRESULT CD3DX12AffinityCommandAllocator::Reset(void)\r\n{\r\n#if !ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    if (mUseDeviceActiveMaskOnReset)\r\n    {\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n#endif\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandAllocator* Allocator = mCommandAllocators[i];\r\n            HRESULT const hr = Allocator->Reset();\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nID3D12CommandAllocator* CD3DX12AffinityCommandAllocator::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandAllocators[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandAllocator.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandAllocator : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityCommandAllocator(CD3DX12AffinityDevice* device, ID3D12CommandAllocator** commandAllocators, UINT Count, bool UseDeviceActiveMaskOnReset);\r\n\r\n    HRESULT STDMETHODCALLTYPE Reset(void);\r\n    ID3D12CommandAllocator* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    ID3D12CommandAllocator* mCommandAllocators[D3DX12_MAX_ACTIVE_NODES];\r\n    bool mUseDeviceActiveMaskOnReset;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandList.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nCD3DX12AffinityCommandList::CD3DX12AffinityCommandList(CD3DX12AffinityDevice* device, ID3D12CommandList** commandLists, UINT Count)\r\n    : CD3DX12AffinityDeviceChild(device, reinterpret_cast<ID3D12DeviceChild**>(commandLists), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandLists[i] = commandLists[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandLists[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandList\";\r\n#endif\r\n}\r\n\r\nD3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE CD3DX12AffinityCommandList::GetType(UINT AffinityIndex)\r\n{\r\n    return mCommandLists[AffinityIndex]->GetType();\r\n}\r\n\r\nBOOL STDMETHODCALLTYPE CD3DX12AffinityCommandList::AssertResourceState(\r\n    CD3DX12AffinityResource* pResource,\r\n    UINT Subresource,\r\n    UINT State)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    ID3D12CommandList* CommandList = mCommandLists[i];\r\n    ID3D12DebugCommandList* DebugCommandList = nullptr;\r\n\r\n    HRESULT const hr = CommandList->QueryInterface(IID_PPV_ARGS(&DebugCommandList));\r\n    if (S_OK != hr)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    if (false == DebugCommandList->AssertResourceState(pResource->mResources[i], Subresource, State))\r\n    {\r\n        return false;\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandList::SetFeatureMask(\r\n    D3D12_DEBUG_FEATURE Mask)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandList* CommandList = mCommandLists[i];\r\n            ID3D12DebugCommandList* DebugCommandList = nullptr;\r\n\r\n            HRESULT hr = CommandList->QueryInterface(IID_PPV_ARGS(&DebugCommandList));\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n\r\n            hr = DebugCommandList->SetFeatureMask(Mask);\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nID3D12CommandList* CD3DX12AffinityCommandList::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandLists[AffinityIndex];\r\n}\r\n\r\nbool CD3DX12AffinityCommandList::IsReady()\r\n{\r\n    return mPendingBroadcast == 0;\r\n}\r\n\r\nvoid CD3DX12AffinityCommandList::RegisterPendingBroadcast()\r\n{\r\n    std::lock_guard<std::mutex> lock(mMutexPendingBroadcast);\r\n    mPendingBroadcast++;\r\n}\r\n\r\nvoid CD3DX12AffinityCommandList::UnRegisterPendingBroadcast()\r\n{\r\n    std::lock_guard<std::mutex> lock(mMutexPendingBroadcast);\r\n    mPendingBroadcast--;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandList.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandList : public CD3DX12AffinityDeviceChild\r\n{\r\npublic:\r\n    CD3DX12AffinityCommandList(CD3DX12AffinityDevice* device, ID3D12CommandList** commandLists, UINT Count);\r\n\r\n    D3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE GetType(UINT AffinityIndex = 0);\r\n\r\n    BOOL STDMETHODCALLTYPE AssertResourceState(\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        UINT Subresource,\r\n        UINT State);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetFeatureMask(\r\n        D3D12_DEBUG_FEATURE Mask);\r\n\r\n    ID3D12CommandList* GetChildObject(UINT AffinityIndex);\r\n\r\n    bool IsReady();\r\n    void RegisterPendingBroadcast();\r\n    void UnRegisterPendingBroadcast();\r\n\r\nprivate:\r\n    ID3D12CommandList* mCommandLists[D3DX12_MAX_ACTIVE_NODES];\r\n    std::mutex mMutexPendingBroadcast;\r\n    UINT mPendingBroadcast = 0;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandQueue.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::UpdateTileMappings(\r\n    CD3DX12AffinityResource* pResource,\r\n    UINT NumResourceRegions,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pResourceRegionStartCoordinates,\r\n    const D3D12_TILE_REGION_SIZE* pResourceRegionSizes,\r\n    CD3DX12AffinityHeap* pHeap,\r\n    UINT NumRanges,\r\n    const D3D12_TILE_RANGE_FLAGS* pRangeFlags,\r\n    const UINT* pHeapRangeStartOffsets,\r\n    const UINT* pRangeTileCounts,\r\n    D3D12_TILE_MAPPING_FLAGS Flags,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            {\r\n                ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n                Queue->UpdateTileMappings(\r\n                    pResource->mResources[i],\r\n                    NumResourceRegions,\r\n                    pResourceRegionStartCoordinates,\r\n                    pResourceRegionSizes,\r\n                    pHeap->GetChildObject(i),\r\n                    NumRanges,\r\n                    pRangeFlags,\r\n                    pHeapRangeStartOffsets,\r\n                    pRangeTileCounts,\r\n                    Flags);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::CopyTileMappings(\r\n    CD3DX12AffinityResource* pDstResource,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pDstRegionStartCoordinate,\r\n    CD3DX12AffinityResource* pSrcResource,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pSrcRegionStartCoordinate,\r\n    const D3D12_TILE_REGION_SIZE* pRegionSize,\r\n    D3D12_TILE_MAPPING_FLAGS Flags,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n            Queue->CopyTileMappings(\r\n                pDstResource->mResources[i],\r\n                pDstRegionStartCoordinate,\r\n                pSrcResource->mResources[i],\r\n                pSrcRegionStartCoordinate,\r\n                pRegionSize,\r\n                Flags);\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::ExecuteCommandLists(\r\n    UINT NumCommandLists,\r\n    CD3DX12AffinityCommandList* const* ppCommandLists,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12CommandList*> mCachedCommandLists;\r\n    mCachedCommandLists.resize(NumCommandLists);\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            {\r\n                ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n                UINT index = 0;\r\n                for (UINT c = 0; c < NumCommandLists; ++c)\r\n                {\r\n                    CD3DX12AffinityGraphicsCommandList* AffinityCommandList = static_cast<CD3DX12AffinityGraphicsCommandList*>(ppCommandLists[c]);\r\n                    if (AffinityCommandList->GetActiveAffinityMask() & (1 << i))\r\n                    {\r\n                        mCachedCommandLists[index++] = AffinityCommandList->GetChildObject(i);\r\n                    }\r\n                }\r\n\r\n                Queue->ExecuteCommandLists(index, mCachedCommandLists.data());\r\n\r\n#ifdef SERIALIZE_COMMNANDLIST_EXECUTION\r\n                ID3D12Fence* pFence;\r\n                GetParentDevice()->mDevices[0]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n                Queue->Signal(pFence, 1);\r\n                HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n                pFence->SetEventOnCompletion(1, hEvent);\r\n                WaitForSingleObject(hEvent, INFINITE);\r\n                CloseHandle(hEvent);\r\n                pFence->Release();\r\n                if (FAILED(GetParentDevice()->mDevices[0]->GetDeviceRemovedReason()))\r\n                {\r\n                    __debugbreak();\r\n                }\r\n#endif\r\n            }\r\n        }\r\n    }\r\n    ReleaseLog(L\"D3DX12AffinityLayer: [event] ExecuteCommandLists\\n\");\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::SetMarker(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size,\r\n    UINT AffinityMask)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    {\r\n        ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n        Queue->SetMarker(Metadata, pData, Size);\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::BeginEvent(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size,\r\n    UINT AffinityMask)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    {\r\n        ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n        Queue->BeginEvent(Metadata, pData, Size);\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::EndEvent(UINT AffinityMask)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    {\r\n        ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n        Queue->EndEvent();\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::Signal(\r\n    CD3DX12AffinityFence* pFence,\r\n    UINT64 Value,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            {\r\n                ID3D12CommandQueue* Queue = mCommandQueues[i];\r\n\r\n                HRESULT const hr = Queue->Signal(pFence->mFences[i], Value);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::Wait(\r\n    CD3DX12AffinityFence* pFence,\r\n    UINT64 Value,\r\n    bool UseActiveQueueOnly,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            ID3D12CommandQueue* Queue = UseActiveQueueOnly ? mCommandQueues[ActiveNodeIndex] : mCommandQueues[i];\r\n\r\n            HRESULT const hr = Queue->Wait(pFence->mFences[i], Value);\r\n\r\n            if (hr != S_OK)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::GetTimestampFrequency(\r\n    UINT64* pFrequency,\r\n    UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex]->GetTimestampFrequency(pFrequency);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::GetClockCalibration(\r\n    UINT64* pGpuTimestamp,\r\n    UINT64* pCpuTimestamp,\r\n    UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex]->GetClockCalibration(pGpuTimestamp, pCpuTimestamp);\r\n}\r\n\r\nD3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE CD3DX12AffinityCommandQueue::GetDesc(UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex]->GetDesc();\r\n}\r\n\r\nID3D12CommandQueue* CD3DX12AffinityCommandQueue::GetQueueForSwapChainCreation(UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex];\r\n}\r\n\r\nCD3DX12AffinityCommandQueue::CD3DX12AffinityCommandQueue(CD3DX12AffinityDevice* device, ID3D12CommandQueue** commandQueues, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(commandQueues), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandQueues[i] = commandQueues[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandQueues[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandQueue\";\r\n#endif\r\n}\r\n\r\nID3D12CommandQueue* CD3DX12AffinityCommandQueue::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandQueues[AffinityIndex];\r\n}\r\n\r\nvoid CD3DX12AffinityCommandQueue::WaitForCompletion(UINT AffinityMask)\r\n{\r\n    // Very inefficient. Should be used very sparingly.\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            ID3D12Fence* pFence;\r\n            ID3D12Device* pDevice = GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA ?\r\n                GetParentDevice()->GetChildObject(0) : GetParentDevice()->GetChildObject(i);\r\n            pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n            mCommandQueues[i]->Signal(pFence, 1);\r\n            HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n            pFence->SetEventOnCompletion(1, hEvent);\r\n            WaitForSingleObject(hEvent, INFINITE);\r\n            CloseHandle(hEvent);\r\n            pFence->Release();\r\n            if (FAILED(pDevice->GetDeviceRemovedReason()))\r\n            {\r\n                __debugbreak();\r\n            }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandQueue.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandQueue : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    void STDMETHODCALLTYPE UpdateTileMappings(\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        UINT NumResourceRegions,\r\n        _In_reads_opt_(NumResourceRegions)  const D3D12_TILED_RESOURCE_COORDINATE* pResourceRegionStartCoordinates,\r\n        _In_reads_opt_(NumResourceRegions)  const D3D12_TILE_REGION_SIZE* pResourceRegionSizes,\r\n        _In_opt_  CD3DX12AffinityHeap* pHeap,\r\n        UINT NumRanges,\r\n        _In_reads_opt_(NumRanges)  const D3D12_TILE_RANGE_FLAGS* pRangeFlags,\r\n        _In_reads_opt_(NumRanges)  const UINT* pHeapRangeStartOffsets,\r\n        _In_reads_opt_(NumRanges)  const UINT* pRangeTileCounts,\r\n        D3D12_TILE_MAPPING_FLAGS Flags,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyTileMappings(\r\n        _In_  CD3DX12AffinityResource* pDstResource,\r\n        _In_  const D3D12_TILED_RESOURCE_COORDINATE* pDstRegionStartCoordinate,\r\n        _In_  CD3DX12AffinityResource* pSrcResource,\r\n        _In_  const D3D12_TILED_RESOURCE_COORDINATE* pSrcRegionStartCoordinate,\r\n        _In_  const D3D12_TILE_REGION_SIZE* pRegionSize,\r\n        D3D12_TILE_MAPPING_FLAGS Flags,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE ExecuteCommandLists(\r\n        _In_  UINT NumCommandLists,\r\n        _In_reads_(NumCommandLists)  CD3DX12AffinityCommandList* const* ppCommandLists,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE SetMarker(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE BeginEvent(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE EndEvent(_In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE Signal(\r\n        CD3DX12AffinityFence* pFence,\r\n        UINT64 Value,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE Wait(\r\n        CD3DX12AffinityFence* pFence,\r\n        UINT64 Value,\r\n        bool UseActiveQueueOnly = false,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetTimestampFrequency(\r\n        _Out_  UINT64* pFrequency,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetClockCalibration(\r\n        _Out_  UINT64* pGpuTimestamp,\r\n        _Out_  UINT64* pCpuTimestamp,\r\n        UINT AffinityIndex = 0);\r\n\r\n    D3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n\r\n    ID3D12CommandQueue* GetQueueForSwapChainCreation(UINT AffinityIndex);\r\n    ID3D12CommandQueue* GetChildObject(UINT AffinityIndex);\r\n    void WaitForCompletion(UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    CD3DX12AffinityCommandQueue(CD3DX12AffinityDevice* device, ID3D12CommandQueue** commandQueues, UINT Count);\r\n\r\nprivate:\r\n    std::vector<ID3D12CommandList*> mCachedCommandLists;\r\n    ID3D12CommandQueue* mCommandQueues[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandSignature.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityCommandSignature::CD3DX12AffinityCommandSignature(CD3DX12AffinityDevice* device, ID3D12CommandSignature** commandSignatures, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(commandSignatures), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mCommandSignatures[i] = commandSignatures[i];\r\n        }\r\n        else\r\n        {\r\n            mCommandSignatures[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"CommandSignature\";\r\n#endif\r\n}\r\n\r\nID3D12CommandSignature* CD3DX12AffinityCommandSignature::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mCommandSignatures[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityCommandSignature.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityCommandSignature : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityCommandSignature(CD3DX12AffinityDevice* device, ID3D12CommandSignature** commandSignatures, UINT Count);\r\n    ID3D12CommandSignature* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    ID3D12CommandSignature* mCommandSignatures[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityDescriptorHeap.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nD3D12_DESCRIPTOR_HEAP_DESC STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetDesc(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex]->GetDesc();\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetCPUDescriptorHandleForHeapStart(void)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return mDescriptorHeaps[0]->GetCPUDescriptorHandleForHeapStart();\r\n    }\r\n    D3D12_CPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = (SIZE_T)mCPUHeapStart;\r\n    return handle;\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetGPUDescriptorHandleForHeapStart(void)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return mDescriptorHeaps[0]->GetGPUDescriptorHandleForHeapStart();\r\n    }\r\n    D3D12_GPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = (SIZE_T)mGPUHeapStart;\r\n    return handle;\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetActiveCPUDescriptorHandleForHeapStart(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex]->GetCPUDescriptorHandleForHeapStart();\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE CD3DX12AffinityDescriptorHeap::GetActiveGPUDescriptorHandleForHeapStart(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex]->GetGPUDescriptorHandleForHeapStart();\r\n}\r\n\r\nvoid CD3DX12AffinityDescriptorHeap::InitDescriptorHandles(D3D12_DESCRIPTOR_HEAP_TYPE type)\r\n{\r\n    UINT const NodeCount = GetNodeCount();\r\n\r\n    UINT maxindex = 0;\r\n    for (UINT i = 0; i < NodeCount; ++i)\r\n    {\r\n        D3D12_CPU_DESCRIPTOR_HANDLE const CPUBase = mDescriptorHeaps[i]->GetCPUDescriptorHandleForHeapStart();\r\n        D3D12_GPU_DESCRIPTOR_HANDLE const GPUBase = mDescriptorHeaps[i]->GetGPUDescriptorHandleForHeapStart();\r\n        UINT HandleIncrement = 0;\r\n        if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n        {\r\n            HandleIncrement = GetParentDevice()->GetChildObject(0)->GetDescriptorHandleIncrementSize(type);\r\n        }\r\n        for (UINT j = 0; j < mNumDescriptors; ++j)\r\n        {\r\n            mCPUHeapStart[j * NodeCount + i] = CPUBase.ptr + HandleIncrement * j;\r\n            mGPUHeapStart[j * NodeCount + i] = GPUBase.ptr + HandleIncrement * j;\r\n            maxindex = max(maxindex, j * NodeCount + i);\r\n        }\r\n    }\r\n\r\n\r\n    DebugLog(L\"Used up to index %u in heap array\\n\", maxindex);\r\n\r\n    DebugLog(L\"Created a descriptor heap with CPU start at 0x%IX and GPU start a 0x%IX\\n\", mCPUHeapStart, mGPUHeapStart);\r\n    for (UINT i = 0; i < NodeCount; ++i)\r\n    {\r\n        DebugLog(L\"  Device %u CPU starts at 0x%IX and GPU starts at 0x%IX\\n\",\r\n            i, mDescriptorHeaps[i]->GetCPUDescriptorHandleForHeapStart().ptr, mDescriptorHeaps[i]->GetGPUDescriptorHandleForHeapStart().ptr);\r\n    }\r\n\r\n#ifdef D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n    // Validation\r\n    {\r\n        std::lock_guard<std::mutex> lock(GetParentDevice()->MutexPointerRanges);\r\n\r\n        GetParentDevice()->CPUHeapPointerRanges.push_back(std::make_pair((SIZE_T)mCPUHeapStart, (SIZE_T)(mCPUHeapStart + mNumDescriptors * NodeCount)));\r\n        GetParentDevice()->GPUHeapPointerRanges.push_back(std::make_pair((SIZE_T)mGPUHeapStart, (SIZE_T)(mGPUHeapStart + mNumDescriptors * NodeCount)));\r\n    }\r\n#endif\r\n}\r\n\r\nCD3DX12AffinityDescriptorHeap::CD3DX12AffinityDescriptorHeap(CD3DX12AffinityDevice* device, ID3D12DescriptorHeap** descriptorHeaps, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(descriptorHeaps), Count)\r\n    , mCPUHeapStart(nullptr)\r\n    , mGPUHeapStart(nullptr)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mDescriptorHeaps[i] = descriptorHeaps[i];\r\n        }\r\n        else\r\n        {\r\n            mDescriptorHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"DescriptorHeap\";\r\n#endif\r\n}\r\n\r\nCD3DX12AffinityDescriptorHeap::~CD3DX12AffinityDescriptorHeap()\r\n{\r\n    if (mCPUHeapStart != nullptr)\r\n    {\r\n        delete[] mCPUHeapStart;\r\n    }\r\n    if (mGPUHeapStart != nullptr)\r\n    {\r\n        delete[] mGPUHeapStart;\r\n    }\r\n}\r\n\r\nID3D12DescriptorHeap* CD3DX12AffinityDescriptorHeap::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mDescriptorHeaps[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityDescriptorHeap.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityDescriptorHeap : public CD3DX12AffinityPageable\r\n{\r\n    friend class CD3DX12AffinityDevice;\r\n\r\npublic:\r\n    D3D12_DESCRIPTOR_HEAP_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetCPUDescriptorHandleForHeapStart(void);\r\n\r\n    D3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetGPUDescriptorHandleForHeapStart(void);\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetActiveCPUDescriptorHandleForHeapStart(UINT AffinityIndex);\r\n\r\n    D3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetActiveGPUDescriptorHandleForHeapStart(UINT AffinityIndex);\r\n\r\n    void InitDescriptorHandles(D3D12_DESCRIPTOR_HEAP_TYPE type);\r\n\r\n    CD3DX12AffinityDescriptorHeap(CD3DX12AffinityDevice* device, ID3D12DescriptorHeap** descriptorHeaps, UINT Count);\r\n    CD3DX12AffinityDescriptorHeap::~CD3DX12AffinityDescriptorHeap();\r\n\r\n    ID3D12DescriptorHeap* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    UINT mNumDescriptors;\r\n    ID3D12DescriptorHeap* mDescriptorHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n    UINT64* mCPUHeapStart;\r\n    UINT64* mGPUHeapStart;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityDevice.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::SetAffinity(UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityObject::SetAffinity(AffinityMask);\r\n    UpdateActiveDevices();\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::UpdateActiveDevices()\r\n{\r\n    mNumActiveDevices = 0;\r\n    for (int i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (mDevices[i])\r\n        {\r\n            mNumActiveDevices++;\r\n        }\r\n        else\r\n        {\r\n            break;\r\n        }\r\n    }\r\n}\r\n\r\nUINT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetNodeCount(void)\r\n{\r\n    return g_CachedNodeCount;\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::LDAAllNodeMasks()\r\n{\r\n    return (1 << mLDANodeCount) - 1;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandQueue(\r\n    const D3D12_COMMAND_QUEUE_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppCommandQueue,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_COMMAND_QUEUE_DESC Desc = *pDesc;\r\n\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    std::vector<ID3D12CommandQueue*> Queues;\r\n    Queues.resize(GetNodeCount(), nullptr);\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12CommandQueue* Queue = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT hr = Device->CreateCommandQueue(&Desc, IID_PPV_ARGS(&Queue));\r\n                if (S_OK == hr)\r\n                {\r\n                    Queues[i] = Queue;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityCommandQueue* CommandQueue = new CD3DX12AffinityCommandQueue(this, &(Queues[0]), (UINT)Queues.size());\r\n    (*ppCommandQueue) = CommandQueue;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandAllocator(\r\n    D3D12_COMMAND_LIST_TYPE type,\r\n    REFIID riid,\r\n    void** ppCommandAllocator,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12CommandAllocator*> Allocators;\r\n    Allocators.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12CommandAllocator* Allocator = nullptr;\r\n                HRESULT hr = Device->CreateCommandAllocator(type, IID_PPV_ARGS(&Allocator));\r\n                if (S_OK == hr)\r\n                {\r\n                    Allocators[i] = Allocator;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityCommandAllocator* CommandAllocator = new CD3DX12AffinityCommandAllocator(this, &(Allocators[0]), (UINT)Allocators.size(), AffinityMask == 0);\r\n    (*ppCommandAllocator) = CommandAllocator;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateGraphicsPipelineState(\r\n    const D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppPipelineState,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityRootSignature* AffinityRootSignature = static_cast<CD3DX12AffinityRootSignature*>(pDesc->pRootSignature);\r\n\r\n    std::vector<ID3D12PipelineState*> PipelineStates;\r\n    PipelineStates.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        //\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC ActualDescriptor;\r\n        ActualDescriptor = pDesc->ToD3D12();\r\n        ActualDescriptor.pRootSignature = AffinityRootSignature->mRootSignatures[0];\r\n        ActualDescriptor.NodeMask = LDAAllNodeMasks();\r\n\r\n        ID3D12PipelineState* PipelineState = nullptr;\r\n        HRESULT const hr = Device->CreateGraphicsPipelineState(&ActualDescriptor, IID_PPV_ARGS(&PipelineState));\r\n        if (S_OK == hr)\r\n        {\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n                    PipelineState->AddRef();\r\n                    PipelineStates[i] = PipelineState;\r\n\r\n                }\r\n            }\r\n            PipelineState->Release();\r\n        }\r\n        else\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n    CD3DX12AffinityPipelineState* AffinityPipelineState = new CD3DX12AffinityPipelineState(this, &(PipelineStates[0]), (UINT)PipelineStates.size());\r\n    (*ppPipelineState) = AffinityPipelineState;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateComputePipelineState(\r\n    const D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppPipelineState,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityRootSignature* AffinityRootSignature = static_cast<CD3DX12AffinityRootSignature*>(pDesc->pRootSignature);\r\n\r\n    std::vector<ID3D12PipelineState*> PipelineStates;\r\n    PipelineStates.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC ActualDescriptor;\r\n        ActualDescriptor = pDesc->ToD3D12();\r\n        ActualDescriptor.pRootSignature = AffinityRootSignature->mRootSignatures[0];\r\n        ActualDescriptor.NodeMask = LDAAllNodeMasks();\r\n\r\n        ID3D12PipelineState* PipelineState = nullptr;\r\n        HRESULT const hr = Device->CreateComputePipelineState(&ActualDescriptor, IID_PPV_ARGS(&PipelineState));\r\n        if (S_OK == hr)\r\n        {\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n                    PipelineState->AddRef();\r\n                    PipelineStates[i] = PipelineState;\r\n                }\r\n            }\r\n            PipelineState->Release();\r\n        }\r\n        else\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityPipelineState* AffinityPipelineState = new CD3DX12AffinityPipelineState(this, &(PipelineStates[0]), (UINT)PipelineStates.size());\r\n    (*ppPipelineState) = AffinityPipelineState;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandList(\r\n    UINT nodeMask,\r\n    D3D12_COMMAND_LIST_TYPE type,\r\n    CD3DX12AffinityCommandAllocator* pCommandAllocator,\r\n    CD3DX12AffinityPipelineState* pInitialState,\r\n    REFIID riid,\r\n    void** ppCommandList,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12GraphicsCommandList*> CommandLists;\r\n    CommandLists.resize(GetNodeCount(), nullptr);\r\n    CD3DX12AffinityCommandAllocator* WrappedAllocator = static_cast<CD3DX12AffinityCommandAllocator*>(pCommandAllocator);\r\n    CD3DX12AffinityPipelineState* WrappedState = static_cast<CD3DX12AffinityPipelineState*>(pInitialState);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12GraphicsCommandList* CommandList = nullptr;\r\n                HRESULT hr = Device->CreateCommandList(AffinityIndexToNodeMask(i), type,\r\n                    WrappedAllocator->GetChildObject(i),\r\n                    WrappedState ? WrappedState->mPipelineStates[i] : nullptr, IID_PPV_ARGS(&CommandList));\r\n\r\n                if (S_OK == hr)\r\n                {\r\n#if !ALWAYS_RESET_ALL_COMMAND_LISTS\r\n                    //When a new commandlist is created, it is in active state\r\n                    //the next time the active node is changed the commnadlist will be in closed state\r\n                    //So make sure all commandlists on non-active nodes are closed for next reuse\r\n                    if (i != GetActiveNodeIndex() && AffinityMask == 0)\r\n                    {\r\n                        CommandList->Close();\r\n                    }\r\n#endif\r\n                    CommandLists[i] = CommandList;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    CD3DX12AffinityGraphicsCommandList* CommandList = new CD3DX12AffinityGraphicsCommandList(this, &(CommandLists[0]), (UINT)CommandLists.size(), AffinityMask == 0);\r\n    (*ppCommandList) = CommandList;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CheckFeatureSupport(\r\n    D3D12_FEATURE Feature,\r\n    void* pFeatureSupportData,\r\n    UINT FeatureSupportDataSize,\r\n    UINT AffinityIndex)\r\n{\r\n    // Return feature support for device 0 and hope that that's consistent!\r\n    return mDevices[AffinityIndex]->CheckFeatureSupport(Feature, pFeatureSupportData, FeatureSupportDataSize);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateDescriptorHeap(\r\n    const D3D12_DESCRIPTOR_HEAP_DESC* pDescriptorHeapDesc,\r\n    REFIID riid,\r\n    void** ppvHeap,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_DESCRIPTOR_HEAP_DESC Desc = *pDescriptorHeapDesc;\r\n\r\n    std::vector<ID3D12DescriptorHeap*> Heaps;\r\n    Heaps.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12DescriptorHeap* Heap = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT hr = Device->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&Heap));\r\n                if (S_OK == hr)\r\n                {\r\n                    Heaps[i] = Heap;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityDescriptorHeap* DescriptorHeap = new CD3DX12AffinityDescriptorHeap(this, &(Heaps[0]), (UINT)Heaps.size());\r\n    DescriptorHeap->mNumDescriptors = pDescriptorHeapDesc->NumDescriptors;\r\n    if (GetNodeCount() > 1)\r\n    {\r\n        DescriptorHeap->mCPUHeapStart = new UINT64[pDescriptorHeapDesc->NumDescriptors * GetNodeCount()]();\r\n        DescriptorHeap->mGPUHeapStart = new UINT64[pDescriptorHeapDesc->NumDescriptors * GetNodeCount()]();\r\n\r\n        DebugLog(L\"Allocated %u spots in heap array\\n\", pDescriptorHeapDesc->NumDescriptors * GetNodeCount());\r\n\r\n        DescriptorHeap->InitDescriptorHandles(pDescriptorHeapDesc->Type);\r\n    }\r\n    (*ppvHeap) = DescriptorHeap;\r\n\r\n    return S_OK;\r\n}\r\n\r\nUINT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetDescriptorHandleIncrementSize(\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n    UINT AffinityMask)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return mDevices[0]->GetDescriptorHandleIncrementSize(DescriptorHeapType);\r\n    }\r\n    return sizeof(UINT64) * GetNodeCount();\r\n}\r\n\r\nUINT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetActiveDescriptorHandleIncrementSize(\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n    UINT AffinityIndex)\r\n{\r\n    UINT HandleIncrementSize = 0;\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        HandleIncrementSize = mDevices[0]->GetDescriptorHandleIncrementSize(DescriptorHeapType);\r\n    }\r\n    return HandleIncrementSize;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateRootSignature(\r\n    UINT nodeMask,\r\n    const void* pBlobWithRootSignature,\r\n    SIZE_T blobLengthInBytes,\r\n    REFIID riid,\r\n    void** ppvRootSignature,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12RootSignature*> Signatures;\r\n    Signatures.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        ID3D12RootSignature* Signature = nullptr;\r\n        UINT MaskToUse = LDAAllNodeMasks();\r\n        HRESULT hr = Device->CreateRootSignature(MaskToUse, pBlobWithRootSignature, blobLengthInBytes, IID_PPV_ARGS(&Signature));\r\n        if (S_OK == hr)\r\n        {\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n                    Signature->AddRef();\r\n                    Signatures[i] = Signature;\r\n                }\r\n            }\r\n            Signature->Release();\r\n        }\r\n        else\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n    CD3DX12AffinityRootSignature* Signature = new CD3DX12AffinityRootSignature(this, &(Signatures[0]), (UINT)Signatures.size());\r\n    (*ppvRootSignature) = Signature;\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateConstantBufferView(\r\n    const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                D3D12_CONSTANT_BUFFER_VIEW_DESC ActualDesc = *pDesc;\r\n                ActualDesc.BufferLocation = GetGPUVirtualAddress(pDesc->BufferLocation, i);\r\n\r\n                Device->CreateConstantBufferView(&ActualDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateShaderResourceView(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateShaderResourceViewWithAffinity(pResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateShaderResourceViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                Device->CreateShaderResourceView(AffinityResource ? AffinityResource->mResources[i] : nullptr, pDesc, ActualDestDescriptor);\r\n\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateUnorderedAccessView(\r\n    CD3DX12AffinityResource* pResource,\r\n    CD3DX12AffinityResource* pCounterResource,\r\n    const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateUnorderedAccessViewWithAffinity(pResource, pCounterResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateUnorderedAccessViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    CD3DX12AffinityResource* pCounterResource,\r\n    const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n    CD3DX12AffinityResource* AffinityCounterResource = nullptr;\r\n    if (pCounterResource)\r\n    {\r\n        AffinityCounterResource = static_cast<CD3DX12AffinityResource*>(pCounterResource);\r\n    }\r\n\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                Device->CreateUnorderedAccessView(\r\n                    AffinityResource ? AffinityResource->mResources[i] : nullptr,\r\n                    AffinityCounterResource ? AffinityCounterResource->mResources[i] : nullptr,\r\n                    pDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateRenderTargetView(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateRenderTargetViewWithAffinity(pResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateRenderTargetViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                ID3D12Resource* Resource = nullptr;\r\n                if (AffinityResource)\r\n                {\r\n                    Resource = AffinityResource->mResources[i];\r\n                    if (Resource != nullptr)\r\n                    {\r\n                        Device->CreateRenderTargetView(Resource, pDesc, ActualDestDescriptor);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateDepthStencilView(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor)\r\n{\r\n    CreateDepthStencilViewWithAffinity(pResource, pDesc, DestDescriptor, EAffinityMask::AllNodes);\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateDepthStencilViewWithAffinity(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityResource* AffinityResource = nullptr;\r\n    if (pResource)\r\n    {\r\n        AffinityResource = static_cast<CD3DX12AffinityResource*>(pResource);\r\n    }\r\n\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n\r\n                ID3D12Resource* Resource = nullptr;\r\n                if (AffinityResource)\r\n                {\r\n                    Resource = AffinityResource->mResources[i];\r\n                }\r\n                Device->CreateDepthStencilView(Resource, pDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateSampler(\r\n    const D3D12_SAMPLER_DESC* pDesc,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptor, i);\r\n                Device->CreateSampler(pDesc, ActualDestDescriptor);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CopyDescriptors(\r\n    UINT NumDestDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n    const UINT* pDestDescriptorRangeSizes,\r\n    UINT NumSrcDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n    const UINT* pSrcDescriptorRangeSizes,\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n    UINT AffinityMask)\r\n{\r\n    if (NumDestDescriptorRanges == 1 && NumSrcDescriptorRanges == 1)\r\n    {\r\n        return CopyDescriptorsOne(NumDestDescriptorRanges, pDestDescriptorRangeStarts, pDestDescriptorRangeSizes, NumSrcDescriptorRanges,\r\n            pSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes, DescriptorHeapsType, AffinityMask);\r\n    }\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* ActualDestDescriptorRangeStarts = new D3D12_CPU_DESCRIPTOR_HANDLE[NumDestDescriptorRanges];\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* ActualSrcDescriptorRangeStarts = new D3D12_CPU_DESCRIPTOR_HANDLE[NumSrcDescriptorRanges];\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n\r\n                {\r\n                    for (UINT t = 0; t < NumDestDescriptorRanges; ++t)\r\n                    {\r\n                        ActualDestDescriptorRangeStarts[t] = GetCPUHeapPointer(pDestDescriptorRangeStarts[t], i);\r\n                    }\r\n                    for (UINT t = 0; t < NumSrcDescriptorRanges; ++t)\r\n                    {\r\n                        ActualSrcDescriptorRangeStarts[t] = GetCPUHeapPointer(pSrcDescriptorRangeStarts[t], i);\r\n                    }\r\n\r\n                    Device->CopyDescriptors(\r\n                        NumDestDescriptorRanges, ActualDestDescriptorRangeStarts, pDestDescriptorRangeSizes,\r\n                        NumSrcDescriptorRanges, ActualSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes,\r\n                        DescriptorHeapsType);\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    delete[] ActualDestDescriptorRangeStarts;\r\n    delete[] ActualSrcDescriptorRangeStarts;\r\n\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CopyDescriptorsOne(\r\n    UINT NumDestDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n    const UINT* pDestDescriptorRangeSizes,\r\n    UINT NumSrcDescriptorRanges,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n    const UINT* pSrcDescriptorRangeSizes,\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n    UINT AffinityMask)\r\n{\r\n    UINT ActiveNodeIndex = GetActiveNodeIndex();\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptorRangeStarts[1];\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ActualSrcDescriptorRangeStarts[1];\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                {\r\n                    ActualDestDescriptorRangeStarts[0] = GetCPUHeapPointer(pDestDescriptorRangeStarts[0], i);\r\n                    ActualSrcDescriptorRangeStarts[0] = GetCPUHeapPointer(pSrcDescriptorRangeStarts[0], i);\r\n\r\n                    Device->CopyDescriptors(\r\n                        NumDestDescriptorRanges, ActualDestDescriptorRangeStarts, pDestDescriptorRangeSizes,\r\n                        NumSrcDescriptorRanges, ActualSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes,\r\n                        DescriptorHeapsType);\r\n                }\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::CopyDescriptorsSimple(\r\n    UINT NumDescriptors,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptorRangeStart,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRangeStart,\r\n    D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDestDescriptor = GetCPUHeapPointer(DestDescriptorRangeStart, i);\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualSrcDescriptor = GetCPUHeapPointer(SrcDescriptorRangeStart, i);\r\n\r\n                Device->CopyDescriptorsSimple(NumDescriptors, ActualDestDescriptor, ActualSrcDescriptor, DescriptorHeapsType);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nD3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE CD3DX12AffinityDevice::GetResourceAllocationInfo(\r\n    UINT visibleMask,\r\n    UINT numResourceDescs,\r\n    const D3D12_RESOURCE_DESC* pResourceDescs,\r\n    UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetResourceAllocationInfo(visibleMask, numResourceDescs, pResourceDescs);\r\n}\r\n\r\nD3D12_HEAP_PROPERTIES STDMETHODCALLTYPE CD3DX12AffinityDevice::GetCustomHeapProperties(\r\n    UINT nodeMask,\r\n    D3D12_HEAP_TYPE heapType,\r\n    UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetCustomHeapProperties(nodeMask, heapType);\r\n}\r\n\r\nUINT64 GetBufferSizeForResource(\r\n    ID3D12Resource* pResource)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pResource->GetDesc();\r\n    UINT64 Size = 0;\r\n    switch (Desc.Dimension)\r\n    {\r\n    case D3D12_RESOURCE_DIMENSION_BUFFER:\r\n    {\r\n        DEBUG_ASSERT(Desc.Height == 1);\r\n        Size = Desc.Width;\r\n    }\r\n    break;\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n    {\r\n        ID3D12Device* pDevice;\r\n        pResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n        auto info = pDevice->GetResourceAllocationInfo(0, 1, &Desc);\r\n        pDevice->Release();\r\n\r\n        Size = info.SizeInBytes;\r\n    }\r\n    break;\r\n    default:\r\n    case D3D12_RESOURCE_DIMENSION_UNKNOWN:\r\n    {\r\n        DEBUG_ASSERT(false);\r\n    }\r\n    break;\r\n    }\r\n    return Size;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommittedResource(\r\n    const D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n    D3D12_HEAP_FLAGS HeapFlags,\r\n    const D3D12_RESOURCE_DESC* pResourceDesc,\r\n    D3D12_RESOURCE_STATES InitialResourceState,\r\n    const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n    REFIID riid,\r\n    void** ppvResource,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_HEAP_PROPERTIES& Properties = *(const_cast<D3D12_HEAP_PROPERTIES*>(pHeapProperties));\r\n\r\n    ID3D12Resource* Resources[D3DX12_MAX_ACTIVE_NODES] = {};\r\n    ID3D12Heap* Heaps[D3DX12_MAX_ACTIVE_NODES] = {};\r\n    ID3D12Heap** pHeaps = nullptr;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        D3D12_HEAP_PROPERTIES heapProp = Device->GetCustomHeapProperties(0, pHeapProperties->Type);\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                UINT nodeMask = AffinityIndexToNodeMask(i);\r\n                Properties.CreationNodeMask = nodeMask;\r\n                Properties.VisibleNodeMask = LDAAllNodeMasks();\r\n                if (heapProp.MemoryPoolPreference == D3D12_MEMORY_POOL_L0)\r\n                {\r\n                    // System memory, don't create the resource more than once or manager syncronization.\r\n                    if (i == 0)\r\n                    {\r\n                        HRESULT hr = Device->CreateCommittedResource(&Properties, HeapFlags, pResourceDesc, InitialResourceState, pOptimizedClearValue, IID_PPV_ARGS(&Resources[i]));\r\n                        RETURN_IF_FAILED(hr);\r\n                    }\r\n                    else\r\n                    {\r\n                        Resources[i] = Resources[i - 1];\r\n                        Resources[i]->AddRef();\r\n                    }\r\n\r\n                }\r\n                else\r\n                {\r\n                    Properties.VisibleNodeMask = nodeMask;\r\n#if TILE_MAPPING_GPUVA\r\n                    if (GetNodeCount() > 1 &&\r\n                        pResourceDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n                    {\r\n                        UINT64 Width = (pResourceDesc->Width + D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES - 1)\r\n                            & ~(D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES - 1);\r\n                        // Video memory buffers - allocate heaps on each GPU and a single reserved resource so we don't have to remap GPUVA.\r\n                        D3D12_HEAP_DESC HeapDesc = { Width, Properties, pResourceDesc->Alignment, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS };\r\n                        HRESULT hr = Device->CreateHeap(&HeapDesc, IID_PPV_ARGS(&Heaps[i]));\r\n                        RETURN_IF_FAILED(hr);\r\n                    }\r\n                    else\r\n#endif\r\n                    {\r\n                        HRESULT hr = Device->CreateCommittedResource(&Properties, HeapFlags, pResourceDesc, InitialResourceState, pOptimizedClearValue, IID_PPV_ARGS(&Resources[i]));\r\n                        RETURN_IF_FAILED(hr);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n#if TILE_MAPPING_GPUVA\r\n        if (GetNodeCount() > 1 &&\r\n            pResourceDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&\r\n            heapProp.MemoryPoolPreference != D3D12_MEMORY_POOL_L0)\r\n        {\r\n            HRESULT hr = Device->CreateReservedResource(pResourceDesc, InitialResourceState, pOptimizedClearValue, IID_PPV_ARGS(&Resources[0]));\r\n            RETURN_IF_FAILED(hr);\r\n\r\n            pHeaps = Heaps;\r\n\r\n            for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n            {\r\n                if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                {\r\n\r\n                    if (i > 0)\r\n                    {\r\n                        Resources[i] = Resources[0];\r\n                        Resources[i]->AddRef();\r\n                    }\r\n\r\n                    D3D12_TILED_RESOURCE_COORDINATE Coord = {};\r\n                    D3D12_TILE_REGION_SIZE Region = { (UINT)(((pResourceDesc->Width - 1ull) / D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES) + 1) };\r\n                    D3D12_TILE_RANGE_FLAGS RangeFlags = D3D12_TILE_RANGE_FLAG_NONE;\r\n                    UINT RangeStart = 0;\r\n\r\n                    UINT HeapIndex = i;\r\n#if FORCE_REMOTE_TILE_MAPPING_GPUVA\r\n                    HeapIndex = AffinityIndices[(Counter + 1) % IndicesCount];\r\n#endif\r\n\r\n                    mSyncCommandQueues[i]->UpdateTileMappings(Resources[i], 1, &Coord, &Region, Heaps[HeapIndex], 1, &RangeFlags, &RangeStart, &Region.NumTiles, D3D12_TILE_MAPPING_FLAG_NO_HAZARD);\r\n                }\r\n\r\n                ID3D12Fence* pFence = nullptr;\r\n                RETURN_IF_FAILED(Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence)));\r\n                HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n                for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n                {\r\n                    if (((1 << i) & EffectiveAffinityMask) != 0)\r\n                    {\r\n                        mSyncCommandQueues[i]->Signal(pFence, i + 1);\r\n                        pFence->SetEventOnCompletion(i + 1, hEvent);\r\n                        WaitForSingleObject(hEvent, INFINITE);\r\n                    }\r\n                }\r\n                pFence->Release();\r\n            }\r\n        }\r\n#endif\r\n    }\r\n\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(this, Resources, GetNodeCount(), pHeaps);\r\n    Resource->mReferenceCount = 0;\r\n    Resource->mBufferSize = GetBufferSizeForResource(Resources[0]);\r\n    Resource->mCPUPageProperty = mDevices[0]->GetCustomHeapProperties(0, pHeapProperties->Type).CPUPageProperty;\r\n    {\r\n        ReleaseLog(L\"D3DX12AffinityLayer: Committed resource is not write combine, creating no shadow buffer.\\n\", Resource->mBufferSize);\r\n        Resource->mShadowBuffer = nullptr;\r\n    }\r\n\r\n    (*ppvResource) = Resource;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateHeap(\r\n    const D3D12_HEAP_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppvHeap,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Heap*> Heaps;\r\n    Heaps.resize(GetNodeCount(), nullptr);\r\n    D3D12_HEAP_PROPERTIES& Properties = (const_cast<D3D12_HEAP_DESC*>(pDesc))->Properties;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Heap* Heap = nullptr;\r\n                Properties.CreationNodeMask = AffinityIndexToNodeMask(i);\r\n                Properties.VisibleNodeMask = LDAAllNodeMasks();\r\n\r\n                HRESULT hr = Device->CreateHeap(pDesc, IID_PPV_ARGS(&Heap));\r\n                if (S_OK == hr)\r\n                {\r\n                    Heaps[i] = Heap;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityHeap* Heap = new CD3DX12AffinityHeap(this, &(Heaps[0]), (UINT)Heaps.size());\r\n    (*ppvHeap) = Heap;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreatePlacedResource(\r\n    CD3DX12AffinityHeap* pHeap,\r\n    UINT64 HeapOffset,\r\n    const D3D12_RESOURCE_DESC* pDesc,\r\n    D3D12_RESOURCE_STATES InitialState,\r\n    const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n    REFIID riid,\r\n    void** ppvResource,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Resource*> Resources;\r\n    Resources.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n#if TILE_MAPPING_GPUVA\r\n        if (pDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n        {\r\n            return E_NOTIMPL;\r\n        }\r\n#endif\r\n\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = nullptr;\r\n\r\n                HRESULT hr = Device->CreatePlacedResource(\r\n                    pHeap->GetChildObject(i),\r\n                    HeapOffset,\r\n                    pDesc,\r\n                    InitialState,\r\n                    pOptimizedClearValue,\r\n                    IID_PPV_ARGS(&Resource));\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Resource;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(this, &(Resources[0]), (UINT)Resources.size());\r\n    (*ppvResource) = Resource;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateReservedResource(\r\n    const D3D12_RESOURCE_DESC* pDesc,\r\n    D3D12_RESOURCE_STATES InitialState,\r\n    const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n    REFIID riid,\r\n    void** ppvResource,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Resource*> Resources;\r\n    Resources.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n#if TILE_MAPPING_GPUVA\r\n        if (pDesc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n        {\r\n            return E_NOTIMPL;\r\n        }\r\n#endif\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = nullptr;\r\n\r\n                HRESULT hr = Device->CreateReservedResource(\r\n                    pDesc,\r\n                    InitialState,\r\n                    pOptimizedClearValue,\r\n                    IID_PPV_ARGS(&Resource));\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Resource;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(this, &(Resources[0]), (UINT)Resources.size());\r\n    (*ppvResource) = Resource;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::MakeResident(\r\n    UINT NumObjects,\r\n    CD3DX12AffinityPageable* const* ppObjects,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Pageable*> Objects(NumObjects);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                for (UINT j = 0; j < NumObjects; ++j)\r\n                {\r\n                    Objects[j] = static_cast<CD3DX12AffinityPageable*>(ppObjects[j])->mPageables[i];\r\n                }\r\n                HRESULT const hr = Device->MakeResident(NumObjects, Objects.data());\r\n                if (S_OK != hr)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::Evict(\r\n    UINT NumObjects,\r\n    CD3DX12AffinityPageable* const* ppObjects,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<CD3DX12AffinityPageable*> AffinityPageables;\r\n    AffinityPageables.resize(NumObjects);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < NumObjects; ++i)\r\n    {\r\n        AffinityPageables[i] = static_cast<CD3DX12AffinityPageable*>(ppObjects[i]);\r\n    }\r\n\r\n    std::vector<ID3D12Pageable*> Pageables;\r\n    Pageables.resize(NumObjects);\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                for (UINT j = 0; j < NumObjects; ++j)\r\n                {\r\n                    Pageables[j] = AffinityPageables[j]->mPageables[i];\r\n                }\r\n\r\n                HRESULT const hr = Device->Evict(NumObjects, Pageables.data());\r\n                if (S_OK != hr)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateFence(\r\n    UINT64 InitialValue,\r\n    D3D12_FENCE_FLAGS Flags,\r\n    REFIID riid,\r\n    void** ppFence,\r\n    UINT AffinityMask)\r\n{\r\n    std::vector<ID3D12Fence*> Fences;\r\n    Fences.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        ID3D12Fence* Fence = nullptr;\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                HRESULT const hr = Device->CreateFence(InitialValue, Flags, IID_PPV_ARGS(&Fence));\r\n                if (S_OK == hr)\r\n                {\r\n                    Fences[i] = Fence;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    CD3DX12AffinityFence* Fence = new CD3DX12AffinityFence(this, &(Fences[0]), (UINT)Fences.size());\r\n    (*ppFence) = Fence;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::GetDeviceRemovedReason(UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetDeviceRemovedReason();\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::GetCopyableFootprints(\r\n    const D3D12_RESOURCE_DESC* pResourceDesc,\r\n    UINT FirstSubresource,\r\n    UINT NumSubresources,\r\n    UINT64 BaseOffset,\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    UINT* pNumRows,\r\n    UINT64* pRowSizeInBytes,\r\n    UINT64* pTotalBytes,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        Device->GetCopyableFootprints(\r\n            pResourceDesc,\r\n            FirstSubresource,\r\n            NumSubresources,\r\n            BaseOffset,\r\n            pLayouts,\r\n            pNumRows,\r\n            pRowSizeInBytes,\r\n            pTotalBytes);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateQueryHeap(\r\n    const D3D12_QUERY_HEAP_DESC* pDesc,\r\n    REFIID riid,\r\n    void** ppvHeap,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_QUERY_HEAP_DESC Desc = *pDesc;\r\n\r\n    std::vector<ID3D12QueryHeap*> QueryHeaps;\r\n    QueryHeaps.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12QueryHeap* QueryHeap = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT const hr = Device->CreateQueryHeap(&Desc, IID_PPV_ARGS(&QueryHeap));\r\n                if (S_OK == hr)\r\n                {\r\n                    QueryHeaps[i] = QueryHeap;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityQueryHeap* QueryHeap = new CD3DX12AffinityQueryHeap(this, &(QueryHeaps[0]), (UINT)QueryHeaps.size());\r\n    (*ppvHeap) = QueryHeap;\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::SetStablePowerState(\r\n    BOOL Enable,\r\n    UINT AffinityMask)\r\n{\r\n    for (UINT ActiveIndex = 0; ActiveIndex < mNumActiveDevices; ++ActiveIndex)\r\n    {\r\n        ID3D12Device* Device = mDevices[ActiveIndex];\r\n        UINT const i = ActiveIndex;\r\n\r\n        HRESULT const hr = Device->SetStablePowerState(Enable);\r\n\r\n        if (S_OK != hr)\r\n        {\r\n            return hr;\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDevice::CreateCommandSignature(\r\n    const D3D12_COMMAND_SIGNATURE_DESC* pDesc,\r\n    CD3DX12AffinityRootSignature* pRootSignature,\r\n    REFIID riid,\r\n    CD3DX12AffinityCommandSignature** ppvCommandSignature,\r\n    UINT AffinityMask)\r\n{\r\n    D3D12_COMMAND_SIGNATURE_DESC Desc = *pDesc;\r\n    CD3DX12AffinityRootSignature* RootSignature = static_cast<CD3DX12AffinityRootSignature*>(pRootSignature);\r\n\r\n    std::vector<ID3D12CommandSignature*> CommandSignatures;\r\n    CommandSignatures.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        ID3D12Device* Device = mDevices[0];\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12CommandSignature* CommandSignature = nullptr;\r\n\r\n                Desc.NodeMask = AffinityIndexToNodeMask(i);\r\n                HRESULT const hr = Device->CreateCommandSignature(&Desc, RootSignature ? RootSignature->mRootSignatures[i] : nullptr, IID_PPV_ARGS(&CommandSignature));\r\n                if (S_OK == hr)\r\n                {\r\n                    CommandSignatures[i] = CommandSignature;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    CD3DX12AffinityCommandSignature* CommandSignature = new CD3DX12AffinityCommandSignature(this, &(CommandSignatures[0]), (UINT)CommandSignatures.size());\r\n    (*ppvCommandSignature) = CommandSignature;\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityDevice::GetResourceTiling(\r\n    CD3DX12AffinityResource* pTiledResource,\r\n    UINT* pNumTilesForEntireResource,\r\n    D3D12_PACKED_MIP_INFO* pPackedMipDesc,\r\n    D3D12_TILE_SHAPE* pStandardTileShapeForNonPackedMips,\r\n    UINT* pNumSubresourceTilings,\r\n    UINT FirstSubresourceTilingToGet,\r\n    D3D12_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips,\r\n    UINT AffinityIndex)\r\n{\r\n    mDevices[AffinityIndex]->GetResourceTiling(\r\n        pTiledResource->mResources[AffinityIndex],\r\n        pNumTilesForEntireResource,\r\n        pPackedMipDesc,\r\n        pStandardTileShapeForNonPackedMips,\r\n        pNumSubresourceTilings,\r\n        FirstSubresourceTilingToGet,\r\n        pSubresourceTilingsForNonPackedMips);\r\n}\r\n\r\nLUID STDMETHODCALLTYPE CD3DX12AffinityDevice::GetAdapterLuid(UINT AffinityIndex)\r\n{\r\n    return mDevices[AffinityIndex]->GetAdapterLuid();\r\n}\r\n\r\nID3D12Device* CD3DX12AffinityDevice::GetChildObject(UINT AffinityIndex)\r\n{\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        return mDevices[0];\r\n    }\r\n    else\r\n    {\r\n        return mDevices[AffinityIndex];\r\n    }\r\n}\r\n\r\nbool CD3DX12AffinityDevice::IsD3D()\r\n{\r\n    return true;\r\n}\r\n\r\nCD3DX12AffinityDevice::CD3DX12AffinityDevice(ID3D12Device** devices, UINT Count, EAffinityMode::Mask affinitymode)\r\n    : CD3DX12AffinityObject(this, reinterpret_cast<IUnknown**>(devices), Count)\r\n{\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Device\";\r\n#endif\r\n    mAffinityMode = affinitymode;\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mDevices[i] = devices[i];\r\n        }\r\n        else\r\n        {\r\n            mDevices[i] = nullptr;\r\n        }\r\n    }\r\n    if (mAffinityMode == EAffinityMode::LDA)\r\n    {\r\n        mLDANodeCount = min(mDevices[0]->GetNodeCount(), D3DX12_MAX_ACTIVE_NODES);\r\n    }\r\n    else\r\n    {\r\n        mLDANodeCount = 0;\r\n    }\r\n    mDeviceCount = Count;\r\n    if (mAffinityMode == EAffinityMode::LDA)\r\n    {\r\n        g_CachedNodeCount = mLDANodeCount;\r\n        g_CachedNodeMask = (1 << mLDANodeCount) - 1;\r\n\r\n    }\r\n    else\r\n    {\r\n        g_CachedNodeCount = mDeviceCount;\r\n        g_CachedNodeMask = (1 << mDeviceCount) - 1;\r\n\r\n    }\r\n    mAffinityRenderingMode = EAffinityRenderingMode::AFR;\r\n\r\n    mParentDevice = this;\r\n    // Re-calculate the affinity based on the effective affinity node mask.\r\n    SetAffinity(GetNodeMask());\r\n\r\n    UpdateActiveDevices();\r\n\r\n    // Initialize sync queues for cross frame resources.\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        for (UINT i = 0; i < GetNodeCount(); i++)\r\n        {\r\n            D3D12_COMMAND_QUEUE_DESC desc;\r\n            desc.Type = D3D12_COMMAND_LIST_TYPE_COPY;\r\n            desc.Priority = 0;\r\n            desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;\r\n            desc.NodeMask = 1 << i;\r\n\r\n            mDevices[0]->CreateCommandQueue(&desc, IID_PPV_ARGS(&mSyncCommandQueues[i]));\r\n            mDevices[0]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mSyncFences[i]));\r\n        }\r\n    }\r\n}\r\n\r\nCD3DX12AffinityDevice::~CD3DX12AffinityDevice()\r\n{\r\n    for (UINT i = 0; i < GetNodeCount(); i++)\r\n    {\r\n        mSyncCommandQueues[i]->Release();\r\n        mSyncFences[i]->Release();\r\n    }\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::GetDeviceCount()\r\n{\r\n    return mDeviceCount;\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE CD3DX12AffinityDevice::GetCPUHeapPointer(D3D12_CPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return Original;\r\n    }\r\n#ifdef D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n    // Validation\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexPointerRanges);\r\n\r\n        bool IsOK = false;\r\n        for (auto Range : GetParentDevice()->CPUHeapPointerRanges)\r\n        {\r\n            if (Original.ptr >= Range.first && Original.ptr < Range.second)\r\n            {\r\n                IsOK = true;\r\n                break;\r\n            }\r\n        }\r\n\r\n        if (!IsOK)\r\n        {\r\n            DebugLog(L\"Found a pointer outside of expected memory ranges!\\n\");\r\n            DEBUG_FAIL_MESSAGE(L\"Found a pointer outside of expected memory ranges!\\n\");\r\n        }\r\n\r\n    }\r\n#endif\r\n    D3D12_CPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = static_cast<size_t>(((UINT64*)Original.ptr)[NodeIndex]);\r\n    return handle;\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE CD3DX12AffinityDevice::GetGPUHeapPointer(D3D12_GPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex)\r\n{\r\n    if (GetNodeCount() == 1)\r\n    {\r\n        return Original;\r\n    }\r\n#ifdef D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n    // Validation\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexPointerRanges);\r\n\r\n        bool IsOK = false;\r\n        for (auto Range : GetParentDevice()->GPUHeapPointerRanges)\r\n        {\r\n            if (Original.ptr >= Range.first && Original.ptr < Range.second)\r\n            {\r\n                IsOK = true;\r\n                break;\r\n            }\r\n        }\r\n\r\n        if (!IsOK)\r\n        {\r\n            DebugLog(L\"Found a pointer outside of expected memory ranges!\\n\");\r\n            DEBUG_FAIL_MESSAGE(\"Found a pointer outside of expected memory ranges!\\n\");\r\n        }\r\n\r\n    }\r\n#endif\r\n    D3D12_GPU_DESCRIPTOR_HANDLE handle;\r\n    handle.ptr = ((UINT64*)Original.ptr)[NodeIndex];\r\n    return handle;\r\n}\r\n\r\nD3D12_GPU_VIRTUAL_ADDRESS CD3DX12AffinityDevice::GetGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS const& Original, UINT const NodeIndex)\r\n{\r\n    if (NodeIndex == 0)\r\n        return Original;\r\n\r\n    if (Original == 0)\r\n        return 0;\r\n\r\n#if TILE_MAPPING_GPUVA\r\n    if (GetAffinityMode() == EAffinityMode::LDA)\r\n        return Original;\r\n#endif\r\n\r\n\r\n    // This function searches through our list of known GPU virtual addresses and finds the next lowest (or equal) address to the Original\r\n    // The Original pointer is then assumed to be an offset into some segment of memory that starts at the next lowest address.\r\n    // We use that offset against the equivalent base addresses across all devices.\r\n\r\n    // TODO: It is inefficient to look through this every time i.e. for each DeviceIndex.\r\n    // Possibly just cache the NextLowest here or change the interface to return a vector of offsetted pointers.\r\n    // Should probably do both, since surely the user will be using heap pointers often and it would be nice\r\n    // to simply save the base pointers for future lookup.\r\n    // Of course this would all go away if we had a way to have consistent virtual addresses across all devices!\r\n    // Also it might be possible to use proxy CPU memory allocated by the affinity layer to make this a simple lookup - see GetGPUHeapPointer.\r\n    D3D12_GPU_VIRTUAL_ADDRESS NextLowest;\r\n    D3D12_GPU_VIRTUAL_ADDRESS Return;\r\n\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexGPUVirtualAddresses);\r\n\r\n        auto NextGreatestIterator = GPUVirtualAddresses.upper_bound(Original);\r\n        auto NextLowestIterator = --NextGreatestIterator;\r\n        NextLowest = NextLowestIterator->first;\r\n        Return = NextLowestIterator->second[NodeIndex];\r\n    }\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS const Offset = Original - NextLowest;\r\n    Return += Offset;\r\n\r\n    return Return;\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::WriteApplicationMessage(D3D12_MESSAGE_SEVERITY const Severity, char const* const Message)\r\n{\r\n    DebugLog(L\"Writing application message: %s\\n\", Message);\r\n    if (InfoQueue)\r\n    {\r\n        InfoQueue->AddApplicationMessage(Severity, Message);\r\n    }\r\n    else\r\n    {\r\n        DebugLog(L\"No InfoQueue to write application message.\\n\");\r\n    }\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::AffinityIndexToNodeMask(UINT const Index)\r\n{\r\n#ifndef D3DX12_SIMULATE_LDA_ON_SINGLE_NODE  \r\n    if (mAffinityMode == EAffinityMode::LDA)\r\n        return 1 << Index;\r\n    else\r\n#endif\r\n        return 0;\r\n}\r\n\r\nEAffinityMode::Mask CD3DX12AffinityDevice::GetAffinityMode()\r\n{\r\n    return mAffinityMode;\r\n}\r\n\r\nEAffinityRenderingMode::Mask CD3DX12AffinityDevice::GetAffinityRenderingMode()\r\n{\r\n    return mAffinityRenderingMode;\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::SetAffinityRenderingMode(EAffinityRenderingMode::Mask renderingmode)\r\n{\r\n    mAffinityRenderingMode = renderingmode;\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::GetActiveNodeMask()\r\n{\r\n    return 1 << g_ActiveNodeIndex;\r\n}\r\n\r\nvoid CD3DX12AffinityDevice::SwitchToNextNode()\r\n{\r\n#ifdef SYNC_CROSS_FRAME_RESOURCES\r\n    // Sync all cross frame resources.\r\n    {\r\n        std::lock_guard<std::mutex> lock(MutexSyncResources);\r\n        for (UINT i = 0; i < mSyncResources.size(); i++)\r\n        {\r\n            mSyncResources[i]->BroadcastResourceForCrossGPUSync();\r\n        }\r\n\r\n        //#ifdef SERIALIZE_COMMNANDLIST_EXECUTION\r\n        ID3D12Fence* pFence;\r\n        GetParentDevice()->mDevices[0]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n        mSyncCommandQueues[mActiveNodeIndex]->Signal(pFence, 1);\r\n        HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n        pFence->SetEventOnCompletion(1, hEvent);\r\n        WaitForSingleObject(hEvent, INFINITE);\r\n        CloseHandle(hEvent);\r\n        pFence->Release();\r\n        if (FAILED(mDevices[0]->GetDeviceRemovedReason()))\r\n        {\r\n            __debugbreak();\r\n        }\r\n        //#endif\r\n    }\r\n#endif\r\n\r\n    g_ActiveNodeIndex = (g_ActiveNodeIndex + 1) % GetNodeCount();\r\n}\r\n\r\nUINT CD3DX12AffinityDevice::g_ActiveNodeIndex = 0;\r\nUINT CD3DX12AffinityDevice::g_CachedNodeCount = 0;\r\nUINT CD3DX12AffinityDevice::g_CachedNodeMask = 0;\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityDevice.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"d3dx12affinity_structs.h\"\r\n#include \"CD3DX12AffinityObject.h\"\r\n\r\nstruct D3DX12_CPU_DESCRIPTOR_HANDLE_COMPARATOR\r\n{\r\n    bool operator()(D3D12_CPU_DESCRIPTOR_HANDLE const& Left, D3D12_CPU_DESCRIPTOR_HANDLE const& Right) const\r\n    {\r\n        return Left.ptr < Right.ptr;\r\n    }\r\n};\r\n\r\nstruct D3DX12_GPU_DESCRIPTOR_HANDLE_COMPARATOR\r\n{\r\n    bool operator()(D3D12_GPU_DESCRIPTOR_HANDLE const& Left, D3D12_GPU_DESCRIPTOR_HANDLE const& Right) const\r\n    {\r\n        return Left.ptr < Right.ptr;\r\n    }\r\n};\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityDevice : public CD3DX12AffinityObject\r\n{\r\n    friend class CD3DX12AffinityResource;\r\n\r\npublic:\r\n    virtual void STDMETHODCALLTYPE SetAffinity(\r\n        _In_  UINT AffinityMask);\r\n\r\n    UINT STDMETHODCALLTYPE GetNodeCount(void);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandQueue(\r\n        _In_  const D3D12_COMMAND_QUEUE_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppCommandQueue,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandAllocator(\r\n        _In_  D3D12_COMMAND_LIST_TYPE type,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppCommandAllocator,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateGraphicsPipelineState(\r\n        _In_  const D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppPipelineState,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateComputePipelineState(\r\n        _In_  const D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppPipelineState,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandList(\r\n        _In_  UINT nodeMask,\r\n        _In_  D3D12_COMMAND_LIST_TYPE type,\r\n        _In_  CD3DX12AffinityCommandAllocator* pCommandAllocator,\r\n        _In_opt_  CD3DX12AffinityPipelineState* pInitialState,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppCommandList,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CheckFeatureSupport(\r\n        D3D12_FEATURE Feature,\r\n        _Inout_updates_bytes_(FeatureSupportDataSize)  void* pFeatureSupportData,\r\n        UINT FeatureSupportDataSize,\r\n        _In_ UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateDescriptorHeap(\r\n        _In_  const D3D12_DESCRIPTOR_HEAP_DESC* pDescriptorHeapDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppvHeap,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    UINT STDMETHODCALLTYPE GetDescriptorHandleIncrementSize(\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    UINT STDMETHODCALLTYPE GetActiveDescriptorHandleIncrementSize(\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapType,\r\n        _In_opt_  UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateRootSignature(\r\n        _In_  UINT nodeMask,\r\n        _In_reads_(blobLengthInBytes)  const void* pBlobWithRootSignature,\r\n        _In_  SIZE_T blobLengthInBytes,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppvRootSignature,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateConstantBufferView(\r\n        _In_opt_  const D3D12_CONSTANT_BUFFER_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateShaderResourceView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateShaderResourceViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateUnorderedAccessView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  CD3DX12AffinityResource* pCounterResource,\r\n        _In_opt_  const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateUnorderedAccessViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  CD3DX12AffinityResource* pCounterResource,\r\n        _In_opt_  const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateRenderTargetView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateRenderTargetViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_RENDER_TARGET_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateDepthStencilView(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor);\r\n\r\n    void STDMETHODCALLTYPE CreateDepthStencilViewWithAffinity(\r\n        _In_opt_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CreateSampler(\r\n        _In_  const D3D12_SAMPLER_DESC* pDesc,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyDescriptors(\r\n        _In_  UINT NumDestDescriptorRanges,\r\n        _In_reads_(NumDestDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n        _In_reads_opt_(NumDestDescriptorRanges)  const UINT* pDestDescriptorRangeSizes,\r\n        _In_  UINT NumSrcDescriptorRanges,\r\n        _In_reads_(NumSrcDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n        _In_reads_opt_(NumSrcDescriptorRanges)  const UINT* pSrcDescriptorRangeSizes,\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyDescriptorsOne(\r\n        _In_  UINT NumDestDescriptorRanges,\r\n        _In_reads_(NumDestDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pDestDescriptorRangeStarts,\r\n        _In_reads_opt_(NumDestDescriptorRanges)  const UINT* pDestDescriptorRangeSizes,\r\n        _In_  UINT NumSrcDescriptorRanges,\r\n        _In_reads_(NumSrcDescriptorRanges)  const D3D12_CPU_DESCRIPTOR_HANDLE* pSrcDescriptorRangeStarts,\r\n        _In_reads_opt_(NumSrcDescriptorRanges)  const UINT* pSrcDescriptorRangeSizes,\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE CopyDescriptorsSimple(\r\n        _In_  UINT NumDescriptors,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptorRangeStart,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE SrcDescriptorRangeStart,\r\n        _In_  D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeapsType,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    D3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE GetResourceAllocationInfo(\r\n        _In_  UINT visibleMask,\r\n        _In_  UINT numResourceDescs,\r\n        _In_reads_(numResourceDescs)  const D3D12_RESOURCE_DESC* pResourceDescs,\r\n        UINT AffinityIndex = 0);\r\n\r\n    D3D12_HEAP_PROPERTIES STDMETHODCALLTYPE GetCustomHeapProperties(\r\n        _In_  UINT nodeMask,\r\n        D3D12_HEAP_TYPE heapType,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommittedResource(\r\n        _In_  const D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n        D3D12_HEAP_FLAGS HeapFlags,\r\n        _In_  const D3D12_RESOURCE_DESC* pResourceDesc,\r\n        D3D12_RESOURCE_STATES InitialResourceState,\r\n        _In_opt_  const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n        _In_ REFIID riid,\r\n        _Outptr_opt_  void** ppvResource,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateHeap(\r\n        _In_  const D3D12_HEAP_DESC* pDesc,\r\n        REFIID riid,\r\n        _Outptr_opt_  void** ppvHeap,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreatePlacedResource(\r\n        _In_  CD3DX12AffinityHeap* pHeap,\r\n        UINT64 HeapOffset,\r\n        _In_  const D3D12_RESOURCE_DESC* pDesc,\r\n        D3D12_RESOURCE_STATES InitialState,\r\n        _In_opt_  const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n        REFIID riid,\r\n        _Outptr_opt_  void** ppvResource,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateReservedResource(\r\n        _In_  const D3D12_RESOURCE_DESC* pDesc,\r\n        D3D12_RESOURCE_STATES InitialState,\r\n        _In_opt_  const D3D12_CLEAR_VALUE* pOptimizedClearValue,\r\n        REFIID riid,\r\n        _Outptr_opt_  void** ppvResource,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE MakeResident(\r\n        UINT NumObjects,\r\n        _In_reads_(NumObjects)  CD3DX12AffinityPageable* const* ppObjects,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE Evict(\r\n        UINT NumObjects,\r\n        _In_reads_(NumObjects)  CD3DX12AffinityPageable* const* ppObjects,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateFence(\r\n        UINT64 InitialValue,\r\n        D3D12_FENCE_FLAGS Flags,\r\n        _In_ REFIID riid,\r\n        _COM_Outptr_  void** ppFence,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(UINT AffinityIndex = 0);\r\n\r\n    void STDMETHODCALLTYPE GetCopyableFootprints(\r\n        _In_  const D3D12_RESOURCE_DESC* pResourceDesc,\r\n        _In_range_(0, D3D12_REQ_SUBRESOURCES)  UINT FirstSubresource,\r\n        _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource)  UINT NumSubresources,\r\n        UINT64 BaseOffset,\r\n        _Out_writes_opt_(NumSubresources)  D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n        _Out_writes_opt_(NumSubresources)  UINT* pNumRows,\r\n        _Out_writes_opt_(NumSubresources)  UINT64* pRowSizeInBytes,\r\n        _Out_opt_  UINT64* pTotalBytes,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateQueryHeap(\r\n        _In_  const D3D12_QUERY_HEAP_DESC* pDesc,\r\n        _In_ REFIID riid,\r\n        _Outptr_opt_  void** ppvHeap,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetStablePowerState(\r\n        BOOL Enable,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE CreateCommandSignature(\r\n        _In_  const D3D12_COMMAND_SIGNATURE_DESC* pDesc,\r\n        _In_opt_  CD3DX12AffinityRootSignature* pRootSignature,\r\n        _In_ REFIID riid,\r\n        _Outptr_opt_  CD3DX12AffinityCommandSignature** ppvCommandSignature,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    void STDMETHODCALLTYPE GetResourceTiling(\r\n        _In_  CD3DX12AffinityResource* pTiledResource,\r\n        _Out_opt_  UINT* pNumTilesForEntireResource,\r\n        _Out_opt_  D3D12_PACKED_MIP_INFO* pPackedMipDesc,\r\n        _Out_opt_  D3D12_TILE_SHAPE* pStandardTileShapeForNonPackedMips,\r\n        _Inout_opt_  UINT* pNumSubresourceTilings,\r\n        _In_  UINT FirstSubresourceTilingToGet,\r\n        _Out_writes_(*pNumSubresourceTilings)  D3D12_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips,\r\n        UINT AffinityIndex = 0);\r\n\r\n    LUID STDMETHODCALLTYPE GetAdapterLuid(UINT AffinityIndex = 0);\r\n    ID3D12Device* GetChildObject(UINT AffinityIndex);\r\n\r\n    CD3DX12AffinityDevice(ID3D12Device** devices, UINT Count, EAffinityMode::Mask affinitymode);\r\n    virtual ~CD3DX12AffinityDevice();\r\n    EAffinityMode::Mask GetAffinityMode();\r\n    EAffinityRenderingMode::Mask GetAffinityRenderingMode();\r\n    void SetAffinityRenderingMode(EAffinityRenderingMode::Mask renderingmode);\r\n    UINT AffinityIndexToNodeMask(UINT const Index);\r\n    UINT GetDeviceCount();\r\n\r\n    UINT LDAAllNodeMasks();\r\n    UINT GetActiveNodeMask();\r\n    void SwitchToNextNode();\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHeapPointer(D3D12_CPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex);\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHeapPointer(D3D12_GPU_DESCRIPTOR_HANDLE const& Original, UINT const NodeIndex);\r\n    D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS const& Original, UINT const NodeIndex);\r\n\r\nprotected:\r\n    virtual bool IsD3D();\r\n\r\nprivate:\r\n    void UpdateActiveDevices();\r\n    ID3D12Device* mDevices[D3DX12_MAX_ACTIVE_NODES];\r\n\r\n    UINT mNumActiveDevices = 0;\r\n    EAffinityMode::Mask mAffinityMode;\r\n    EAffinityRenderingMode::Mask mAffinityRenderingMode;\r\n\r\n    UINT mDeviceCount = 0;\r\n\r\n    std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> DestDescriptorRangeStartsCache;\r\n    std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> SrcDescriptorRangeStartsCache;\r\n\r\n    std::mutex MutexPointerRanges;\r\n    std::vector<std::pair<SIZE_T, SIZE_T>> CPUHeapPointerRanges;\r\n    std::vector<std::pair<SIZE_T, SIZE_T>> GPUHeapPointerRanges;\r\n\r\n    std::map<D3D12_GPU_VIRTUAL_ADDRESS, std::vector<D3D12_GPU_VIRTUAL_ADDRESS>> GPUVirtualAddresses;\r\n    std::mutex MutexGPUVirtualAddresses;\r\n\r\n    std::set<CD3DX12AffinityResource*> StillMappedResources;\r\n    std::mutex MutexStillMappedResources;\r\n\r\n    UINT mLDANodeCount = 0;\r\n\r\n    ID3D12CommandQueue* mSyncCommandQueues[D3DX12_MAX_ACTIVE_NODES];\r\n    ID3D12Fence* mSyncFences[D3DX12_MAX_ACTIVE_NODES];\r\n    std::mutex MutexSyncResources;\r\n    std::vector<CD3DX12AffinityResource*> mSyncResources;\r\n    ID3D12InfoQueue* InfoQueue = nullptr;\r\n\r\npublic:\r\n    void WriteApplicationMessage(D3D12_MESSAGE_SEVERITY const Severity, char const* const Message);\r\n\r\n    // Static Member Variables\r\n\r\n    // Used to do super simple \"device that's doing work in an AFR scenario\" tracking\r\n    // Probably this should be application controlled, but this very simple mechanism\r\n    // is a good starting point and also helps keep the first affinity integration step\r\n    // as minimal as possible.\r\n    static UINT g_ActiveNodeIndex;\r\n    static UINT g_CachedNodeCount;\r\n    static UINT g_CachedNodeMask;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityDeviceChild.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nCD3DX12AffinityDeviceChild::CD3DX12AffinityDeviceChild(CD3DX12AffinityDevice* device, ID3D12DeviceChild** deviceChilds, UINT Count)\r\n    : CD3DX12AffinityObject(device, reinterpret_cast<IUnknown**>(deviceChilds), Count)\r\n{\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"DeviceChild\";\r\n#endif\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDeviceChild::GetDevice(\r\n    REFIID riid,\r\n    void** ppvDevice)\r\n{\r\n    CD3DX12AffinityDevice* pDevice = GetParentDevice();\r\n    pDevice->AddRef();\r\n    *ppvDevice = (void*)pDevice;\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityDeviceChild::GetDevice(\r\n    CD3DX12AffinityDevice** ppDevice)\r\n{\r\n    *ppDevice = GetParentDevice();\r\n    (*ppDevice)->AddRef();\r\n    return S_OK;\r\n}\r\n\r\nbool CD3DX12AffinityDeviceChild::IsD3D()\r\n{\r\n    return true;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityDeviceChild.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityObject.h\"\r\n\r\nclass CD3DX12AffinityDevice;\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityDeviceChild : public CD3DX12AffinityObject\r\n{\r\npublic:\r\n    CD3DX12AffinityDeviceChild(CD3DX12AffinityDevice* device, ID3D12DeviceChild* deviceChilds[], UINT Count);\r\n    HRESULT STDMETHODCALLTYPE GetDevice(CD3DX12AffinityDevice** ppDevice);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDevice(\r\n        REFIID riid,\r\n        void** ppvDevice);\r\n\r\nprotected:\r\n    virtual bool IsD3D();\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityFence.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nUINT64 STDMETHODCALLTYPE CD3DX12AffinityFence::GetCompletedValue(void)\r\n{\r\n    UINT64 Minimum = mFences[0]->GetCompletedValue();\r\n    for (UINT i = 1; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n\r\n            UINT64 CompletedValue = mFences[i]->GetCompletedValue();\r\n            Minimum = min(CompletedValue, Minimum);\r\n        }\r\n    }\r\n\r\n    return Minimum;\r\n}\r\n\r\nUINT64 CD3DX12AffinityFence::GetCompletedValue(UINT AffinityMask)\r\n{\r\n    UINT64 Minimum = 0 - 1ull;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            UINT64 CompletedValue = mFences[i]->GetCompletedValue();\r\n            Minimum = min(CompletedValue, Minimum);\r\n        }\r\n    }\r\n    return Minimum;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityFence::SetEventOnCompletion(\r\n    UINT64 Value,\r\n    HANDLE hEvent)\r\n{\r\n    UINT i = GetActiveNodeIndex();\r\n    ID3D12Fence* Fence = mFences[i];\r\n    return Fence->SetEventOnCompletion(Value, hEvent);\r\n}\r\n\r\nHRESULT CD3DX12AffinityFence::SetEventOnCompletion(UINT64 Value, HANDLE hEvent, UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & EffectiveAffinityMask) != 0)\r\n        {\r\n            return mFences[i]->SetEventOnCompletion(Value, hEvent);\r\n        }\r\n    }\r\n    //should never get here, mask is incorrect\r\n    return E_FAIL;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityFence::WaitOnFenceCompletion(\r\n    UINT64 Value)\r\n{\r\n    std::vector<HANDLE> Events;\r\n\r\n    UINT EventCount = 0;\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12Fence* Fence = mFences[i];\r\n            Events.push_back(0);\r\n            Events[EventCount] = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n            HRESULT const hr = Fence->SetEventOnCompletion(Value, Events[EventCount]);\r\n\r\n            if (hr != S_OK)\r\n            {\r\n                return hr;\r\n            }\r\n\r\n            ++EventCount;\r\n        }\r\n    }\r\n    WaitForMultipleObjects((DWORD)EventCount, Events.data(), TRUE, INFINITE);\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityFence::Signal(\r\n    UINT64 Value)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12Fence* Fence = mFences[i];\r\n\r\n            HRESULT const hr = Fence->Signal(Value);\r\n\r\n            if (hr != S_OK)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT CD3DX12AffinityFence::Signal(UINT64 Value, UINT AffinityIndex)\r\n{\r\n    return mFences[AffinityIndex]->Signal(Value);\r\n}\r\n\r\nCD3DX12AffinityFence::CD3DX12AffinityFence(CD3DX12AffinityDevice* device, ID3D12Fence** fences, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(fences), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mFences[i] = fences[i];\r\n        }\r\n        else\r\n        {\r\n            mFences[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Fence\";\r\n#endif\r\n    mDevice = device;\r\n}\r\n\r\nCD3DX12AffinityFence::~CD3DX12AffinityFence()\r\n{\r\n}\r\n\r\nID3D12Fence* CD3DX12AffinityFence::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mFences[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityFence.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityFence : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    UINT64 STDMETHODCALLTYPE GetCompletedValue(void);\r\n\r\n    UINT64 STDMETHODCALLTYPE GetCompletedValue(UINT AffinityMask);\r\n\r\n    // It is not recommended to use this function in multi-GPU scenarios \r\n    // as it operates only on the active GPU fence.\r\n    // Please refactor your engine to use WaitOnFenceCompletion instead.\r\n    HRESULT STDMETHODCALLTYPE SetEventOnCompletion(\r\n        UINT64 Value,\r\n        HANDLE hEvent);\r\n\r\n    // The mask should resolve to a single Node Index.\r\n    HRESULT STDMETHODCALLTYPE SetEventOnCompletion(\r\n        UINT64 Value,\r\n        HANDLE hEvent,\r\n        UINT AffinityMask);\r\n\r\n    HRESULT STDMETHODCALLTYPE WaitOnFenceCompletion(\r\n        UINT64 Value);\r\n\r\n    HRESULT STDMETHODCALLTYPE Signal(\r\n        UINT64 Value);\r\n\r\n    HRESULT STDMETHODCALLTYPE Signal(\r\n        UINT64 Value,\r\n        UINT AffinityIndex);\r\n\r\n    CD3DX12AffinityFence(CD3DX12AffinityDevice* device, ID3D12Fence** fences, UINT Count);\r\n    ~CD3DX12AffinityFence();\r\n    ID3D12Fence* GetChildObject(UINT AffinityIndex);\r\n\r\n    ID3D12Fence* mFences[D3DX12_MAX_ACTIVE_NODES];\r\n    HANDLE mCompletionEvent;\r\n\r\nprivate:\r\n    CD3DX12AffinityDevice* mDevice;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityGraphicsCommandList.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityGraphicsCommandList::SetAffinity(UINT AffinityMask)\r\n{\r\n    CD3DX12AffinityObject::SetAffinity(AffinityMask);\r\n    mAccumulatedAffinityMask |= AffinityMask;\r\n}\r\n\r\nD3D12_COMMAND_LIST_TYPE CD3DX12AffinityGraphicsCommandList::GetType()\r\n{\r\n    return mGraphicsCommandLists[0]->GetType();\r\n}\r\n\r\nHRESULT CD3DX12AffinityGraphicsCommandList::Close()\r\n{\r\n#if ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    for (UINT i = 0; i < GetNodeCount(); ++i)\r\n    {\r\n        ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#else\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#endif\r\n            HRESULT const hr = List->Close();\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n#ifdef ALWAYS_RESET_ALL_COMMAND_LISTS\r\n#else\r\n    }\r\n#endif\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT CD3DX12AffinityGraphicsCommandList::Reset(\r\n    CD3DX12AffinityCommandAllocator* pAllocator,\r\n    CD3DX12AffinityPipelineState* pInitialState)\r\n{\r\n    if (mUseDeviceActiveMaskOnReset)\r\n    {\r\n        mAccumulatedAffinityMask = 0;\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n\r\n#if ALWAYS_RESET_ALL_COMMAND_LISTS\r\n    for (UINT i = 0; i < GetNodeCount(); ++i)\r\n    {\r\n        ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#else\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n#endif\r\n\r\n            HRESULT const hr = List->Reset(pAllocator->GetChildObject(i),\r\n                pInitialState ? pInitialState->mPipelineStates[i] : nullptr);\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearState(\r\n    CD3DX12AffinityPipelineState* pPipelineState)\r\n{\r\n    CD3DX12AffinityPipelineState* PipelineState = static_cast<CD3DX12AffinityPipelineState*>(pPipelineState);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->ClearState(PipelineState->mPipelineStates[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::DrawInstanced(\r\n    UINT VertexCountPerInstance,\r\n    UINT InstanceCount,\r\n    UINT StartVertexLocation,\r\n    UINT StartInstanceLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::Dispatch(\r\n    UINT ThreadGroupCountX,\r\n    UINT ThreadGroupCountY,\r\n    UINT ThreadGroupCountZ)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->Dispatch(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyBufferRegion(\r\n    CD3DX12AffinityResource* pDstBuffer,\r\n    UINT64 DstOffset,\r\n    CD3DX12AffinityResource* pSrcBuffer,\r\n    UINT64 SrcOffset,\r\n    UINT64 NumBytes)\r\n{\r\n    CD3DX12AffinityResource* DstBuffer = static_cast<CD3DX12AffinityResource*>(pDstBuffer);\r\n    CD3DX12AffinityResource* SrcBuffer = static_cast<CD3DX12AffinityResource*>(pSrcBuffer);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->CopyBufferRegion(DstBuffer->mResources[i], DstOffset, SrcBuffer->mResources[i], SrcOffset, NumBytes);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyTextureRegion(\r\n    const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pDst,\r\n    UINT DstX,\r\n    UINT DstY,\r\n    UINT DstZ,\r\n    const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pSrc,\r\n    const D3D12_BOX* pSrcBox)\r\n{\r\n    CD3DX12AffinityResource* DstTexture = static_cast<CD3DX12AffinityResource*>(pDst->pResource);\r\n    CD3DX12AffinityResource* SrcTexture = static_cast<CD3DX12AffinityResource*>(pSrc->pResource);\r\n\r\n    D3D12_TEXTURE_COPY_LOCATION Dst = pDst->ToD3D12();\r\n    D3D12_TEXTURE_COPY_LOCATION Src = pSrc->ToD3D12();\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            Dst.pResource = DstTexture->mResources[i];\r\n            Src.pResource = SrcTexture->mResources[i];\r\n            List->CopyTextureRegion(&Dst, DstX, DstY, DstZ, &Src, pSrcBox);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyResource(\r\n    CD3DX12AffinityResource* pDstResource,\r\n    CD3DX12AffinityResource* pSrcResource)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->CopyResource(pDstResource->mResources[i], pSrcResource->mResources[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::CopyTiles(\r\n    CD3DX12AffinityResource* pTiledResource,\r\n    const D3D12_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,\r\n    const D3D12_TILE_REGION_SIZE* pTileRegionSize,\r\n    CD3DX12AffinityResource* pBuffer,\r\n    UINT64 BufferStartOffsetInBytes,\r\n    D3D12_TILE_COPY_FLAGS Flags)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->CopyTiles(\r\n                pTiledResource->mResources[i],\r\n                pTileRegionStartCoordinate,\r\n                pTileRegionSize,\r\n                pBuffer->mResources[i],\r\n                BufferStartOffsetInBytes,\r\n                Flags);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ResolveSubresource(\r\n    CD3DX12AffinityResource* pDstResource,\r\n    UINT DstSubresource,\r\n    CD3DX12AffinityResource* pSrcResource,\r\n    UINT SrcSubresource,\r\n    DXGI_FORMAT Format)\r\n{\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ResolveSubresource(pDstResource->mResources[i], DstSubresource, pSrcResource->mResources[i], SrcSubresource, Format);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::IASetPrimitiveTopology(\r\n    D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->IASetPrimitiveTopology(PrimitiveTopology);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::RSSetViewports(\r\n    UINT NumViewports,\r\n    const D3D12_VIEWPORT* pViewports)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->RSSetViewports(NumViewports, pViewports);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::RSSetScissorRects(\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->RSSetScissorRects(NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::OMSetBlendFactor(\r\n    const FLOAT BlendFactor[4])\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->OMSetBlendFactor(BlendFactor);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::OMSetStencilRef(\r\n    UINT StencilRef)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            List->OMSetStencilRef(StencilRef);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ResourceBarrier(\r\n    UINT NumBarriers,\r\n    const D3DX12_AFFINITY_RESOURCE_BARRIER* pBarriers)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            mCachedResourceBarriers.resize(NumBarriers);\r\n            for (UINT b = 0; b < NumBarriers; ++b)\r\n            {\r\n                D3D12_RESOURCE_BARRIER Use = pBarriers[b].ToD3D12();\r\n\r\n                switch (pBarriers[b].Type)\r\n                {\r\n                case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:\r\n                {\r\n                    if (pBarriers[b].Transition.pResource)\r\n                    {\r\n                        Use.Transition.pResource = pBarriers[b].Transition.pResource->mResources[i];\r\n                    }\r\n                    break;\r\n                }\r\n                case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:\r\n                {\r\n                    if (pBarriers[b].Aliasing.pResourceAfter)\r\n                    {\r\n                        Use.Aliasing.pResourceAfter = pBarriers[b].Aliasing.pResourceAfter->mResources[i];\r\n                    }\r\n                    if (pBarriers[b].Aliasing.pResourceBefore)\r\n                    {\r\n                        Use.Aliasing.pResourceBefore = pBarriers[b].Aliasing.pResourceBefore->mResources[i];\r\n                    }\r\n                    break;\r\n                }\r\n                case D3D12_RESOURCE_BARRIER_TYPE_UAV:\r\n                {\r\n                    if (pBarriers[b].UAV.pResource)\r\n                    {\r\n                        Use.UAV.pResource = pBarriers[b].UAV.pResource->mResources[i];\r\n                    }\r\n                    break;\r\n                }\r\n                }\r\n\r\n                mCachedResourceBarriers[b] = Use;\r\n            }\r\n\r\n            List->ResourceBarrier(NumBarriers, mCachedResourceBarriers.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ExecuteBundle(\r\n    CD3DX12AffinityGraphicsCommandList* pCommandList)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->ExecuteBundle(pCommandList->mGraphicsCommandLists[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetDescriptorHeaps(\r\n    UINT NumDescriptorHeaps,\r\n    CD3DX12AffinityDescriptorHeap** ppDescriptorHeaps)\r\n{\r\n    mCachedDescriptorHeaps.resize(NumDescriptorHeaps);\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            for (UINT h = 0; h < NumDescriptorHeaps; ++h)\r\n            {\r\n                mCachedDescriptorHeaps[h] = static_cast<CD3DX12AffinityDescriptorHeap*>(ppDescriptorHeaps[h])->GetChildObject(i);\r\n            }\r\n\r\n            List->SetDescriptorHeaps(NumDescriptorHeaps, mCachedDescriptorHeaps.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootSignature(\r\n    CD3DX12AffinityRootSignature* pRootSignature)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootSignature(pRootSignature->mRootSignatures[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootSignature(\r\n    CD3DX12AffinityRootSignature* pRootSignature)\r\n{\r\n    CD3DX12AffinityRootSignature* AffinityRootSignature = static_cast<CD3DX12AffinityRootSignature*>(pRootSignature);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootSignature(AffinityRootSignature->mRootSignatures[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRoot32BitConstant(\r\n    UINT RootParameterIndex,\r\n    UINT SrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRoot32BitConstant(RootParameterIndex, SrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRoot32BitConstant(\r\n    UINT RootParameterIndex,\r\n    UINT SrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRoot32BitConstant(RootParameterIndex, SrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRoot32BitConstants(\r\n    UINT RootParameterIndex,\r\n    UINT Num32BitValuesToSet,\r\n    const void* pSrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n           \r\n            List->SetComputeRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRoot32BitConstants(\r\n    UINT RootParameterIndex,\r\n    UINT Num32BitValuesToSet,\r\n    const void* pSrcData,\r\n    UINT DestOffsetIn32BitValues)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootConstantBufferView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootConstantBufferView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootConstantBufferView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootConstantBufferView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootShaderResourceView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootShaderResourceView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootShaderResourceView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootShaderResourceView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootUnorderedAccessView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootUnorderedAccessView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootUnorderedAccessView(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetGraphicsRootUnorderedAccessView(RootParameterIndex, GetParentDevice()->GetGPUVirtualAddress(BufferLocation, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::IASetVertexBuffers(\r\n    UINT StartSlot,\r\n    UINT NumViews,\r\n    const D3D12_VERTEX_BUFFER_VIEW* pViews)\r\n{\r\n    mCachedBufferViews.resize(NumViews);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            for (UINT v = 0; v < NumViews; ++v)\r\n            {\r\n                mCachedBufferViews[v] = pViews[v];\r\n                mCachedBufferViews[v].BufferLocation = GetParentDevice()->GetGPUVirtualAddress(pViews[v].BufferLocation, i);\r\n            }\r\n\r\n            List->IASetVertexBuffers(StartSlot, NumViews, mCachedBufferViews.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SOSetTargets(\r\n    UINT StartSlot,\r\n    UINT NumViews,\r\n    const D3D12_STREAM_OUTPUT_BUFFER_VIEW* pViews)\r\n{\r\n    mCachedStreamOutBufferViews.resize(NumViews);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            for (UINT v = 0; v < NumViews; ++v)\r\n            {\r\n                mCachedStreamOutBufferViews[v] = pViews[v];\r\n                mCachedStreamOutBufferViews[v].BufferLocation = GetParentDevice()->GetGPUVirtualAddress(pViews[v].BufferLocation, i);\r\n                mCachedStreamOutBufferViews[v].BufferFilledSizeLocation = GetParentDevice()->GetGPUVirtualAddress(pViews[v].BufferFilledSizeLocation, i);\r\n            }\r\n\r\n            List->SOSetTargets(StartSlot, NumViews, mCachedStreamOutBufferViews.data());\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::OMSetRenderTargets(\r\n    UINT NumRenderTargetDescriptors,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pRenderTargetDescriptors,\r\n    BOOL RTsSingleHandleToDescriptorRange,\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE* pDepthStencilDescriptor)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            mCachedRenderTargetViews.resize(NumRenderTargetDescriptors);\r\n            for (UINT r = 0; r < NumRenderTargetDescriptors; ++r)\r\n            {\r\n                mCachedRenderTargetViews[r] = GetParentDevice()->GetCPUHeapPointer(pRenderTargetDescriptors[r], i);\r\n            }\r\n\r\n            if (pDepthStencilDescriptor)\r\n            {\r\n                D3D12_CPU_DESCRIPTOR_HANDLE ActualDepthStencilDescriptor = GetParentDevice()->GetCPUHeapPointer(*pDepthStencilDescriptor, i);\r\n                List->OMSetRenderTargets(NumRenderTargetDescriptors, mCachedRenderTargetViews.data(), RTsSingleHandleToDescriptorRange, &ActualDepthStencilDescriptor);\r\n            }\r\n            else\r\n            {\r\n                List->OMSetRenderTargets(NumRenderTargetDescriptors, mCachedRenderTargetViews.data(), RTsSingleHandleToDescriptorRange, nullptr);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearDepthStencilView(\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView,\r\n    D3D12_CLEAR_FLAGS ClearFlags,\r\n    FLOAT Depth,\r\n    UINT8 Stencil,\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ClearDepthStencilView(GetParentDevice()->GetCPUHeapPointer(DepthStencilView, i), ClearFlags, Depth, Stencil, NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearRenderTargetView(\r\n    D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView,\r\n    const FLOAT ColorRGBA[4],\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n#ifdef D3DX12_DEBUG_CLEAR_WHITE\r\n            FLOAT White[4] = { 1, 1, 1, 1 };\r\n            List->ClearRenderTargetView(GetParentDevice()->GetCPUHeapPointer(RenderTargetView, i), White, NumRects, pRects);\r\n#else\r\n            List->ClearRenderTargetView(GetParentDevice()->GetCPUHeapPointer(RenderTargetView, i), ColorRGBA, NumRects, pRects);\r\n#endif\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearUnorderedAccessViewUint(\r\n    D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n    CD3DX12AffinityResource* pResource,\r\n    const UINT Values[4],\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ClearUnorderedAccessViewUint(\r\n                GetParentDevice()->GetGPUHeapPointer(ViewGPUHandleInCurrentHeap, i),\r\n                GetParentDevice()->GetCPUHeapPointer(ViewCPUHandle, i),\r\n                pResource->mResources[i], Values, NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ClearUnorderedAccessViewFloat(\r\n    D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n    CD3DX12AffinityResource* pResource,\r\n    const FLOAT Values[4],\r\n    UINT NumRects,\r\n    const D3D12_RECT* pRects)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ClearUnorderedAccessViewFloat(\r\n                GetParentDevice()->GetGPUHeapPointer(ViewGPUHandleInCurrentHeap, i),\r\n                GetParentDevice()->GetCPUHeapPointer(ViewCPUHandle, i),\r\n                pResource->mResources[i], Values, NumRects, pRects);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::DiscardResource(\r\n    CD3DX12AffinityResource* pResource,\r\n    const D3D12_DISCARD_REGION* pRegion)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->DiscardResource(\r\n                pResource->mResources[i],\r\n                pRegion);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::BeginQuery(\r\n    CD3DX12AffinityQueryHeap* pQueryHeap,\r\n    D3D12_QUERY_TYPE Type,\r\n    UINT Index)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            ID3D12QueryHeap* QueryHeap = pQueryHeap->mQueryHeaps[i];\r\n\r\n            List->BeginQuery(\r\n                QueryHeap,\r\n                Type,\r\n                Index);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::EndQuery(\r\n    CD3DX12AffinityQueryHeap* pQueryHeap,\r\n    D3D12_QUERY_TYPE Type,\r\n    UINT Index)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            ID3D12QueryHeap* QueryHeap = pQueryHeap->mQueryHeaps[i];\r\n\r\n            List->EndQuery(\r\n                QueryHeap,\r\n                Type,\r\n                Index);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ResolveQueryData(\r\n    CD3DX12AffinityQueryHeap* pQueryHeap,\r\n    D3D12_QUERY_TYPE Type,\r\n    UINT StartIndex,\r\n    UINT NumQueries,\r\n    CD3DX12AffinityResource* pDestinationBuffer,\r\n    UINT64 AlignedDestinationBufferOffset)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            ID3D12QueryHeap* QueryHeap = pQueryHeap->mQueryHeaps[i];\r\n            ID3D12Resource* DestinationBuffer = pDestinationBuffer->mResources[i];\r\n\r\n            List->ResolveQueryData(\r\n                QueryHeap,\r\n                Type,\r\n                StartIndex,\r\n                NumQueries,\r\n                DestinationBuffer,\r\n                AlignedDestinationBufferOffset);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetPredication(\r\n    CD3DX12AffinityResource* pBuffer,\r\n    UINT64 AlignedBufferOffset,\r\n    D3D12_PREDICATION_OP Operation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetPredication(\r\n                pBuffer->mResources[i],\r\n                AlignedBufferOffset,\r\n                Operation);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetMarker(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->SetMarker(\r\n                Metadata,\r\n                pData,\r\n                Size);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::BeginEvent(\r\n    UINT Metadata,\r\n    const void* pData,\r\n    UINT Size)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->BeginEvent(\r\n                Metadata,\r\n                pData,\r\n                Size);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::EndEvent(void)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n\r\n            List->EndEvent();\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::ExecuteIndirect(\r\n    CD3DX12AffinityCommandSignature* pCommandSignature,\r\n    UINT MaxCommandCount,\r\n    CD3DX12AffinityResource* pArgumentBuffer,\r\n    UINT64 ArgumentBufferOffset,\r\n    CD3DX12AffinityResource* pCountBuffer,\r\n    UINT64 CountBufferOffset)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->ExecuteIndirect(\r\n                pCommandSignature->GetChildObject(i),\r\n                MaxCommandCount,\r\n                pArgumentBuffer->mResources[i], ArgumentBufferOffset,\r\n                pCountBuffer ? pCountBuffer->mResources[i] : nullptr, CountBufferOffset);\r\n        }\r\n    }\r\n}\r\n\r\nCD3DX12AffinityGraphicsCommandList::CD3DX12AffinityGraphicsCommandList(CD3DX12AffinityDevice* device, ID3D12GraphicsCommandList** graphicsCommandLists, UINT Count, bool UseDeviceActiveMaskOnReset)\r\n    : CD3DX12AffinityCommandList(device, reinterpret_cast<ID3D12CommandList**>(graphicsCommandLists), Count)\r\n    , mUseDeviceActiveMaskOnReset(UseDeviceActiveMaskOnReset)\r\n    , mAccumulatedAffinityMask(0)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mGraphicsCommandLists[i] = graphicsCommandLists[i];\r\n        }\r\n        else\r\n        {\r\n            mGraphicsCommandLists[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"GraphicsCommandList\";\r\n#endif\r\n\r\n    if (UseDeviceActiveMaskOnReset)\r\n    {\r\n        SetAffinity(1 << GetActiveNodeIndex());\r\n    }\r\n    else\r\n    {\r\n        mAccumulatedAffinityMask = GetNodeMask();\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetPipelineState(\r\n    CD3DX12AffinityPipelineState* pPipelineState)\r\n{\r\n    CD3DX12AffinityPipelineState* PipelineState = static_cast<CD3DX12AffinityPipelineState*>(pPipelineState);\r\n\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetPipelineState(PipelineState->mPipelineStates[i]);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetComputeRootDescriptorTable(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n            \r\n            List->SetComputeRootDescriptorTable(RootParameterIndex, GetParentDevice()->GetGPUHeapPointer(BaseDescriptor, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::SetGraphicsRootDescriptorTable(\r\n    UINT RootParameterIndex,\r\n    D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            mGraphicsCommandLists[i]->SetGraphicsRootDescriptorTable(\r\n                RootParameterIndex,\r\n                GetParentDevice()->GetGPUHeapPointer(BaseDescriptor, i));\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::IASetIndexBuffer(\r\n    const D3D12_INDEX_BUFFER_VIEW* pView)\r\n{\r\n    if (pView)\r\n    {\r\n        D3D12_INDEX_BUFFER_VIEW View = *pView;\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n                \r\n                View.BufferLocation = GetParentDevice()->GetGPUVirtualAddress(pView->BufferLocation, i);\r\n                List->IASetIndexBuffer(&View);\r\n            }\r\n        }\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12GraphicsCommandList* List = mGraphicsCommandLists[i];\r\n                List->IASetIndexBuffer(nullptr);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::DrawIndexedInstanced(\r\n    UINT IndexCountPerInstance,\r\n    UINT InstanceCount,\r\n    UINT StartIndexLocation,\r\n    INT BaseVertexLocation,\r\n    UINT StartInstanceLocation)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            mGraphicsCommandLists[i]->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityGraphicsCommandList::BroadcastResource(CD3DX12AffinityResource* pResource, UINT NodeIndex, UINT TargetNodeMask)\r\n{\r\n    // The command list affinity must match the supplied source node\r\n    DEBUG_ASSERT(mAffinityMask == (1 << NodeIndex));\r\n\r\n    // Copy is a push operation on the Source node commandlist to a target resource\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & TargetNodeMask) != 0)\r\n        {\r\n            if (NodeIndex != i)\r\n            {\r\n                mGraphicsCommandLists[NodeIndex]->CopyResource(\r\n                    pResource->GetChildObject(i),\r\n                    pResource->GetChildObject(NodeIndex)\r\n                    );\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nID3D12GraphicsCommandList* CD3DX12AffinityGraphicsCommandList::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mGraphicsCommandLists[AffinityIndex];\r\n}\r\n\r\nUINT CD3DX12AffinityGraphicsCommandList::GetActiveAffinityMask()\r\n{\r\n    return mAccumulatedAffinityMask;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityGraphicsCommandList.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityCommandList.h\"\r\n#include \"CD3DX12AffinityQueryHeap.h\"\r\n#include \"CD3DX12AffinityDevice.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityGraphicsCommandList : public CD3DX12AffinityCommandList\r\n{\r\npublic:\r\n    virtual void STDMETHODCALLTYPE SetAffinity(\r\n        _In_  UINT AffinityMask);\r\n\r\n    D3D12_COMMAND_LIST_TYPE GetType();\r\n\r\n    HRESULT Close();\r\n\r\n    HRESULT Reset(\r\n        _In_  CD3DX12AffinityCommandAllocator* pAllocator,\r\n        _In_opt_  CD3DX12AffinityPipelineState* pInitialState);\r\n\r\n    void ClearState(\r\n        _In_opt_  CD3DX12AffinityPipelineState* pPipelineState);\r\n\r\n    void DrawInstanced(\r\n        _In_  UINT VertexCountPerInstance,\r\n        _In_  UINT InstanceCount,\r\n        _In_  UINT StartVertexLocation,\r\n        _In_  UINT StartInstanceLocation);\r\n\r\n    void DrawIndexedInstanced(\r\n        _In_  UINT IndexCountPerInstance,\r\n        _In_  UINT InstanceCount,\r\n        _In_  UINT StartIndexLocation,\r\n        _In_  INT BaseVertexLocation,\r\n        _In_  UINT StartInstanceLocation);\r\n\r\n    void Dispatch(\r\n        _In_  UINT ThreadGroupCountX,\r\n        _In_  UINT ThreadGroupCountY,\r\n        _In_  UINT ThreadGroupCountZ);\r\n\r\n    void CopyBufferRegion(\r\n        _In_  CD3DX12AffinityResource* pDstBuffer,\r\n        UINT64 DstOffset,\r\n        _In_  CD3DX12AffinityResource* pSrcBuffer,\r\n        UINT64 SrcOffset,\r\n        UINT64 NumBytes);\r\n\r\n    void CopyTextureRegion(\r\n        _In_  const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pDst,\r\n        UINT DstX,\r\n        UINT DstY,\r\n        UINT DstZ,\r\n        _In_  const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION* pSrc,\r\n        _In_opt_  const D3D12_BOX* pSrcBox);\r\n\r\n    void CopyResource(\r\n        _In_  CD3DX12AffinityResource* pDstResource,\r\n        _In_  CD3DX12AffinityResource* pSrcResource);\r\n\r\n    void CopyTiles(\r\n        _In_  CD3DX12AffinityResource* pTiledResource,\r\n        _In_  const D3D12_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,\r\n        _In_  const D3D12_TILE_REGION_SIZE* pTileRegionSize,\r\n        _In_  CD3DX12AffinityResource* pBuffer,\r\n        UINT64 BufferStartOffsetInBytes,\r\n        D3D12_TILE_COPY_FLAGS Flags);\r\n\r\n    void ResolveSubresource(\r\n        _In_  CD3DX12AffinityResource* pDstResource,\r\n        _In_  UINT DstSubresource,\r\n        _In_  CD3DX12AffinityResource* pSrcResource,\r\n        _In_  UINT SrcSubresource,\r\n        _In_  DXGI_FORMAT Format);\r\n\r\n    void IASetPrimitiveTopology(\r\n        _In_  D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology);\r\n\r\n    void RSSetViewports(\r\n        _In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE)  UINT NumViewports,\r\n        _In_reads_(NumViewports)  const D3D12_VIEWPORT* pViewports);\r\n\r\n    void RSSetScissorRects(\r\n        _In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE)  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void OMSetBlendFactor(\r\n        _In_opt_  const FLOAT BlendFactor[4]);\r\n\r\n    void OMSetStencilRef(\r\n        _In_  UINT StencilRef);\r\n\r\n    void SetPipelineState(\r\n        _In_  CD3DX12AffinityPipelineState* pPipelineState);\r\n\r\n    void ResourceBarrier(\r\n        _In_  UINT NumBarriers,\r\n        _In_reads_(NumBarriers)  const D3DX12_AFFINITY_RESOURCE_BARRIER* pBarriers);\r\n\r\n    void ExecuteBundle(\r\n        _In_  CD3DX12AffinityGraphicsCommandList* pCommandList);\r\n\r\n    void SetDescriptorHeaps(\r\n        _In_  UINT NumDescriptorHeaps,\r\n        _In_reads_(NumDescriptorHeaps)  CD3DX12AffinityDescriptorHeap** ppDescriptorHeaps);\r\n\r\n    void SetComputeRootSignature(\r\n        _In_  CD3DX12AffinityRootSignature* pRootSignature);\r\n\r\n    void SetGraphicsRootSignature(\r\n        _In_  CD3DX12AffinityRootSignature* pRootSignature);\r\n\r\n    void SetComputeRootDescriptorTable(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);\r\n\r\n    void SetGraphicsRootDescriptorTable(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);\r\n\r\n    void SetComputeRoot32BitConstant(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT SrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetGraphicsRoot32BitConstant(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT SrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetComputeRoot32BitConstants(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT Num32BitValuesToSet,\r\n        _In_reads_(Num32BitValuesToSet* sizeof(UINT))  const void* pSrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetGraphicsRoot32BitConstants(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  UINT Num32BitValuesToSet,\r\n        _In_reads_(Num32BitValuesToSet* sizeof(UINT))  const void* pSrcData,\r\n        _In_  UINT DestOffsetIn32BitValues);\r\n\r\n    void SetComputeRootConstantBufferView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetGraphicsRootConstantBufferView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetComputeRootShaderResourceView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetGraphicsRootShaderResourceView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetComputeRootUnorderedAccessView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void SetGraphicsRootUnorderedAccessView(\r\n        _In_  UINT RootParameterIndex,\r\n        _In_  D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);\r\n\r\n    void IASetIndexBuffer(\r\n        _In_opt_  const D3D12_INDEX_BUFFER_VIEW* pView);\r\n\r\n    void IASetVertexBuffers(\r\n        _In_  UINT StartSlot,\r\n        _In_  UINT NumViews,\r\n        _In_reads_opt_(NumViews)  const D3D12_VERTEX_BUFFER_VIEW* pViews);\r\n\r\n    void SOSetTargets(\r\n        _In_  UINT StartSlot,\r\n        _In_  UINT NumViews,\r\n        _In_reads_opt_(NumViews)  const D3D12_STREAM_OUTPUT_BUFFER_VIEW* pViews);\r\n\r\n    void OMSetRenderTargets(\r\n        _In_  UINT NumRenderTargetDescriptors,\r\n        _In_  const D3D12_CPU_DESCRIPTOR_HANDLE* pRenderTargetDescriptors,\r\n        _In_  BOOL RTsSingleHandleToDescriptorRange,\r\n        _In_opt_  const D3D12_CPU_DESCRIPTOR_HANDLE* pDepthStencilDescriptor);\r\n\r\n    void ClearDepthStencilView(\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView,\r\n        _In_  D3D12_CLEAR_FLAGS ClearFlags,\r\n        _In_  FLOAT Depth,\r\n        _In_  UINT8 Stencil,\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void ClearRenderTargetView(\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView,\r\n        _In_  const FLOAT ColorRGBA[4],\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void ClearUnorderedAccessViewUint(\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        _In_  const UINT Values[4],\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void ClearUnorderedAccessViewFloat(\r\n        _In_  D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap,\r\n        _In_  D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle,\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        _In_  const FLOAT Values[4],\r\n        _In_  UINT NumRects,\r\n        _In_reads_(NumRects)  const D3D12_RECT* pRects);\r\n\r\n    void DiscardResource(\r\n        _In_  CD3DX12AffinityResource* pResource,\r\n        _In_opt_  const D3D12_DISCARD_REGION* pRegion);\r\n\r\n    void BeginQuery(\r\n        _In_  CD3DX12AffinityQueryHeap* pQueryHeap,\r\n        _In_  D3D12_QUERY_TYPE Type,\r\n        _In_  UINT Index);\r\n\r\n    void EndQuery(\r\n        _In_  CD3DX12AffinityQueryHeap* pQueryHeap,\r\n        _In_  D3D12_QUERY_TYPE Type,\r\n        _In_  UINT Index);\r\n\r\n    void ResolveQueryData(\r\n        _In_  CD3DX12AffinityQueryHeap* pQueryHeap,\r\n        _In_  D3D12_QUERY_TYPE Type,\r\n        _In_  UINT StartIndex,\r\n        _In_  UINT NumQueries,\r\n        _In_  CD3DX12AffinityResource* pDestinationBuffer,\r\n        _In_  UINT64 AlignedDestinationBufferOffset);\r\n\r\n    void SetPredication(\r\n        _In_opt_  CD3DX12AffinityResource* pBuffer,\r\n        _In_  UINT64 AlignedBufferOffset,\r\n        _In_  D3D12_PREDICATION_OP Operation);\r\n\r\n    void SetMarker(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size);\r\n\r\n    void BeginEvent(\r\n        UINT Metadata,\r\n        _In_reads_bytes_opt_(Size)  const void* pData,\r\n        UINT Size);\r\n\r\n    void EndEvent(void);\r\n\r\n    void ExecuteIndirect(\r\n        _In_  CD3DX12AffinityCommandSignature* pCommandSignature,\r\n        _In_  UINT MaxCommandCount,\r\n        _In_  CD3DX12AffinityResource* pArgumentBuffer,\r\n        _In_  UINT64 ArgumentBufferOffset,\r\n        _In_opt_  CD3DX12AffinityResource* pCountBuffer,\r\n        _In_  UINT64 CountBufferOffset);\r\n\r\n    void BroadcastResource(CD3DX12AffinityResource* pResource, UINT NodeIndex, UINT TargetNodeMask);\r\n\r\n    CD3DX12AffinityGraphicsCommandList(CD3DX12AffinityDevice* device, ID3D12GraphicsCommandList** graphicsCommandLists, UINT Count, bool UseDeviceActiveMaskOnReset);\r\n\r\n    ID3D12GraphicsCommandList* GetChildObject(UINT AffinityIndex);\r\n    UINT GetActiveAffinityMask();\r\n\r\nprivate:\r\n    ID3D12GraphicsCommandList* mGraphicsCommandLists[D3DX12_MAX_ACTIVE_NODES];\r\n    UINT mAccumulatedAffinityMask;\r\n    bool mUseDeviceActiveMaskOnReset;\r\n    std::vector<D3D12_RESOURCE_BARRIER> mCachedResourceBarriers;\r\n    std::vector<ID3D12DescriptorHeap*> mCachedDescriptorHeaps;\r\n    std::vector<D3D12_VERTEX_BUFFER_VIEW> mCachedBufferViews;\r\n    std::vector<D3D12_STREAM_OUTPUT_BUFFER_VIEW> mCachedStreamOutBufferViews;\r\n    std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> mCachedRenderTargetViews;\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityHeap.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nCD3DX12AffinityHeap::CD3DX12AffinityHeap(CD3DX12AffinityDevice* device, ID3D12Heap** heaps, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(heaps), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mHeaps[i] = heaps[i];\r\n        }\r\n        else\r\n        {\r\n            mHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Heap\";\r\n#endif\r\n}\r\n\r\nD3D12_HEAP_DESC STDMETHODCALLTYPE CD3DX12AffinityHeap::GetDesc(UINT AffinityIndex)\r\n{\r\n    return mHeaps[AffinityIndex]->GetDesc();\r\n}\r\n\r\nID3D12Heap* CD3DX12AffinityHeap::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mHeaps[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityHeap.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityHeap : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityHeap(CD3DX12AffinityDevice* device, ID3D12Heap** heaps, UINT Count);\r\n\r\n    D3D12_HEAP_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n    ID3D12Heap* GetChildObject(UINT AffinityIndex);\r\n\r\nprivate:\r\n    ID3D12Heap* mHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityObject.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::GetPrivateData(\r\n    REFGUID guid,\r\n    UINT* pDataSize,\r\n    void* pData,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        return ((ID3D12Object*)mObjects[AffinityIndex])->GetPrivateData(guid, pDataSize, pData);\r\n    }\r\n    else\r\n    {\r\n        return ((IDXGIObject*)mObjects[AffinityIndex])->GetPrivateData(guid, pDataSize, pData);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::SetPrivateData(\r\n    REFGUID guid,\r\n    UINT DataSize,\r\n    const void* pData,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        return ((ID3D12Object*)mObjects[AffinityIndex])->SetPrivateData(guid, DataSize, pData);\r\n    }\r\n    else\r\n    {\r\n        return ((IDXGIObject*)mObjects[AffinityIndex])->SetPrivateData(guid, DataSize, pData);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::SetPrivateDataInterface(\r\n    REFGUID guid,\r\n    const IUnknown* pData,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        return ((ID3D12Object*)mObjects[AffinityIndex])->SetPrivateDataInterface(guid, pData);\r\n    }\r\n    else\r\n    {\r\n        return ((IDXGIObject*)mObjects[AffinityIndex])->SetPrivateDataInterface(guid, pData);\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityObject::SetName(\r\n    LPCWSTR Name,\r\n    UINT AffinityIndex)\r\n{\r\n    if (IsD3D())\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; ++i)\r\n        {\r\n            if (mObjects[i])\r\n            {\r\n                ((ID3D12Object*)mObjects[i])->SetName(Name);\r\n            }\r\n            else\r\n            {\r\n                break;\r\n            }\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectDebugName = Name;\r\n#endif\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityObject::SetAffinity(\r\n    UINT AffinityMask)\r\n{\r\n    mAffinityMask = AffinityMask & GetNodeMask();\r\n}\r\n\r\nUINT CD3DX12AffinityObject::AffinityIndexToMask(UINT const Index)\r\n{\r\n    return 1 << Index;\r\n}\r\n\r\nCD3DX12AffinityObject::CD3DX12AffinityObject(CD3DX12AffinityDevice* device, IUnknown** objects, UINT Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mObjects[i] = objects[i];\r\n        }\r\n        else\r\n        {\r\n            mObjects[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Object\";\r\n#endif\r\n    mReferenceCount = 1;\r\n    mParentDevice = device;\r\n    SetAffinity(mParentDevice->GetNodeMask());\r\n}\r\n\r\nCD3DX12AffinityObject::~CD3DX12AffinityObject()\r\n{\r\n    for (size_t i = 0; i < D3DX12_MAX_ACTIVE_NODES; ++i)\r\n    {\r\n        if (mObjects[i])\r\n        {\r\n            ULONG RefCount = mObjects[i]->Release();\r\n            DebugLog(L\"Releasing handle 0x%p, ref count is now %lu\\n\", mObjects[i], RefCount);\r\n        }\r\n    }\r\n}\r\n\r\nULONG CD3DX12AffinityObject::AddRef()\r\n{\r\n    InterlockedIncrement(&mReferenceCount);\r\n    return mReferenceCount;\r\n}\r\n\r\nULONG CD3DX12AffinityObject::Release()\r\n{\r\n    ULONG currentRefCount = InterlockedDecrement(&mReferenceCount);\r\n#ifdef DEBUG_OBJECT_NAME\r\n    DebugLog(L\"Release() called on an affinity object, reference count now %u [%p] [%s] [%s]\\n\", mReferenceCount, this, mObjectTypeName.c_str(), mObjectDebugName.c_str());\r\n#endif\r\n    if (mReferenceCount == 0)\r\n    {\r\n        delete this;\r\n    }\r\n\r\n    return currentRefCount;\r\n}\r\n\r\nCD3DX12AffinityDevice* CD3DX12AffinityObject::GetParentDevice()\r\n{\r\n    return mParentDevice;\r\n}\r\n\r\nUINT CD3DX12AffinityObject::GetNodeMask()\r\n{\r\n    return CD3DX12AffinityDevice::g_CachedNodeMask;\r\n}\r\n\r\nUINT CD3DX12AffinityObject::GetNodeCount()\r\n{\r\n    return CD3DX12AffinityDevice::g_CachedNodeCount;\r\n}\r\n\r\nUINT CD3DX12AffinityObject::GetActiveNodeIndex()\r\n{\r\n    return CD3DX12AffinityDevice::g_ActiveNodeIndex;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityObject.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityObject : public IUnknown\r\n{\r\npublic:\r\n#pragma region\r\n    // IUnknown\r\n    virtual HRESULT STDMETHODCALLTYPE QueryInterface(\r\n        REFIID riid,\r\n        __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject\r\n    )\r\n    {\r\n        //Simple QueryInterface implementation, Not real COM\r\n        *ppvObject = this;\r\n        AddRef();\r\n        return S_OK;\r\n    }\r\n#pragma endregion\r\n\r\n    HRESULT STDMETHODCALLTYPE GetPrivateData(\r\n        _In_  REFGUID guid,\r\n        _Inout_  UINT* pDataSize,\r\n        _Out_writes_bytes_opt_(*pDataSize)  void* pData,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetPrivateData(\r\n        _In_  REFGUID guid,\r\n        _In_  UINT DataSize,\r\n        _In_reads_bytes_opt_(DataSize)  const void* pData,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(\r\n        _In_  REFGUID guid,\r\n        _In_opt_  const IUnknown* pData,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetName(\r\n        _In_z_  LPCWSTR Name,\r\n        UINT AffinityIndex = 0);\r\n\r\n    virtual void STDMETHODCALLTYPE SetAffinity(\r\n        _In_  UINT AffinityMask);\r\n\r\n    virtual ULONG STDMETHODCALLTYPE AddRef();\r\n    virtual ULONG STDMETHODCALLTYPE Release();\r\n\r\n    CD3DX12AffinityObject(CD3DX12AffinityDevice* device, IUnknown** objects, UINT Count);\r\n    virtual ~CD3DX12AffinityObject();\r\n\r\n    CD3DX12AffinityDevice* GetParentDevice();\r\n\r\n    IUnknown* mObjects[D3DX12_MAX_ACTIVE_NODES];\r\n    UINT mAffinityMask = 0;\r\n    UINT mReferenceCount;\r\n\r\n#ifdef DEBUG_OBJECT_NAME\r\n    std::wstring mObjectTypeName;\r\n    std::wstring mObjectDebugName;\r\n#endif\r\n    CD3DX12AffinityDevice* mParentDevice;\r\n\r\n    static UINT AffinityIndexToMask(UINT const Index);\r\n    UINT GetNodeMask();\r\n\r\n    UINT GetNodeCount();\r\n    UINT GetActiveNodeIndex();\r\n\r\nprotected:\r\n    virtual bool IsD3D() = 0;\r\n\r\nprivate:\r\n    // Non-copyable\r\n    CD3DX12AffinityObject(CD3DX12AffinityObject const&);\r\n    CD3DX12AffinityObject& operator=(CD3DX12AffinityObject const&);\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityPageable.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityPageable::CD3DX12AffinityPageable(CD3DX12AffinityDevice* device, ID3D12Pageable** pageables, UINT Count)\r\n    : CD3DX12AffinityDeviceChild(device, reinterpret_cast<ID3D12DeviceChild**>(pageables), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mPageables[i] = pageables[i];\r\n        }\r\n        else\r\n        {\r\n            mPageables[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Pageable\";\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityPageable.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityPageable : public CD3DX12AffinityDeviceChild\r\n{\r\npublic:\r\n    CD3DX12AffinityPageable(CD3DX12AffinityDevice* device, ID3D12Pageable** pageables, UINT Count);\r\n\r\n    ID3D12Pageable* mPageables[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityPipelineState.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityPipelineState::GetCachedBlob(\r\n    ID3DBlob** ppBlob,\r\n    UINT AffinityIndex)\r\n{\r\n    return mPipelineStates[AffinityIndex]->GetCachedBlob(ppBlob);\r\n}\r\n\r\nCD3DX12AffinityPipelineState::CD3DX12AffinityPipelineState(CD3DX12AffinityDevice* device, ID3D12PipelineState** pipelineStates, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(pipelineStates), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mPipelineStates[i] = pipelineStates[i];\r\n        }\r\n        else\r\n        {\r\n            mPipelineStates[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"PipelineState\";\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityPipelineState.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityPipelineState : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    HRESULT STDMETHODCALLTYPE GetCachedBlob(\r\n        _COM_Outptr_  ID3DBlob** ppBlob,\r\n        UINT AffinityIndex = 0);\r\n\r\n    CD3DX12AffinityPipelineState(CD3DX12AffinityDevice* device, ID3D12PipelineState** pipelineStates, UINT Count);\r\n\r\n    ID3D12PipelineState* mPipelineStates[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityQueryHeap.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityQueryHeap::CD3DX12AffinityQueryHeap(CD3DX12AffinityDevice* device, ID3D12QueryHeap** queryHeaps, UINT Count)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(queryHeaps), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mQueryHeaps[i] = queryHeaps[i];\r\n        }\r\n        else\r\n        {\r\n            mQueryHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"QueryHeap\";\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityQueryHeap.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityQueryHeap : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    CD3DX12AffinityQueryHeap(CD3DX12AffinityDevice* device, ID3D12QueryHeap** queryHeaps, UINT Count);\r\n\r\n    ID3D12QueryHeap* mQueryHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityResource.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::Map(\r\n    UINT Subresource,\r\n    const D3D12_RANGE* pReadRange,\r\n    void** ppData)\r\n{\r\n    if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        return mResources[0]->Map(Subresource, pReadRange, ppData);\r\n    }\r\n\r\n    if (++mReferenceCount == 1)\r\n    {\r\n        DEBUG_ASSERT(mMappedAddresses.empty());\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = mResources[i];\r\n                void* MappedAddress = nullptr;\r\n                HRESULT const hr = Resource->Map(Subresource, pReadRange, &MappedAddress);\r\n\r\n                if (S_OK == hr)\r\n                {\r\n                    mMappedAddresses.push_back(MappedAddress);\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n\r\n            {\r\n                std::lock_guard<std::mutex> lock(GetParentDevice()->MutexStillMappedResources);\r\n                GetParentDevice()->StillMappedResources.insert(this);\r\n            }\r\n        }\r\n    }\r\n\r\n    switch (mCPUPageProperty)\r\n    {\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK:\r\n        *ppData = mMappedAddresses[0];\r\n        break;\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE:\r\n        *ppData = mShadowBuffer;\r\n        break;\r\n    default:\r\n    case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE:\r\n    case D3D12_CPU_PAGE_PROPERTY_UNKNOWN:\r\n        DEBUG_ASSERT(false);\r\n        return S_FALSE;\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nvoid STDMETHODCALLTYPE CD3DX12AffinityResource::Unmap(\r\n    UINT Subresource,\r\n    const D3D12_RANGE* pWrittenRange)\r\n{\r\n    if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        mResources[0]->Unmap(Subresource, pWrittenRange);\r\n        return;\r\n    }\r\n\r\n    if (--mReferenceCount == 0)\r\n    {\r\n        SynchronizeAcrossDevices();\r\n\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Resource = mResources[i];\r\n                Resource->Unmap(Subresource, pWrittenRange);\r\n            }\r\n        }\r\n\r\n        {\r\n            std::lock_guard<std::mutex> lock(GetParentDevice()->MutexStillMappedResources);\r\n            GetParentDevice()->StillMappedResources.erase(this);\r\n        }\r\n        mMappedAddresses.clear();\r\n    }\r\n\r\n    DEBUG_ASSERT(mReferenceCount >= 0);\r\n}\r\n\r\nD3D12_RESOURCE_DESC STDMETHODCALLTYPE CD3DX12AffinityResource::GetDesc(UINT AffinityIndex)\r\n{\r\n    while (!mResources[AffinityIndex])\r\n    {\r\n        AffinityIndex++;\r\n    }\r\n    return mResources[AffinityIndex]->GetDesc();\r\n}\r\n\r\nD3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE CD3DX12AffinityResource::GetGPUVirtualAddress(void)\r\n{\r\n    if (GetNodeCount() == 1\r\n#if TILE_MAPPING_GPUVA\r\n        || GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA\r\n#endif\r\n        )\r\n    {\r\n        return mResources[0]->GetGPUVirtualAddress();\r\n    }\r\n    if (0 == mVirtualAddress)\r\n    {\r\n        std::vector<D3D12_GPU_VIRTUAL_ADDRESS> Addresses(GetNodeCount());\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & mAffinityMask) != 0)\r\n            {\r\n                Addresses[i] = mResources[i]->GetGPUVirtualAddress();\r\n            }\r\n        }\r\n        mVirtualAddress = Addresses[0];\r\n\r\n        GetParentDevice()->MutexGPUVirtualAddresses.lock();\r\n        GetParentDevice()->GPUVirtualAddresses[mVirtualAddress] = std::move(Addresses);\r\n        GetParentDevice()->MutexGPUVirtualAddresses.unlock();\r\n    }\r\n\r\n    return mVirtualAddress;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::WriteToSubresource(\r\n    UINT DstSubresource,\r\n    const D3D12_BOX* pDstBox,\r\n    const void* pSrcData,\r\n    UINT SrcRowPitch,\r\n    UINT SrcDepthPitch)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n    {\r\n        if (((1 << i) & mAffinityMask) != 0)\r\n        {\r\n            ID3D12Resource* Resource = mResources[i];\r\n            HRESULT const hr = Resource->WriteToSubresource(\r\n                DstSubresource,\r\n                pDstBox,\r\n                pSrcData,\r\n                SrcRowPitch,\r\n                SrcDepthPitch);\r\n\r\n            if (S_OK != hr)\r\n            {\r\n                return hr;\r\n            }\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::ReadFromSubresource(\r\n    void* pDstData,\r\n    UINT DstRowPitch,\r\n    UINT DstDepthPitch,\r\n    UINT SrcSubresource,\r\n    const D3D12_BOX* pSrcBox,\r\n    UINT AffinityIndex)\r\n{\r\n    return mResources[AffinityIndex]->ReadFromSubresource(\r\n        pDstData,\r\n        DstRowPitch,\r\n        DstDepthPitch,\r\n        SrcSubresource,\r\n        pSrcBox);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CD3DX12AffinityResource::GetHeapProperties(\r\n    D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n    D3D12_HEAP_FLAGS* pHeapFlags,\r\n    UINT AffinityIndex)\r\n{\r\n    return mResources[AffinityIndex]->GetHeapProperties(pHeapProperties, pHeapFlags);\r\n}\r\n\r\nCD3DX12AffinityResource::CD3DX12AffinityResource(CD3DX12AffinityDevice* device, ID3D12Resource** resources, UINT Count, ID3D12Heap** heaps)\r\n    : CD3DX12AffinityPageable(device, reinterpret_cast<ID3D12Pageable**>(resources), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mResources[i] = resources[i];\r\n            mHeaps[i] = heaps ? heaps[i] : nullptr;\r\n        }\r\n        else\r\n        {\r\n            mResources[i] = nullptr;\r\n            mHeaps[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"Resource\";\r\n#endif\r\n    mVirtualAddress = 0;\r\n}\r\n\r\nCD3DX12AffinityResource::~CD3DX12AffinityResource()\r\n{\r\n    std::lock_guard<std::mutex> lock(GetParentDevice()->MutexStillMappedResources);\r\n    GetParentDevice()->StillMappedResources.erase(this);\r\n\r\n    if (0 != mVirtualAddress)\r\n    {\r\n        GetParentDevice()->GPUVirtualAddresses.erase(mVirtualAddress);\r\n    }\r\n\r\n    for (UINT i = 0; i < GetNodeCount(); i++)\r\n    {\r\n        if (mHeaps[i])\r\n        {\r\n            mHeaps[i]->Release();\r\n            mHeaps[i] = nullptr;\r\n        }\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityResource::SynchronizeAcrossDevices()\r\n{\r\n    if (GetParentDevice()->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        return;\r\n    }\r\n\r\n    switch (mCPUPageProperty)\r\n    {\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK:\r\n        for (size_t i = 1; i < mMappedAddresses.size(); ++i)\r\n        {\r\n            memcpy(mMappedAddresses[i], mMappedAddresses[0], static_cast<size_t>(mBufferSize));\r\n        }\r\n        ReleaseLog(L\"D3DX12AffinityLayer: [memcpy] Synchronized %lu bytes of WRITE_BACK memory.\\n\", mBufferSize);\r\n        break;\r\n    case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE:\r\n    {\r\n        static UINT const WrittenAddressBufferSize = 8192;\r\n        UINT NumUpdated = 0;\r\n        UINT64 BytesCopied = 0;\r\n\r\n#ifdef DO_FULL_MAPPED_MEM_COPY\r\n        for (size_t i = 0; i < mMappedAddresses.size(); ++i)\r\n        {\r\n            memcpy(mMappedAddresses[i], mShadowBuffer, static_cast<size_t>(mBufferSize));\r\n            BytesCopied += mBufferSize;\r\n        }\r\n#else\r\n        static thread_local void** WrittenAddresses = nullptr;\r\n        if (nullptr == WrittenAddresses)\r\n        {\r\n            WrittenAddresses = new void*[WrittenAddressBufferSize];\r\n        }\r\n\r\n        ULONG_PTR Count = WrittenAddressBufferSize;\r\n        ULONG Granularity = 0;\r\n        GetWriteWatch(WRITE_WATCH_FLAG_RESET, mShadowBuffer, static_cast<size_t>(mBufferSize), WrittenAddresses, &Count, &Granularity);\r\n\r\n        while (Count)\r\n        {\r\n            for (ULONG_PTR address = 0; address < Count; ++address)\r\n            {\r\n                ULONG_PTR const PageOffsetFromBasePtr = ((byte*)WrittenAddresses[address] - (byte*)mShadowBuffer);\r\n                for (size_t i = 0; i < mMappedAddresses.size(); ++i)\r\n                {\r\n                    memcpy((byte*)mMappedAddresses[i] + PageOffsetFromBasePtr, WrittenAddresses[address], Granularity);\r\n                }\r\n                NumUpdated++;\r\n                BytesCopied += Granularity;\r\n            }\r\n\r\n            Count = WrittenAddressBufferSize;\r\n            GetWriteWatch(WRITE_WATCH_FLAG_RESET, mShadowBuffer, static_cast<size_t>(mBufferSize), WrittenAddresses, &Count, &Granularity);\r\n        }\r\n#endif\r\n\r\n        ReleaseLog(L\"D3DX12AffinityLayer: [memcpy] Synchronized %lu bytes of shadow buffered memory.\\n\", BytesCopied);\r\n        break;\r\n    }\r\n    case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE:\r\n        DEBUG_FAIL_MESSAGE(L\"Property of CPU Page unnavailable while synchronizing.\");\r\n        break;\r\n    case D3D12_CPU_PAGE_PROPERTY_UNKNOWN:\r\n        DEBUG_FAIL_MESSAGE(L\"Property of CPU Page unknown while synchronizing.\");\r\n        break;\r\n    default:\r\n        DebugLog(L\"Unexpected CPU page value: %d\\n\", mCPUPageProperty);\r\n        DEBUG_FAIL_MESSAGE(L\"Property of CPU Page entirely unexpected while synchronizing. Possible corruption.\");\r\n        break;\r\n    }\r\n}\r\n\r\nvoid CD3DX12AffinityResource::UpdatePersistentMaps(CD3DX12AffinityDevice* pDevice)\r\n{\r\n    std::lock_guard<std::mutex> lock(pDevice->MutexStillMappedResources);\r\n    for (CD3DX12AffinityResource* Resource : pDevice->StillMappedResources)\r\n    {\r\n        Resource->SynchronizeAcrossDevices();\r\n    }\r\n}\r\n\r\nID3D12Resource* CD3DX12AffinityResource::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mResources[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityResource.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityResource : public CD3DX12AffinityPageable\r\n{\r\npublic:\r\n    HRESULT STDMETHODCALLTYPE Map(\r\n        UINT Subresource,\r\n        _In_opt_  const D3D12_RANGE* pReadRange,\r\n        _Outptr_opt_result_bytebuffer_(_Inexpressible_(\"Dependent on resource\"))  void** ppData);\r\n\r\n    void STDMETHODCALLTYPE Unmap(\r\n        UINT Subresource,\r\n        _In_opt_  const D3D12_RANGE* pWrittenRange);\r\n\r\n    D3D12_RESOURCE_DESC STDMETHODCALLTYPE GetDesc(UINT AffinityIndex = 0);\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE GetGPUVirtualAddress(void);\r\n\r\n    HRESULT STDMETHODCALLTYPE WriteToSubresource(\r\n        UINT DstSubresource,\r\n        _In_opt_  const D3D12_BOX* pDstBox,\r\n        _In_  const void* pSrcData,\r\n        UINT SrcRowPitch,\r\n        UINT SrcDepthPitch);\r\n\r\n    HRESULT STDMETHODCALLTYPE ReadFromSubresource(\r\n        _Out_  void* pDstData,\r\n        UINT DstRowPitch,\r\n        UINT DstDepthPitch,\r\n        UINT SrcSubresource,\r\n        _In_opt_  const D3D12_BOX* pSrcBox,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetHeapProperties(\r\n        _Out_opt_  D3D12_HEAP_PROPERTIES* pHeapProperties,\r\n        _Out_opt_  D3D12_HEAP_FLAGS* pHeapFlags,\r\n        UINT AffinityIndex = 0);\r\n\r\n    CD3DX12AffinityResource(CD3DX12AffinityDevice* device, ID3D12Resource** resources, UINT Count, ID3D12Heap** heaps = nullptr);\r\n    ~CD3DX12AffinityResource();\r\n\r\n    ID3D12Resource* GetChildObject(UINT AffinityIndex);\r\n    void SynchronizeAcrossDevices();\r\n\r\n    static void UpdatePersistentMaps(CD3DX12AffinityDevice* pDevice);\r\n\r\n\r\n    ID3D12Resource* mResources[D3DX12_MAX_ACTIVE_NODES];\r\n    ID3D12Heap* mHeaps[D3DX12_MAX_ACTIVE_NODES];\r\n    std::vector<void*> mMappedAddresses;\r\n    int mReferenceCount;\r\n    void* mShadowBuffer;\r\n    UINT64 mBufferSize;\r\n    D3D12_CPU_PAGE_PROPERTY mCPUPageProperty;\r\n    D3D12_GPU_VIRTUAL_ADDRESS mVirtualAddress;\r\n\r\n    ID3D12CommandList* mSyncCommandLists[D3DX12_MAX_ACTIVE_NODES];\r\n    ID3D12CommandAllocator* mSyncCommandAllocators[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityRootSignature.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\nCD3DX12AffinityRootSignature::CD3DX12AffinityRootSignature(CD3DX12AffinityDevice* device, ID3D12RootSignature** rootSignatures, UINT Count)\r\n    : CD3DX12AffinityDeviceChild(device, reinterpret_cast<ID3D12DeviceChild**>(rootSignatures), Count)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mRootSignatures[i] = rootSignatures[i];\r\n        }\r\n        else\r\n        {\r\n            mRootSignatures[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"RootSignature\";\r\n#endif\r\n}\r\n\r\nID3D12RootSignature* CD3DX12AffinityRootSignature::GetChildObject(UINT AffinityIndex)\r\n{\r\n    return mRootSignatures[AffinityIndex];\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CD3DX12AffinityRootSignature.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CD3DX12AffinityRootSignature : public CD3DX12AffinityDeviceChild\r\n{\r\npublic:\r\n    CD3DX12AffinityRootSignature(CD3DX12AffinityDevice* device, ID3D12RootSignature** rootSignatures, UINT Count);\r\n    ID3D12RootSignature* GetChildObject(UINT AffinityIndex);\r\n\r\n    ID3D12RootSignature* mRootSignatures[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CDXGIAffinitySwapChain.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"d3dx12.h\"\r\n#include \"Utils.h\"\r\n\r\n#include <string>\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetParent(\r\n    REFIID riid,\r\n    void** ppParent,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetParent(riid, ppParent);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::Present(\r\n    UINT SyncInterval,\r\n    UINT Flags,\r\n    UINT AffinityMask)\r\n{\r\n    UINT IndicesCount = 0;\r\n    HRESULT hr = S_OK;\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    switch (mMode)\r\n    {\r\n    case EAffinitySwapChainMode::MultiWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n                hr = SwapChain->Present(SyncInterval, Flags);\r\n                RETURN_IF_FAILED(hr);\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::LDA:\r\n    {\r\n        hr = mSwapChains[0]->Present(SyncInterval, Flags);\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::SingleWindow:\r\n    {\r\n        UINT const i = 0;\r\n        DebugLog(L\"Presenting contents of backbuffer %d on device %d\", mCurrentBackBufferIndex, i);\r\n\r\n        DebugLog(L\" [marshalled]\\n\");\r\n        SDeviceContext& Context = mDeviceContexts[i];\r\n        ID3D12Resource* RenderTarget = Context.mRenderTargets[mCurrentBackBufferIndex];\r\n        ID3D12Resource* CopyBuffer = Context.mCrossAdapterCopyBuffers[mCurrentBackBufferIndex];\r\n\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(RenderTarget, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_SOURCE));\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBuffer, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));\r\n        Context.mDisplayCommandList->CopyResource(CopyBuffer, RenderTarget);\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON));\r\n        Context.mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(RenderTarget, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT));\r\n        Context.mDisplayCommandList->Close();\r\n\r\n        if (Context.mFenceValue)\r\n            Context.mDisplayCommandQueue->Wait(Context.mCrossAdapterCopyFence, Context.mFenceValue);\r\n        ID3D12CommandList* ppCommandLists1[] = { Context.mDisplayCommandList };\r\n        Context.mDisplayCommandQueue->ExecuteCommandLists(_countof(ppCommandLists1), ppCommandLists1);\r\n        Context.mDisplayCommandQueue->Signal(Context.mCrossAdapterCopyFence, ++Context.mFenceValue);\r\n\r\n        Context.mDisplayCommandList->Reset(Context.mDisplayCommandAllocator, nullptr);\r\n\r\n        ID3D12Resource* CopyBufferOnHost = Context.mCrossAdapterCopyBuffersOnHost[mCurrentBackBufferIndex];\r\n        ID3D12Resource* TargetBackBufferResource = nullptr;\r\n        mSwapChains[0]->GetBuffer(mCurrentBackBufferIndex, IID_PPV_ARGS(&TargetBackBufferResource));\r\n\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(TargetBackBufferResource, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST));\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBufferOnHost, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE));\r\n        mDeviceContexts[0].mDisplayCommandList->CopyResource(TargetBackBufferResource, CopyBufferOnHost);\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CopyBufferOnHost, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON));\r\n        mDeviceContexts[0].mDisplayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(TargetBackBufferResource, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT));\r\n        mDeviceContexts[0].mDisplayCommandList->Close();\r\n\r\n        mDeviceContexts[0].mDisplayCommandQueue->Wait(Context.mCrossAdapterCopyFenceOnHost, Context.mFenceValue);\r\n        ID3D12CommandList* ppCommandLists2[] = { mDeviceContexts[0].mDisplayCommandList };\r\n        mDeviceContexts[0].mDisplayCommandQueue->ExecuteCommandLists(_countof(ppCommandLists2), ppCommandLists2);\r\n        mDeviceContexts[0].mDisplayCommandQueue->Signal(Context.mCrossAdapterCopyFenceOnHost, ++Context.mFenceValue);\r\n\r\n        mDeviceContexts[0].mDisplayCommandList->Reset(mDeviceContexts[0].mDisplayCommandAllocator, nullptr);\r\n\r\n        hr = mSwapChains[0]->Present(SyncInterval, Flags);\r\n\r\n        TargetBackBufferResource->Release();\r\n\r\n        break;\r\n    }\r\n    }\r\n\r\n    mCurrentBackBufferIndex = mSwapChains[0]->GetCurrentBackBufferIndex();\r\n    return hr;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetBuffer(\r\n    UINT Buffer,\r\n    REFIID riid,\r\n    void** ppSurface,\r\n    UINT AffinityMask)\r\n{\r\n    UINT IndicesCount = 0;\r\n    \r\n    std::vector<ID3D12Resource*> Resources;\r\n    Resources.resize(GetNodeCount(), nullptr);\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    switch (mMode)\r\n    {\r\n    case EAffinitySwapChainMode::MultiWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n                ID3D12Resource* Surface = nullptr;\r\n                HRESULT const hr = SwapChain->GetBuffer(Buffer, IID_PPV_ARGS(&Surface));\r\n\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Surface;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::LDA:\r\n    {\r\n        for (UINT b = 0; b < mNumBackBuffers; ++b)\r\n        {\r\n            UINT bufferIndex = b % mNumRequestedBackBuffers;\r\n            if (bufferIndex == Buffer)\r\n            {\r\n                UINT nodeIndex = b % GetNodeCount();\r\n                HRESULT hr = mSwapChains[0]->GetBuffer(b, IID_PPV_ARGS(&Resources[nodeIndex]));\r\n                if (FAILED(hr))\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::SingleWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                ID3D12Resource* Surface = nullptr;\r\n                HRESULT hr = S_OK;\r\n\r\n                Surface = mDeviceContexts[i].mRenderTargets[Buffer];\r\n                Surface->AddRef();\r\n\r\n                if (S_OK == hr)\r\n                {\r\n                    Resources[i] = Surface;\r\n                }\r\n                else\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    }\r\n\r\n    CD3DX12AffinityResource* Resource = new CD3DX12AffinityResource(GetParentDevice(), &(Resources[0]), (UINT)Resources.size());\r\n#ifdef DEBUG_OBJECT_NAME\r\n    Resource->mObjectDebugName = L\"SwapChainBackBuffer\";\r\n#endif\r\n\r\n    *ppSurface = Resource;\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetFullscreenState(\r\n    BOOL Fullscreen,\r\n    IDXGIOutput* pTarget,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetFullscreenState(Fullscreen, pTarget);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetFullscreenState(Fullscreen, pTarget);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetFullscreenState(\r\n    BOOL* pFullscreen,\r\n    IDXGIOutput** ppTarget,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFullscreenState(pFullscreen, ppTarget);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetDesc(\r\n    DXGI_SWAP_CHAIN_DESC* pDesc,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetDesc(pDesc);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::ResizeBuffers(\r\n    UINT BufferCount,\r\n    UINT Width,\r\n    UINT Height,\r\n    DXGI_FORMAT NewFormat,\r\n    UINT SwapChainFlags,\r\n    UINT AffinityMask)\r\n{\r\n    DebugLog(L\"Doing swap chain buffer resize...\\n\");\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n\r\n    // First free up any existing resources.\r\n\r\n    for (UINT i = 1; i < mDeviceContexts.size(); ++i)\r\n    {\r\n        CDXGIAffinitySwapChain::SDeviceContext& DeviceContext = mDeviceContexts[i];\r\n\r\n        for (size_t i = 0; i < DeviceContext.mRenderTargets.size(); ++i)\r\n        {\r\n            DeviceContext.mRenderTargets[i]->Release();\r\n        }\r\n        DeviceContext.mRenderTargets.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBufferHeaps.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBufferHeaps[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBufferHeaps.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBuffers.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBuffers[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBuffers.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBufferHeapsOnHost.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBufferHeapsOnHost[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBufferHeapsOnHost.clear();\r\n        for (size_t i = 0; i < DeviceContext.mCrossAdapterCopyBuffersOnHost.size(); ++i)\r\n        {\r\n            DeviceContext.mCrossAdapterCopyBuffersOnHost[i]->Release();\r\n        }\r\n        DeviceContext.mCrossAdapterCopyBuffersOnHost.clear();\r\n    }\r\n\r\n    // Resize the actual swap buffers.\r\n\r\n    switch (mMode)\r\n    {\r\n    case EAffinitySwapChainMode::MultiWindow:\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n                RETURN_IF_FAILED(\r\n                    SwapChain->ResizeBuffers(\r\n                        BufferCount,\r\n                        Width,\r\n                        Height,\r\n                        NewFormat,\r\n                        SwapChainFlags));\r\n            }\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::LDA:\r\n    {\r\n        std::vector<UINT> creationNodeMasks;\r\n        std::vector<IUnknown*> pQueues;\r\n        UINT nodeCount = GetNodeCount();\r\n        if (nodeCount > 1)\r\n        {\r\n            mNumBackBuffers = lcm(BufferCount, nodeCount);\r\n            mNumRequestedBackBuffers = BufferCount;\r\n            creationNodeMasks.resize(mNumBackBuffers);\r\n            pQueues.resize(mNumBackBuffers);\r\n            for (UINT i = 0; i < mNumBackBuffers; i++)\r\n            {\r\n                creationNodeMasks[i] = GetParentDevice()->AffinityIndexToNodeMask(i % nodeCount);\r\n                pQueues[i] = mParentQueue->GetChildObject(i % nodeCount);\r\n            }\r\n            RETURN_IF_FAILED(\r\n                mSwapChains[0]->ResizeBuffers1(\r\n                    mNumBackBuffers,\r\n                    Width,\r\n                    Height,\r\n                    NewFormat,\r\n                    SwapChainFlags,\r\n                    creationNodeMasks.data(),\r\n                    pQueues.data()));\r\n\r\n            GetParentDevice()->g_ActiveNodeIndex = 0;\r\n        }\r\n        else\r\n        {\r\n            RETURN_IF_FAILED(\r\n                mSwapChains[0]->ResizeBuffers(\r\n                    BufferCount,\r\n                    Width,\r\n                    Height,\r\n                    NewFormat,\r\n                    SwapChainFlags));\r\n        }\r\n        break;\r\n    }\r\n    case EAffinitySwapChainMode::SingleWindow:\r\n        RETURN_IF_FAILED(\r\n            mSwapChains[0]->ResizeBuffers(\r\n                BufferCount,\r\n                Width,\r\n                Height,\r\n                NewFormat,\r\n                SwapChainFlags));\r\n        break;\r\n    }\r\n\r\n    mCurrentBackBufferIndex = 0;\r\n\r\n    // Recreate render targets.\r\n\r\n    if (mMode != EAffinitySwapChainMode::LDA)\r\n    {\r\n        for (UINT i = 0; i < mDeviceContexts.size(); ++i)\r\n        {\r\n            RETURN_IF_FAILED(\r\n                CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n                    i,\r\n                    GetParentDevice(),\r\n                    mHostDevice,\r\n                    mDeviceContexts[i],\r\n                    Width, Height, NewFormat,\r\n                    mNumBackBuffers));\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::ResizeTarget(\r\n    const DXGI_MODE_DESC* pNewTargetParameters,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->ResizeTarget(pNewTargetParameters);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->ResizeTarget(pNewTargetParameters);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetContainingOutput(\r\n    IDXGIOutput** ppOutput,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetContainingOutput(ppOutput);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetFrameStatistics(\r\n    DXGI_FRAME_STATISTICS* pStats,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFrameStatistics(pStats);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetLastPresentCount(\r\n    UINT* pLastPresentCount,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetLastPresentCount(pLastPresentCount);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetDesc1(DXGI_SWAP_CHAIN_DESC1* pDesc, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetDesc1(pDesc);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFullscreenDesc(pDesc);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetHwnd(HWND* pHwnd, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetHwnd(pHwnd);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetCoreWindow(REFIID refiid, void** ppUnk, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetCoreWindow(refiid, ppUnk);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters, UINT AffinityMask)\r\n{\r\n    HRESULT_METHOD_NOT_YET_IMPLEMENTED(CDXGIAffinitySwapChain::Present1);\r\n}\r\n\r\nBOOL CDXGIAffinitySwapChain::IsTemporaryMonoSupported(UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->IsTemporaryMonoSupported();\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetRestrictToOutput(ppRestrictToOutput);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::SetBackgroundColor(const DXGI_RGBA* pColor, UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain1* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetBackgroundColor(pColor);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetBackgroundColor(pColor);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetBackgroundColor(DXGI_RGBA* pColor, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetBackgroundColor(pColor);\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::SetRotation(DXGI_MODE_ROTATION Rotation, UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain1* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetRotation(Rotation);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetRotation(Rotation);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetRotation(DXGI_MODE_ROTATION* pRotation, UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetRotation(pRotation);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetSourceSize(\r\n    UINT Width,\r\n    UINT Height,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain2* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetSourceSize(Width, Height);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetSourceSize(Width, Height);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetSourceSize(\r\n    UINT* pWidth,\r\n    UINT* pHeight,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetSourceSize(pWidth, pHeight);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetMaximumFrameLatency(\r\n    UINT MaxLatency,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain2* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetMaximumFrameLatency(MaxLatency);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetMaximumFrameLatency(MaxLatency);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetMaximumFrameLatency(\r\n    UINT* pMaxLatency,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetMaximumFrameLatency(pMaxLatency);\r\n}\r\n\r\nHANDLE STDMETHODCALLTYPE CDXGIAffinitySwapChain::GetFrameLatencyWaitableObject(UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetFrameLatencyWaitableObject();\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::SetMatrixTransform(\r\n    const DXGI_MATRIX_3X2_F* pMatrix,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain2* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetMatrixTransform(pMatrix);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetMatrixTransform(pMatrix);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::GetMatrixTransform(\r\n    DXGI_MATRIX_3X2_F* pMatrix,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->GetMatrixTransform(pMatrix);\r\n}\r\n\r\nUINT CDXGIAffinitySwapChain::GetCurrentBackBufferIndex()\r\n{\r\n    return mCurrentBackBufferIndex;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::CheckColorSpaceSupport(\r\n    DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n    UINT* pColorSpaceSupport,\r\n    UINT AffinityIndex)\r\n{\r\n    if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        AffinityIndex = 0;\r\n    }\r\n\r\n    return mSwapChains[AffinityIndex]->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport);\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::SetColorSpace1(\r\n    DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n    UINT AffinityMask)\r\n{\r\n    UINT EffectiveAffinityMask = (AffinityMask == 0) ? GetNodeMask() : AffinityMask & GetNodeMask();\r\n    if (mMode == EAffinitySwapChainMode::MultiWindow)\r\n    {\r\n        for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES;i++)\r\n        {\r\n            if (((1 << i) & EffectiveAffinityMask) != 0)\r\n            {\r\n                IDXGISwapChain3* SwapChain = mSwapChains[i];\r\n\r\n                HRESULT const hr = SwapChain->SetColorSpace1(ColorSpace);\r\n\r\n                if (hr != S_OK)\r\n                {\r\n                    return hr;\r\n                }\r\n            }\r\n        }\r\n        return S_OK;\r\n    }\r\n    else if (mMode == EAffinitySwapChainMode::LDA || mMode == EAffinitySwapChainMode::SingleWindow)\r\n    {\r\n        return mSwapChains[0]->SetColorSpace1(ColorSpace);\r\n    }\r\n    else\r\n    {\r\n        return E_NOTIMPL;\r\n    }\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE CDXGIAffinitySwapChain::ResizeBuffers1(\r\n    UINT BufferCount,\r\n    UINT Width,\r\n    UINT Height,\r\n    DXGI_FORMAT Format,\r\n    UINT SwapChainFlags,\r\n    const UINT* pCreationNodeMask,\r\n    IUnknown* const* ppPresentQueue)\r\n{\r\n    HRESULT_METHOD_NOT_YET_IMPLEMENTED(CDXGIAffinitySwapChain::ResizeBuffers1);\r\n}\r\n\r\nCDXGIAffinitySwapChain::CDXGIAffinitySwapChain(CD3DX12AffinityDevice* device, CD3DX12AffinityCommandQueue* queue, IDXGISwapChain3** swapChains, UINT Count)\r\n    : CD3DX12AffinityObject(device, reinterpret_cast<IUnknown**>(swapChains), Count)\r\n    , mCurrentBackBufferIndex(0)\r\n{\r\n    for (UINT i = 0; i < D3DX12_MAX_ACTIVE_NODES; i++)\r\n    {\r\n        if (i < Count)\r\n        {\r\n            mSwapChains[i] = swapChains[i];\r\n        }\r\n        else\r\n        {\r\n            mSwapChains[i] = nullptr;\r\n        }\r\n    }\r\n#ifdef DEBUG_OBJECT_NAME\r\n    mObjectTypeName = L\"SwapChain\";\r\n#endif\r\n    mParentQueue = queue;\r\n}\r\n\r\nHRESULT CDXGIAffinitySwapChain::CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n    UINT const Index,\r\n    CD3DX12AffinityDevice* AffinityDevice,\r\n    ID3D12Device* const HostDevice,\r\n    CDXGIAffinitySwapChain::SDeviceContext& DeviceContext,\r\n    UINT const Width,\r\n    UINT const Height,\r\n    DXGI_FORMAT const Format,\r\n    UINT const NumBackBuffers)\r\n{\r\n    for (UINT b = 0; b < NumBackBuffers; ++b)\r\n    {\r\n        // Create the render target itself.\r\n\r\n        ID3D12Resource* RenderTarget = nullptr;\r\n\r\n        CD3DX12_HEAP_PROPERTIES renderTargetHeapProps(D3D12_HEAP_TYPE_DEFAULT);\r\n        if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA)\r\n        {\r\n            renderTargetHeapProps.CreationNodeMask = AffinityDevice->AffinityIndexToNodeMask(Index);\r\n            renderTargetHeapProps.VisibleNodeMask = AffinityDevice->LDAAllNodeMasks();\r\n        }\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateCommittedResource(\r\n                &renderTargetHeapProps,\r\n                D3D12_HEAP_FLAG_NONE,\r\n                &CD3DX12_RESOURCE_DESC::Tex2D(\r\n                    Format,\r\n                    Width,\r\n                    Height,\r\n                    1, 1,\r\n                    1, 0,\r\n                    D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,\r\n                    D3D12_TEXTURE_LAYOUT_UNKNOWN),\r\n                D3D12_RESOURCE_STATE_COMMON,\r\n                nullptr,\r\n                IID_PPV_ARGS(&RenderTarget)\r\n            ),\r\n            \"Failed to create render target committed resource during affinity swap chain setup.\", AffinityDevice);\r\n        WCHAR name[256] = {};\r\n        swprintf_s(name, L\"SwapChain RenderTarget: %u\", b);\r\n        RenderTarget->SetName(name);\r\n        DeviceContext.mRenderTargets.push_back(RenderTarget);\r\n\r\n        // Next create a heap for the cross adapter copy.\r\n\r\n        ID3D12Resource* CrossAdapterCopyResource = nullptr;\r\n        ID3D12Heap* CrossAdapterCopyBufferHeap = nullptr;\r\n\r\n        CD3DX12_RESOURCE_DESC const ResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(\r\n            Format,\r\n            Width,\r\n            Height,\r\n            1, 1,\r\n            1, 0,\r\n            D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER,\r\n            D3D12_TEXTURE_LAYOUT_ROW_MAJOR);\r\n\r\n        D3D12_RESOURCE_ALLOCATION_INFO const AllocationInfo = DeviceContext.mDevice->GetResourceAllocationInfo(\r\n            0,\r\n            1, &ResourceDesc);\r\n        CD3DX12_HEAP_DESC heapDesc(AllocationInfo.SizeInBytes, D3D12_HEAP_TYPE_DEFAULT, 0, D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER);\r\n        if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA)\r\n        {\r\n            heapDesc.Properties.CreationNodeMask = AffinityDevice->AffinityIndexToNodeMask(Index);\r\n            heapDesc.Properties.VisibleNodeMask = AffinityDevice->LDAAllNodeMasks();\r\n        }\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateHeap(\r\n                &heapDesc,\r\n                IID_PPV_ARGS(&CrossAdapterCopyBufferHeap)),\r\n            \"Failed to create cross-adapter heap during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        DeviceContext.mCrossAdapterCopyBufferHeaps.push_back(CrossAdapterCopyBufferHeap);\r\n\r\n        // Create a placed resource with that heap on the current device.\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreatePlacedResource(\r\n                CrossAdapterCopyBufferHeap, 0,\r\n                &ResourceDesc,\r\n                D3D12_RESOURCE_STATE_COMMON,\r\n                nullptr,\r\n                IID_PPV_ARGS(&CrossAdapterCopyResource)\r\n            ),\r\n            \"Failed to create cross-adapter placed resource during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        std::wstring Name = std::wstring(L\"CrossAdapterCopyBuffer\") + std::to_wstring(Index) + L\"-\" + std::to_wstring(b);\r\n        CrossAdapterCopyResource->SetName(Name.c_str());\r\n        DeviceContext.mCrossAdapterCopyBuffers.push_back(CrossAdapterCopyResource);\r\n\r\n        // Now open the heap up on the host device.\r\n\r\n        HANDLE CrossAdapterCopyBufferSharedHandle = nullptr;\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateSharedHandle(\r\n                CrossAdapterCopyBufferHeap,\r\n                nullptr,\r\n                GENERIC_ALL,\r\n                nullptr,\r\n                &CrossAdapterCopyBufferSharedHandle),\r\n            \"Failed to create shared handle to cross-adapter copy buffer heap during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        CrossAdapterCopyBufferHeap = nullptr;\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            HostDevice->OpenSharedHandle(CrossAdapterCopyBufferSharedHandle, IID_PPV_ARGS(&CrossAdapterCopyBufferHeap)),\r\n            \"Failed to open shared handle to cross-adapter copy buffer heap during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        DeviceContext.mCrossAdapterCopyBufferHeapsOnHost.push_back(CrossAdapterCopyBufferHeap);\r\n\r\n        // And finally use that heap to create placed resource on the host device.\r\n\r\n        CrossAdapterCopyResource = nullptr;\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            HostDevice->CreatePlacedResource(\r\n                CrossAdapterCopyBufferHeap, 0,\r\n                &CD3DX12_RESOURCE_DESC::Tex2D(\r\n                    Format,\r\n                    Width,\r\n                    Height,\r\n                    1, 1,\r\n                    1, 0,\r\n                    D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER,\r\n                    D3D12_TEXTURE_LAYOUT_ROW_MAJOR),\r\n                D3D12_RESOURCE_STATE_COMMON,\r\n                nullptr,\r\n                IID_PPV_ARGS(&CrossAdapterCopyResource)),\r\n            \"Failed to create cross-adapter placed resource on host device during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        CrossAdapterCopyResource->SetName(L\"CrossAdapterCopyBufferOnHost\");\r\n        DeviceContext.mCrossAdapterCopyBuffersOnHost.push_back(CrossAdapterCopyResource);\r\n\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/CDXGIAffinitySwapChain.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#include \"Utils.h\"\r\n#include \"CD3DX12AffinityObject.h\"\r\n\r\n#include <dxgi1_4.h>\r\n\r\ninline UINT gcd(UINT a, UINT b)\r\n{\r\n    for (;;)\r\n    {\r\n        if (a == 0) return b;\r\n        b %= a;\r\n        if (b == 0) return a;\r\n        a %= b;\r\n    }\r\n}\r\n\r\ninline UINT lcm(UINT a, UINT b)\r\n{\r\n    UINT temp = gcd(a, b);\r\n\r\n    return temp ? (a / temp * b) : 0;\r\n}\r\n\r\nenum EAffinitySwapChainMode\r\n{\r\n    SingleWindow,\r\n    MultiWindow,\r\n    LDA\r\n};\r\n\r\n// Implements up to IDXGISwapChain3.\r\nclass __declspec(uuid(\"BE1D71C8-88FD-4623-ABFA-D0E546D12FAF\")) CDXGIAffinitySwapChain : public CD3DX12AffinityObject\r\n{\r\npublic:\r\n    virtual HRESULT QueryInterface(CDXGIAffinitySwapChain** ppvObject)\r\n    {\r\n        *ppvObject = this;\r\n        AddRef();\r\n        return S_OK;\r\n    }\r\n\r\n    HRESULT STDMETHODCALLTYPE GetParent(\r\n        _In_  REFIID riid,\r\n        _COM_Outptr_  void** ppParent,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE Present(\r\n        UINT SyncInterval,\r\n        UINT Flags,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetBuffer(\r\n        UINT Buffer,\r\n        _In_ REFIID riid,\r\n        _Outptr_  void** ppSurface,\r\n        _In_opt_  UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetFullscreenState(\r\n        BOOL Fullscreen,\r\n        _In_opt_  IDXGIOutput* pTarget,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetFullscreenState(\r\n        _Out_opt_  BOOL* pFullscreen,\r\n        _COM_Outptr_opt_result_maybenull_  IDXGIOutput** ppTarget,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDesc(\r\n        _Out_  DXGI_SWAP_CHAIN_DESC* pDesc,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE ResizeBuffers(\r\n        UINT BufferCount,\r\n        UINT Width,\r\n        UINT Height,\r\n        DXGI_FORMAT NewFormat,\r\n        UINT SwapChainFlags,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE ResizeTarget(\r\n        _In_  const DXGI_MODE_DESC* pNewTargetParameters,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetContainingOutput(\r\n        _COM_Outptr_  IDXGIOutput** ppOutput,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetFrameStatistics(\r\n        _Out_  DXGI_FRAME_STATISTICS* pStats,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetLastPresentCount(\r\n        _Out_  UINT* pLastPresentCount,\r\n        UINT AffinityIndex = 0);\r\n\r\n    // IDXGISwapChain1\r\n\r\n    HRESULT STDMETHODCALLTYPE GetDesc1(\r\n        _Out_  DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetFullscreenDesc(\r\n        _Out_  DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetHwnd(\r\n        _Out_  HWND* pHwnd,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetCoreWindow(\r\n        _In_  REFIID refiid,\r\n        _COM_Outptr_  void** ppUnk,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE Present1(\r\n        UINT SyncInterval,\r\n        UINT PresentFlags,\r\n        _In_  const DXGI_PRESENT_PARAMETERS* pPresentParameters,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported(UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetRestrictToOutput(\r\n        _Out_  IDXGIOutput** ppRestrictToOutput,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetBackgroundColor(\r\n        _In_  const DXGI_RGBA* pColor,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetBackgroundColor(\r\n        _Out_  DXGI_RGBA* pColor,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetRotation(\r\n        _In_  DXGI_MODE_ROTATION Rotation,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetRotation(\r\n        _Out_  DXGI_MODE_ROTATION* pRotation,\r\n        UINT AffinityIndex = 0);\r\n\r\n    // IDXGISwapChain2\r\n\r\n    HRESULT STDMETHODCALLTYPE SetSourceSize(\r\n        UINT Width,\r\n        UINT Height,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetSourceSize(\r\n        _Out_  UINT* pWidth,\r\n        _Out_  UINT* pHeight,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(\r\n        UINT MaxLatency,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(\r\n        _Out_  UINT* pMaxLatency,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject(\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetMatrixTransform(\r\n        const DXGI_MATRIX_3X2_F* pMatrix,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE GetMatrixTransform(\r\n        _Out_  DXGI_MATRIX_3X2_F* pMatrix,\r\n        UINT AffinityIndex = 0);\r\n\r\n    // IDXGISwapChain3\r\n\r\n    UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex();\r\n\r\n    HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport(\r\n        _In_  DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n        _Out_  UINT* pColorSpaceSupport,\r\n        UINT AffinityIndex = 0);\r\n\r\n    HRESULT STDMETHODCALLTYPE SetColorSpace1(\r\n        _In_  DXGI_COLOR_SPACE_TYPE ColorSpace,\r\n        UINT AffinityMask = EAffinityMask::AllNodes);\r\n\r\n    HRESULT STDMETHODCALLTYPE ResizeBuffers1(\r\n        _In_  UINT BufferCount,\r\n        _In_  UINT Width,\r\n        _In_  UINT Height,\r\n        _In_  DXGI_FORMAT Format,\r\n        _In_  UINT SwapChainFlags,\r\n        _In_reads_(BufferCount)  const UINT* pCreationNodeMask,\r\n        _In_reads_(BufferCount)  IUnknown* const* ppPresentQueue);\r\n\r\n    CDXGIAffinitySwapChain(CD3DX12AffinityDevice* device, CD3DX12AffinityCommandQueue* queue, IDXGISwapChain3** swapChains, UINT Count);\r\n\r\n    struct SDeviceContext\r\n    {\r\n        std::vector<ID3D12Resource*> mRenderTargets;\r\n        std::vector<ID3D12Resource*> mCrossAdapterCopyBuffers;\r\n        std::vector<ID3D12Heap*> mCrossAdapterCopyBufferHeaps;\r\n        std::vector<ID3D12Resource*> mCrossAdapterCopyBuffersOnHost;\r\n        std::vector<ID3D12Heap*> mCrossAdapterCopyBufferHeapsOnHost;\r\n        ID3D12Fence* mCrossAdapterCopyFence;\r\n        ID3D12Fence* mCrossAdapterCopyFenceOnHost;\r\n\r\n        ID3D12CommandQueue* mDisplayCommandQueue;\r\n        ID3D12CommandAllocator* mDisplayCommandAllocator;\r\n        ID3D12GraphicsCommandList* mDisplayCommandList;\r\n\r\n        UINT mFenceValue;\r\n        ID3D12Device* mDevice;\r\n\r\n        SDeviceContext()\r\n        {\r\n            mCrossAdapterCopyFence = nullptr;\r\n            mCrossAdapterCopyFenceOnHost = nullptr;\r\n\r\n            mDisplayCommandQueue = nullptr;\r\n            mDisplayCommandAllocator = nullptr;\r\n            mDisplayCommandList = nullptr;\r\n\r\n            mFenceValue = 0;\r\n            mDevice = nullptr;\r\n        }\r\n    };\r\n\r\n    static HRESULT CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n        UINT const Index,\r\n        CD3DX12AffinityDevice* AffinityDevice,\r\n        ID3D12Device* const HostDevice,\r\n        CDXGIAffinitySwapChain::SDeviceContext& DeviceContext,\r\n        UINT const Width,\r\n        UINT const Height,\r\n        DXGI_FORMAT const Format,\r\n        UINT const NumBackBuffers);\r\n\r\n    CD3DX12AffinityCommandQueue* mParentQueue;\r\n    std::vector<SDeviceContext> mDeviceContexts;\r\n\r\n    UINT mCurrentBackBufferIndex;\r\n    UINT mNumBackBuffers;\r\n    UINT mNumRequestedBackBuffers;\r\n    EAffinitySwapChainMode mMode;\r\n\r\n    ID3D12Device* mHostDevice;\r\n\r\nprotected:\r\n    virtual bool IsD3D()\r\n    {\r\n        return false;\r\n    }\r\n\r\nprivate:\r\n    IDXGISwapChain3* mSwapChains[D3DX12_MAX_ACTIVE_NODES];\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/D3DX12AffinityCreateMultiDevice.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This is the standard (only) method for creating a D3DX12 Affinity device. It takes\r\n * an array of ID3D12Devices and does some very minimal setup.\r\n */\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\nHRESULT WINAPI D3DX12AffinityCreateLDADevice(\r\n    ID3D12Device* Device,\r\n    CD3DX12AffinityDevice** ppDevice)\r\n{\r\n\r\n    CD3DX12AffinityDevice* Instance = new CD3DX12AffinityDevice(&Device, 1, EAffinityMode::LDA);\r\n    Device->AddRef();\r\n\r\n#ifdef DEBUG\r\n    ID3D12Debug* debugController = nullptr;\r\n    if (!CD3DX12AffinityDevice::InfoQueue && SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))\r\n    {\r\n        ID3D12InfoQueue* infoQueue = nullptr;\r\n        if (SUCCEEDED(debugController->QueryInterface(IID_PPV_ARGS(&infoQueue))))\r\n        {\r\n            CD3DX12AffinityDevice::InfoQueue = infoQueue;\r\n        }\r\n    }\r\n#endif\r\n\r\n    (*ppDevice) = Instance;\r\n    return S_OK;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/D3DX12AffinityLayer.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|ARM\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>ARM</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|ARM\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>ARM</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{dbfb5d41-279e-4906-aa95-4cb9d94e6428}</ProjectGuid>\r\n    <Keyword>StaticLibrary</Keyword>\r\n    <ProjectName>D3DX12AffinityLayer</ProjectName>\r\n    <RootNamespace>D3DX12AffinityLayer</RootNamespace>\r\n    <DefaultLanguage>en-US</DefaultLanguage>\r\n    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\r\n    <AppContainerApplication>true</AppContainerApplication>\r\n    <ApplicationType>Windows Store</ApplicationType>\r\n    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>\r\n    <WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>\r\n    <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"Shared\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <GenerateManifest>false</GenerateManifest>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <GenerateManifest>false</GenerateManifest>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\">\r\n    <GenerateManifest>false</GenerateManifest>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\">\r\n    <GenerateManifest>false</GenerateManifest>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <GenerateManifest>false</GenerateManifest>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <GenerateManifest>false</GenerateManifest>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\r\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\r\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\">\r\n    <ClCompile>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\r\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\">\r\n    <ClCompile>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\r\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <SDLCheck>true</SDLCheck>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\r\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <SDLCheck>true</SDLCheck>\r\n      <PrecompiledHeaderFile>d3dx12affinity.h</PrecompiledHeaderFile>\r\n      <AdditionalIncludeDirectories></AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\r\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandAllocator.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityCommandList.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityCommandQueue.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityCommandSignature.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityDescriptorHeap.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityDevice.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityDeviceChild.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityFence.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityGraphicsCommandList.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityHeap.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityObject.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityPageable.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityPipelineState.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityQueryHeap.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityResource.h\" />\r\n    <ClInclude Include=\"CD3DX12AffinityRootSignature.h\" />\r\n    <ClInclude Include=\"CDXGIAffinitySwapChain.h\" />\r\n    <ClInclude Include=\"d3dx12.h\" />\r\n    <ClInclude Include=\"d3dx12affinity.h\" />\r\n    <ClInclude Include=\"d3dx12affinity_d3dx12.h\" />\r\n    <ClInclude Include=\"d3dx12affinity_structs.h\" />\r\n    <ClInclude Include=\"Utils.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandAllocator.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityCommandList.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityCommandQueue.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityCommandSignature.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityDescriptorHeap.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityDevice.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityDeviceChild.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityFence.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityGraphicsCommandList.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityHeap.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityObject.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityPageable.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityPipelineState.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityQueryHeap.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityResource.cpp\" />\r\n    <ClCompile Include=\"CD3DX12AffinityRootSignature.cpp\" />\r\n    <ClCompile Include=\"CDXGIAffinitySwapChain.cpp\" />\r\n    <ClCompile Include=\"d3dx12affinity.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\">Create</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3DX12AffinityCreateMultiDevice.cpp\" />\r\n    <ClCompile Include=\"DXGIXAffinityCreateLDASwapChain.cpp\" />\r\n    <ClCompile Include=\"DXGIXAffinityCreateSingleWindowSwapChain.cpp\" />\r\n    <ClCompile Include=\"Utils.cpp\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/D3DX12AffinityLayer.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Header Files\">\r\n      <UniqueIdentifier>{a0200164-4e64-4c0d-9c86-ac1556798323}</UniqueIdentifier>\r\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{03dc92c8-5001-4e40-aaae-3d9c08787e07}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandAllocator.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandList.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandQueue.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityCommandSignature.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityDescriptorHeap.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityDevice.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityDeviceChild.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityFence.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityGraphicsCommandList.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityHeap.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityObject.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityPageable.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityPipelineState.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityQueryHeap.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityResource.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CD3DX12AffinityRootSignature.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CDXGIAffinitySwapChain.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"d3dx12affinity.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3DX12AffinityCreateMultiDevice.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DXGIXAffinityCreateLDASwapChain.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DXGIXAffinityCreateSingleWindowSwapChain.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Utils.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandAllocator.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandList.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandQueue.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityCommandSignature.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityDescriptorHeap.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityDevice.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityDeviceChild.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityFence.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityGraphicsCommandList.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityHeap.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityObject.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityPageable.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityPipelineState.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityQueryHeap.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityResource.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CD3DX12AffinityRootSignature.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CDXGIAffinitySwapChain.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12affinity.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12affinity_d3dx12.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12affinity_structs.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Utils.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/DXGIXAffinityCreateLDASwapChain.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include <dxgi1_2.h>\r\n#include <string>\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    IDXGISwapChain* pSwapChain,\r\n    CD3DX12AffinityCommandQueue* pQueue,\r\n    CD3DX12AffinityDevice* pDevice,\r\n    CDXGIAffinitySwapChain** ppSwapChain)\r\n{\r\n    IDXGISwapChain3* pSwapChain3;\r\n    if (SUCCEEDED(pSwapChain->QueryInterface(IID_PPV_ARGS(&pSwapChain3))))\r\n    {\r\n        DXGI_SWAP_CHAIN_DESC1 desc;\r\n        if (SUCCEEDED(pSwapChain3->GetDesc1(&desc)))\r\n        {\r\n            HRESULT hr = DXGIXAffinityCreateLDASwapChain(pSwapChain3, pQueue, pDevice, &desc, ppSwapChain);\r\n            pSwapChain3->Release();\r\n            return hr;\r\n        }\r\n    }\r\n    return E_FAIL;\r\n}\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    IDXGISwapChain3* pSwapChain,\r\n    CD3DX12AffinityCommandQueue* pQueue,\r\n    CD3DX12AffinityDevice* pDevice,\r\n    DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    CDXGIAffinitySwapChain** ppSwapChain)\r\n{\r\n    CD3DX12AffinityCommandQueue* AffinityQueue = static_cast<CD3DX12AffinityCommandQueue*>(pQueue);\r\n    CD3DX12AffinityDevice* AffinityDevice = static_cast<CD3DX12AffinityDevice*>(pDevice);\r\n    ID3D12Device* HostDevice = AffinityDevice->GetChildObject(0);\r\n\r\n    std::vector<CDXGIAffinitySwapChain::SDeviceContext> NodeContexts;\r\n    NodeContexts.reserve(AffinityDevice->GetNodeCount());\r\n\r\n    for (UINT i = 0; i < AffinityDevice->GetNodeCount(); ++i)\r\n    {\r\n        NodeContexts.push_back(CDXGIAffinitySwapChain::SDeviceContext());\r\n        CDXGIAffinitySwapChain::SDeviceContext& NodeContext = NodeContexts.back();\r\n\r\n        NodeContext.mDevice = AffinityDevice->GetChildObject(0); //single device in LDA case\r\n        NodeContext.mDisplayCommandQueue = AffinityQueue->GetChildObject(i);\r\n    }\r\n\r\n    CDXGIAffinitySwapChain* AffinityChain = new CDXGIAffinitySwapChain(AffinityDevice, AffinityQueue, &pSwapChain, 1);\r\n    AffinityChain->mMode = EAffinitySwapChainMode::LDA;\r\n\r\n    AffinityChain->mDeviceContexts = NodeContexts;\r\n    AffinityChain->mNumBackBuffers = lcm(pDesc->BufferCount, AffinityDevice->GetNodeCount());\r\n    AffinityChain->mNumRequestedBackBuffers = pDesc->BufferCount;\r\n    AffinityChain->mHostDevice = HostDevice;\r\n    *ppSwapChain = AffinityChain;\r\n\r\n    std::vector<IUnknown*> ppCommandQueues;\r\n    std::vector<UINT> pCreationNodes;\r\n    for (UINT i = 0; i < AffinityChain->mNumBackBuffers; ++i)\r\n    {\r\n        UINT node = i % AffinityDevice->GetNodeCount();\r\n        ppCommandQueues.push_back(AffinityQueue->GetChildObject(node));\r\n        pCreationNodes.push_back(AffinityDevice->AffinityIndexToNodeMask(node));\r\n    }\r\n\r\n    pSwapChain->AddRef();\r\n    const HRESULT hr = pSwapChain->ResizeBuffers1(AffinityChain->mNumBackBuffers, pDesc->Width, pDesc->Height, pDesc->Format, pDesc->Flags,\r\n        pCreationNodes.data(), ppCommandQueues.data());\r\n\r\n    return hr;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/DXGIXAffinityCreateSingleWindowSwapChain.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This is your standard \"SFR or AFR or SPR (split pipeline rendering)\" scenario where\r\n * there is just ONE actual swapchain and Present()s from any other adapter means we\r\n * have to copy the render target to the adapter which owns the actual swapchain.\r\n *\r\n * As such this method does a lot of the heavy lifting in terms of creating all the\r\n * resources and objects we need to perform that copy.\r\n */\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include <dxgi1_2.h>\r\n#include <string>\r\n#include \"Utils.h\"\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateSingleWindowSwapChain(\r\n    IDXGISwapChain3* pSwapChain,\r\n    CD3DX12AffinityCommandQueue* pQueue,\r\n    CD3DX12AffinityDevice* pDevice,\r\n    DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    CDXGIAffinitySwapChain** ppSwapChain)\r\n{\r\n    CD3DX12AffinityCommandQueue* AffinityQueue = static_cast<CD3DX12AffinityCommandQueue*>(pQueue);\r\n    CD3DX12AffinityDevice* AffinityDevice = static_cast<CD3DX12AffinityDevice*>(pDevice);\r\n    ID3D12Device* HostDevice = AffinityDevice->GetChildObject(0);\r\n\r\n    std::vector<CDXGIAffinitySwapChain::SDeviceContext> DeviceContexts;\r\n    DeviceContexts.reserve(AffinityDevice->GetDeviceCount());\r\n\r\n    for (UINT i = 0; i < AffinityDevice->GetDeviceCount(); ++i)\r\n    {\r\n        DeviceContexts.push_back(CDXGIAffinitySwapChain::SDeviceContext());\r\n        CDXGIAffinitySwapChain::SDeviceContext& DeviceContext = DeviceContexts.back();\r\n\r\n        DeviceContext.mDevice = AffinityDevice->GetChildObject(i);\r\n        DeviceContext.mDisplayCommandQueue = AffinityQueue->GetChildObject(i);\r\n\r\n        // Each device needs a command list and respective command allocator.\r\n        // This list will be used for submitting resource barriers and copies from the \"dummy\" rendertarget.\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&DeviceContext.mDisplayCommandAllocator)),\r\n            \"Failed to create command allocator during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n            DeviceContext.mDevice->CreateCommandList(\r\n                0, D3D12_COMMAND_LIST_TYPE_DIRECT, DeviceContext.mDisplayCommandAllocator,\r\n                nullptr, IID_PPV_ARGS(&DeviceContext.mDisplayCommandList)),\r\n            \"Failed to create command list during affinity swap chain setup.\", AffinityDevice);\r\n\r\n        // The device at index 0 is the \"host\" device, it uses it's own actual render targets\r\n        // and presents from this device occur in the usual fashion.\r\n        //\r\n        // For all devices index 1 and up, we need to create some fences and intermediate buffers\r\n        // to facilitate presents.\r\n\r\n        {\r\n            // Create the cross-adapter copy fence, used to control access to the cross-adapter copy buffer\r\n\r\n            RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n                DeviceContext.mDevice->CreateFence(\r\n                    0,\r\n                    D3D12_FENCE_FLAG_SHARED | D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER,\r\n                    IID_PPV_ARGS(&DeviceContext.mCrossAdapterCopyFence)),\r\n                \"Failed to create fence during affinity swap chain setup.\", AffinityDevice);\r\n\r\n            std::wstring Name = std::wstring(L\"CrossAdapterCopyFence\") + std::to_wstring(i);\r\n            RETURN_IF_FAILED(DeviceContext.mCrossAdapterCopyFence->SetName(Name.c_str()));\r\n\r\n            {\r\n                HANDLE CrossAdapterCopyFenceSharedHandle = nullptr;\r\n                RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n                    DeviceContext.mDevice->CreateSharedHandle(\r\n                        DeviceContext.mCrossAdapterCopyFence,\r\n                        nullptr,\r\n                        GENERIC_ALL,\r\n                        Name.c_str(),\r\n                        &CrossAdapterCopyFenceSharedHandle),\r\n                    \"Failed to create shared handle to cross adapter copy fence during affinity swap chain setup.\", AffinityDevice);\r\n\r\n                RETURN_IF_FAILED_WITH_ERROR_LOG(\r\n                    HostDevice->OpenSharedHandle(CrossAdapterCopyFenceSharedHandle, IID_PPV_ARGS(&DeviceContext.mCrossAdapterCopyFenceOnHost)),\r\n                    \"Failed to open shared handle to cross adapter copy fence during affinity swap chain setup.\", AffinityDevice);\r\n\r\n                Name = std::wstring(L\"CrossAdapterCopyFenceOnHost\") + std::to_wstring(i);\r\n                RETURN_IF_FAILED(DeviceContext.mCrossAdapterCopyFenceOnHost->SetName(L\"CrossAdapterCopyFenceOnHost\"));\r\n            }\r\n            // Create the \"dummy\" render targets and cross-adapter copy buffers.\r\n            // For a swap chain with (n) back buffers, we create (n) render targets and (n) cross-adapter copy buffers.\r\n\r\n            DeviceContext.mRenderTargets.reserve(pDesc->BufferCount);\r\n            DeviceContext.mCrossAdapterCopyBuffers.reserve(pDesc->BufferCount);\r\n\r\n            RETURN_IF_FAILED(CDXGIAffinitySwapChain::CreateDummyRenderTargetsAndCrossAdapterCopyBuffers(\r\n                i,\r\n                AffinityDevice,\r\n                HostDevice,\r\n                DeviceContext,\r\n                pDesc->Width,\r\n                pDesc->Height,\r\n                pDesc->Format,\r\n                pDesc->BufferCount\r\n            ));\r\n        }\r\n    }\r\n\r\n    pSwapChain->AddRef();\r\n\r\n    CDXGIAffinitySwapChain* AffinityChain = new CDXGIAffinitySwapChain(AffinityDevice, AffinityQueue, &pSwapChain, 1);\r\n    if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA)\r\n    {\r\n        AffinityChain->mMode = EAffinitySwapChainMode::LDA;\r\n    }\r\n    else\r\n    {\r\n        AffinityChain->mMode = EAffinitySwapChainMode::SingleWindow;\r\n    }\r\n\r\n    AffinityChain->mDeviceContexts = DeviceContexts;\r\n    AffinityChain->mNumBackBuffers = pDesc->BufferCount;\r\n    AffinityChain->mHostDevice = HostDevice;\r\n    *ppSwapChain = AffinityChain;\r\n\r\n    return S_OK;\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/Utils.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n#include \"Utils.h\"\r\n\r\n#include <locale>\r\n#include <codecvt>\r\n#include <string>\r\n#include <comdef.h>\r\n\r\nvoid WriteHRESULTError(HRESULT const hr)\r\n{\r\n    _com_error err(hr, nullptr);\r\n    DebugLog(L\"HRESULT Failure: %d 0x%08X %s\\n\", hr, hr, std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(err.ErrorMessage()).c_str());\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/Utils.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This is a utility header with:\r\n * - Configuration macros\r\n * - Commonly used (STL) headers\r\n * - Logging/Assertion methods for debugging\r\n */\r\n\r\n#pragma once\r\n\r\n#include <stdio.h>\r\n#include <wtypes.h>\r\n\r\n////////////////////////////\r\n// CONFIG //////////////////\r\n////////////////////////////\r\n\r\n//#define D3DX12_DEBUG_CLEAR_WHITE\r\n\r\n// Max number of nodes(devices or lda nodes) useable by the affinity layer.\r\n// Note that it's fine to have less than this. You don't need to\r\n// recompile anything if you pull a GPU out of your system.\r\n#define D3DX12_MAX_ACTIVE_NODES 2\r\n\r\n// This mode allows catching bugs in the affinity layer itself\r\n// by running the recorder for n GPU nodes but execute on GPU0.\r\n//#define D3DX12_SIMULATE_LDA_ON_SINGLE_NODE 1\r\n\r\n// Insert a fence, wait and a check for device removed after every commandlist\r\n// useful for debugging the source command-list when a TDR occurs.\r\n//#define SERIALIZE_COMMNANDLIST_EXECUTION\r\n\r\n//#define SYNC_CROSS_FRAME_RESOURCES\r\n\r\n//#define DEBUG_OBJECT_NAME\r\n\r\n// On LDA devices, makes all buffers have a single GPUVA by either having a single\r\n// resource in system memory, or having a single reserved buffer mapped to separate\r\n// heaps on each GPU (via unicast page table mappings). Removes any GPUVA translation\r\n// overhead.\r\n#define TILE_MAPPING_GPUVA 1\r\n\r\n// Just a fun experiment to see what happens when all buffers are accessed from remote GPUs.\r\n//#define FORCE_REMOTE_TILE_MAPPING_GPUVA 1\r\n\r\n//#define ALWAYS_RESET_ALL_COMMAND_LISTS 1\r\n\r\n////////////////////////////\r\n// DEBUG CONFIG ////////////\r\n////////////////////////////\r\n\r\n// Logging options. (e.g. memory mapped, every ECL)\r\n//#define ENABLE_DEBUG_LOG 1\r\n//#define ENABLE_RELEASE_LOG 1\r\n//#define D3DX_AFFINITY_ENABLE_HEAP_POINTER_VALIDATION\r\n\r\n// Instead of using GetWriteWatch, just upload ALL mapped data when unmapped or ECL.\r\n// This is mostly just used to prove how SLOW it is not to use GetWriteWatch.\r\n//#define DO_FULL_MAPPED_MEM_COPY\r\n\r\n////////////////////////////\r\n////////////////////////////\r\n\r\n#include <windows.h>\r\n#include <vector>\r\n#include <map>\r\n#include <set>\r\n#include <mutex>\r\n#include <cstdio>\r\n\r\nstruct EAffinityMask\r\n{\r\n    enum Mask\r\n    {\r\n        AllNodes = 0,\r\n        Node0 = 0x01,\r\n        Node1 = 0x02,\r\n        Node2 = 0x04,\r\n        Node3 = 0x08,\r\n        Node4 = 0x10,\r\n    };\r\n};\r\n\r\nstruct EAffinityMode\r\n{\r\n    enum Mask\r\n    {\r\n        LDA,\r\n    };\r\n};\r\n\r\nstruct EAffinityRenderingMode\r\n{\r\n    enum Mask\r\n    {\r\n        AFR,\r\n    };\r\n};\r\n\r\nvoid WriteHRESULTError(HRESULT const hr);\r\n\r\n#define RETURN_IF_FAILED(x) do { HRESULT const _hr_check = (x); if (S_OK != _hr_check) { WriteHRESULTError(_hr_check); return _hr_check; } } while (false);\r\n#define RETURN_IF_FAILED_WITH_ERROR_LOG(x, y, z) do { HRESULT const _hr_check = (x); if (S_OK != _hr_check) { WriteHRESULTError(_hr_check); z->WriteApplicationMessage(D3D12_MESSAGE_SEVERITY_ERROR, (y)); return _hr_check; } } while (false);\r\n\r\n#ifdef DEBUG\r\n\r\n#include <cassert>\r\n\r\n#define METHOD_NOT_YET_IMPLEMENTED(x) _wassert(L\"Method not yet implemented: \" L ## #x, L\"\", 0);\r\n#define HRESULT_METHOD_NOT_YET_IMPLEMENTED(x) _wassert(L\"Method not yet implemented: \" L ## #x, L\"\", 0); return E_NOTIMPL;\r\n#define DEBUG_ASSERT(x) assert((x));\r\n#define DEBUG_FAIL_MESSAGE(x) _wassert((x), L\"\", 0);\r\n\r\n#else\r\n\r\n#define METHOD_NOT_YET_IMPLEMENTED(x)\r\n#define HRESULT_METHOD_NOT_YET_IMPLEMENTED(x) return S_FALSE;\r\n#define DEBUG_ASSERT(x)\r\n#define DEBUG_FAIL_MESSAGE(x)\r\n\r\n#endif\r\n\r\n// Thread_local is only available in C++11, so if we're compiling under VS 2012 we need\r\n// to define it.\r\n#if _MSC_VER == 1700\r\n#define thread_local __declspec(thread)\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////////////////////////\r\n// See http://stackoverflow.com/a/8712996\r\n\r\n#if defined(_MSC_VER) && _MSC_VER < 1900\r\n\r\n#define snprintf c99_snprintf\r\n#define vsnprintf c99_vsnprintf\r\n\r\ninline int c99_vsnprintf(char* outBuf, size_t size, const char* format, va_list ap)\r\n{\r\n    int count = -1;\r\n\r\n    if (size != 0)\r\n        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);\r\n    if (count == -1)\r\n        count = _vscprintf(format, ap);\r\n\r\n    return count;\r\n}\r\n\r\ninline int c99_snprintf(char* outBuf, size_t size, const char* format, ...)\r\n{\r\n    int count;\r\n    va_list ap;\r\n\r\n    va_start(ap, format);\r\n    count = c99_vsnprintf(outBuf, size, format, ap);\r\n    va_end(ap);\r\n\r\n    return count;\r\n}\r\n\r\n#endif\r\n\r\n// End code borrowed from StackOverflow\r\n///////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\ninline void DebugLog(wchar_t const* const Format, ...)\r\n{\r\n#ifdef ENABLE_DEBUG_LOG\r\n    static int const BufferSize = 65536;\r\n    static wchar_t* WideBuffer = nullptr;\r\n\r\n    if (!WideBuffer)\r\n    {\r\n        WideBuffer = new wchar_t[BufferSize];\r\n    }\r\n\r\n    va_list Args;\r\n    va_start(Args, Format);\r\n    _vsnwprintf_s(WideBuffer, BufferSize, BufferSize - 1, Format, Args);\r\n    va_end(Args);\r\n\r\n    OutputDebugString(WideBuffer);\r\n#endif\r\n}\r\n\r\ninline void ReleaseLog(wchar_t const* const Format, ...)\r\n{\r\n#ifdef ENABLE_RELEASE_LOG\r\n    static int const BufferSize = 65536;\r\n    static wchar_t* WideBuffer = nullptr;\r\n\r\n    if (!WideBuffer)\r\n    {\r\n        WideBuffer = new wchar_t[BufferSize];\r\n    }\r\n\r\n    va_list Args;\r\n    va_start(Args, Format);\r\n    //_vsnwprintf(WideBuffer, BufferSize, Format, Args);\r\n    _vsnwprintf_s(WideBuffer, BufferSize, BufferSize, Format, Args);\r\n    va_end(Args);\r\n\r\n    OutputDebugString(WideBuffer);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#ifndef __D3DX12_H__\r\n#define __D3DX12_H__\r\n\r\n#include \"d3d12.h\"\r\n\r\n#if defined( __cplusplus )\r\n\r\nstruct CD3DX12_DEFAULT {};\r\nextern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT;\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{\r\n    return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width &&\r\n        l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RECT : public D3D12_RECT\r\n{\r\n    CD3DX12_RECT()\r\n    {}\r\n    explicit CD3DX12_RECT( const D3D12_RECT& o ) :\r\n        D3D12_RECT( o )\r\n    {}\r\n    explicit CD3DX12_RECT(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        right = Right;\r\n        bottom = Bottom;\r\n    }\r\n    ~CD3DX12_RECT() {}\r\n    operator const D3D12_RECT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VIEWPORT : public D3D12_VIEWPORT\r\n{\r\n    CD3DX12_VIEWPORT()\r\n    {}\r\n    explicit CD3DX12_VIEWPORT( const D3D12_VIEWPORT& o ) :\r\n        D3D12_VIEWPORT( o )\r\n    {}\r\n    explicit CD3DX12_VIEWPORT(\r\n        FLOAT topLeftX,\r\n        FLOAT topLeftY,\r\n        FLOAT width,\r\n        FLOAT height,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        TopLeftX = topLeftX;\r\n        TopLeftY = topLeftY;\r\n        Width = width;\r\n        Height = height;\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    explicit CD3DX12_VIEWPORT(\r\n        _In_ ID3D12Resource* pResource,\r\n        UINT mipSlice = 0,\r\n        FLOAT topLeftX = 0.0f,\r\n        FLOAT topLeftY = 0.0f,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        D3D12_RESOURCE_DESC Desc = pResource->GetDesc();\r\n        const UINT64 SubresourceWidth = Desc.Width >> mipSlice;\r\n        const UINT64 SubresourceHeight = Desc.Height >> mipSlice;\r\n        switch (Desc.Dimension)\r\n        {\r\n        case D3D12_RESOURCE_DIMENSION_BUFFER:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = Desc.Width - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = topLeftY;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = (SubresourceHeight ? SubresourceHeight: 1.0f) - topLeftY;\r\n            break;\r\n        default: break;\r\n        }\r\n\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    ~CD3DX12_VIEWPORT() {}\r\n    operator const D3D12_VIEWPORT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BOX : public D3D12_BOX\r\n{\r\n    CD3DX12_BOX()\r\n    {}\r\n    explicit CD3DX12_BOX( const D3D12_BOX& o ) :\r\n        D3D12_BOX( o )\r\n    {}\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Right )\r\n    {\r\n        left = Left;\r\n        top = 0;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = 1;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Front,\r\n        LONG Right,\r\n        LONG Bottom,\r\n        LONG Back )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = Front;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = Back;\r\n    }\r\n    ~CD3DX12_BOX() {}\r\n    operator const D3D12_BOX&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{\r\n    return l.left == r.left && l.top == r.top && l.front == r.front &&\r\n        l.right == r.right && l.bottom == r.bottom && l.back == r.back;\r\n}\r\ninline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC1 : public D3D12_DEPTH_STENCIL_DESC1\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC1()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC1& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC1( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC& o )\r\n    {\r\n        DepthEnable                  = o.DepthEnable;\r\n        DepthWriteMask               = o.DepthWriteMask;\r\n        DepthFunc                    = o.DepthFunc;\r\n        StencilEnable                = o.StencilEnable;\r\n        StencilReadMask              = o.StencilReadMask;\r\n        StencilWriteMask             = o.StencilWriteMask;\r\n        FrontFace.StencilFailOp      = o.FrontFace.StencilFailOp;\r\n        FrontFace.StencilDepthFailOp = o.FrontFace.StencilDepthFailOp;\r\n        FrontFace.StencilPassOp      = o.FrontFace.StencilPassOp;\r\n        FrontFace.StencilFunc        = o.FrontFace.StencilFunc;\r\n        BackFace.StencilFailOp       = o.BackFace.StencilFailOp;\r\n        BackFace.StencilDepthFailOp  = o.BackFace.StencilDepthFailOp;\r\n        BackFace.StencilPassOp       = o.BackFace.StencilPassOp;\r\n        BackFace.StencilFunc         = o.BackFace.StencilFunc;\r\n        DepthBoundsTestEnable        = FALSE;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n        DepthBoundsTestEnable = FALSE;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC1(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc,\r\n        BOOL depthBoundsTestEnable )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n        DepthBoundsTestEnable = depthBoundsTestEnable;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC1() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC1&() const { return *this; }\r\n    operator const D3D12_DEPTH_STENCIL_DESC() const\r\n    {\r\n        D3D12_DEPTH_STENCIL_DESC D;\r\n        D.DepthEnable                  = DepthEnable;\r\n        D.DepthWriteMask               = DepthWriteMask;\r\n        D.DepthFunc                    = DepthFunc;\r\n        D.StencilEnable                = StencilEnable;\r\n        D.StencilReadMask              = StencilReadMask;\r\n        D.StencilWriteMask             = StencilWriteMask;\r\n        D.FrontFace.StencilFailOp      = FrontFace.StencilFailOp;\r\n        D.FrontFace.StencilDepthFailOp = FrontFace.StencilDepthFailOp;\r\n        D.FrontFace.StencilPassOp      = FrontFace.StencilPassOp;\r\n        D.FrontFace.StencilFunc        = FrontFace.StencilFunc;\r\n        D.BackFace.StencilFailOp       = BackFace.StencilFailOp;\r\n        D.BackFace.StencilDepthFailOp  = BackFace.StencilDepthFailOp;\r\n        D.BackFace.StencilPassOp       = BackFace.StencilPassOp;\r\n        D.BackFace.StencilFunc         = BackFace.StencilFunc;\r\n        return D;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC\r\n{\r\n    CD3DX12_BLEND_DESC()\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) :\r\n        D3D12_BLEND_DESC( o )\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        AlphaToCoverageEnable = FALSE;\r\n        IndependentBlendEnable = FALSE;\r\n        const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =\r\n        {\r\n            FALSE,FALSE,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_LOGIC_OP_NOOP,\r\n            D3D12_COLOR_WRITE_ENABLE_ALL,\r\n        };\r\n        for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)\r\n            RenderTarget[ i ] = defaultRenderTargetBlendDesc;\r\n    }\r\n    ~CD3DX12_BLEND_DESC() {}\r\n    operator const D3D12_BLEND_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC\r\n{\r\n    CD3DX12_RASTERIZER_DESC()\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) :\r\n        D3D12_RASTERIZER_DESC( o )\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        FillMode = D3D12_FILL_MODE_SOLID;\r\n        CullMode = D3D12_CULL_MODE_BACK;\r\n        FrontCounterClockwise = FALSE;\r\n        DepthBias = D3D12_DEFAULT_DEPTH_BIAS;\r\n        DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;\r\n        SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;\r\n        DepthClipEnable = TRUE;\r\n        MultisampleEnable = FALSE;\r\n        AntialiasedLineEnable = FALSE;\r\n        ForcedSampleCount = 0;\r\n        ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;\r\n    }\r\n    explicit CD3DX12_RASTERIZER_DESC(\r\n        D3D12_FILL_MODE fillMode,\r\n        D3D12_CULL_MODE cullMode,\r\n        BOOL frontCounterClockwise,\r\n        INT depthBias,\r\n        FLOAT depthBiasClamp,\r\n        FLOAT slopeScaledDepthBias,\r\n        BOOL depthClipEnable,\r\n        BOOL multisampleEnable,\r\n        BOOL antialiasedLineEnable, \r\n        UINT forcedSampleCount, \r\n        D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster)\r\n    {\r\n        FillMode = fillMode;\r\n        CullMode = cullMode;\r\n        FrontCounterClockwise = frontCounterClockwise;\r\n        DepthBias = depthBias;\r\n        DepthBiasClamp = depthBiasClamp;\r\n        SlopeScaledDepthBias = slopeScaledDepthBias;\r\n        DepthClipEnable = depthClipEnable;\r\n        MultisampleEnable = multisampleEnable;\r\n        AntialiasedLineEnable = antialiasedLineEnable;\r\n        ForcedSampleCount = forcedSampleCount;\r\n        ConservativeRaster = conservativeRaster;\r\n    }\r\n    ~CD3DX12_RASTERIZER_DESC() {}\r\n    operator const D3D12_RASTERIZER_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO\r\n{\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) :\r\n        D3D12_RESOURCE_ALLOCATION_INFO( o )\r\n    {}\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO(\r\n        UINT64 size,\r\n        UINT64 alignment )\r\n    {\r\n        SizeInBytes = size;\r\n        Alignment = alignment;\r\n    }\r\n    operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES\r\n{\r\n    CD3DX12_HEAP_PROPERTIES()\r\n    {}\r\n    explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) :\r\n        D3D12_HEAP_PROPERTIES(o)\r\n    {}\r\n    CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference,\r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = D3D12_HEAP_TYPE_CUSTOM;\r\n        CPUPageProperty = cpuPageProperty;\r\n        MemoryPoolPreference = memoryPoolPreference;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    explicit CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_HEAP_TYPE type, \r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = type;\r\n        CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n        MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    operator const D3D12_HEAP_PROPERTIES&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    {\r\n        return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&\r\n            (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));\r\n    }\r\n};\r\ninline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{\r\n    return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && \r\n        l.MemoryPoolPreference == r.MemoryPoolPreference &&\r\n        l.CreationNodeMask == r.CreationNodeMask &&\r\n        l.VisibleNodeMask == r.VisibleNodeMask;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC\r\n{\r\n    CD3DX12_HEAP_DESC()\r\n    {}\r\n    explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) :\r\n        D3D12_HEAP_DESC(o)\r\n    {}\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_PROPERTIES properties, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = properties;\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_TYPE type, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_PROPERTIES properties, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = properties;\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_TYPE type, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    operator const D3D12_HEAP_DESC&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }\r\n};\r\ninline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{\r\n    return l.SizeInBytes == r.SizeInBytes &&\r\n        l.Properties == r.Properties && \r\n        l.Alignment == r.Alignment &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE\r\n{\r\n    CD3DX12_CLEAR_VALUE()\r\n    {}\r\n    explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) :\r\n        D3D12_CLEAR_VALUE(o)\r\n    {}\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        const FLOAT color[4] )\r\n    {\r\n        Format = format;\r\n        memcpy( Color, color, sizeof( Color ) );\r\n    }\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        FLOAT depth,\r\n        UINT8 stencil )\r\n    {\r\n        Format = format;\r\n        /* Use memcpy to preserve NAN values */\r\n        memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );\r\n        DepthStencil.Stencil = stencil;\r\n    }\r\n    operator const D3D12_CLEAR_VALUE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE : public D3D12_RANGE\r\n{\r\n    CD3DX12_RANGE()\r\n    {}\r\n    explicit CD3DX12_RANGE(const D3D12_RANGE &o) :\r\n        D3D12_RANGE(o)\r\n    {}\r\n    CD3DX12_RANGE( \r\n        SIZE_T begin, \r\n        SIZE_T end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE_UINT64 : public D3D12_RANGE_UINT64\r\n{\r\n    CD3DX12_RANGE_UINT64()\r\n    {}\r\n    explicit CD3DX12_RANGE_UINT64(const D3D12_RANGE_UINT64 &o) :\r\n        D3D12_RANGE_UINT64(o)\r\n    {}\r\n    CD3DX12_RANGE_UINT64( \r\n        UINT64 begin, \r\n        UINT64 end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE_UINT64&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_RANGE_UINT64 : public D3D12_SUBRESOURCE_RANGE_UINT64\r\n{\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_RANGE_UINT64(const D3D12_SUBRESOURCE_RANGE_UINT64 &o) :\r\n        D3D12_SUBRESOURCE_RANGE_UINT64(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64( \r\n        UINT subresource,\r\n        const D3D12_RANGE_UINT64& range )\r\n    {\r\n        Subresource = subresource;\r\n        Range = range;\r\n    }\r\n    CD3DX12_SUBRESOURCE_RANGE_UINT64( \r\n        UINT subresource,\r\n        UINT64 begin, \r\n        UINT64 end )\r\n    {\r\n        Subresource = subresource;\r\n        Range.Begin = begin;\r\n        Range.End = end;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_RANGE_UINT64&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE\r\n{\r\n    CD3DX12_SHADER_BYTECODE()\r\n    {}\r\n    explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) :\r\n        D3D12_SHADER_BYTECODE(o)\r\n    {}\r\n    CD3DX12_SHADER_BYTECODE(\r\n        _In_ ID3DBlob* pShaderBlob )\r\n    {\r\n        pShaderBytecode = pShaderBlob->GetBufferPointer();\r\n        BytecodeLength = pShaderBlob->GetBufferSize();\r\n    }\r\n    CD3DX12_SHADER_BYTECODE(\r\n        const void* _pShaderBytecode,\r\n        SIZE_T bytecodeLength )\r\n    {\r\n        pShaderBytecode = _pShaderBytecode;\r\n        BytecodeLength = bytecodeLength;\r\n    }\r\n    operator const D3D12_SHADER_BYTECODE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE\r\n{\r\n    CD3DX12_TILED_RESOURCE_COORDINATE()\r\n    {}\r\n    explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) :\r\n        D3D12_TILED_RESOURCE_COORDINATE(o)\r\n    {}\r\n    CD3DX12_TILED_RESOURCE_COORDINATE( \r\n        UINT x, \r\n        UINT y, \r\n        UINT z, \r\n        UINT subresource ) \r\n    {\r\n        X = x;\r\n        Y = y;\r\n        Z = z;\r\n        Subresource = subresource;\r\n    }\r\n    operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE\r\n{\r\n    CD3DX12_TILE_REGION_SIZE()\r\n    {}\r\n    explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) :\r\n        D3D12_TILE_REGION_SIZE(o)\r\n    {}\r\n    CD3DX12_TILE_REGION_SIZE( \r\n        UINT numTiles, \r\n        BOOL useBox, \r\n        UINT width, \r\n        UINT16 height, \r\n        UINT16 depth ) \r\n    {\r\n        NumTiles = numTiles;\r\n        UseBox = useBox;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n    }\r\n    operator const D3D12_TILE_REGION_SIZE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING\r\n{\r\n    CD3DX12_SUBRESOURCE_TILING()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) :\r\n        D3D12_SUBRESOURCE_TILING(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_TILING( \r\n        UINT widthInTiles, \r\n        UINT16 heightInTiles, \r\n        UINT16 depthInTiles, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        WidthInTiles = widthInTiles;\r\n        HeightInTiles = heightInTiles;\r\n        DepthInTiles = depthInTiles;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE\r\n{\r\n    CD3DX12_TILE_SHAPE()\r\n    {}\r\n    explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) :\r\n        D3D12_TILE_SHAPE(o)\r\n    {}\r\n    CD3DX12_TILE_SHAPE( \r\n        UINT widthInTexels, \r\n        UINT heightInTexels, \r\n        UINT depthInTexels ) \r\n    {\r\n        WidthInTexels = widthInTexels;\r\n        HeightInTexels = heightInTexels;\r\n        DepthInTexels = depthInTexels;\r\n    }\r\n    operator const D3D12_TILE_SHAPE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) :\r\n        D3D12_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_RESOURCE_BARRIER Transition(\r\n        _In_ ID3D12Resource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER Aliasing(\r\n        _In_ ID3D12Resource* pResourceBefore,\r\n        _In_ ID3D12Resource* pResourceAfter)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER UAV(\r\n        _In_ ID3D12Resource* pResource)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3D12_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO\r\n{\r\n    CD3DX12_PACKED_MIP_INFO()\r\n    {}\r\n    explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) :\r\n        D3D12_PACKED_MIP_INFO(o)\r\n    {}\r\n    CD3DX12_PACKED_MIP_INFO( \r\n        UINT8 numStandardMips, \r\n        UINT8 numPackedMips, \r\n        UINT numTilesForPackedMips, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        NumStandardMips = numStandardMips;\r\n        NumPackedMips = numPackedMips;\r\n        NumTilesForPackedMips = numTilesForPackedMips;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_PACKED_MIP_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT\r\n{\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) :\r\n        D3D12_SUBRESOURCE_FOOTPRINT(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        DXGI_FORMAT format, \r\n        UINT width, \r\n        UINT height, \r\n        UINT depth, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = format;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n        RowPitch = rowPitch;\r\n    }\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        const D3D12_RESOURCE_DESC& resDesc, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = resDesc.Format;\r\n        Width = UINT( resDesc.Width );\r\n        Height = resDesc.Height;\r\n        Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);\r\n        RowPitch = rowPitch;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION\r\n{ \r\n    CD3DX12_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) :\r\n        D3D12_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n}; \r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) :\r\n        D3D12_DESCRIPTOR_RANGE(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS\r\n{\r\n    CD3DX12_ROOT_CONSTANTS() {}\r\n    explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) :\r\n        D3D12_ROOT_CONSTANTS(o)\r\n    {}\r\n    CD3DX12_ROOT_CONSTANTS(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_CONSTANTS &rootConstants,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        rootConstants.Num32BitValues = num32BitValues;\r\n        rootConstants.ShaderRegister = shaderRegister;\r\n        rootConstants.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) :\r\n        D3D12_ROOT_DESCRIPTOR(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER\r\n{\r\n    CD3DX12_ROOT_PARAMETER() {}\r\n    explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) :\r\n        D3D12_ROOT_PARAMETER(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC\r\n{\r\n    CD3DX12_STATIC_SAMPLER_DESC() {}\r\n    explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) :\r\n        D3D12_STATIC_SAMPLER_DESC(o)\r\n    {}\r\n    CD3DX12_STATIC_SAMPLER_DESC(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc,\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        samplerDesc.ShaderRegister = shaderRegister;\r\n        samplerDesc.Filter = filter;\r\n        samplerDesc.AddressU = addressU;\r\n        samplerDesc.AddressV = addressV;\r\n        samplerDesc.AddressW = addressW;\r\n        samplerDesc.MipLODBias = mipLODBias;\r\n        samplerDesc.MaxAnisotropy = maxAnisotropy;\r\n        samplerDesc.ComparisonFunc = comparisonFunc;\r\n        samplerDesc.BorderColor = borderColor;\r\n        samplerDesc.MinLOD = minLOD;\r\n        samplerDesc.MaxLOD = maxLOD;\r\n        samplerDesc.ShaderVisibility = shaderVisibility;\r\n        samplerDesc.RegisterSpace = registerSpace;\r\n    }\r\n    inline void Init(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            *this,\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    CD3DX12_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.NumParameters = numParameters;\r\n        desc.pParameters = _pParameters;\r\n        desc.NumStaticSamplers = numStaticSamplers;\r\n        desc.pStaticSamplers = _pStaticSamplers;\r\n        desc.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE1 : public D3D12_DESCRIPTOR_RANGE1\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE1() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE1(const D3D12_DESCRIPTOR_RANGE1 &o) :\r\n        D3D12_DESCRIPTOR_RANGE1(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE1(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE1 &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.Flags = flags;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE1 : public D3D12_ROOT_DESCRIPTOR_TABLE1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE1(const D3D12_ROOT_DESCRIPTOR_TABLE1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE1 &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR1 : public D3D12_ROOT_DESCRIPTOR1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR1(const D3D12_ROOT_DESCRIPTOR1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR1(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR1 &table, \r\n        UINT shaderRegister, \r\n        UINT registerSpace = 0, \r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n        table.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER1 : public D3D12_ROOT_PARAMETER1\r\n{\r\n    CD3DX12_ROOT_PARAMETER1() {}\r\n    explicit CD3DX12_ROOT_PARAMETER1(const D3D12_ROOT_PARAMETER1 &o) :\r\n        D3D12_ROOT_PARAMETER1(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE1::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_VERSIONED_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        Desc_1_0 = o;\r\n    }\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC1 &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        Desc_1_1 = o;\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init_1_1(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init_1_0(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_0(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        desc.Desc_1_0.NumParameters = numParameters;\r\n        desc.Desc_1_0.pParameters = _pParameters;\r\n        desc.Desc_1_0.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_0.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_0.Flags = flags;\r\n    }\r\n\r\n    inline void Init_1_1(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_1(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        desc.Desc_1_1.NumParameters = numParameters;\r\n        desc.Desc_1_1.pParameters = _pParameters;\r\n        desc.Desc_1_1.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_1.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_1.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_CPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_GPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )\r\n{ \r\n    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; \r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename T, typename U, typename V>\r\ninline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )\r\n{\r\n    MipSlice = static_cast<T>(Subresource % MipLevels);\r\n    ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);\r\n    PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ ID3D12Device* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format};\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo))))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) :\r\n        D3D12_RESOURCE_DESC( o )\r\n    {}\r\n    CD3DX12_RESOURCE_DESC( \r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags )\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, \r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, \r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex1D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex2D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, \r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex3D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    inline UINT16 Depth() const\r\n    { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT16 ArraySize() const\r\n    { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const\r\n    { return D3D12GetFormatPlaneCount(pDevice, Format); }\r\n    inline UINT Subresources(_In_ ID3D12Device* pDevice) const\r\n    { return MipLevels * ArraySize() * PlaneCount(pDevice); }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Row-by-row memcpy\r\ninline void MemcpySubresource(\r\n    _In_ const D3D12_MEMCPY_DEST* pDest,\r\n    _In_ const D3D12_SUBRESOURCE_DATA* pSrc,\r\n    SIZE_T RowSizeInBytes,\r\n    UINT NumRows,\r\n    UINT NumSlices)\r\n{\r\n    for (UINT z = 0; z < NumSlices; ++z)\r\n    {\r\n        BYTE* pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;\r\n        const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * z;\r\n        for (UINT y = 0; y < NumRows; ++y)\r\n        {\r\n            memcpy(pDestSlice + pDest->RowPitch * y,\r\n                   pSrcSlice + pSrc->RowPitch * y,\r\n                   RowSizeInBytes);\r\n        }\r\n    }\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    UINT64 RequiredSize = 0;\r\n    \r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || \r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || \r\n        RequiredSize > (SIZE_T)-1 || \r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && \r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n    \r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n       return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n       return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout )\r\n{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename t_CommandListType>\r\ninline ID3D12CommandList * const * CommandListCast(t_CommandListType * const * pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<ID3D12CommandList * const *>(pp);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// D3D12 exports a new method for serializing root signatures in the Windows 10 Anniversary Update.\r\n// To help enable root signature 1.1 features when they are available and not require maintaining\r\n// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when\r\n// 1.1 is not supported.\r\ninline HRESULT D3DX12SerializeVersionedRootSignature(\r\n    _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n    D3D_ROOT_SIGNATURE_VERSION MaxVersion,\r\n    _Outptr_ ID3DBlob** ppBlob,\r\n    _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob)\r\n{\r\n    if (ppErrorBlob != NULL)\r\n    {\r\n        *ppErrorBlob = NULL;\r\n    }\r\n\r\n    switch (MaxVersion)\r\n    {\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n            switch (pRootSignatureDesc->Version)\r\n            {\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n                    return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n                {\r\n                    HRESULT hr = S_OK;\r\n                    const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1;\r\n\r\n                    const SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters;\r\n                    void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL;\r\n                    if (ParametersSize > 0 && pParameters == NULL)\r\n                    {\r\n                        hr = E_OUTOFMEMORY;\r\n                    }\r\n                    D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast<D3D12_ROOT_PARAMETER*>(pParameters);\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            __analysis_assume(ParametersSize == sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters);\r\n                            pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType;\r\n                            pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility;\r\n\r\n                            switch (desc_1_1.pParameters[n].ParameterType)\r\n                            {\r\n                            case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:\r\n                                pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues;\r\n                                pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace;\r\n                                pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_CBV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_SRV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_UAV:\r\n                                pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace;\r\n                                pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:\r\n                                const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable;\r\n\r\n                                const SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges;\r\n                                void* pDescriptorRanges = (DescriptorRangesSize > 0 && SUCCEEDED(hr)) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL;\r\n                                if (DescriptorRangesSize > 0 && pDescriptorRanges == NULL)\r\n                                {\r\n                                    hr = E_OUTOFMEMORY;\r\n                                }\r\n                                D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pDescriptorRanges);\r\n\r\n                                if (SUCCEEDED(hr))\r\n                                {\r\n                                    for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++)\r\n                                    {\r\n                                        __analysis_assume(DescriptorRangesSize == sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges);\r\n                                        pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister;\r\n                                        pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors;\r\n                                        pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart;\r\n                                        pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType;\r\n                                        pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace;\r\n                                    }\r\n                                }\r\n\r\n                                D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable;\r\n                                table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges;\r\n                                table_1_0.pDescriptorRanges = pDescriptorRanges_1_0;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags);\r\n                        hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n                    }\r\n\r\n                    if (pParameters)\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            if (desc_1_1.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n                            {\r\n                                HeapFree(GetProcessHeap(), 0, reinterpret_cast<void*>(const_cast<D3D12_DESCRIPTOR_RANGE*>(pParameters_1_0[n].DescriptorTable.pDescriptorRanges)));\r\n                            }\r\n                        }\r\n                        HeapFree(GetProcessHeap(), 0, pParameters);\r\n                    }\r\n                    return hr;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n            return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);\r\n    }\r\n\r\n    return E_INVALIDARG;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RT_FORMAT_ARRAY : public D3D12_RT_FORMAT_ARRAY\r\n{\r\n    CD3DX12_RT_FORMAT_ARRAY() {}\r\n    explicit CD3DX12_RT_FORMAT_ARRAY(const D3D12_RT_FORMAT_ARRAY& o)\r\n        : D3D12_RT_FORMAT_ARRAY(o)\r\n    {}\r\n    explicit CD3DX12_RT_FORMAT_ARRAY(const DXGI_FORMAT* pFormats, UINT NumFormats)\r\n    {\r\n        NumRenderTargets = NumFormats;\r\n        memcpy(RTFormats, pFormats, sizeof(RTFormats));\r\n        // assumes ARRAY_SIZE(pFormats) == ARRAY_SIZE(RTFormats)\r\n    }\r\n    operator const D3D12_RT_FORMAT_ARRAY&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Pipeline State Stream Helpers\r\n//------------------------------------------------------------------------------------------------\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stream Subobjects, i.e. elements of a stream\r\n\r\ntemplate <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type, typename DefaultArg = InnerStructType>\r\nclass alignas(void*) CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT\r\n{\r\nprivate:\r\n    D3D12_PIPELINE_STATE_SUBOBJECT_TYPE _Type;\r\n    InnerStructType _Inner;\r\npublic:\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT() : _Type(Type), _Inner(DefaultArg()) {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT(InnerStructType const& i) : _Type(Type), _Inner(i) {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT& operator=(InnerStructType const& i) { _Inner = i; return *this; }\r\n    operator InnerStructType() const { return _Inner; }\r\n};\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PIPELINE_STATE_FLAGS,         D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS>                           CD3DX12_PIPELINE_STATE_STREAM_FLAGS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT,                               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK>                       CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< ID3D12RootSignature*,               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE>                  CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INPUT_LAYOUT_DESC,            D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT>                    CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INDEX_BUFFER_STRIP_CUT_VALUE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE>              CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PRIMITIVE_TOPOLOGY_TYPE,      D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY>              CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS>                              CD3DX12_PIPELINE_STATE_STREAM_VS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS>                              CD3DX12_PIPELINE_STATE_STREAM_GS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_STREAM_OUTPUT_DESC,           D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT>                   CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS>                              CD3DX12_PIPELINE_STATE_STREAM_HS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS>                              CD3DX12_PIPELINE_STATE_STREAM_DS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS>                              CD3DX12_PIPELINE_STATE_STREAM_PS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS>                              CD3DX12_PIPELINE_STATE_STREAM_CS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_BLEND_DESC,                 D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND,          CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC,         D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL,  CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC1,        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_FORMAT,                        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT>            CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC,            D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER,     CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_RT_FORMAT_ARRAY,              D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS>           CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_SAMPLE_DESC,                   D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC>                     CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT,                               D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK>                     CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK;\r\ntypedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_CACHED_PIPELINE_STATE,        D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO>                      CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO;\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stream Parser Helpers\r\n\r\nstruct ID3DX12PipelineParserCallbacks\r\n{\r\n    // Subobject Callbacks\r\n    virtual void FlagsCb(D3D12_PIPELINE_STATE_FLAGS) {}\r\n    virtual void NodeMaskCb(UINT) {}\r\n    virtual void RootSignatureCb(ID3D12RootSignature*) {}\r\n    virtual void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC&) {}\r\n    virtual void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE) {}\r\n    virtual void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE) {}\r\n    virtual void VSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void GSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC&) {}\r\n    virtual void HSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void DSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void PSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void CSCb(const D3D12_SHADER_BYTECODE&) {}\r\n    virtual void BlendStateCb(const D3D12_BLEND_DESC&) {}\r\n    virtual void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC&) {}\r\n    virtual void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1&) {}\r\n    virtual void DSVFormatCb(DXGI_FORMAT) {}\r\n    virtual void RasterizerStateCb(const D3D12_RASTERIZER_DESC&) {}\r\n    virtual void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY&) {}\r\n    virtual void SampleDescCb(const DXGI_SAMPLE_DESC&) {}\r\n    virtual void SampleMaskCb(UINT) {}\r\n    virtual void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE&) {}\r\n\r\n    // Error Callbacks\r\n    virtual void ErrorBadInputParameter(UINT /*ParameterIndex*/) {}\r\n    virtual void ErrorDuplicateSubobject(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE /*DuplicateType*/) {}\r\n    virtual void ErrorUnknownSubobject(UINT /*UnknownTypeValue*/) {}\r\n\r\n};\r\n\r\nstruct CD3DX12_PIPELINE_STATE_STREAM\r\n{\r\n    CD3DX12_PIPELINE_STATE_STREAM() {}\r\n    CD3DX12_PIPELINE_STATE_STREAM(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& Desc)\r\n        : Flags(Desc.Flags)\r\n        , NodeMask(Desc.NodeMask)\r\n        , pRootSignature(Desc.pRootSignature)\r\n        , InputLayout(Desc.InputLayout)\r\n        , IBStripCutValue(Desc.IBStripCutValue)\r\n        , PrimitiveTopologyType(Desc.PrimitiveTopologyType)\r\n        , VS(Desc.VS)\r\n        , GS(Desc.GS)\r\n        , StreamOutput(Desc.StreamOutput)\r\n        , HS(Desc.HS)\r\n        , DS(Desc.DS)\r\n        , PS(Desc.PS)\r\n        , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState))\r\n        , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC1(Desc.DepthStencilState))\r\n        , DSVFormat(Desc.DSVFormat)\r\n        , RasterizerState(CD3DX12_RASTERIZER_DESC(Desc.RasterizerState))\r\n        , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets))\r\n        , SampleDesc(Desc.SampleDesc)\r\n        , SampleMask(Desc.SampleMask)\r\n        , CachedPSO(Desc.CachedPSO)\r\n    {}\r\n    CD3DX12_PIPELINE_STATE_STREAM(const D3D12_COMPUTE_PIPELINE_STATE_DESC& Desc)\r\n        : Flags(Desc.Flags)\r\n        , NodeMask(Desc.NodeMask)\r\n        , pRootSignature(Desc.pRootSignature)\r\n        , CS(CD3DX12_SHADER_BYTECODE(Desc.CS))\r\n        , CachedPSO(Desc.CachedPSO)\r\n    {}\r\n    CD3DX12_PIPELINE_STATE_STREAM_FLAGS Flags;\r\n    CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK NodeMask;\r\n    CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE pRootSignature;\r\n    CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT InputLayout;\r\n    CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE IBStripCutValue;\r\n    CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY PrimitiveTopologyType;\r\n    CD3DX12_PIPELINE_STATE_STREAM_VS VS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_GS GS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT StreamOutput;\r\n    CD3DX12_PIPELINE_STATE_STREAM_HS HS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DS DS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_PS PS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_CS CS;\r\n    CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC BlendState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1 DepthStencilState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT DSVFormat;\r\n    CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER RasterizerState;\r\n    CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS RTVFormats;\r\n    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC SampleDesc;\r\n    CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK SampleMask;\r\n    CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO CachedPSO;\r\n    D3D12_GRAPHICS_PIPELINE_STATE_DESC GraphicsDescV0() const\r\n    {\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC D;\r\n        D.Flags                 = this->Flags;\r\n        D.NodeMask              = this->NodeMask;\r\n        D.pRootSignature        = this->pRootSignature;\r\n        D.InputLayout           = this->InputLayout;\r\n        D.IBStripCutValue       = this->IBStripCutValue;\r\n        D.PrimitiveTopologyType = this->PrimitiveTopologyType;\r\n        D.VS                    = this->VS;\r\n        D.GS                    = this->GS;\r\n        D.StreamOutput          = this->StreamOutput;\r\n        D.HS                    = this->HS;\r\n        D.DS                    = this->DS;\r\n        D.PS                    = this->PS;\r\n        D.BlendState            = this->BlendState;\r\n        D.DepthStencilState     = CD3DX12_DEPTH_STENCIL_DESC1(D3D12_DEPTH_STENCIL_DESC1(this->DepthStencilState));\r\n        D.DSVFormat             = this->DSVFormat;\r\n        D.RasterizerState       = this->RasterizerState;\r\n        D.NumRenderTargets      = D3D12_RT_FORMAT_ARRAY(this->RTVFormats).NumRenderTargets;\r\n        memcpy(D.RTVFormats, D3D12_RT_FORMAT_ARRAY(this->RTVFormats).RTFormats, sizeof(D.RTVFormats));\r\n        D.SampleDesc            = this->SampleDesc;\r\n        D.SampleMask            = this->SampleMask;\r\n        D.CachedPSO             = this->CachedPSO;\r\n        return D;\r\n    }\r\n    D3D12_COMPUTE_PIPELINE_STATE_DESC ComputeDescV0() const\r\n    {\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC D;\r\n        D.Flags                 = this->Flags;\r\n        D.NodeMask              = this->NodeMask;\r\n        D.pRootSignature        = this->pRootSignature;\r\n        D.CS                    = this->CS;\r\n        D.CachedPSO             = this->CachedPSO;\r\n        return D;\r\n    }\r\n};\r\n\r\nstruct CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER : public ID3DX12PipelineParserCallbacks\r\n{\r\n    CD3DX12_PIPELINE_STATE_STREAM PipelineStream;\r\n\r\n    // ID3DX12PipelineParserCallbacks\r\n    void FlagsCb(D3D12_PIPELINE_STATE_FLAGS Flags) {PipelineStream.Flags = Flags;}\r\n    void NodeMaskCb(UINT NodeMask) {PipelineStream.NodeMask = NodeMask;}\r\n    void RootSignatureCb(ID3D12RootSignature* pRootSignature) {PipelineStream.pRootSignature = pRootSignature;}\r\n    void InputLayoutCb(const D3D12_INPUT_LAYOUT_DESC& InputLayout) {PipelineStream.InputLayout = InputLayout;}\r\n    void IBStripCutValueCb(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue) {PipelineStream.IBStripCutValue = IBStripCutValue;}\r\n    void PrimitiveTopologyTypeCb(D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType) {PipelineStream.PrimitiveTopologyType = PrimitiveTopologyType;}\r\n    void VSCb(const D3D12_SHADER_BYTECODE& VS) {PipelineStream.VS = VS;}\r\n    void GSCb(const D3D12_SHADER_BYTECODE& GS) {PipelineStream.GS = GS;}\r\n    void StreamOutputCb(const D3D12_STREAM_OUTPUT_DESC& StreamOutput) {PipelineStream.StreamOutput = StreamOutput;}\r\n    void HSCb(const D3D12_SHADER_BYTECODE& HS) {PipelineStream.HS = HS;}\r\n    void DSCb(const D3D12_SHADER_BYTECODE& DS) {PipelineStream.DS = DS;}\r\n    void PSCb(const D3D12_SHADER_BYTECODE& PS) {PipelineStream.PS = PS;}\r\n    void CSCb(const D3D12_SHADER_BYTECODE& CS) {PipelineStream.CS = CS;}\r\n    void BlendStateCb(const D3D12_BLEND_DESC& BlendState) {PipelineStream.BlendState = CD3DX12_BLEND_DESC(BlendState);}\r\n    void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC& DepthStencilState) {PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(DepthStencilState);}\r\n    void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1& DepthStencilState) {PipelineStream.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(DepthStencilState);}\r\n    void DSVFormatCb(DXGI_FORMAT DSVFormat) {PipelineStream.DSVFormat = DSVFormat;}\r\n    void RasterizerStateCb(const D3D12_RASTERIZER_DESC& RasterizerState) {PipelineStream.RasterizerState = CD3DX12_RASTERIZER_DESC(RasterizerState);}\r\n    void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY& RTVFormats) {PipelineStream.RTVFormats = RTVFormats;}\r\n    void SampleDescCb(const DXGI_SAMPLE_DESC& SampleDesc) {PipelineStream.SampleDesc = SampleDesc;}\r\n    void SampleMaskCb(UINT SampleMask) {PipelineStream.SampleMask = SampleMask;}\r\n    void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE& CachedPSO) {PipelineStream.CachedPSO = CachedPSO;}\r\n    void ErrorBadInputParameter(UINT) {}\r\n    void ErrorDuplicateSubobject(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE) {}\r\n    void ErrorUnknownSubobject(UINT) {}\r\n};\r\n\r\ninline D3D12_PIPELINE_STATE_SUBOBJECT_TYPE D3DX12GetBaseSubobjectType(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE SubobjectType)\r\n{\r\n    switch (SubobjectType)\r\n    {\r\n    case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1: \r\n        return D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL;\r\n    default:\r\n        return SubobjectType;\r\n    }\r\n}\r\n\r\ninline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& Desc, ID3DX12PipelineParserCallbacks* pCallbacks)\r\n{\r\n    if (Desc.SizeInBytes == 0 || Desc.pPipelineStateSubobjectStream == nullptr)\r\n    {\r\n        pCallbacks->ErrorBadInputParameter(1); // first parameter issue\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    if (pCallbacks == nullptr)\r\n    {\r\n        pCallbacks->ErrorBadInputParameter(2); // second parameter issue\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    bool SubobjectSeen[D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID] = {0};\r\n    for (SIZE_T CurOffset = 0, SizeOfSubobject = 0; CurOffset < Desc.SizeInBytes; CurOffset += SizeOfSubobject)\r\n    {\r\n        BYTE* pStream = static_cast<BYTE*>(Desc.pPipelineStateSubobjectStream)+CurOffset;\r\n        auto SubobjectType = *reinterpret_cast<D3D12_PIPELINE_STATE_SUBOBJECT_TYPE*>(pStream);\r\n        if (SubobjectType >= D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID)\r\n        {\r\n            pCallbacks->ErrorUnknownSubobject(SubobjectType);\r\n            return E_INVALIDARG;\r\n        }\r\n        if (SubobjectSeen[D3DX12GetBaseSubobjectType(SubobjectType)])\r\n        {\r\n            pCallbacks->ErrorDuplicateSubobject(SubobjectType);\r\n            return E_INVALIDARG; // disallow subobject duplicates in a stream\r\n        }\r\n        SubobjectSeen[SubobjectType] = true;\r\n        switch (SubobjectType)\r\n        {\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE: \r\n            pCallbacks->RootSignatureCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::pRootSignature)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::pRootSignature);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS:\r\n            pCallbacks->VSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::VS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::VS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS: \r\n            pCallbacks->PSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::PS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::PS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS: \r\n            pCallbacks->DSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS: \r\n            pCallbacks->HSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::HS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::HS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS: \r\n            pCallbacks->GSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::GS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::GS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS:\r\n            pCallbacks->CSCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::CS)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CS);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT: \r\n            pCallbacks->StreamOutputCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND: \r\n            pCallbacks->BlendStateCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::BlendState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::BlendState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK: \r\n            pCallbacks->SampleMaskCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::SampleMask)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::SampleMask);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER: \r\n            pCallbacks->RasterizerStateCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::RasterizerState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::RasterizerState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL: \r\n            pCallbacks->DepthStencilStateCb(*reinterpret_cast<CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1: \r\n            pCallbacks->DepthStencilState1Cb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DepthStencilState)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DepthStencilState);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT: \r\n            pCallbacks->InputLayoutCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::InputLayout)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::InputLayout);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE: \r\n            pCallbacks->IBStripCutValueCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::IBStripCutValue)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::IBStripCutValue);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY: \r\n            pCallbacks->PrimitiveTopologyTypeCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::PrimitiveTopologyType)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::PrimitiveTopologyType);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS: \r\n            pCallbacks->RTVFormatsCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::RTVFormats)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::RTVFormats);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT: \r\n            pCallbacks->DSVFormatCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::DSVFormat)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::DSVFormat);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC: \r\n            pCallbacks->SampleDescCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::SampleDesc)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::SampleDesc);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK: \r\n            pCallbacks->NodeMaskCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::NodeMask)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::NodeMask);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO: \r\n            pCallbacks->CachedPSOCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::CachedPSO)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CachedPSO);\r\n            break;\r\n        case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS:\r\n            pCallbacks->FlagsCb(*reinterpret_cast<decltype(CD3DX12_PIPELINE_STATE_STREAM::Flags)*>(pStream));\r\n            SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::Flags);\r\n            break;\r\n        default:\r\n            pCallbacks->ErrorUnknownSubobject(SubobjectType);\r\n            return E_INVALIDARG;\r\n            break;\r\n        }\r\n    }\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n#endif // defined( __cplusplus )\r\n\r\n#endif //__D3DX12_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/d3dx12affinity.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"d3dx12affinity.h\"\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/d3dx12affinity.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * Primary included header for the affinity layer. You should change all\r\n * #include <d3d12.h> in your engine source to include this file instead.\r\n */\r\n\r\n#pragma once\r\n\r\n#pragma pack(push,16)\r\n\r\n\r\n#include <d3d12.h>\r\n\r\nclass CD3DX12AffinityObject;\r\nclass CD3DX12AffinityDeviceChild;\r\nclass CD3DX12AffinityPageable;\r\nclass CD3DX12AffinityRootSignature;\r\nclass CD3DX12AffinityRootSignatureDeserializer;\r\nclass CD3DX12AffinityHeap;\r\nclass CD3DX12AffinityResource;\r\nclass CD3DX12AffinityCommandAllocator;\r\nclass CD3DX12AffinityFence;\r\nclass CD3DX12AffinityPipelineState;\r\nclass CD3DX12AffinityDescriptorHeap;\r\nclass CD3DX12AffinityQueryHeap;\r\nclass CD3DX12AffinityCommandSignature;\r\nclass CD3DX12AffinityCommandList;\r\nclass CD3DX12AffinityGraphicsCommandList;\r\nclass CD3DX12AffinityCommandQueue;\r\nclass CD3DX12AffinityDevice;\r\nclass CDXGIAffinitySwapChain;\r\n\r\n#include \"CD3DX12AffinityObject.h\"\r\n#include \"CD3DX12AffinityDeviceChild.h\"\r\n#include \"CD3DX12AffinityPageable.h\"\r\n#include \"CD3DX12AffinityRootSignature.h\"\r\n#include \"CD3DX12AffinityHeap.h\"\r\n#include \"CD3DX12AffinityResource.h\"\r\n#include \"CD3DX12AffinityCommandAllocator.h\"\r\n#include \"CD3DX12AffinityFence.h\"\r\n#include \"CD3DX12AffinityPipelineState.h\"\r\n#include \"CD3DX12AffinityDescriptorHeap.h\"\r\n#include \"CD3DX12AffinityQueryHeap.h\"\r\n#include \"CD3DX12AffinityCommandSignature.h\"\r\n#include \"CD3DX12AffinityCommandList.h\"\r\n#include \"CD3DX12AffinityGraphicsCommandList.h\"\r\n#include \"CD3DX12AffinityCommandQueue.h\"\r\n#include \"CD3DX12AffinityDevice.h\"\r\n#include \"CDXGIAffinitySwapChain.h\"\r\n#include \"d3dx12affinity_structs.h\"\r\n\r\n\r\nHRESULT WINAPI D3DX12AffinityCreateLDADevice(\r\n    _In_ ID3D12Device* Device,\r\n    _Outptr_  CD3DX12AffinityDevice** ppDevice);\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateSingleWindowSwapChain(\r\n    _In_  IDXGISwapChain3* pSwapChain,\r\n    _In_  CD3DX12AffinityCommandQueue* pQueue,\r\n    _In_  CD3DX12AffinityDevice* pDevice,\r\n    _In_  DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    _Outptr_  CDXGIAffinitySwapChain** ppSwapChain);\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    _In_  IDXGISwapChain* pSwapChain,\r\n    _In_  CD3DX12AffinityCommandQueue* pQueue,\r\n    _In_  CD3DX12AffinityDevice* pDevice,\r\n    _Outptr_  CDXGIAffinitySwapChain** ppSwapChain);\r\n\r\nHRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain(\r\n    _In_  IDXGISwapChain3* pSwapChain,\r\n    _In_  CD3DX12AffinityCommandQueue* pQueue,\r\n    _In_  CD3DX12AffinityDevice* pDevice,\r\n    _In_  DXGI_SWAP_CHAIN_DESC1* pDesc,\r\n    _Outptr_  CDXGIAffinitySwapChain** ppSwapChain);\r\n\r\n#pragma pack(pop)\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/d3dx12affinity_d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This header provides \"affinity\" versions of some structs provided by <d3dx12.h>\r\n * Any struct that includes \"ID3D12____\" pointers needs to have an affinity version\r\n * that has a \"CD3DX12____\" pointer instead. AFAIK I haven't modified any of these\r\n * structs so if there are any differences vs. <d3dx12.h> it is probably due to\r\n * API changes.\r\n *\r\n * Very few if any of these have been used extensively, so they are relatively\r\n * untested.\r\n */\r\n\r\n#pragma once\r\n\r\n#include \"d3dx12.h\"\r\n#include \"d3dx12affinity.h\"\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_AFFINITY_RESOURCE_BARRIER : public D3DX12_AFFINITY_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_AFFINITY_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_AFFINITY_RESOURCE_BARRIER(const D3DX12_AFFINITY_RESOURCE_BARRIER &o) :\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_AFFINITY_RESOURCE_BARRIER Transition(\r\n        _In_ CD3DX12AffinityResource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_AFFINITY_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_BARRIER Aliasing(\r\n        _In_ CD3DX12AffinityResource* pResourceBefore,\r\n        _In_ CD3DX12AffinityResource* pResourceAfter)\r\n    {\r\n        CD3DX12_AFFINITY_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_BARRIER UAV(\r\n        _In_ CD3DX12AffinityResource* pResource)\r\n    {\r\n        CD3DX12_AFFINITY_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3DX12_AFFINITY_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3DX12_AFFINITY_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION : public D3DX12_AFFINITY_TEXTURE_COPY_LOCATION\r\n{\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(const D3DX12_AFFINITY_TEXTURE_COPY_LOCATION &o) :\r\n        D3DX12_AFFINITY_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(CD3DX12AffinityResource* pRes) { pResource = pRes; }\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(CD3DX12AffinityResource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION(CD3DX12AffinityResource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ CD3DX12AffinityDevice* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = { Format };\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo), 0)))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_AFFINITY_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_AFFINITY_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_AFFINITY_RESOURCE_DESC(const D3D12_RESOURCE_DESC& o) :\r\n        D3D12_RESOURCE_DESC(o)\r\n    {}\r\n    CD3DX12_AFFINITY_RESOURCE_DESC(\r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags)\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Buffer(\r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes,\r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Buffer(\r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1,\r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Tex1D(\r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize,\r\n            mipLevels, format, 1, 0, layout, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Tex2D(\r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize,\r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags);\r\n    }\r\n    static inline CD3DX12_AFFINITY_RESOURCE_DESC Tex3D(\r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0)\r\n    {\r\n        return CD3DX12_AFFINITY_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth,\r\n            mipLevels, format, 1, 0, layout, flags);\r\n    }\r\n    inline UINT16 Depth() const\r\n    {\r\n        return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1);\r\n    }\r\n    inline UINT16 ArraySize() const\r\n    {\r\n        return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1);\r\n    }\r\n    inline UINT8 PlaneCount(_In_ CD3DX12AffinityDevice* pDevice) const\r\n    {\r\n        return D3D12GetFormatPlaneCount(pDevice, Format);\r\n    }\r\n    inline UINT Subresources(_In_ CD3DX12AffinityDevice* pDevice) const\r\n    {\r\n        return MipLevels * ArraySize() * PlaneCount(pDevice);\r\n    }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    {\r\n        return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize());\r\n    }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==(const CD3DX12_AFFINITY_RESOURCE_DESC& l, const CD3DX12_AFFINITY_RESOURCE_DESC& r)\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=(const CD3DX12_AFFINITY_RESOURCE_DESC& l, const CD3DX12_AFFINITY_RESOURCE_DESC& r)\r\n{\r\n    return !(l == r);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    UINT64 RequiredSize = 0;\r\n\r\n    CD3DX12AffinityDevice* pDevice;\r\n    pDestinationResource->GetDevice(&pDevice);\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ CD3DX12AffinityGraphicsCommandList* pCmdList,\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_ CD3DX12AffinityResource* pIntermediate,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc(/* DeviceIndex */ 0);\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||\r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||\r\n        RequiredSize >(SIZE_T) - 1 ||\r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&\r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n\r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n\r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox(UINT(pLayouts[0].Offset), UINT(pLayouts[0].Offset + pLayouts[0].Footprint.Width));\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_AFFINITY_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources(\r\n    _In_ CD3DX12AffinityGraphicsCommandList* pCmdList,\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_ CD3DX12AffinityResource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n        return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n        return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    CD3DX12AffinityDevice* pDevice;\r\n    pDestinationResource->GetDevice(&pDevice);\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n\r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources(\r\n    _In_ CD3DX12AffinityGraphicsCommandList* pCmdList,\r\n    _In_ CD3DX12AffinityResource* pDestinationResource,\r\n    _In_ CD3DX12AffinityResource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(/* DeviceIndex */ 0);\r\n    CD3DX12AffinityDevice* pDevice;\r\n    pDestinationResource->GetDevice(&pDevice);\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n\r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline CD3DX12AffinityCommandList* const* CommandListCast(CD3DX12AffinityGraphicsCommandList* const* pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<CD3DX12AffinityCommandList* const*>(pp);\r\n}\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/UWP/d3dx12affinity_structs.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n/**\r\n * This header provides \"affinity\" versions of the structs provided by <d3d12.h>\r\n * Any struct that includes \"ID3D12____\" pointers needs to have an affinity version\r\n * that has a \"CD3DX12____\" pointer instead. The only modification made to these\r\n * structs is to add ToD3D12() methods that produce copies of the D3D12 structs\r\n * with NULL substituted for the \"ID3D12____\" members, so if there are any differences\r\n * vs. <d3dx12.h> it is probably due to API changes.\r\n */\r\n\r\n#pragma once\r\n\r\n#include \"d3dx12affinity.h\"\r\n\r\ntypedef struct D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC\r\n{\r\n    CD3DX12AffinityRootSignature* pRootSignature;\r\n    D3D12_SHADER_BYTECODE VS;\r\n    D3D12_SHADER_BYTECODE PS;\r\n    D3D12_SHADER_BYTECODE DS;\r\n    D3D12_SHADER_BYTECODE HS;\r\n    D3D12_SHADER_BYTECODE GS;\r\n    D3D12_STREAM_OUTPUT_DESC StreamOutput;\r\n    D3D12_BLEND_DESC BlendState;\r\n    UINT SampleMask;\r\n    D3D12_RASTERIZER_DESC RasterizerState;\r\n    D3D12_DEPTH_STENCIL_DESC DepthStencilState;\r\n    D3D12_INPUT_LAYOUT_DESC InputLayout;\r\n    D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;\r\n    D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;\r\n    UINT NumRenderTargets;\r\n    DXGI_FORMAT RTVFormats[8];\r\n    DXGI_FORMAT DSVFormat;\r\n    DXGI_SAMPLE_DESC SampleDesc;\r\n    UINT NodeMask;\r\n    D3D12_CACHED_PIPELINE_STATE CachedPSO;\r\n    D3D12_PIPELINE_STATE_FLAGS Flags;\r\n\r\n    D3D12_GRAPHICS_PIPELINE_STATE_DESC ToD3D12() const\r\n    {\r\n        D3D12_GRAPHICS_PIPELINE_STATE_DESC Desc;\r\n        Desc.pRootSignature = nullptr;\r\n        Desc.VS = VS;\r\n        Desc.PS = PS;\r\n        Desc.DS = DS;\r\n        Desc.HS = HS;\r\n        Desc.GS = GS;\r\n        Desc.StreamOutput = StreamOutput;\r\n        Desc.BlendState = BlendState;\r\n        Desc.SampleMask = SampleMask;\r\n        Desc.RasterizerState = RasterizerState;\r\n        Desc.DepthStencilState = DepthStencilState;\r\n        Desc.InputLayout = InputLayout;\r\n        Desc.IBStripCutValue = IBStripCutValue;\r\n        Desc.PrimitiveTopologyType = PrimitiveTopologyType;\r\n        Desc.NumRenderTargets = NumRenderTargets;\r\n        for (int i = 0; i < 8; ++i)\r\n            Desc.RTVFormats[i] = RTVFormats[i];\r\n        Desc.DSVFormat = DSVFormat;\r\n        Desc.SampleDesc = SampleDesc;\r\n        Desc.NodeMask = NodeMask;\r\n        Desc.CachedPSO = CachedPSO;\r\n        Desc.Flags = Flags;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_GRAPHICS_PIPELINE_STATE_DESC;\r\n\r\ntypedef struct D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC\r\n{\r\n    CD3DX12AffinityRootSignature* pRootSignature;\r\n    D3D12_SHADER_BYTECODE CS;\r\n    UINT NodeMask;\r\n    D3D12_CACHED_PIPELINE_STATE CachedPSO;\r\n    D3D12_PIPELINE_STATE_FLAGS Flags;\r\n\r\n    D3D12_COMPUTE_PIPELINE_STATE_DESC ToD3D12() const\r\n    {\r\n        D3D12_COMPUTE_PIPELINE_STATE_DESC Desc;\r\n        Desc.pRootSignature = nullptr;\r\n        Desc.CS = CS;\r\n        Desc.NodeMask = NodeMask;\r\n        Desc.CachedPSO = CachedPSO;\r\n        Desc.Flags = Flags;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_COMPUTE_PIPELINE_STATE_DESC;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_TRANSITION_BARRIER\r\n{\r\n    CD3DX12AffinityResource* pResource;\r\n    UINT Subresource;\r\n    D3D12_RESOURCE_STATES StateBefore;\r\n    D3D12_RESOURCE_STATES StateAfter;\r\n\r\n    D3D12_RESOURCE_TRANSITION_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_TRANSITION_BARRIER Desc;\r\n        Desc.pResource = nullptr;\r\n        Desc.Subresource = Subresource;\r\n        Desc.StateBefore = StateBefore;\r\n        Desc.StateAfter = StateAfter;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_TRANSITION_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_ALIASING_BARRIER\r\n{\r\n    CD3DX12AffinityResource* pResourceBefore;\r\n    CD3DX12AffinityResource* pResourceAfter;\r\n\r\n    D3D12_RESOURCE_ALIASING_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_ALIASING_BARRIER Desc;\r\n        Desc.pResourceBefore = nullptr;\r\n        Desc.pResourceAfter = nullptr;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_ALIASING_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_UAV_BARRIER\r\n{\r\n    CD3DX12AffinityResource* pResource;\r\n\r\n    D3D12_RESOURCE_UAV_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_UAV_BARRIER Desc;\r\n        Desc.pResource = nullptr;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_UAV_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_RESOURCE_BARRIER\r\n{\r\n    D3D12_RESOURCE_BARRIER_TYPE Type;\r\n    D3D12_RESOURCE_BARRIER_FLAGS Flags;\r\n    union\r\n    {\r\n        D3DX12_AFFINITY_RESOURCE_TRANSITION_BARRIER Transition;\r\n        D3DX12_AFFINITY_RESOURCE_ALIASING_BARRIER Aliasing;\r\n        D3DX12_AFFINITY_RESOURCE_UAV_BARRIER UAV;\r\n    };\r\n\r\n    D3D12_RESOURCE_BARRIER ToD3D12() const\r\n    {\r\n        D3D12_RESOURCE_BARRIER Desc;\r\n        Desc.Type = Type;\r\n        Desc.Flags = Flags;\r\n        switch (Type)\r\n        {\r\n        case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:\r\n            Desc.Transition = Transition.ToD3D12();\r\n            break;\r\n        case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:\r\n            Desc.Aliasing = Aliasing.ToD3D12();\r\n            break;\r\n        case D3D12_RESOURCE_BARRIER_TYPE_UAV:\r\n            Desc.UAV = UAV.ToD3D12();\r\n            break;\r\n        }\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_RESOURCE_BARRIER;\r\n\r\ntypedef struct D3DX12_AFFINITY_TEXTURE_COPY_LOCATION\r\n{\r\n    CD3DX12AffinityResource* pResource;\r\n    D3D12_TEXTURE_COPY_TYPE Type;\r\n    union\r\n    {\r\n        D3D12_PLACED_SUBRESOURCE_FOOTPRINT PlacedFootprint;\r\n        UINT SubresourceIndex;\r\n    };\r\n\r\n    D3D12_TEXTURE_COPY_LOCATION ToD3D12() const\r\n    {\r\n        D3D12_TEXTURE_COPY_LOCATION Desc;\r\n        Desc.pResource = nullptr;\r\n        switch (Type)\r\n        {\r\n        case D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT:\r\n            Desc.PlacedFootprint = PlacedFootprint;\r\n            break;\r\n        case D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX:\r\n            Desc.SubresourceIndex = SubresourceIndex;\r\n            break;\r\n        }\r\n        Desc.Type = Type;\r\n\r\n        return Desc;\r\n    }\r\n} D3DX12_AFFINITY_TEXTURE_COPY_LOCATION;\r\n"
  },
  {
    "path": "Libraries/D3DX12AffinityLayer/readme.md",
    "content": "# The D3D12 MultiGPU Starter Library\n\nThis library is intended to help apps kick start their MultiGPU implementation.  The library itself is called the affinity layer in that execution and resources can be 'affinitized' to one or more GPUs in the system.  This library should help developers quickly bring up DirectX 12 MultiGPU in their engines. \n\n## What do you mean by 'MultiGPU'?\nMultiGPU can take on a few meanings.  The name indicates that we are referring to the use of multiple GPUs in a user's systems but does not imply how or why.  At the core, the MultiGPU features in DirectX 12 are designed to expose multiple GPUs to the app.  The power is then in the app's hands to use those GPUs to their maximum potential. \n\nAll in all, the idea of MultiGPU in DirectX 12 is to give the app full access to the graphics hardware in the system whether it is execution resources, graphics memory, etc. \n\n## Exactly what problem does the library try to solve right now?\nCurrently, this library tries to help developers implement one of the most commonly used MultiGPU techniques, Alternate Frame Rendering (AFR) using linked GPUs.  There are a large number of other possibilities with DirectX 12's explicit MultiGPU features but AFR is one of the most widely used techniques.  The library may be expanded in the future to support other scenarios. \n\nThere are many other possible techniques (other than AFR) for MultiGPU; some that are suitable candidates to be abstracted out into a library like the affinity layer, others that are not.  We are looking at other scenarios where the library can fit in as a (almost) drop in solution.\n\n## What is Alternate Frame Rendering (AFR)?\nAFR does exactly as the name suggests.  Frames are rendered in an alternating (i.e. round-robin) manner on each of the GPUs in the system.  If there are two GPUs, the first GPU will render every even frame and the second GPU will render every odd frame.  Since both GPUs can render in parallel, the theoretical maximum rendering frequency is twice that of a single GPU system.  This is of course assuming both GPUs are identical in power, which, in linked GPU systems, they almost always are. \n\n## How does the library help apps implement AFR?\nOne of the most common methods of achieving dual GPU AFR is to: \n  * Duplicate all non-system memory resources on both GPUs (i.e. textures, buffers, render targets, etc.) \n  * Execute the same work on both GPUs\n    * The ideal case being GPU1 starts rendering when GPU0 is 50% through it's rendering pass theoretically doubling the frame rate \n  * Copy any inter-frame dependencies across the GPUs so that they are available when the next frame (ie. the other GPU) starts rendering \n    * An example of this might be a temporal AA dependency from frame N-1 needed for frame N \n\nConceptually, it might look something like this:\n```\n   GPU0   |---Frame 0---|---Frame 2---|---Frame 4---|--- etc\n   GPU1          |---Frame 1---|---Frame 3---|---Frame 5---|--- etc\n```\n\nThe library provides the app a simple abstracted way of executing commands, uploading data, and synchronizing on one or many GPUs simultaneously.\n\nAnother thing to note is that this library does allow for apps to switch between single GPU and multi GPU scenarios.  You don't need two code paths.  The library does naturally come with some CPU overhead.  Please profile your games and if the extra CPU usage seems to be abnormal, feel free to let us know.\n\n# How do I use it?\nHere are the high level steps for using the library:\n  1. The library is a thin wrapper around the entire D3D12 API. The expectation is to find and replace ```ID3D12``` with ```CD3DX12Affinity``` (and similar for structure names) through an entire codebase and have the code compile and work correctly on single-GPU.\n    1. The exception is device and swap chain creation, where the normal API should be invoked first, followed by construction of the affinity wrapper.\n    2. Note that it might be desirable to use typedefs wrapped in #ifs (e.g. GPUD3D12*) which can be toggled back and forth between the core D3D12 types and the affinity layer types.\n  2. For AFR, use the ```CD3DX12Device::SwitchToNextNode()``` method on the affinity device after each successful ```Present()```.\n  3. Your resource tracker will need to detect and track the following cases:\n    1. Static resources which are initialized via GPU writes, e.g. textures/buffers/etc. These copies need to be issued on both GPUs. Create command lists (and allocators) with an explicit node mask indicating all GPUs.  Command lists created this way do not inherit the active node on reset.\n    2. Cross-frame dependencies. At this point, you should be able to run on two GPUs with flickering (hopefully not between correct and black content). This is because contents on GPU N is intending to read contents from the previous frame (which are on GPU N-1), but the resource it's reading from has contents from N frames ago on GPU N. The engine needs to either break these dependencies, or marshal contents from frame N-1 to N using correct synchronization. Note: You will also want to ensure synchronization to cause your frames to be serialized.\n    3. Resource states are independent for each GPU since the library instantiates N resources under the hood. Your tracker should transition the resource using the active state of the resource on the current node you are recording the command list on.\n\n# Other considerations\n\n## What if I'm using a 3rd party library?\nAll resources in Direct3D 12 need to specify a Node mask to run properly targeting a specific GPU. If the 3rd party library doesn't support MultiGPU and is creating resources on your behalf, it will need to be updated to take a NodeMask parameter to be set on Direct3D 12 object creation. After that you can instantiate the library for N number of GPUs.  The affinity objects have a GetChildObject method to access underlying affinitized D3D12 resources to pass to the active instance of the library.\n\n## I've heard terms like 'Linked' and 'Unlinked' MultiGPU; what do they mean?\nSimplifying a bit, linked GPUs usually refer to multiple GPUs connected in a way which satisfies a specific OS/API contract enabling the NodeMask feature.  In conforming to this special contract, it's possible for application simultaneously use the linked GPUs more efficiently than if they were unlinked.  Though this is not necessarily always the case, linked GPUs are often found in pairs as identical cards from the same vendor sometimes even physically connected by a special cable. \n\nUnlinked GPUs on the other hand can be completely different in power and even vendor.  The DirectX 12 API also allows communication between unlinked GPUs though it may be slower/less efficient than what linked GPUs can manage.  As a tradeoff, unlinked GPUs open a huge number of possibilities essentially removing restrictions on video card capability, vendor, etc.  Any card of any capability should be able to work with any other card. \n"
  },
  {
    "path": "Libraries/D3DX12Residency/d3dx12Residency.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\nnamespace D3DX12Residency\r\n{\r\n\t__declspec(selectany) INT64 g_ResidencyManagerUniqueID = 0;\r\n\r\n#if 0\r\n#define RESIDENCY_CHECK(x) \\\r\n\tif((x) == false) { DebugBreak(); }\r\n\r\n#define RESIDENCY_CHECK_RESULT(x) \\\r\n\tif((x) != S_OK) { DebugBreak(); }\r\n#else\r\n#define RESIDENCY_CHECK(x)\r\n#define RESIDENCY_CHECK_RESULT(x) x\r\n#endif\r\n\r\n#define RESIDENCY_SINGLE_THREADED 0\r\n\r\n#define RESIDENCY_MIN(x,y) ((x) < (y) ? (x) : (y))\r\n#define RESIDENCY_MAX(x,y) ((x) > (y) ? (x) : (y))\r\n\r\n\t// This size can be tuned to your app in order to save space\r\n#define MAX_NUM_CONCURRENT_CMD_LISTS 32\r\n\r\n\tnamespace Internal\r\n\t{\r\n\t\tclass CriticalSection\r\n\t\t{\r\n\t\t\tfriend class ScopedLock;\r\n\t\tpublic:\r\n\t\t\tCriticalSection()\r\n\t\t\t{\r\n\t\t\t\tInitializeCriticalSectionAndSpinCount(&CS, 8);\r\n\t\t\t}\r\n\r\n\t\t\t~CriticalSection()\r\n\t\t\t{\r\n\t\t\t\tDeleteCriticalSection(&CS);\r\n\t\t\t}\r\n\r\n\t\tprivate:\r\n\t\t\tCRITICAL_SECTION CS;\r\n\t\t};\r\n\r\n\t\tclass ScopedLock\r\n\t\t{\r\n\t\tpublic:\r\n\r\n\t\t\tScopedLock() : pCS(nullptr) {};\r\n\t\t\tScopedLock(CriticalSection* pCSIn) : pCS(pCSIn)\r\n\t\t\t{\r\n\t\t\t\tif (pCS)\r\n\t\t\t\t{\r\n\t\t\t\t\tEnterCriticalSection(&pCS->CS);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t~ScopedLock()\r\n\t\t\t{\r\n\t\t\t\tif (pCS)\r\n\t\t\t\t{\r\n\t\t\t\t\tLeaveCriticalSection(&pCS->CS);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\tprivate:\r\n\r\n\t\t\tCriticalSection* pCS;\r\n\t\t};\r\n\r\n\t\t// One per Residency Manager\r\n\t\tclass SyncManager\r\n\t\t{\r\n\t\tpublic:\r\n\t\t\tSyncManager()\r\n\t\t\t{\r\n\t\t\t\tfor (UINT32 i = 0; i < ARRAYSIZE(AvailableCommandLists); i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tAvailableCommandLists[i] = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tInternal::CriticalSection MaskCriticalSection;\r\n\r\n\t\t\tstatic const UINT32 sUnsetValue = UINT32(-1);\r\n\t\t\t// Represents which command lists are currently open for recording\r\n\t\t\tbool AvailableCommandLists[MAX_NUM_CONCURRENT_CMD_LISTS];\r\n\t\t};\r\n\r\n\t\t//Forward Declaration\r\n\t\tclass ResidencyManagerInternal;\r\n\t}\r\n\r\n\t// Used to track meta data for each object the app potentially wants\r\n\t// to make resident or evict.\r\n\tclass ManagedObject\r\n\t{\r\n\tpublic:\r\n\t\tenum class RESIDENCY_STATUS\r\n\t\t{\r\n\t\t\tRESIDENT,\r\n\t\t\tEVICTED\r\n\t\t};\r\n\r\n\t\tManagedObject() :\r\n\t\t\tpUnderlying(nullptr),\r\n\t\t\tSize(0),\r\n\t\t\tResidencyStatus(RESIDENCY_STATUS::RESIDENT),\r\n\t\t\tLastGPUSyncPoint(0),\r\n\t\t\tLastUsedTimestamp(0)\r\n\t\t{\r\n\t\t\tmemset(CommandListsUsedOn, 0, sizeof(CommandListsUsedOn));\r\n\t\t}\r\n\r\n\t\tvoid Initialize(ID3D12Pageable* pUnderlyingIn, UINT64 ObjectSize, UINT64 InitialGPUSyncPoint = 0)\r\n\t\t{\r\n\t\t\tRESIDENCY_CHECK(pUnderlying == nullptr);\r\n\t\t\tpUnderlying = pUnderlyingIn;\r\n\t\t\tSize = ObjectSize;\r\n\t\t\tLastGPUSyncPoint = InitialGPUSyncPoint;\r\n\t\t}\r\n\r\n\t\tinline bool IsInitialized() { return pUnderlying != nullptr; }\r\n\r\n\t\t// Wether the object is resident or not\r\n\t\tRESIDENCY_STATUS ResidencyStatus;\r\n\r\n\t\t// The underlying D3D Object being tracked\r\n\t\tID3D12Pageable* pUnderlying;\r\n\t\t// The size of the D3D Object in bytes\r\n\t\tUINT64 Size;\r\n\r\n\t\tUINT64 LastGPUSyncPoint;\r\n\t\tUINT64 LastUsedTimestamp;\r\n\r\n\t\t// This is used to track which open command lists this resource is currently used on.\r\n\t\tbool CommandListsUsedOn[MAX_NUM_CONCURRENT_CMD_LISTS];\r\n\r\n\t\t// Linked list entry\r\n\t\tLIST_ENTRY ListEntry;\r\n\t};\r\n\r\n\t// This represents a set of objects which are referenced by a command list i.e. every time a resource\r\n\t// is bound for rendering, clearing, copy etc. the set must be updated to ensure the it is resident \r\n\t// for execution.\r\n\tclass ResidencySet\r\n\t{\r\n\t\tfriend class ResidencyManager;\r\n\t\tfriend class Internal::ResidencyManagerInternal;\r\n\tpublic:\r\n\r\n\t\tstatic const UINT32 InvalidIndex = (UINT32)-1;\r\n\r\n\t\tResidencySet() :\r\n\t\t\tCommandListIndex(InvalidIndex),\r\n\t\t\tMaxResidencySetSize(0),\r\n\t\t\tCurrentSetSize(0),\r\n\t\t\tppSet(nullptr),\r\n\t\t\tIsOpen(false),\r\n\t\t\tOutOfMemory(false),\r\n\t\t\tpSyncManager(nullptr)\r\n\t\t{\r\n\t\t};\r\n\r\n\t\t~ResidencySet()\r\n\t\t{\r\n\t\t\tdelete[](ppSet);\r\n\t\t}\r\n\r\n\t\t// Returns true if the object was inserted, false otherwise\r\n\t\tinline bool Insert(ManagedObject* pObject)\r\n\t\t{\r\n\t\t\tRESIDENCY_CHECK(IsOpen);\r\n\t\t\tRESIDENCY_CHECK(CommandListIndex != InvalidIndex);\r\n\r\n\t\t\t// If we haven't seen this object on this command list mark it\r\n\t\t\tif (pObject->CommandListsUsedOn[CommandListIndex] == false)\r\n\t\t\t{\r\n\t\t\t\tpObject->CommandListsUsedOn[CommandListIndex] = true;\r\n\t\t\t\tif (ppSet == nullptr || CurrentSetSize >= MaxResidencySetSize)\r\n\t\t\t\t{\r\n\t\t\t\t\tRealloc();\r\n\t\t\t\t}\r\n\t\t\t\tif (ppSet == nullptr)\r\n\t\t\t\t{\r\n\t\t\t\t\tOutOfMemory = true;\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tppSet[CurrentSetSize++] = pObject;\r\n\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tHRESULT Open()\r\n\t\t{\r\n\t\t\tInternal::ScopedLock Lock(&pSyncManager->MaskCriticalSection);\r\n\r\n\t\t\t// It's invalid to open a set that is already open\r\n\t\t\tif (IsOpen)\r\n\t\t\t{\r\n\t\t\t\treturn E_INVALIDARG;\r\n\t\t\t}\r\n\r\n\t\t\tRESIDENCY_CHECK(CommandListIndex == InvalidIndex);\r\n\r\n\t\t\tbool CommandlistAvailable = false;\r\n\t\t\t// Find the first available command list by bitscanning\r\n\t\t\tfor (UINT32 i = 0; i < ARRAYSIZE(pSyncManager->AvailableCommandLists); i++)\r\n\t\t\t{\r\n\t\t\t\tif (pSyncManager->AvailableCommandLists[i] == false)\r\n\t\t\t\t{\r\n\t\t\t\t\tCommandListIndex = i;\r\n\t\t\t\t\tpSyncManager->AvailableCommandLists[i] = true;\r\n\t\t\t\t\tCommandlistAvailable = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (CommandlistAvailable == false)\r\n\t\t\t{\r\n\t\t\t\t// There are too many open residency sets, consider using less or increasing the value of MAX_NUM_CONCURRENT_CMD_LISTS\r\n\t\t\t\tRESIDENCY_CHECK(false);\r\n\t\t\t\treturn E_OUTOFMEMORY;\r\n\t\t\t}\r\n\r\n\t\t\tCurrentSetSize = 0;\r\n\r\n\t\t\tIsOpen = true;\r\n\t\t\tOutOfMemory = false;\r\n\t\t\treturn S_OK;\r\n\t\t}\r\n\r\n\t\tHRESULT Close()\r\n\t\t{\r\n\t\t\tif (IsOpen == false)\r\n\t\t\t{\r\n\t\t\t\treturn E_INVALIDARG;\r\n\t\t\t}\r\n\r\n\t\t\tif (OutOfMemory == true)\r\n\t\t\t{\r\n\t\t\t\treturn E_OUTOFMEMORY;\r\n\t\t\t}\r\n\r\n\t\t\tfor (INT32 i = 0; i < CurrentSetSize; i++)\r\n\t\t\t{\r\n\t\t\t\tRemove(ppSet[i]);\r\n\t\t\t}\r\n\r\n\t\t\tReturnCommandListReservation();\r\n\r\n\t\t\tIsOpen = false;\r\n\r\n\t\t\treturn S_OK;\r\n\t\t}\r\n\r\n\tprivate:\r\n\r\n\t\tinline void Remove(ManagedObject* pObject)\r\n\t\t{\r\n\t\t\tpObject->CommandListsUsedOn[CommandListIndex] = false;\r\n\t\t}\r\n\r\n\t\tinline void ReturnCommandListReservation()\r\n\t\t{\r\n\t\t\tInternal::ScopedLock Lock(&pSyncManager->MaskCriticalSection);\r\n\r\n\t\t\tpSyncManager->AvailableCommandLists[CommandListIndex] = false;\r\n\r\n\t\t\tCommandListIndex = ResidencySet::InvalidIndex;\r\n\r\n\t\t\tIsOpen = false;\r\n\t\t}\r\n\r\n\t\tvoid Initialize(Internal::SyncManager* pSyncManagerIn)\r\n\t\t{\r\n\t\t\tpSyncManager = pSyncManagerIn;\r\n\t\t}\r\n\r\n\t\tbool Initialize(Internal::SyncManager* pSyncManagerIn, UINT32 MaxSize)\r\n\t\t{\r\n\t\t\tpSyncManager = pSyncManagerIn;\r\n\t\t\tMaxResidencySetSize = MaxSize;\r\n\r\n\t\t\tppSet = new ManagedObject*[MaxResidencySetSize];\r\n\r\n\t\t\treturn ppSet != nullptr;\r\n\t\t}\r\n\r\n\t\tinline void Realloc()\r\n\t\t{\r\n\t\t\tMaxResidencySetSize = (MaxResidencySetSize == 0) ? 4096 : INT32(MaxResidencySetSize + (MaxResidencySetSize / 2.0f));\r\n\t\t\tManagedObject** ppNewAlloc = new ManagedObject*[MaxResidencySetSize];\r\n\r\n\t\t\tif (ppSet && ppNewAlloc)\r\n\t\t\t{\r\n\t\t\t\tmemcpy(ppNewAlloc, ppSet, CurrentSetSize * sizeof(ManagedObject*));\r\n\t\t\t\tdelete[](ppSet);\r\n\t\t\t}\r\n\r\n\t\t\tppSet = ppNewAlloc;\r\n\t\t}\r\n\r\n\t\tUINT32 CommandListIndex;\r\n\r\n\t\tManagedObject** ppSet;\r\n\t\tINT32 MaxResidencySetSize;\r\n\t\tINT32 CurrentSetSize;\r\n\r\n\t\tbool IsOpen;\r\n\t\tbool OutOfMemory;\r\n\r\n\t\tInternal::SyncManager* pSyncManager;\r\n\t};\r\n\r\n\tnamespace Internal\r\n\t{\r\n\t\t/* List Helpers */\r\n\t\tinline void InitializeListHead(LIST_ENTRY* pHead)\r\n\t\t{\r\n\t\t\tpHead->Flink = pHead->Blink = pHead;\r\n\t\t}\r\n\r\n\t\tinline void InsertHeadList(LIST_ENTRY* pHead, LIST_ENTRY* pEntry)\r\n\t\t{\r\n\t\t\tpEntry->Blink = pHead;\r\n\t\t\tpEntry->Flink = pHead->Flink;\r\n\r\n\t\t\tpHead->Flink->Blink = pEntry;\r\n\t\t\tpHead->Flink = pEntry;\r\n\t\t}\r\n\r\n\t\tinline void InsertTailList(LIST_ENTRY* pHead, LIST_ENTRY* pEntry)\r\n\t\t{\r\n\t\t\tpEntry->Flink = pHead;\r\n\t\t\tpEntry->Blink = pHead->Blink;\r\n\r\n\t\t\tpHead->Blink->Flink = pEntry;\r\n\t\t\tpHead->Blink = pEntry;\r\n\t\t}\r\n\r\n\t\tinline void RemoveEntryList(LIST_ENTRY* pEntry)\r\n\t\t{\r\n\t\t\tpEntry->Blink->Flink = pEntry->Flink;\r\n\t\t\tpEntry->Flink->Blink = pEntry->Blink;\r\n\t\t}\r\n\r\n\t\tinline LIST_ENTRY* RemoveHeadList(LIST_ENTRY* pHead)\r\n\t\t{\r\n\t\t\tLIST_ENTRY* pEntry = pHead->Flink;\r\n\t\t\tInternal::RemoveEntryList(pEntry);\r\n\t\t\treturn pEntry;\r\n\t\t}\r\n\r\n\t\tinline LIST_ENTRY* RemoveTailList(LIST_ENTRY* pHead)\r\n\t\t{\r\n\t\t\tLIST_ENTRY* pEntry = pHead->Blink;\r\n\t\t\tInternal::RemoveEntryList(pEntry);\r\n\t\t\treturn pEntry;\r\n\t\t}\r\n\r\n\t\tinline bool IsListEmpty(LIST_ENTRY* pEntry)\r\n\t\t{\r\n\t\t\treturn pEntry->Flink == pEntry;\r\n\t\t}\r\n\r\n\t\tstruct Fence\r\n\t\t{\r\n\t\t\tFence(UINT64 StartingValue) : pFence(nullptr), FenceValue(StartingValue)\r\n\t\t\t{\r\n\t\t\t\tInternal::InitializeListHead(&ListEntry);\r\n\t\t\t};\r\n\r\n\t\t\tHRESULT Initialize(ID3D12Device* pDevice)\r\n\t\t\t{\r\n\t\t\t\tHRESULT hr = pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&pFence));\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(hr);\r\n\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tvoid Destroy()\r\n\t\t\t{\r\n\t\t\t\tif (pFence)\r\n\t\t\t\t{\r\n\t\t\t\t\tpFence->Release();\r\n\t\t\t\t\tpFence = nullptr;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tHRESULT GPUWait(ID3D12CommandQueue* pQueue)\r\n\t\t\t{\r\n\t\t\t\tHRESULT hr = pQueue->Wait(pFence, FenceValue);\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tHRESULT GPUSignal(ID3D12CommandQueue* pQueue)\r\n\t\t\t{\r\n\t\t\t\tHRESULT hr = pQueue->Signal(pFence, FenceValue);\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tinline void Increment()\r\n\t\t\t{\r\n\t\t\t\tFenceValue++;\r\n\t\t\t}\r\n\r\n\t\t\tID3D12Fence* pFence;\r\n\t\t\tUINT64 FenceValue;\r\n\t\t\tLIST_ENTRY ListEntry;\r\n\t\t};\r\n\r\n\t\t// Represents a time on a particular queue that a resource was used\r\n\t\tstruct QueueSyncPoint\r\n\t\t{\r\n\t\t\tQueueSyncPoint() : pFence(nullptr), LastUsedValue(0) {};\r\n\r\n\t\t\tinline bool IsCompleted() { return LastUsedValue <= pFence->pFence->GetCompletedValue(); }\r\n\r\n\t\t\tinline void WaitForCompletion(HANDLE Event)\r\n\t\t\t{\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(pFence->pFence->SetEventOnCompletion(LastUsedValue, Event));\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(WaitForSingleObject(Event, INFINITE));\r\n\t\t\t}\r\n\r\n\t\t\tFence* pFence;\r\n\t\t\tUINT64 LastUsedValue;\r\n\t\t};\r\n\r\n\t\tstruct DeviceWideSyncPoint\r\n\t\t{\r\n\t\t\tDeviceWideSyncPoint(UINT32 NumQueues, UINT64 Generation) :\r\n\t\t\t\tGenerationID(Generation), NumQueueSyncPoints(NumQueues) {};\r\n\r\n\t\t\t// Create the whole structure in one allocation for locality\r\n\t\t\tstatic DeviceWideSyncPoint* CreateSyncPoint(UINT32 NumQueues, UINT64 Generation)\r\n\t\t\t{\r\n\t\t\t\tDeviceWideSyncPoint* pSyncPoint = nullptr;\r\n\t\t\t\tconst SIZE_T Size = sizeof(DeviceWideSyncPoint) + (sizeof(QueueSyncPoint) * (NumQueues - 1));\r\n\r\n\t\t\t\tBYTE* pAlloc = new BYTE[Size];\r\n\t\t\t\tif (pAlloc && Size >= sizeof(DeviceWideSyncPoint))\r\n\t\t\t\t{\r\n\t\t\t\t\tpSyncPoint = new (pAlloc) DeviceWideSyncPoint(NumQueues, Generation);\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn pSyncPoint;\r\n\t\t\t}\r\n\r\n\t\t\t// A device wide fence is completed if all of the queues that were active at that point are completed\r\n\t\t\tinline bool IsCompleted()\r\n\t\t\t{\r\n\t\t\t\tfor (UINT32 i = 0; i < NumQueueSyncPoints; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (pQueueSyncPoints[i].IsCompleted() == false)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\r\n\t\t\tinline void WaitForCompletion(HANDLE Event)\r\n\t\t\t{\r\n\t\t\t\tfor (UINT32 i = 0; i < NumQueueSyncPoints; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (pQueueSyncPoints[i].IsCompleted() == false)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpQueueSyncPoints[i].WaitForCompletion(Event);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tconst UINT64 GenerationID;\r\n\t\t\tconst UINT32 NumQueueSyncPoints;\r\n\t\t\tLIST_ENTRY ListEntry;\r\n\t\t\t// NumQueueSyncPoints QueueSyncPoints will be placed below here\r\n\t\t\tQueueSyncPoint pQueueSyncPoints[1];\r\n\t\t};\r\n\r\n\t\t// A Least Recently Used Cache. Tracks all of the objects requested by the app so that objects\r\n\t\t// that aren't used freqently can get evicted to help the app stay under buget.\r\n\t\tclass LRUCache\r\n\t\t{\r\n\t\tpublic:\r\n\t\t\tLRUCache() :\r\n\t\t\t\tNumResidentObjects(0),\r\n\t\t\t\tNumEvictedObjects(0),\r\n\t\t\t\tResidentSize(0)\r\n\t\t\t{\r\n\t\t\t\tInternal::InitializeListHead(&ResidentObjectListHead);\r\n\t\t\t\tInternal::InitializeListHead(&EvictedObjectListHead);\r\n\t\t\t};\r\n\r\n\t\t\tvoid Insert(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tif (pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::RESIDENT)\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::InsertHeadList(&ResidentObjectListHead, &pObject->ListEntry);\r\n\t\t\t\t\tNumResidentObjects++;\r\n\t\t\t\t\tResidentSize += pObject->Size;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::InsertHeadList(&EvictedObjectListHead, &pObject->ListEntry);\r\n\t\t\t\t\tNumEvictedObjects++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tvoid Remove(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tInternal::RemoveEntryList(&pObject->ListEntry);\r\n\t\t\t\tif (pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::RESIDENT)\r\n\t\t\t\t{\r\n\t\t\t\t\tNumResidentObjects--;\r\n\t\t\t\t\tResidentSize -= pObject->Size;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tNumEvictedObjects--;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// When an object is used by the GPU we move it to the end of the list.\r\n\t\t\t// This way things closer to the head of the list are the objects which\r\n\t\t\t// are stale and better candidates for eviction\r\n\t\t\tvoid ObjectReferenced(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tRESIDENCY_CHECK(pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::RESIDENT);\r\n\r\n\t\t\t\tInternal::RemoveEntryList(&pObject->ListEntry);\r\n\t\t\t\tInternal::InsertTailList(&ResidentObjectListHead, &pObject->ListEntry);\r\n\t\t\t}\r\n\r\n\t\t\tvoid MakeResident(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tRESIDENCY_CHECK(pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::EVICTED);\r\n\r\n\t\t\t\tpObject->ResidencyStatus = ManagedObject::RESIDENCY_STATUS::RESIDENT;\r\n\t\t\t\tInternal::RemoveEntryList(&pObject->ListEntry);\r\n\t\t\t\tInternal::InsertTailList(&ResidentObjectListHead, &pObject->ListEntry);\r\n\r\n\t\t\t\tNumEvictedObjects--;\r\n\t\t\t\tNumResidentObjects++;\r\n\t\t\t\tResidentSize += pObject->Size;\r\n\t\t\t}\r\n\r\n\t\t\tvoid Evict(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tRESIDENCY_CHECK(pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::RESIDENT);\r\n\r\n\t\t\t\tpObject->ResidencyStatus = ManagedObject::RESIDENCY_STATUS::EVICTED;\r\n\t\t\t\tInternal::RemoveEntryList(&pObject->ListEntry);\r\n\t\t\t\tInternal::InsertTailList(&EvictedObjectListHead, &pObject->ListEntry);\r\n\r\n\t\t\t\tNumResidentObjects--;\r\n\t\t\t\tResidentSize -= pObject->Size;\r\n\t\t\t\tNumEvictedObjects++;\r\n\t\t\t}\r\n\r\n\t\t\t// Evict all of the resident objects used in sync points up to the specficied one (inclusive)\r\n\t\t\tvoid TrimToSyncPointInclusive(INT64 CurrentUsage, INT64 CurrentBudget, ID3D12Pageable** EvictionList, UINT32& NumObjectsToEvict, UINT64 SyncPoint)\r\n\t\t\t{\r\n\t\t\t\tNumObjectsToEvict = 0;\r\n\r\n\t\t\t\tLIST_ENTRY* pResourceEntry = ResidentObjectListHead.Flink;\r\n\t\t\t\twhile (pResourceEntry != &ResidentObjectListHead)\r\n\t\t\t\t{\r\n\t\t\t\t\tManagedObject* pObject = CONTAINING_RECORD(pResourceEntry, ManagedObject, ListEntry);\r\n\r\n\t\t\t\t\tif (pObject->LastGPUSyncPoint > SyncPoint || CurrentUsage < CurrentBudget)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tRESIDENCY_CHECK(pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::RESIDENT);\r\n\r\n\t\t\t\t\tEvictionList[NumObjectsToEvict++] = pObject->pUnderlying;\r\n\t\t\t\t\tEvict(pObject);\r\n\r\n\t\t\t\t\tCurrentUsage -= pObject->Size;\r\n\r\n\t\t\t\t\tpResourceEntry = ResidentObjectListHead.Flink;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Trim all objects which are older than the specified time\r\n\t\t\tvoid TrimAgedAllocations(DeviceWideSyncPoint* MaxSyncPoint, ID3D12Pageable** EvictionList, UINT32& NumObjectsToEvict, UINT64 CurrentTimeStamp, UINT64 MinDelta)\r\n\t\t\t{\r\n\t\t\t\tLIST_ENTRY* pResourceEntry = ResidentObjectListHead.Flink;\r\n\t\t\t\twhile (pResourceEntry != &ResidentObjectListHead)\r\n\t\t\t\t{\r\n\t\t\t\t\tManagedObject* pObject = CONTAINING_RECORD(pResourceEntry, ManagedObject, ListEntry);\r\n\r\n\t\t\t\t\tif ((MaxSyncPoint && pObject->LastGPUSyncPoint >= MaxSyncPoint->GenerationID) || // Only trim allocations done on the GPU\r\n\t\t\t\t\t\tCurrentTimeStamp - pObject->LastUsedTimestamp <= MinDelta) // Don't evict things which have been used recently\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tRESIDENCY_CHECK(pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::RESIDENT);\r\n\t\t\t\t\tEvictionList[NumObjectsToEvict++] = pObject->pUnderlying;\r\n\t\t\t\t\tEvict(pObject);\r\n\r\n\t\t\t\t\tpResourceEntry = ResidentObjectListHead.Flink;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tManagedObject* GetResidentListHead()\r\n\t\t\t{\r\n\t\t\t\tif (IsListEmpty(&ResidentObjectListHead))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn nullptr;\r\n\t\t\t\t}\r\n\t\t\t\treturn CONTAINING_RECORD(ResidentObjectListHead.Flink, ManagedObject, ListEntry);\r\n\t\t\t}\r\n\r\n\t\t\tLIST_ENTRY ResidentObjectListHead;\r\n\t\t\tLIST_ENTRY EvictedObjectListHead;\r\n\r\n\t\t\tUINT32 NumResidentObjects;\r\n\t\t\tUINT32 NumEvictedObjects;\r\n\r\n\t\t\tUINT64 ResidentSize;\r\n\t\t};\r\n\r\n\t\tclass ResidencyManagerInternal\r\n\t\t{\r\n\t\tpublic:\r\n\t\t\tResidencyManagerInternal(SyncManager* pSyncManagerIn) :\r\n\t\t\t\tDevice(nullptr),\r\n\t\t\t\tAsyncThreadFence(1),\r\n\t\t\t\tCompletionEvent(INVALID_HANDLE_VALUE),\r\n\t\t\t\tAsyncThreadWorkCompletionEvent(INVALID_HANDLE_VALUE),\r\n\t\t\t\tAdapter(nullptr),\r\n\t\t\t\tAsyncWorkEvent(INVALID_HANDLE_VALUE),\r\n\t\t\t\tAsyncWorkThread(INVALID_HANDLE_VALUE),\r\n\t\t\t\tFinishAsyncWork(false),\r\n\t\t\t\tcStartEvicted(false),\r\n\t\t\t\tCurrentSyncPointGeneration(0),\r\n\t\t\t\tNumQueuesSeen(0),\r\n\t\t\t\tNodeIndex(0),\r\n\t\t\t\tCurrentAsyncWorkloadHead(0),\r\n\t\t\t\tCurrentAsyncWorkloadTail(0),\r\n\t\t\t\tcMinEvictionGracePeriod(1.0f),\r\n\t\t\t\tcMaxEvictionGracePeriod(60.0f),\r\n\t\t\t\tcTrimPercentageMemoryUsageThreshold(0.7f),\r\n\t\t\t\tAsyncWorkQueue(nullptr),\r\n\t\t\t\tMaxSoftwareQueueLatency(6),\r\n\t\t\t\tAsyncWorkQueueSize(7),\r\n\t\t\t\tpSyncManager(pSyncManagerIn)\r\n\t\t\t{\r\n\t\t\t\tInternal::InitializeListHead(&QueueFencesListHead);\r\n\t\t\t\tInternal::InitializeListHead(&InFlightSyncPointsHead);\r\n\r\n\t\t\t\tResidencyManagerUniqueID = InterlockedIncrement64(&g_ResidencyManagerUniqueID);\r\n\t\t\t};\r\n\r\n\t\t\t// NOTE: DeviceNodeIndex is an index not a mask. The majority of D3D12 uses bit masks to identify a GPU node whereas DXGI uses 0 based indices.\r\n\t\t\tHRESULT Initialize(ID3D12Device* ParentDevice, UINT DeviceNodeIndex, IDXGIAdapter3* ParentAdapter, UINT32 MaxLatency)\r\n\t\t\t{\r\n\t\t\t\tDevice = ParentDevice;\r\n\t\t\t\tNodeIndex = DeviceNodeIndex;\r\n\t\t\t\tAdapter = ParentAdapter;\r\n\t\t\t\tMaxSoftwareQueueLatency = MaxLatency;\r\n\r\n\t\t\t\tAsyncWorkQueueSize = MaxLatency + 1;\r\n\t\t\t\tAsyncWorkQueue = new AsyncWorkload[AsyncWorkQueueSize];\r\n\r\n\t\t\t\tif (AsyncWorkQueue == nullptr)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn E_OUTOFMEMORY;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tLARGE_INTEGER Frequency;\r\n\t\t\t\tQueryPerformanceFrequency(&Frequency);\r\n\r\n\t\t\t\t// Calculate how many QPC ticks are equivalent to the given time in seconds\r\n\t\t\t\tMinEvictionGracePeriodTicks = UINT64(Frequency.QuadPart * cMinEvictionGracePeriod);\r\n\t\t\t\tMaxEvictionGracePeriodTicks = UINT64(Frequency.QuadPart * cMaxEvictionGracePeriod);\r\n\r\n\t\t\t\tHRESULT hr = S_OK;\r\n\t\t\t\thr = AsyncThreadFence.Initialize(Device);\r\n\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\tCompletionEvent = CreateEvent(nullptr, false, false, nullptr);\r\n\t\t\t\t\tif (CompletionEvent == INVALID_HANDLE_VALUE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thr = HRESULT_FROM_WIN32(GetLastError());\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\tAsyncThreadWorkCompletionEvent = CreateEvent(nullptr, false, false, nullptr);\r\n\t\t\t\t\tif (AsyncThreadWorkCompletionEvent == INVALID_HANDLE_VALUE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thr = HRESULT_FROM_WIN32(GetLastError());\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\tAsyncWorkEvent = CreateEvent(nullptr, true, false, nullptr);\r\n\t\t\t\t\tif (AsyncWorkEvent == INVALID_HANDLE_VALUE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thr = HRESULT_FROM_WIN32(GetLastError());\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n#if !RESIDENCY_SINGLE_THREADED\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\tAsyncWorkThread = CreateThread(nullptr, 0, AsyncThreadStart, (void*) this, 0, nullptr);\r\n\r\n\t\t\t\t\tif (AsyncWorkThread == INVALID_HANDLE_VALUE)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thr = HRESULT_FROM_WIN32(GetLastError());\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n#endif\r\n\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tvoid Destroy()\r\n\t\t\t{\r\n\t\t\t\tAsyncThreadFence.Destroy();\r\n\r\n\t\t\t\tif (CompletionEvent != INVALID_HANDLE_VALUE)\r\n\t\t\t\t{\r\n\t\t\t\t\tCloseHandle(CompletionEvent);\r\n\t\t\t\t\tCompletionEvent = INVALID_HANDLE_VALUE;\r\n\t\t\t\t}\r\n\r\n#if !RESIDENCY_SINGLE_THREADED\r\n\t\t\t\tAsyncWorkload* pWork = DequeueAsyncWork();\r\n\r\n\t\t\t\twhile (pWork)\r\n\t\t\t\t{\r\n\t\t\t\t\tpWork = DequeueAsyncWork();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tFinishAsyncWork = true;\r\n\t\t\t\tif (SetEvent(AsyncWorkEvent) == false)\r\n\t\t\t\t{\r\n\t\t\t\t\tRESIDENCY_CHECK_RESULT(HRESULT_FROM_WIN32(GetLastError()));\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Make sure the async worker thread is finished to prevent dereferencing\r\n\t\t\t\t// dangling pointers to ResidencyManagerInternal\r\n\t\t\t\tWaitForSingleObject(AsyncWorkThread, INFINITE);\r\n\t\t\t\tif (AsyncWorkThread != INVALID_HANDLE_VALUE)\r\n\t\t\t\t{\r\n\t\t\t\t\tCloseHandle(AsyncWorkThread);\r\n\t\t\t\t\tAsyncWorkThread = INVALID_HANDLE_VALUE;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (AsyncWorkEvent != INVALID_HANDLE_VALUE)\r\n\t\t\t\t{\r\n\t\t\t\t\tCloseHandle(AsyncWorkEvent);\r\n\t\t\t\t\tAsyncWorkEvent = INVALID_HANDLE_VALUE;\r\n\t\t\t\t}\r\n#endif\r\n\r\n\t\t\t\tif (AsyncThreadWorkCompletionEvent != INVALID_HANDLE_VALUE)\r\n\t\t\t\t{\r\n\t\t\t\t\tCloseHandle(AsyncThreadWorkCompletionEvent);\r\n\t\t\t\t\tAsyncThreadWorkCompletionEvent = INVALID_HANDLE_VALUE;\r\n\t\t\t\t}\r\n\r\n\t\t\t\twhile (Internal::IsListEmpty(&QueueFencesListHead) == false)\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::Fence* pObject =\r\n\t\t\t\t\t\tCONTAINING_RECORD(QueueFencesListHead.Flink, Internal::Fence, ListEntry);\r\n\r\n\t\t\t\t\tpObject->Destroy();\r\n\t\t\t\t\tInternal::RemoveHeadList(&QueueFencesListHead);\r\n\t\t\t\t\tdelete(pObject);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tvoid BeginTrackingObject(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tInternal::ScopedLock Lock(&Mutex);\r\n\r\n\t\t\t\tif (pObject)\r\n\t\t\t\t{\r\n\t\t\t\t\tRESIDENCY_CHECK(pObject->pUnderlying != nullptr);\r\n\t\t\t\t\tif (cStartEvicted)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpObject->ResidencyStatus = ManagedObject::RESIDENCY_STATUS::EVICTED;\r\n\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(Device->Evict(1, &pObject->pUnderlying));\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tLRU.Insert(pObject);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tvoid EndTrackingObject(ManagedObject* pObject)\r\n\t\t\t{\r\n\t\t\t\tInternal::ScopedLock Lock(&Mutex);\r\n\r\n\t\t\t\tLRU.Remove(pObject);\r\n\t\t\t}\r\n\r\n\t\t\t// One residency set per command-list\r\n\t\t\tHRESULT ExecuteCommandLists(ID3D12CommandQueue* Queue, ID3D12CommandList** CommandLists, ResidencySet** ResidencySets, UINT32 Count)\r\n\t\t\t{\r\n\t\t\t\treturn ExecuteSubset(Queue, CommandLists, ResidencySets, Count);\r\n\t\t\t}\r\n\r\n\t\t\tHRESULT GetCurrentGPUSyncPoint(ID3D12CommandQueue* Queue, UINT64 *pGPUSyncPoint)\r\n\t\t\t{\r\n\t\t\t\tInternal::Fence* QueueFence = nullptr;\r\n\t\t\t\tHRESULT hr = GetFence(Queue, QueueFence);\r\n\r\n\t\t\t\t// The signal and increment need to be atomic\r\n\t\t\t\tif(SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::ScopedLock Lock(&ExecutionCS);\r\n\t\t\t\t\t*pGPUSyncPoint = QueueFence->FenceValue;\r\n\t\t\t\t\thr = SignalFence(Queue, QueueFence);\r\n\t\t\t\t}\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\tprivate:\r\n\t\t\tHRESULT GetFence(ID3D12CommandQueue *Queue, Internal::Fence *&QueueFence)\r\n\t\t\t{\r\n\t\t\t\t// We have to track each object on each queue so we know when it is safe to evict them. Therefore, for every queue that we\r\n\t\t\t\t// see, associate a fence with it\r\n\t\t\t\tGUID FenceGuid = { 0xf0, 0, 0xd, { 0, 0, 0, 0, 0, 0, 0, 0 } };\r\n\r\n\t\t\t\t// Generate a GUID based on this queue\r\n\t\t\t\tmemcpy((void*)FenceGuid.Data4, Queue, sizeof(ID3D12CommandQueue*));\r\n\r\n\t\t\t\tQueueFence = nullptr;\r\n\t\t\t\tHRESULT hr = S_OK;\r\n\r\n\t\t\t\tstruct\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::Fence* pFence;\r\n\t\t\t\t\tINT64 ResidencyManagerUniqueID;\r\n\t\t\t\t} CommandQueuePrivateData;\r\n\r\n\t\t\t\t// Find or create the fence for this queue\r\n\t\t\t\t{\r\n\t\t\t\t\tUINT32 Size = sizeof(CommandQueuePrivateData);\r\n\t\t\t\t\thr = Queue->GetPrivateData(FenceGuid, &Size, &CommandQueuePrivateData);\r\n\t\t\t\t\tif (FAILED(hr) || ResidencyManagerUniqueID != CommandQueuePrivateData.ResidencyManagerUniqueID)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQueueFence = new Internal::Fence(1);\r\n\t\t\t\t\t\thr = QueueFence->Initialize(Device);\r\n\t\t\t\t\t\tInternal::InsertTailList(&QueueFencesListHead, &QueueFence->ListEntry);\r\n\r\n\t\t\t\t\t\tInterlockedIncrement(&NumQueuesSeen);\r\n\r\n\t\t\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tCommandQueuePrivateData = { QueueFence, ResidencyManagerUniqueID };\r\n\t\t\t\t\t\t\thr = Queue->SetPrivateData(FenceGuid, UINT32(sizeof(CommandQueuePrivateData)), &CommandQueuePrivateData);\r\n\t\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(hr);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tQueueFence = CommandQueuePrivateData.pFence;\r\n\t\t\t\t\tRESIDENCY_CHECK(QueueFence != nullptr);\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tHRESULT SignalFence(ID3D12CommandQueue *Queue, Internal::Fence *QueueFence)\r\n\t\t\t{\r\n\t\t\t\t// When this fence is passed it is safe to evict the resources used in the list just submitted\r\n\t\t\t\tHRESULT hr = QueueFence->GPUSignal(Queue);\r\n\t\t\t\tQueueFence->Increment();\r\n\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\thr = EnqueueSyncPoint();\r\n\t\t\t\t\tRESIDENCY_CHECK_RESULT(hr);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tCurrentSyncPointGeneration++;\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tHRESULT ExecuteSubset(ID3D12CommandQueue* Queue, ID3D12CommandList** CommandLists, ResidencySet** ResidencySets, UINT32 Count)\r\n\t\t\t{\r\n\t\t\t\tHRESULT hr = S_OK;\r\n\r\n\t\t\t\tDXGI_QUERY_VIDEO_MEMORY_INFO LocalMemory;\r\n\t\t\t\tZeroMemory(&LocalMemory, sizeof(LocalMemory));\r\n\t\t\t\tGetCurrentBudget(&LocalMemory, DXGI_MEMORY_SEGMENT_GROUP_LOCAL);\r\n\r\n\t\t\t\tDXGI_QUERY_VIDEO_MEMORY_INFO NonLocalMemory;\r\n\t\t\t\tZeroMemory(&NonLocalMemory, sizeof(NonLocalMemory));\r\n\t\t\t\tGetCurrentBudget(&NonLocalMemory, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL);\r\n\r\n\t\t\t\tUINT64 TotalSizeNeeded = 0;\r\n\r\n\t\t\t\tUINT32 MaxObjectsReferenced = 0;\r\n\t\t\t\tfor (UINT32 i = 0; i < Count; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (ResidencySets[i])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (ResidencySets[i]->IsOpen)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// Residency Sets must be closed before execution just like Command Lists\r\n\t\t\t\t\t\t\treturn E_INVALIDARG;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tMaxObjectsReferenced += ResidencySets[i]->CurrentSetSize;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Create a set to gather up all unique resources required by this call\r\n\t\t\t\tResidencySet* pMasterSet = new ResidencySet();\r\n\t\t\t\tif (pMasterSet == nullptr || pMasterSet->Initialize(pSyncManager, MaxObjectsReferenced) == false)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn E_OUTOFMEMORY;\r\n\t\t\t\t}\r\n\r\n\t\t\t\thr = pMasterSet->Open();\r\n\t\t\t\tif (FAILED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn hr;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// For each residency set\r\n\t\t\t\tfor (UINT32 i = 0; i < Count; i++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (ResidencySets[i])\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// For each object in this set\r\n\t\t\t\t\t\tfor (INT32 x = 0; x < ResidencySets[i]->CurrentSetSize; x++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif (pMasterSet->Insert(ResidencySets[i]->ppSet[x]))\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tTotalSizeNeeded += ResidencySets[i]->ppSet[x]->Size;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// Close this set to free it's slot up for the app\r\n\t\t\t\thr = pMasterSet->Close();\r\n\t\t\t\tif (FAILED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\treturn hr;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// This set of commandlists can't possibly fit within the budget, they need to be split up. If the number of command lists is 1 there is\r\n\t\t\t\t// nothing we can do\r\n\t\t\t\tif (Count > 1 && TotalSizeNeeded > LocalMemory.Budget + NonLocalMemory.Budget)\r\n\t\t\t\t{\r\n\t\t\t\t\tdelete(pMasterSet);\r\n\r\n\t\t\t\t\t// Recursively try to find a small enough set to fit in memory\r\n\t\t\t\t\tconst UINT32 Half = Count / 2;\r\n\t\t\t\t\tconst HRESULT LowerHR = ExecuteSubset(Queue, CommandLists, ResidencySets, Half);\r\n\t\t\t\t\tconst HRESULT UpperHR = ExecuteSubset(Queue, &CommandLists[Half], &ResidencySets[Half], Count - Half);\r\n\r\n\t\t\t\t\treturn (LowerHR == S_OK && UpperHR == S_OK) ? S_OK : E_FAIL;\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tInternal::Fence* QueueFence = nullptr;\r\n\t\t\t\thr = GetFence(Queue, QueueFence);\r\n\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\t// The following code must be atomic so that things get ordered correctly\r\n\r\n\t\t\t\t\tInternal::ScopedLock Lock(&ExecutionCS);\r\n\t\t\t\t\t// Evict or make resident all of the objects we identified above.\r\n\t\t\t\t\t// This will run on an async thread, allowing the current to continue while still blocking the GPU if required\r\n\t\t\t\t\thr = EnqueueAsyncWork(pMasterSet, AsyncThreadFence.FenceValue, CurrentSyncPointGeneration);\r\n#if RESIDENCY_SINGLE_THREADED\r\n\t\t\t\t\tAsyncWorkload* pWorkload = DequeueAsyncWork();\r\n\t\t\t\t\tProcessPagingWork(pWorkload);\r\n#endif\r\n\r\n\t\t\t\t\t// If there are some things that need to be made resident we need to make sure that the GPU\r\n\t\t\t\t\t// doesn't execute until the async thread signals that the MakeResident call has returned.\r\n\t\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thr = AsyncThreadFence.GPUWait(Queue);\r\n\t\t\t\t\t\tAsyncThreadFence.Increment();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tQueue->ExecuteCommandLists(Count, CommandLists);\r\n\r\n\t\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thr = SignalFence(Queue, QueueFence);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tstruct AsyncWorkload\r\n\t\t\t{\r\n\t\t\t\tAsyncWorkload() :\r\n\t\t\t\t\tpMasterSet(nullptr),\r\n\t\t\t\t\tFenceValueToSignal(0),\r\n\t\t\t\t\tSyncPointGeneration(0)\r\n\t\t\t\t{}\r\n\r\n\t\t\t\tUINT64 SyncPointGeneration;\r\n\r\n\t\t\t\t// List of objects to make resident\r\n\t\t\t\tResidencySet* pMasterSet;\r\n\r\n\t\t\t\t// The GPU will wait on this value so that it doesn't execute until the objects are made resident\r\n\t\t\t\tUINT64 FenceValueToSignal;\r\n\t\t\t};\r\n\r\n\t\t\tSIZE_T AsyncWorkQueueSize;\r\n\t\t\tAsyncWorkload* AsyncWorkQueue;\r\n\r\n\t\t\tHANDLE AsyncWorkEvent;\r\n\t\t\tHANDLE AsyncWorkThread;\r\n\t\t\tInternal::CriticalSection AsyncWorkMutex;\r\n\t\t\tvolatile bool FinishAsyncWork;\r\n\t\t\tvolatile SIZE_T CurrentAsyncWorkloadHead;\r\n\t\t\tvolatile SIZE_T CurrentAsyncWorkloadTail;\r\n\r\n\t\t\tstatic unsigned long WINAPI AsyncThreadStart(void* pData)\r\n\t\t\t{\r\n\t\t\t\tResidencyManagerInternal* pManager = (ResidencyManagerInternal*)pData;\r\n\r\n\t\t\t\twhile (1)\r\n\t\t\t\t{\r\n\t\t\t\t\tAsyncWorkload* pWork = pManager->DequeueAsyncWork();\r\n\r\n\t\t\t\t\twhile (pWork)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Submit the work\r\n\t\t\t\t\t\tpManager->ProcessPagingWork(pWork);\r\n\t\t\t\t\t\tif (SetEvent(pManager->AsyncThreadWorkCompletionEvent) == false)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(HRESULT_FROM_WIN32(GetLastError()));\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Get more work\r\n\t\t\t\t\t\tpWork = pManager->DequeueAsyncWork();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//Wait until there is more work do be done\r\n\t\t\t\t\tWaitForSingleObject(pManager->AsyncWorkEvent, INFINITE);\r\n\t\t\t\t\tif (ResetEvent(pManager->AsyncWorkEvent) == false)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(HRESULT_FROM_WIN32(GetLastError()));\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (pManager->FinishAsyncWork)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\r\n\t\t\t// This will be run from a worker thread and will emulate a software queue for making gpu resources resident or evicted.\r\n\t\t\t// The GPU will be synchronized by this queue to ensure that it never executes using an evicted resource.\r\n\t\t\tvoid ProcessPagingWork(AsyncWorkload* pWork)\r\n\t\t\t{\r\n\t\t\t\tInternal::DeviceWideSyncPoint* FirstUncompletedSyncPoint = DequeueCompletedSyncPoints();\r\n\r\n\t\t\t\t// Use a union so that we only need 1 allocation\r\n\t\t\t\tunion ResidentScratchSpace\r\n\t\t\t\t{\r\n\t\t\t\t\tManagedObject* pManagedObject;\r\n\t\t\t\t\tID3D12Pageable* pUnderlying;\r\n\t\t\t\t};\r\n\r\n\t\t\t\tResidentScratchSpace* pMakeResidentList = nullptr;\r\n\t\t\t\tUINT32 NumObjectsToMakeResident = 0;\r\n\r\n\t\t\t\tID3D12Pageable** pEvictionList = nullptr;\r\n\t\t\t\tUINT32 NumObjectsToEvict = 0;\r\n\r\n\t\t\t\t// the size of all the objects which will need to be made resident in order to execute this set.\r\n\t\t\t\tUINT64 SizeToMakeResident = 0;\r\n\r\n\t\t\t\tLARGE_INTEGER CurrentTime;\r\n\t\t\t\tQueryPerformanceCounter(&CurrentTime);\r\n\r\n\t\t\t\t{\r\n\t\t\t\t\t// A lock must be taken here as the state of the objects will be altered\r\n\t\t\t\t\tInternal::ScopedLock Lock(&Mutex);\r\n\r\n\t\t\t\t\tpMakeResidentList = new ResidentScratchSpace[pWork->pMasterSet->CurrentSetSize];\r\n\t\t\t\t\tpEvictionList = new ID3D12Pageable*[LRU.NumResidentObjects];\r\n\r\n\t\t\t\t\t// Mark the objects used by this command list to be made resident\r\n\t\t\t\t\tfor (INT32 i = 0; i < pWork->pMasterSet->CurrentSetSize; i++)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tManagedObject*& pObject = pWork->pMasterSet->ppSet[i];\r\n\t\t\t\t\t\t// If it's evicted we need to make it resident again\r\n\t\t\t\t\t\tif (pObject->ResidencyStatus == ManagedObject::RESIDENCY_STATUS::EVICTED)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpMakeResidentList[NumObjectsToMakeResident++].pManagedObject = pObject;\r\n\t\t\t\t\t\t\tLRU.MakeResident(pObject);\r\n\r\n\t\t\t\t\t\t\tSizeToMakeResident += pObject->Size;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Update the last sync point that this was used on\r\n\t\t\t\t\t\tpObject->LastGPUSyncPoint = pWork->SyncPointGeneration;\r\n\r\n\t\t\t\t\t\tpObject->LastUsedTimestamp = CurrentTime.QuadPart;\r\n\t\t\t\t\t\tLRU.ObjectReferenced(pObject);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tDXGI_QUERY_VIDEO_MEMORY_INFO LocalMemory;\r\n\t\t\t\t\tZeroMemory(&LocalMemory, sizeof(LocalMemory));\r\n\t\t\t\t\tGetCurrentBudget(&LocalMemory, DXGI_MEMORY_SEGMENT_GROUP_LOCAL);\r\n\r\n\t\t\t\t\tUINT64 EvictionGracePeriod = GetCurrentEvictionGracePeriod(&LocalMemory);\r\n\t\t\t\t\tLRU.TrimAgedAllocations(FirstUncompletedSyncPoint, pEvictionList, NumObjectsToEvict, CurrentTime.QuadPart, EvictionGracePeriod);\r\n\r\n\t\t\t\t\tif (NumObjectsToEvict)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(Device->Evict(NumObjectsToEvict, pEvictionList));\r\n\t\t\t\t\t\tNumObjectsToEvict = 0;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (NumObjectsToMakeResident)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tUINT32 ObjectsMadeResident = 0;\r\n\t\t\t\t\t\tUINT32 MakeResidentIndex = 0;\r\n\t\t\t\t\t\twhile (true)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tZeroMemory(&LocalMemory, sizeof(LocalMemory));\r\n\r\n\t\t\t\t\t\t\tGetCurrentBudget(&LocalMemory, DXGI_MEMORY_SEGMENT_GROUP_LOCAL);\r\n\t\t\t\t\t\t\tDXGI_QUERY_VIDEO_MEMORY_INFO NonLocalMemory;\r\n\t\t\t\t\t\t\tZeroMemory(&NonLocalMemory, sizeof(NonLocalMemory));\r\n\t\t\t\t\t\t\tGetCurrentBudget(&NonLocalMemory, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL);\r\n\r\n\t\t\t\t\t\t\tINT64 TotalUsage = LocalMemory.CurrentUsage + NonLocalMemory.CurrentUsage;\r\n\t\t\t\t\t\t\tINT64 TotalBudget = LocalMemory.Budget + NonLocalMemory.Budget;\r\n\r\n\t\t\t\t\t\t\tINT64 AvailableSpace = TotalBudget - TotalUsage;\r\n\r\n\t\t\t\t\t\t\tUINT64 BatchSize = 0;\r\n\t\t\t\t\t\t\tUINT32 NumObjectsInBatch = 0;\r\n\t\t\t\t\t\t\tUINT32 BatchStart = MakeResidentIndex;\r\n\r\n\t\t\t\t\t\t\tHRESULT hr = S_OK;\r\n\t\t\t\t\t\t\tif (AvailableSpace > 0)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tfor (UINT32 i = MakeResidentIndex; i < NumObjectsToMakeResident; i++)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// If we try to make this object resident, will we go over budget?\r\n\t\t\t\t\t\t\t\t\tif (BatchSize + pMakeResidentList[i].pManagedObject->Size > UINT64(AvailableSpace))\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t// Next time we will start here\r\n\t\t\t\t\t\t\t\t\t\tMakeResidentIndex = i;\r\n\t\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tBatchSize += pMakeResidentList[i].pManagedObject->Size;\r\n\t\t\t\t\t\t\t\t\t\tNumObjectsInBatch++;\r\n\t\t\t\t\t\t\t\t\t\tObjectsMadeResident++;\r\n\r\n\t\t\t\t\t\t\t\t\t\tpMakeResidentList[i].pUnderlying = pMakeResidentList[i].pManagedObject->pUnderlying;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\thr = Device->MakeResident(NumObjectsInBatch, &pMakeResidentList[BatchStart].pUnderlying);\r\n\t\t\t\t\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tSizeToMakeResident -= BatchSize;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif (FAILED(hr) || ObjectsMadeResident != NumObjectsToMakeResident)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tManagedObject* pResidentHead = LRU.GetResidentListHead();\r\n\r\n\t\t\t\t\t\t\t\t// Get the next sync point to wait for\r\n\t\t\t\t\t\t\t\tFirstUncompletedSyncPoint = DequeueCompletedSyncPoints();\r\n\r\n\t\t\t\t\t\t\t\t// If there is nothing to trim OR the only objects 'Resident' are the ones about to be used by this execute.\r\n\t\t\t\t\t\t\t\tif (pResidentHead == nullptr ||\r\n\t\t\t\t\t\t\t\t\tpResidentHead->LastGPUSyncPoint >= pWork->SyncPointGeneration ||\r\n\t\t\t\t\t\t\t\t\tFirstUncompletedSyncPoint == nullptr)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Make resident the rest of the objects as there is nothing left to trim\r\n\t\t\t\t\t\t\t\t\tUINT32 NumObjects = NumObjectsToMakeResident - ObjectsMadeResident;\r\n\r\n\t\t\t\t\t\t\t\t\t// Gather up the remaining underlying objects\r\n\t\t\t\t\t\t\t\t\tfor (UINT32 i = MakeResidentIndex; i < NumObjectsToMakeResident; i++)\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tpMakeResidentList[i].pUnderlying = pMakeResidentList[i].pManagedObject->pUnderlying;\r\n\t\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\t\thr = Device->MakeResident(NumObjects, &pMakeResidentList[MakeResidentIndex].pUnderlying);\r\n\t\t\t\t\t\t\t\t\tif (FAILED(hr))\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t// TODO: What should we do if this fails? This is a catastrophic failure in which the app is trying to use more memory\r\n\t\t\t\t\t\t\t\t\t\t//       in 1 command list than can possibly be made resident by the system.\r\n\t\t\t\t\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(hr);\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tUINT64 GenerationToWaitFor = FirstUncompletedSyncPoint->GenerationID;\r\n\r\n\t\t\t\t\t\t\t\t// We can't wait for the sync-point that this work is intended for\r\n\t\t\t\t\t\t\t\tif (GenerationToWaitFor == pWork->SyncPointGeneration)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tRESIDENCY_CHECK(GenerationToWaitFor >= 0);\r\n\t\t\t\t\t\t\t\t\tGenerationToWaitFor -= 1;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t// Wait until the GPU is done\r\n\t\t\t\t\t\t\t\tWaitForSyncPoint(GenerationToWaitFor);\r\n\r\n\t\t\t\t\t\t\t\tLRU.TrimToSyncPointInclusive(TotalUsage + INT64(SizeToMakeResident), TotalBudget, pEvictionList, NumObjectsToEvict, GenerationToWaitFor);\r\n\r\n\t\t\t\t\t\t\t\tRESIDENCY_CHECK_RESULT(Device->Evict(NumObjectsToEvict, pEvictionList));\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// We made everything resident, mission accomplished\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tdelete[](pMakeResidentList);\r\n\t\t\t\t\tdelete[](pEvictionList);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Tell the GPU that it's safe to execute since we made things resident\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(AsyncThreadFence.pFence->Signal(pWork->FenceValueToSignal));\r\n\r\n\t\t\t\tdelete(pWork->pMasterSet);\r\n\t\t\t\tpWork->pMasterSet = nullptr;\r\n\t\t\t}\r\n\t\t\t// The Enqueue and Dequeue Async Work functions are threadsafe as there is only 1 producer and 1 consumer, if that changes\r\n\t\t\t// Synchronisation will be required\r\n\t\t\tHRESULT EnqueueAsyncWork(ResidencySet* pMasterSet, UINT64 FenceValueToSignal, UINT64 SyncPointGeneration)\r\n\t\t\t{\r\n\t\t\t\t// We can't get too far ahead of the worker thread otherwise huge hitches occur\r\n\t\t\t\twhile ((CurrentAsyncWorkloadTail - CurrentAsyncWorkloadHead) >= MaxSoftwareQueueLatency)\r\n\t\t\t\t{\r\n\t\t\t\t\tWaitForSingleObject(AsyncThreadWorkCompletionEvent, INFINITE);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tRESIDENCY_CHECK(CurrentAsyncWorkloadTail >= CurrentAsyncWorkloadHead);\r\n\r\n\t\t\t\tconst SIZE_T currentIndex = CurrentAsyncWorkloadTail % AsyncWorkQueueSize;\r\n\t\t\t\tAsyncWorkQueue[currentIndex].pMasterSet = pMasterSet;\r\n\t\t\t\tAsyncWorkQueue[currentIndex].FenceValueToSignal = FenceValueToSignal;\r\n\t\t\t\tAsyncWorkQueue[currentIndex].SyncPointGeneration = SyncPointGeneration;\r\n\r\n\t\t\t\tCurrentAsyncWorkloadTail++;\r\n\t\t\t\tif (SetEvent(AsyncWorkEvent) == false)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn S_OK;\r\n\t\t\t}\r\n\r\n\t\t\tAsyncWorkload* DequeueAsyncWork()\r\n\t\t\t{\r\n\t\t\t\tif (CurrentAsyncWorkloadHead == CurrentAsyncWorkloadTail)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn nullptr;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst SIZE_T currentHead = CurrentAsyncWorkloadHead % AsyncWorkQueueSize;\r\n\t\t\t\tAsyncWorkload* pWork = &AsyncWorkQueue[currentHead];\r\n\r\n\t\t\t\tCurrentAsyncWorkloadHead++;\r\n\t\t\t\treturn pWork;\r\n\t\t\t}\r\n\r\n\t\t\tvoid GetCurrentBudget(DXGI_QUERY_VIDEO_MEMORY_INFO* InfoOut, DXGI_MEMORY_SEGMENT_GROUP Segment)\r\n\t\t\t{\r\n\t\t\t\tRESIDENCY_CHECK_RESULT(Adapter->QueryVideoMemoryInfo(NodeIndex, Segment, InfoOut));\r\n\t\t\t}\r\n\r\n\t\t\tHRESULT EnqueueSyncPoint()\r\n\t\t\t{\r\n\t\t\t\tInternal::ScopedLock Lock(&AsyncWorkMutex);\r\n\r\n\t\t\t\tInternal::DeviceWideSyncPoint* pPoint = Internal::DeviceWideSyncPoint::CreateSyncPoint(NumQueuesSeen, CurrentSyncPointGeneration);\r\n\t\t\t\tif (pPoint == nullptr)\r\n\t\t\t\t{\r\n\t\t\t\t\treturn E_OUTOFMEMORY;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tUINT32 i = 0;\r\n\t\t\t\tLIST_ENTRY* pFenceEntry = QueueFencesListHead.Flink;\r\n\t\t\t\t// Record the current state of each queue we track into this sync point\r\n\t\t\t\twhile (pFenceEntry != &QueueFencesListHead)\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::Fence* pFence = CONTAINING_RECORD(pFenceEntry, Internal::Fence, ListEntry);\r\n\t\t\t\t\tpFenceEntry = pFenceEntry->Flink;\r\n\r\n\t\t\t\t\tpPoint->pQueueSyncPoints[i].pFence = pFence;\r\n\t\t\t\t\tpPoint->pQueueSyncPoints[i].LastUsedValue = pFence->FenceValue - 1;//Minus one as we want the last submitted\r\n\r\n\t\t\t\t\ti++;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tInternal::InsertTailList(&InFlightSyncPointsHead, &pPoint->ListEntry);\r\n\r\n\t\t\t\treturn S_OK;\r\n\t\t\t}\r\n\r\n\t\t\t// Returns a pointer to the first synch point which is not completed\r\n\t\t\tInternal::DeviceWideSyncPoint* DequeueCompletedSyncPoints()\r\n\t\t\t{\r\n\t\t\t\tInternal::ScopedLock Lock(&AsyncWorkMutex);\r\n\r\n\t\t\t\twhile (Internal::IsListEmpty(&InFlightSyncPointsHead) == false)\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::DeviceWideSyncPoint* pPoint =\r\n\t\t\t\t\t\tCONTAINING_RECORD(InFlightSyncPointsHead.Flink, Internal::DeviceWideSyncPoint, ListEntry);\r\n\r\n\t\t\t\t\tif (pPoint->IsCompleted())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tInternal::RemoveHeadList(&InFlightSyncPointsHead);\r\n\t\t\t\t\t\tdelete pPoint;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn pPoint;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn nullptr;\r\n\t\t\t}\r\n\r\n\t\t\tvoid WaitForSyncPoint(UINT64 SyncPointID)\r\n\t\t\t{\r\n\t\t\t\tInternal::ScopedLock Lock(&AsyncWorkMutex);\r\n\r\n\t\t\t\tLIST_ENTRY* pPointEntry = InFlightSyncPointsHead.Flink;\r\n\t\t\t\twhile (pPointEntry != &InFlightSyncPointsHead)\r\n\t\t\t\t{\r\n\t\t\t\t\tInternal::DeviceWideSyncPoint* pPoint =\r\n\t\t\t\t\t\tCONTAINING_RECORD(InFlightSyncPointsHead.Flink, Internal::DeviceWideSyncPoint, ListEntry);\r\n\r\n\t\t\t\t\tif (pPoint->GenerationID > SyncPointID)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// this point is already done\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (pPoint->GenerationID < SyncPointID)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Keep popping off until we find the one to wait on\r\n\t\t\t\t\t\tInternal::RemoveHeadList(&InFlightSyncPointsHead);\r\n\t\t\t\t\t\tdelete(pPoint);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tpPoint->WaitForCompletion(CompletionEvent);\r\n\t\t\t\t\t\tInternal::RemoveHeadList(&InFlightSyncPointsHead);\r\n\t\t\t\t\t\tdelete(pPoint);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Generate a result between the minimum period and the maximum period based on the current\r\n\t\t\t// local memory pressure. I.e. when memory pressure is low, objects will persist longer before\r\n\t\t\t// being evicted.\r\n\t\t\tUINT64 GetCurrentEvictionGracePeriod(DXGI_QUERY_VIDEO_MEMORY_INFO* LocalMemoryState)\r\n\t\t\t{\r\n\t\t\t\t// 1 == full pressure, 0 == no pressure\r\n\t\t\t\tdouble Pressure = (double(LocalMemoryState->CurrentUsage) / double(LocalMemoryState->Budget));\r\n\t\t\t\tPressure = RESIDENCY_MIN(Pressure, 1.0);\r\n\r\n\t\t\t\tif (Pressure > cTrimPercentageMemoryUsageThreshold)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Normalize the pressure for the range 0 to cTrimPercentageMemoryUsageThreshold\r\n\t\t\t\t\tPressure = (Pressure - cTrimPercentageMemoryUsageThreshold) / (1.0 - cTrimPercentageMemoryUsageThreshold);\r\n\r\n\t\t\t\t\t// Linearly interpolate between the min period and the max period based on the pressure\r\n\t\t\t\t\treturn UINT64((MaxEvictionGracePeriodTicks - MinEvictionGracePeriodTicks) * (1.0 - Pressure)) + MinEvictionGracePeriodTicks;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Essentially don't trim at all\r\n\t\t\t\t\treturn MAXUINT64;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tLIST_ENTRY QueueFencesListHead;\r\n\t\t\tUINT32 NumQueuesSeen;\r\n\t\t\tInternal::Fence AsyncThreadFence;\r\n\r\n\t\t\tLIST_ENTRY InFlightSyncPointsHead;\r\n\t\t\tUINT64 CurrentSyncPointGeneration;\r\n\r\n\t\t\tHANDLE CompletionEvent;\r\n\t\t\tHANDLE AsyncThreadWorkCompletionEvent;\r\n\r\n\t\t\tID3D12Device* Device;\r\n\t\t\t// NOTE: This is an index not a mask. The majority of D3D12 uses bit masks to identify a GPU node whereas DXGI uses 0 based indices.\r\n\t\t\tUINT NodeIndex;\r\n\t\t\tIDXGIAdapter3* Adapter;\r\n\t\t\tInternal::LRUCache LRU;\r\n\r\n\t\t\tInternal::CriticalSection Mutex;\r\n\r\n\t\t\tInternal::CriticalSection ExecutionCS;\r\n\r\n\t\t\tconst bool cStartEvicted;\r\n\r\n\t\t\tconst float cMinEvictionGracePeriod;\r\n\t\t\tUINT64 MinEvictionGracePeriodTicks;\r\n\t\t\tconst float cMaxEvictionGracePeriod;\r\n\t\t\tUINT64 MaxEvictionGracePeriodTicks;\r\n\t\t\t// When the app is using more than this % of its budgeted local VidMem trimming will occur\r\n\t\t\t// (valid between 0.0 - 1.0)\r\n\t\t\tconst float cTrimPercentageMemoryUsageThreshold;\r\n\r\n\t\t\tUINT32 MaxSoftwareQueueLatency;\r\n\t\t\tINT64 ResidencyManagerUniqueID;\r\n\r\n\t\t\tSyncManager* pSyncManager;\r\n\t\t};\r\n\t}\r\n\r\n\tclass ResidencyManager\r\n\t{\r\n\tpublic:\r\n\t\tResidencyManager() :\r\n\t\t\tManager(&SyncManager)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\t// NOTE: DeviceNodeIndex is an index not a mask. The majority of D3D12 uses bit masks to identify a GPU node whereas DXGI uses 0 based indices.\r\n\t\tFORCEINLINE HRESULT Initialize(ID3D12Device* ParentDevice, UINT DeviceNodeIndex, IDXGIAdapter3* ParentAdapter, UINT32 MaxLatency)\r\n\t\t{\r\n\t\t\treturn Manager.Initialize(ParentDevice, DeviceNodeIndex, ParentAdapter, MaxLatency);\r\n\t\t}\r\n\r\n\t\tFORCEINLINE void Destroy()\r\n\t\t{\r\n\t\t\tManager.Destroy();\r\n\t\t}\r\n\r\n\t\tFORCEINLINE void BeginTrackingObject(ManagedObject* pObject)\r\n\t\t{\r\n\t\t\tManager.BeginTrackingObject(pObject);\r\n\t\t}\r\n\r\n\t\tFORCEINLINE void EndTrackingObject(ManagedObject* pObject)\r\n\t\t{\r\n\t\t\tManager.EndTrackingObject(pObject);\r\n\t\t}\r\n\r\n\t\tHRESULT GetCurrentGPUSyncPoint(ID3D12CommandQueue* Queue, UINT64 *pCurrentGPUSyncPoint)\r\n\t\t{\r\n\t\t\treturn Manager.GetCurrentGPUSyncPoint(Queue, pCurrentGPUSyncPoint);\r\n\t\t}\r\n\r\n\t\t// One residency set per command-list\r\n\t\tFORCEINLINE HRESULT ExecuteCommandLists(ID3D12CommandQueue* Queue, ID3D12CommandList** CommandLists, ResidencySet** ResidencySets, UINT32 Count)\r\n\t\t{\r\n\t\t\treturn Manager.ExecuteCommandLists(Queue, CommandLists, ResidencySets, Count);\r\n\t\t}\r\n\r\n\t\tFORCEINLINE ResidencySet* CreateResidencySet()\r\n\t\t{\r\n\t\t\tResidencySet* pSet = new ResidencySet();\r\n\r\n\t\t\tif (pSet)\r\n\t\t\t{\r\n\t\t\t\tpSet->Initialize(&SyncManager);\r\n\t\t\t}\r\n\t\t\treturn pSet;\r\n\t\t}\r\n\r\n\t\tFORCEINLINE void DestroyResidencySet(ResidencySet* pSet)\r\n\t\t{\r\n\t\t\tdelete(pSet);\r\n\t\t}\r\n\r\n\tprivate:\r\n\t\tInternal::ResidencyManagerInternal Manager;\r\n\t\tInternal::SyncManager SyncManager;\r\n\t};\r\n};\r\n"
  },
  {
    "path": "Libraries/D3DX12Residency/readme.md",
    "content": "# The D3D12 Residency Starter Library\n\n## What is this library?\nThis library is intended to be a low-integration-cost turnkey solution to managing your D3D12 heaps/committed resources to reduce the chance that you will get into an overcommitted video memory situation as well as ensure your performance remains as good as it can be when you do end up in that situation.\n\nIt implements essentially the same memory management behavior that a D3D11 app would get from the layers below the API.  In D3D12, the layers below the API cannot do this for you on account of the more flexible API, more direct access to memory, and bindless architecture.  That's where this residency library comes in.\n\nThe library should be seen as a stepping stone for D3D12 apps to get good performance when under memory pressure while leaving the door very open for apps to make optimizations that beat D3D11-style memory management algorithms.\n\n## What happens if I don't manage memory (using this library or otherwise)?\nWithout this library or any other sort of memory management, there is a real and significant GPU performance hit when your app uses more memory than is available.  This is most noticeable on low memory (1GB/2GB) boards but can easily happen on 4GB cards as well (e.g. 4k, ultra settings, etc).  The OS's Video Memory Manager (VidMM) will do its absolute best to ensure your application can always make forward progress but any contingencies that VidMM has to use to keep your app running often come with a performance hit.  It is critical that applications manage their memory instead of relying on VidMM to make general case decisions which will invariably be non-optimal.\n\nWith D3D12, you have the responsibility of managing your memory but also the power to do even better than D3D11.  We built this library so that you can maintain D3D11 perf parity first leaving you with time to focus on the customizations that will make your D3D12 game better than it could have been in D3D11.\n\n## Exactly what problem does the library try to solve?\nThere are two main memory related problems both of which contribute to GPU perf regressions relative to D3D11:\n\n1. Using too much memory overall\n2. Not managing the D3D12 heaps you've created (e.g. not getting rid of heaps you aren't using either by destruction or eviction).\n\nThe residency library is explicitly designed to address the second problem.\n\nIt is important to note that apps must account for all of the memory they are using and ensure that they aren't using more memory than D3D11 overall.  No amount of management can overcome a fundamental over-usage of memory.\n\n## How does it solve the management part of the problem?\nThe primary piece of information that the layers below the API would have in D3D11 apps is when a texture/buffer/etc is needed for rendering.  More direct control over memory and a bindless architecture in D3D12 mean that the same information is not directly available through the API.\n\nWith this information, anything that hasn't been used in a while could be evicted (D3D11 had a concept of eviction as well, only it was hidden from the application).  Anything that was needed to render would be made resident (also hidden from the application).\n\nFrom this, you can infer that in order for a D3D12 application to achieve the same behavior as a D3D11 app, the application's memory manager component would need to satisfy these responsibilities (at minimum):\n\n* Know when D3D12 heaps need to be resident (e.g. when they're about to be used)\n* Synchronize correctly so that rendering cannot happen until these heaps are made resident\n* Track when heaps are in use on the GPU so that they can be evicted only when the GPU is done with them\n\nThe library provides interfaces to indicate when a resource is going to be used for rendering and handles all of the ```MakeResident```/```Evict``` calls as well as all the required synchronization.\n\n## Alright, how do I use it?\nHere are the high level steps for using the library:\n\n1. Create a ```D3DX12Residency::ResidencyManager```\n2. Create a ```D3DX12Residency::ManagedObject``` for every heap/committed resource you want the library to manage\n  1. The library works by tracking/evicting/making resident the ```ManagedObject's``` underlying heap/committed resource\n3. Use ```ResidencyManager::BeginTrackingObject``` to start managing each ```ManagedObject```\n4. Use a ```D3DX12Residency::ResidencySet``` to track which heaps will be used in a particular command list (it will be a 1:1 relationship)\n  1. It's essentially a list of ```ManagedObjects``` which will need to be resident when a command list executes\n5. Use ```ResidencyManager::ExecuteCommandLists``` to execute the workload which takes a command queue, array of command lists, an array of residency sets, and a count\n  1. This will execute the command lists and ensure all of the heaps/committed resources that you need to execute are resident at the right times\n\n### FAQs\n\n#### What exactly is Residency?\nResidency correlates to whether a heap is accessible by the GPU or not.  If it is not resident, you should not be touching that resource (neither read nor write).  A resident resource can be used by the GPU.  The ```MakeResident``` and ```Evict``` calls are what controls whether a heap is resident or not.\n\n#### What does calling ```Evict``` do?\n```Evict``` is essentially a promise that you will not touch the heap until you call ```MakeResident``` again at which point you also promise to wait until ```MakeResident``` returns to start using that heap.  It means that VidMM (Video Memory Manager) can repurpose that memory (eg. for another app) if the system is under memory pressure and it needs it.\n\nNote that when you call ```Evict```, the heap is only marked for eviction.  VidMM will try really hard not to evict it if it doesn't need to thereby making the subsequent ```MakeResident``` call (when you call it) a no-op (ie. nothing needs to happen and your heap is ready for use almost immediately).\n\n#### What does calling ```MakeResident``` do?\n```MakeResident``` is a blocking call which will bring your heap data and page table mappings back as they were before you called Evict.  You don't need to copy the data back in.\n\n#### Why would I use ```MakeResident``` and ```Evict```?\nIn return for using ```MakeResident``` and ```Evict```, VidMM promises to return the data and page table mappings back to their original state before you called ```Evict``` as well as try its hardest to not actually evict anything if it nothing else needs that memory.  In many cases, this is better than destroying the heap/committed resource in which case you would need to recreate the heap/committed resource, re-copy the data into an upload heap, and execute a GPU copy before making it available again to the renderer.  The chance for ```MakeResident``` to be a no-op also improves the average case performance when compared to a destruction/recreation/repopulating technique.\n\n### Other Library FAQs\n\n#### What is the ```MaxLatency``` parameter in the ResidencyManager's ```Initialize``` method?\nWhen rendering very quickly, it is possible for the renderer to get too far ahead of the library's worker thread.  The ```MaxLatency``` parameter helps to limit how far ahead it can get.  The value should essentially be the average ```NumberOfBufferedFrames * NumberOfCommandListSubmissionsPerFrame``` throughout the execution of your app.\n\n#### The Visual Studio Graphics Debugging (VSGD) tools crash when capturing an app that uses this library\nYou can work around this bug by using the library's single threaded mode using the line:\n```\n#define RESIDENCY_SINGLE_THREADED 0\n```\n0 is the default; change it to 1 to force single threaded behavior to work around the issue.\n"
  },
  {
    "path": "MiniEngine/.gitignore",
    "content": "*.user\n*.suo\n*.VC.db*\n*.shader_inc\n*.vspscc\n*.opensdf\n*.sdf\n*.ipch\n*.cache\n*.tlog\n*.lastbuildstate\n*.ilk\n*.log\n* - Copy*.*\nBuild_VS11\nBuild_VS12\nBuild_VS14\nBuild_VS15\nBuild_VS17\nPackages\n/ModelConverter/assimp.dll\nPackages"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/AnimatedValue.cpp",
    "content": "#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\n#include \"AnimatedValue.inl\"\r\n\r\n#include <algorithm>\r\n\r\nnamespace ART {\r\n\r\n\t//////////////////////////////////////////////////////////////////////////\r\n\t// AnimatedValueBase\r\n\r\n\tvoid AnimatedValueBase::SetCatRomTension(float value) {\r\n\t\t// We also pre-compute the C-R coefficients\r\n\t\t_tension = value;\r\n\t\t_interpolationValid = false;\r\n\r\n\t\tfloat tau = value;\r\n\t\t\r\n\t\t_CatRomCoefficients[0] = Math::Vector4(0.0f, -tau, 2.0f * tau, -tau);\r\n\t\t_CatRomCoefficients[1] = Math::Vector4(1.0f, 0.0f, tau - 3.0f, 2.0f - tau);\r\n\t\t_CatRomCoefficients[2] = Math::Vector4(0.0f, tau, 3.0f - 2.0f * tau, tau - 2.0f);\r\n\t\t_CatRomCoefficients[3] = Math::Vector4(0.0f, 0.0f, -tau, tau);\r\n\t}\r\n\r\n\tfloat AnimatedValueBase::GetKeyframeTime(size_t idx) const {\r\n\t\tART_ASSERT(idx < _keyframeTimes.size());\r\n\t\treturn _keyframeTimes[idx];\r\n\t}\r\n\r\n\tvoid AnimatedValueBase::SetKeyframeTime(size_t idx, float time) {\r\n\t\tART_ASSERT(idx < _keyframeTimes.size());\r\n\t\t_keyframeTimes[idx] = time;\r\n\t\t_interpolationValid = false;\r\n\t}\r\n\r\n\tfloat AnimatedValueBase::GetStartOffset() const {\r\n\t\tif (_keyframeTimes.size() > 0) return _keyframeTimes[0];\r\n\t\treturn 0.0f;\r\n\t}\r\n\r\n\tfloat AnimatedValueBase::GetDuration() const {\r\n\t\tif (_keyframeTimes.size() < 2) return 0;\r\n\t\treturn _keyframeTimes[_keyframeTimes.size() - 1] - _keyframeTimes[0];\r\n\t}\r\n\r\n\tsize_t AnimatedValueBase::InsertKeyframe(float time) {\r\n\r\n\t\t// add the keyframe to the animation using insertion sort\r\n\t\t\r\n\t\t// by default we insert to the beginning of the key vector,\r\n\t\t// but if an earlier key exists we need to insert right afterwards\r\n\t\tsize_t insertIdx;\r\n\r\n\t\tbool foundPrevKeyframe = GetLastKeyframe(time, insertIdx);\r\n\r\n\t\t_interpolationValid = false;\r\n\r\n\t\t// same time?\r\n\t\tif (insertIdx < GetKeyframeCount() && GetKeyframeTime(insertIdx) == time) return insertIdx;\r\n\r\n\t\tif (!foundPrevKeyframe)\r\n\t\t\tinsertIdx = 0;\r\n\t\telse\r\n\t\t\tinsertIdx++;\r\n\t\t\r\n\t\tinsertKeyframeAt(insertIdx, time);\r\n\r\n\t\treturn insertIdx;\r\n\t}\r\n\r\n\tvoid AnimatedValueBase::insertKeyframeAt(size_t idx, float time) {\r\n\t\t_keyframeTimes.insert(_keyframeTimes.begin() + idx, time);\r\n\t}\r\n\r\n\tvoid AnimatedValueBase::DeleteKeyframe(size_t idx) {\r\n\t\tART_ASSERT(idx < _keyframeTimes.size());\r\n\r\n\t\tdeleteKeyframeAt(idx);\r\n\r\n\t\t_interpolationValid = false;\r\n\t}\r\n\r\n\tvoid AnimatedValueBase::deleteKeyframeAt(size_t idx) {\r\n\t\t_keyframeTimes.erase(_keyframeTimes.begin() + idx);\r\n\t}\r\n\r\n\tbool AnimatedValueBase::GetLastKeyframe(float time, size_t& idx) const {\r\n\r\n\t\tif (_keyframeTimes.size() == 0) return false;\r\n\r\n\t\tauto lowerIt = std::lower_bound(_keyframeTimes.begin(), _keyframeTimes.end(), time);\r\n\r\n\t\tif (lowerIt == _keyframeTimes.end()) {\r\n\t\t\tidx = _keyframeTimes.size() - 1;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tidx = lowerIt - _keyframeTimes.begin();\r\n\r\n\t\t\tif (_keyframeTimes[idx] > time) {\r\n\t\t\t\tif (idx == 0) return false; // even the first keyframe in the series is later than the quieried time\r\n\t\t\t\tidx--;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\tbool AnimatedValueBase::GetNextKeyframe(float time, size_t& idx) const {\r\n\t\tauto upperIt = std::upper_bound(_keyframeTimes.begin(), _keyframeTimes.end(), time);\r\n\r\n\t\tidx = upperIt - _keyframeTimes.begin();\r\n\r\n\t\treturn (upperIt != _keyframeTimes.end());\r\n\t}\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/AnimatedValue.h",
    "content": "#pragma once\r\n\r\n#include \"Math/Vector.h\"\r\n\r\n#include \"../CommonDefs.h\"\r\n\r\n#include \"document.h\"\r\n\r\n#include <vector>\r\n\r\nnamespace ART {\r\n\r\n\t//////////////////////////////////////////////////////////////////////////\r\n\t// Keyframe interpolation modes that we support\r\n\tenum EInterpolationMode {\r\n\t\tINTERPOLATION_MODE_CONSTANT,\r\n\t\tINTERPOLATION_MODE_LINEAR,\r\n\t\tINTERPOLATION_MODE_CATMULL_ROM\r\n\t};\r\n\t\t\r\n\t//////////////////////////////////////////////////////////////////////////\r\n\t// Base interface for animated values\r\n\t//\r\n\t// An animated value contains an array of keyframes, each of which has the same type\r\n\t// There is no direct access to the keyframe vector, that way we can ensure that the vector stays sorted\r\n\t// and the time values of the keyframes are not allowed to change.\r\n\t//\r\n\t// NOTE: currently the interpolation mode is set globally for the entire animated value.\r\n\t//\t\t This is not very practical, it would be better to set this per keyframe.\r\n\r\n\tclass AnimatedValueBase {\r\n\tpublic:\r\n\t\tAnimatedValueBase() : \r\n\t\t\t_interpolationMode(INTERPOLATION_MODE_CATMULL_ROM), _tension(0.5f) {}\r\n\t\tAnimatedValueBase(EInterpolationMode interpolationMode) :\r\n\t\t\t_interpolationMode(interpolationMode), _tension(0.5f), _interpolationValid(false) {}\r\n\t\t\r\n\t\tvirtual ~AnimatedValueBase() {}\r\n\r\n\t\tvoid SetInterpolationMode(EInterpolationMode mode) {\r\n\t\t\t_interpolationMode = mode;\r\n\t\t}\r\n\t\tEInterpolationMode GetInterpolationMode() const {\r\n\t\t\treturn _interpolationMode;\r\n\t\t}\r\n\r\n\t\t// If Catmull-Rom interpolation is used, this parameter defines the smoothness\r\n\t\t// NOTE: it is not practical to set this parameter globally\r\n\t\t//      In the future we would control the interpolation mode per keyframe\r\n\t\tvoid SetCatRomTension(float value);\r\n\t\tfloat GetCatRomTension() const {\r\n\t\t\treturn _tension;\r\n\t\t}\r\n\r\n\t\tsize_t GetKeyframeCount() const {\r\n\t\t\treturn _keyframeTimes.size();\r\n\t\t}\r\n\t\tvirtual void ClearKeyframes() {\r\n\t\t\t_keyframeTimes.clear();\r\n\t\t}\r\n\r\n\t\t// returns the time parameter of the ith keyframe\r\n\t\tfloat GetKeyframeTime(size_t idx) const;\r\n\t\tvoid SetKeyframeTime(size_t idx, float time);\r\n\r\n\t\tfloat GetStartOffset() const;\r\n\t\tfloat GetDuration() const;\r\n\r\n\t\t// Evaluates the animated attribute at a specific time\r\n\t\t// the result of the interpolation will be stored in an internal variable\r\n\t\t// so it is cheap to query it multiple times if the animation is paused, etc.\r\n\t\t// The evaluation method uses the interpolation mode specified in the base class\r\n\t\t// If there are no keyframes specified, the method returns false (and an assertion fails...)\r\n\t\tvirtual bool EvaluateAt(float time) = 0;\r\n\r\n\t\t// Creates a new keyframe at the given time\r\n\t\t// if a keyframe already exists at the same time, the operation does not create a new one\r\n\t\t// The method returns the index of the keyframe that can be useful for further processing, e.g. setting the value of the keyframe\r\n\t\tsize_t InsertKeyframe(float time);\r\n\t\tvoid DeleteKeyframe(size_t idx);\r\n\t\t\r\n\t\t// There are also methods to find neighboring keyframes for a specific time\r\n\t\t// The return values are false if such a key does not exist\r\n\t\t\r\n\t\t// This method returns the index of the last keyframe where 'keyFrame.Time <= time'\r\n\t\t// If no such key exists the method returns false and the idx is invalid\r\n\t\tbool GetLastKeyframe(float time, size_t& idx) const;\r\n\r\n\t\t// This method returns the index of the first keyframe where 'keyFrame.Time > time'\r\n\t\t// If no such key exists the method returns false and the idx is invalid\r\n\t\tbool GetNextKeyframe(float time, size_t& idx) const;\r\n\r\n\tprotected:\r\n\r\n\t\tvirtual void insertKeyframeAt(size_t idx, float time);\r\n\t\tvirtual void deleteKeyframeAt(size_t idx);\r\n\r\n\t\tstd::vector<float>\t\t\t\t\t\t_keyframeTimes;\r\n\r\n\t\tEInterpolationMode\t\t\t\t\t\t_interpolationMode;\r\n\t\tfloat\t\t\t\t\t\t\t\t\t_tension;\r\n\t\tMath::Vector4\t\t\t\t\t\t\t_CatRomCoefficients[4];\r\n\t\tbool\t\t\t\t\t\t\t\t\t_interpolationValid;\r\n\t};\r\n\r\n\tDECLARE_PTR_TYPES(AnimatedValueBase);\r\n\r\n\r\n\t//////////////////////////////////////////////////////////////////////////\r\n\t// Type-specific class for an animated value\r\n\r\n\ttemplate<typename T>\r\n\tclass AnimatedValue : public AnimatedValueBase{\r\n\tpublic:\r\n\r\n\t\tvirtual ~AnimatedValue() {}\r\n\r\n\t\tvirtual void ClearKeyframes() override;\r\n\r\n\t\t// Support for keyframe value manipulation\r\n\t\tvoid SetKeyframeValue(size_t idx, const T& value);\r\n\t\tvoid GetKeyframeValue(size_t idx, T& value) const;\r\n\r\n\t\t// Evaluates the animated attribute at a specific time\r\n\t\t// the result of the interpolation will be stored in an internal variable\r\n\t\t// so it is cheap to query it multiple times if the animation is paused, etc.\r\n\t\t// The evaluation method uses the interpolation mode specified in the base class\r\n\t\t// If there are no keyframes specified, the method returns false (and an assertion fails...)\r\n\t\tvirtual bool EvaluateAt(float time);\r\n\r\n\t\t// returns the last stored result of the interpolation in the argument\r\n\t\t// returns false if the interpolatzed value is not recent (keyframes changed or there are no keyframes)\r\n\t\tbool GetLastInterpolatedValue(T& value) const {\r\n\t\t\tvalue = _lastInterpolatedValue;\r\n\t\t\treturn _interpolationValid;\r\n\t\t}\r\n\r\n\t\ttemplate<class TWriter>\r\n\t\tvoid SerializeJSON(TWriter& writer) const;\r\n\r\n\t\tvoid DeserializeJSON(rapidjson::Value& value);\r\n\r\n\tprotected:\r\n\r\n\t\tvirtual void insertKeyframeAt(size_t idx, float time) override;\r\n\t\tvirtual void deleteKeyframeAt(size_t idx) override;\r\n\r\n\t\tstd::vector<T>\t\t\t\t_keyframeValues;\r\n\r\n\t\tT\t\t\t\t\t\t\t_lastInterpolatedValue;\r\n\t};\r\n\r\n\tDECLARE_PTR_TYPES_T1(AnimatedValue);\r\n\r\n\t//////////////////////////////////////////////////////////////////////////\r\n\t// Limited animated value that cannot be interpolated\r\n\t// For example a text can change over time, but does not support arithmetic operations required by the standard animated value\r\n\r\n\ttemplate<typename T>\r\n\tclass PointAnimatedValue : public AnimatedValueBase {\r\n\tpublic:\r\n\t\tvirtual ~PointAnimatedValue() {}\r\n\r\n\t\tvirtual void ClearKeyframes() override;\r\n\t\r\n\t\t// Support for keyframe value manipulation\r\n\t\tvoid SetKeyframeValue(size_t idx, const T& value);\r\n\t\tvoid GetKeyframeValue(size_t idx, T& value) const;\r\n\r\n\t\tvirtual bool EvaluateAt(float time);\r\n\r\n\t\tbool GetLastInterpolatedValue(T& value) const {\r\n\t\t\tvalue = _lastInterpolatedValue;\r\n\t\t\treturn _interpolationValid;\r\n\t\t}\r\n\r\n\t\ttemplate<class TWriter>\r\n\t\tvoid SerializeJSON(TWriter& writer) const;\r\n\r\n\t\tvoid DeserializeJSON(rapidjson::Value& value);\r\n\r\n\tprotected:\r\n\r\n\t\tvirtual void insertKeyframeAt(size_t idx, float time) override;\r\n\t\tvirtual void deleteKeyframeAt(size_t idx) override;\r\n\r\n\t\tstd::vector<T>\t\t\t\t_keyframeValues;\r\n\r\n\t\tT\t\t\t\t\t\t\t_lastInterpolatedValue;\r\n\t};\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/AnimatedValue.inl",
    "content": "#pragma once\n\n#include \"AnimatedValue.h\"\n#include \"SerializationUtil.h\"\n\n#include \"VectorMath.h\"\n\nnamespace ART {\n\n\t//////////////////////////////////////////////////////////////////////////\n\t// AnimatedValue\n\n\ttemplate<typename T>\n\tvoid AnimatedValue<T>::ClearKeyframes() {\n\t\tAnimatedValueBase::ClearKeyframes();\n\t\t_keyframeValues.clear();\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid AnimatedValue<T>::insertKeyframeAt(size_t idx, float time) {\n\t\tAnimatedValueBase::insertKeyframeAt(idx, time);\n\t\t_keyframeValues.insert(_keyframeValues.begin() + idx, T());\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid AnimatedValue<T>::deleteKeyframeAt(size_t idx) {\n\t\tAnimatedValueBase::deleteKeyframeAt(idx);\n\t\t_keyframeValues.erase(_keyframeValues.begin() + idx);\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid AnimatedValue<T>::SetKeyframeValue(size_t idx, const T& value) {\n\t\tART_ASSERT(idx < _keyframeValues.size());\n\t\t_keyframeValues[idx] = value;\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid AnimatedValue<T>::GetKeyframeValue(size_t idx, T& value) const {\n\t\tART_ASSERT(idx < _keyframeValues.size());\n\t\tvalue = _keyframeValues[idx];\n\t}\n\n\ttemplate<typename T>\n\tbool AnimatedValue<T>::EvaluateAt(float time) {\n\t\t_interpolationValid = false;\n\t\tif (_keyframeValues.empty()) return false;\n\n\t\t// find surrounding keyframes.\n\t\t// if no previous keyframe was found, we snap the previous keyframe to the next keyframe\n\t\t// similarly, if no next keyframe was found, we snap the value of the next keyframe to the previous keyframe\n\n\t\tsize_t prevIdx, nextIdx;\n\t\tbool hasPrevIdx = GetLastKeyframe(time, prevIdx);\n\t\tbool hasNextIdx = GetNextKeyframe(time, nextIdx);\n\t\tART_ASSERT(hasPrevIdx || hasNextIdx); // one of them had to be found because the keyframes are not empty\n\n\t\tif (!hasPrevIdx) prevIdx = nextIdx;\n\t\telse if (!hasNextIdx) nextIdx = prevIdx;\n\n\t\t// the interpolation weight depends on the time parameter of the surrounding keyframes\n\t\tconst float tPrev = _keyframeTimes[prevIdx];\n\t\tconst float tNext = _keyframeTimes[nextIdx];\n\t\tconst float w = (tNext > tPrev) ? (time - tPrev) / (tNext - tPrev) : 1.0f;\n\n\t\tswitch (_interpolationMode) {\n\t\tcase INTERPOLATION_MODE_CONSTANT:\n\t\t\t_lastInterpolatedValue = _keyframeValues[prevIdx];\n\t\t\tbreak;\n\t\tcase INTERPOLATION_MODE_LINEAR:\n\t\t\t_lastInterpolatedValue = _keyframeValues[nextIdx] * w + _keyframeValues[prevIdx] * (1.0f - w);\n\t\t\tbreak;\n\t\tcase INTERPOLATION_MODE_CATMULL_ROM:\n\t\t\t{\n\t\t\t\t// for the Catmull-Rom interpolation we need two more keyframe values, extending the neighborhood\n\t\t\t\tsize_t prev2Idx = (prevIdx > 0) ? prevIdx - 1 : prevIdx;\n\t\t\t\tsize_t next2Idx = (nextIdx < _keyframeValues.size() - 1) ? nextIdx + 1 : nextIdx;\n\n\n\t\t\t\t// compute Catmull-Rom coefficients\n\t\t\t\tMath::Vector4 wVec(1.0f, w, w * w, w * w * w);\n\t\t\t\tfloat w2 = w * w;\n\t\t\t\tfloat w3 = w2 * w;\n\t\t\t\tfloat coeffs[4];\n\t\t\t\t\n\t\t\t\tcoeffs[0] = Dot(wVec, _CatRomCoefficients[0]);\n\t\t\t\tcoeffs[1] = Dot(wVec, _CatRomCoefficients[1]);\n\t\t\t\tcoeffs[2] = Dot(wVec, _CatRomCoefficients[2]);\n\t\t\t\tcoeffs[3] = Dot(wVec, _CatRomCoefficients[3]);\n\t\t\t\t\n\t\t\t\t_lastInterpolatedValue = (coeffs[0] * _keyframeValues[prev2Idx] +\n\t\t\t\t\tcoeffs[1] * _keyframeValues[prevIdx] +\n\t\t\t\t\tcoeffs[2] * _keyframeValues[nextIdx] +\n\t\t\t\t\tcoeffs[3] * _keyframeValues[next2Idx]);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault: \n\t\t\tART_ASSERT(false);\n\t\t\treturn false; // should not get here\n\t\t}\n\t\n\t\t_interpolationValid = true;\n\t\treturn true;\n\t}\n\n\ttemplate<typename T>\n\ttemplate<class TWriter>\n\tvoid AnimatedValue<T>::SerializeJSON(TWriter& writer) const {\n\n\t\twriter.StartObject();\n\n\t\t\twriter.String(\"interpolation\");\n\t\t\twriter.Uint((uint32_t)_interpolationMode);\n\n\t\t\twriter.String(\"tension\");\n\t\t\twriter.Double(_tension);\n\n\t\t\twriter.String(\"keyframes\");\n\t\t\twriter.StartArray();\n\n\t\t\tfor (size_t iKeyframe = 0; iKeyframe < _keyframeValues.size(); iKeyframe++) {\n\t\t\t\twriter.StartObject();\n\n\t\t\t\t\twriter.String(\"time\");\n\t\t\t\t\twriter.Double(_keyframeTimes[iKeyframe]);\n\n\t\t\t\t\twriter.String(\"value\");\n\n\t\t\t\t\tJSONSerializableValue<T> serVal(_keyframeValues[iKeyframe]);\n\t\t\t\t\tserVal.SerializeJSON(writer);\n\n\t\t\t\twriter.EndObject();\n\t\t\t}\n\n\t\t\twriter.EndArray();\n\n\t\twriter.EndObject();\n\n\t}\n\n\ttemplate<typename T>\n\tvoid AnimatedValue<T>::DeserializeJSON(rapidjson::Value& value) {\n\n\t\tClearKeyframes();\n\n\t\tif (!value.IsObject()) {\n\t\t\tthrow SerializationException(\"JSON value not recognized as object\");\n\t\t\treturn;\n\t\t}\n\n\t\tfor (auto it = value.MemberBegin(); it != value.MemberEnd(); it++) {\n\t\t\tconst char* name = it->name.GetString();\n\n\t\t\tif (STRMATCH(name, \"interpolation\")) {\n\t\t\t\tif (!it->value.IsUint())\n\t\t\t\t\tthrow SerializationException(\"'interpolation' : expected UINT value\");\n\t\t\t\tSetInterpolationMode((EInterpolationMode)it->value.GetUint());\n\t\t\t}\n\t\t\telse if (STRMATCH(name, \"tension\")) {\n\t\t\t\tif (!it->value.IsDouble())\n\t\t\t\t\tthrow SerializationException(\"'tension' : expected FLOAT value\");\n\t\t\t\tSetCatRomTension((float) it->value.GetDouble());\n\t\t\t}\n\t\t\telse if (STRMATCH(name, \"keyframes\")) {\n\t\t\t\tif (!it->value.IsArray())\n\t\t\t\t\tthrow SerializationException(\"'keyframes' : expected ARRAY value\");\n\n\t\t\t\tauto& keyframeArray = it->value;\n\t\t\t\t// Deserialize each keyframe\n\t\t\t\tfor (rapidjson::SizeType i = 0; i < keyframeArray.Size(); i++) {\n\t\t\t\t\tif (!keyframeArray[i].IsObject())\n\t\t\t\t\t\tthrow SerializationException(\"'keyframes' array must contain JSON OBJECTS\");\n\t\t\t\t\tbool foundTime = false;\n\t\t\t\t\tbool foundValue = false;\n\n\t\t\t\t\tfor (auto it = keyframeArray[i].MemberBegin(); it != keyframeArray[i].MemberEnd(); it++) {\n\t\t\t\t\t\tconst char* name = it->name.GetString();\n\n\t\t\t\t\t\tif (STRMATCH(name, \"time\")) {\n\t\t\t\t\t\t\tfoundTime = true;\n\t\t\t\t\t\t\tif (!it->value.IsDouble())\n\t\t\t\t\t\t\t\tthrow SerializationException(\"'time' : expected FLOAT value\");\n\t\t\t\t\t\t\t_keyframeTimes.push_back((float) it->value.GetDouble());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (STRMATCH(name, \"value\")) {\n\t\t\t\t\t\t\tfoundValue = true;\n\t\t\t\t\t\t\tJSONSerializableValue<T> serVal;\n\t\t\t\t\t\t\tserVal.DeserializeJSON(it->value);\n\t\t\t\t\t\t\t_keyframeValues.push_back(serVal.Value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!foundTime || !foundValue) {\n\t\t\t\t\t\tClearKeyframes();\n\t\t\t\t\t\tthrow SerializationException(\"All keyframes must contain a 'time' and 'value' field\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\t\t\n\n\t//////////////////////////////////////////////////////////////////////////\n\t// PointAnimatedValue\n\n\ttemplate<typename T>\n\tvoid PointAnimatedValue<T>::ClearKeyframes() {\n\t\tAnimatedValueBase::ClearKeyframes();\n\t\t_keyframeValues.clear();\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid PointAnimatedValue<T>::insertKeyframeAt(size_t idx, float time) {\n\t\tAnimatedValueBase::insertKeyframeAt(idx, time);\n\t\t_keyframeValues.insert(_keyframeValues.begin() + idx, T());\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid PointAnimatedValue<T>::deleteKeyframeAt(size_t idx) {\n\t\tAnimatedValueBase::deleteKeyframeAt(idx);\n\t\t_keyframeValues.erase(_keyframeValues.begin() + idx);\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid PointAnimatedValue<T>::SetKeyframeValue(size_t idx, const T& value) {\n\t\tART_ASSERT(idx < _keyframeValues.size());\n\t\t_keyframeValues[idx] = value;\n\t\t_interpolationValid = false;\n\t}\n\n\ttemplate<typename T>\n\tvoid PointAnimatedValue<T>::GetKeyframeValue(size_t idx, T& value) const {\n\t\tART_ASSERT(idx < _keyframeValues.size());\n\t\tvalue = _keyframeValues[idx];\n\t}\n\n\ttemplate<typename T>\n\tbool PointAnimatedValue<T>::EvaluateAt(float time) {\n\t\t_interpolationValid = false;\n\t\tif (_keyframeValues.empty()) return false;\n\n\t\tsize_t prevIdx, nextIdx;\n\t\tbool hasPrevIdx = GetLastKeyframe(time, prevIdx);\n\t\tbool hasNextIdx = GetNextKeyframe(time, nextIdx);\n\t\tART_ASSERT(hasPrevIdx || hasNextIdx); // one of them had to be found because the keyframes are not empty\n\n\t\tif (!hasPrevIdx) prevIdx = nextIdx;\n\n\t\t// the interpolation weight depends on the time parameter of the surrounding keyframes\n\t\tconst float tPrev = _keyframeTimes[prevIdx];\n\n\t\t_lastInterpolatedValue = _keyframeValues[prevIdx];\n\n\t\t_interpolationValid = true;\n\t\treturn true;\n\t}\n\n\ttemplate<typename T>\n\ttemplate<class TWriter>\n\tvoid PointAnimatedValue<T>::SerializeJSON(TWriter& writer) const {\n\n\t\twriter.StartObject();\n\n\t\twriter.String(\"keyframes\");\n\t\twriter.StartArray();\n\n\t\tfor (size_t iKeyframe = 0; iKeyframe < _keyframeValues.size(); iKeyframe++) {\n\t\t\twriter.StartObject();\n\n\t\t\twriter.String(\"time\");\n\t\t\twriter.Double(_keyframeTimes[iKeyframe]);\n\n\t\t\twriter.String(\"value\");\n\n\t\t\tJSONSerializableValue<T> serVal(_keyframeValues[iKeyframe]);\n\t\t\tserVal.SerializeJSON(writer);\n\n\t\t\twriter.EndObject();\n\t\t}\n\n\t\twriter.EndArray();\n\n\t\twriter.EndObject();\n\n\t}\n\n\ttemplate<typename T>\n\tvoid PointAnimatedValue<T>::DeserializeJSON(rapidjson::Value& value) {\n\n\t\tClearKeyframes();\n\n\t\tif (!value.IsObject()) {\n\t\t\tthrow SerializationException(\"JSON value not recognized as object\");\n\t\t\treturn;\n\t\t}\n\n\t\tfor (auto it = value.MemberBegin(); it != value.MemberEnd(); it++) {\n\t\t\tconst char* name = it->name.GetString();\n\n\t\t\tif (STRMATCH(name, \"keyframes\")) {\n\t\t\t\tif (!it->value.IsArray())\n\t\t\t\t\tthrow SerializationException(\"'keyframes' : expected ARRAY value\");\n\n\t\t\t\tauto& keyframeArray = it->value;\n\t\t\t\t// Deserialize each keyframe\n\t\t\t\tfor (rapidjson::SizeType i = 0; i < keyframeArray.Size(); i++) {\n\t\t\t\t\tif (!keyframeArray[i].IsObject())\n\t\t\t\t\t\tthrow SerializationException(\"'keyframes' array must contain JSON OBJECTS\");\n\t\t\t\t\tbool foundTime = false;\n\t\t\t\t\tbool foundValue = false;\n\n\t\t\t\t\tfor (auto it = keyframeArray[i].MemberBegin(); it != keyframeArray[i].MemberEnd(); it++) {\n\t\t\t\t\t\tconst char* name = it->name.GetString();\n\n\t\t\t\t\t\tif (STRMATCH(name, \"time\")) {\n\t\t\t\t\t\t\tfoundTime = true;\n\t\t\t\t\t\t\tif (!it->value.IsDouble())\n\t\t\t\t\t\t\t\tthrow SerializationException(\"'time' : expected FLOAT value\");\n\t\t\t\t\t\t\t_keyframeTimes.push_back((float)it->value.GetDouble());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (STRMATCH(name, \"value\")) {\n\t\t\t\t\t\t\tfoundValue = true;\n\t\t\t\t\t\t\tJSONSerializableValue<T> serVal;\n\t\t\t\t\t\t\tserVal.DeserializeJSON(it->value);\n\t\t\t\t\t\t\t_keyframeValues.push_back(serVal.Value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!foundTime || !foundValue) {\n\t\t\t\t\t\tClearKeyframes();\n\t\t\t\t\t\tthrow SerializationException(\"All keyframes must contain a 'time' and 'value' field\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/AnimationController.cpp",
    "content": "#include \"pch.h\"\r\n\r\n#include \"AnimationController.h\"\r\n\r\n#include \"AnimatedValue.inl\"\r\n\r\n#include \"..\\..\\GameInput.h\"\r\n\r\n#ifdef ART_ENABLE_GUI\r\n#include \"../GUI/GUICore.h\"\r\n#endif\r\n\r\nusing namespace ART;\r\nusing namespace Math;\r\n\r\nAnimationController::AnimationController() :\r\n\t_isPlaying(false),\r\n\t_isDirty(false),\r\n\t_targetCamera(nullptr)\r\n{\r\n\r\n}\r\n\r\nvoid AnimationController::SetSceneAnimation(SceneAnimation_ptr& animation) {\r\n\t_sceneAnimation = animation;\r\n\t_isDirty = true;\r\n\tStop();\r\n\r\n\t_animBindings.clear();\r\n\r\n\tBindingDesc camBinding;\r\n\tcamBinding.Name = \"Camera\";\r\n\tcamBinding.Type = AnimationController::ETargetType_Camera;\r\n\t_animBindings.push_back(camBinding);\r\n\r\n\tSetActiveTargetIndex(0);\r\n}\r\n\r\nSceneAnimation_ptr& AnimationController::GetSceneAnimation() {\r\n\treturn _sceneAnimation;\r\n}\r\n\r\nvoid AnimationController::SetTargetCamera(BaseCamera* targetCamera) {\r\n\t_targetCamera = targetCamera;\r\n\t_isDirty = true;\r\n}\r\n\r\nBaseCamera* AnimationController::GetTargetCamera() {\r\n\treturn _targetCamera;\r\n}\r\n\r\nvoid AnimationController::AnimateFloatVar(NumVar* engineVar, const char* trackName) {\r\n\tART_ASSERT(_sceneAnimation);\r\n\tART_ASSERT(engineVar && trackName != \"\");\r\n\r\n\tauto animationTrack = _sceneAnimation->GetFloatAnimation(trackName);\r\n\tif (!animationTrack) {\r\n\t\t_sceneAnimation->CreateAnimation(trackName, SceneAnimation::EVarType_Float);\r\n\t\tanimationTrack = _sceneAnimation->GetFloatAnimation(trackName);\r\n\t}\r\n\tART_ASSERT(animationTrack);\r\n\r\n\tFloatBinding binding;\r\n\tbinding.Var = engineVar;\r\n\tbinding.Animation = animationTrack;\r\n\t_floatAnimBindings[trackName] = binding;\r\n\r\n\tBindingDesc desc;\r\n\tdesc.Name = trackName;\r\n\tdesc.Type = AnimationController::ETargetType_Float;\r\n\t_animBindings.push_back(desc);\r\n}\r\n\r\nvoid AnimationController::AnimateBoolVar(BoolVar* engineVar, const char* trackName) {\r\n\tART_ASSERT(_sceneAnimation);\r\n\tART_ASSERT(engineVar && trackName != \"\");\r\n\r\n\tauto animationTrack = _sceneAnimation->GetBoolAnimation(trackName);\r\n\tif (!animationTrack) {\r\n\t\t_sceneAnimation->CreateAnimation(trackName, SceneAnimation::EVarType_Bool);\r\n\t\tanimationTrack = _sceneAnimation->GetBoolAnimation(trackName);\r\n\t}\r\n\tART_ASSERT(animationTrack);\r\n\r\n\tBoolBinding binding;\r\n\tbinding.Var = engineVar;\r\n\tbinding.Animation = animationTrack;\r\n\t_boolAnimBindings[trackName] = binding;\r\n\r\n\tBindingDesc desc;\r\n\tdesc.Name = trackName;\r\n\tdesc.Type = AnimationController::ETargetType_Bool;\r\n\t_animBindings.push_back(desc);\r\n}\r\n\r\nbool AnimationController::IsPlaying() const {\r\n\treturn _isPlaying;\r\n}\r\n\r\nvoid AnimationController::TogglePlaying() {\r\n\tif (IsPlaying())\r\n\t\tPause();\r\n\telse\r\n\t\tPlay();\r\n}\r\n\r\nvoid AnimationController::Play() {\r\n\tif (!_isPlaying) _isDirty = true;\r\n\t_isPlaying = true;\r\n}\r\n\r\nvoid AnimationController::Pause() {\r\n\tif (_isPlaying) _isDirty = true;\r\n\t_isPlaying = false;\r\n}\r\n\r\nvoid AnimationController::Stop() {\r\n\t_isDirty = true;\r\n\r\n\tif (_sceneAnimation) {\r\n\t\tfloat startTime, endTime;\r\n\t\t_sceneAnimation->GetTimeSpan(startTime, endTime);\r\n\r\n\t\t_sceneAnimation->SetTime(startTime);\r\n\t}\r\n\r\n\tapplyAnimation();\r\n\r\n\t_isPlaying = false;\r\n}\r\n\r\n\r\nvoid AnimationController::Update(float elapsedTime) {\r\n\r\n\tif (GameInput::IsFirstPressed(GameInput::kKey_pause))\r\n\t\tTogglePlaying();\r\n\r\n\t// Detect hotkeys for keyframe manipulation\r\n\tif (GameInput::IsPressed(GameInput::kKey_lcontrol)) {\r\n\r\n\t\tif (GameInput::IsFirstPressed(GameInput::kKey_comma)) { // This is also the \"<\" character\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// jump to prev keyframe\r\n\t\t\tJumpPrevKeyframe();\r\n\t\t}\r\n\t\telse if (GameInput::IsFirstPressed(GameInput::kKey_period)) { // This is also the \">\" character\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  // jump to next keyframe\r\n\t\t\tJumpNextKeyframe();\r\n\t\t}\r\n\t\telse if (GameInput::IsFirstPressed(GameInput::kKey_insert)) {\r\n\t\t\tInsertKeyframe();\r\n\t\t}\r\n\t\telse if (GameInput::IsFirstPressed(GameInput::kKey_delete)) {\r\n\t\t\tDeleteLastKeyframe();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tif (!_sceneAnimation) return;\r\n\t\r\n\tif (IsPlaying()) {\r\n\t\tfloat currTime = _sceneAnimation->GetTime();\r\n\t\tcurrTime += elapsedTime;\r\n\r\n\t\tfloat startTime, endTime;\r\n\t\t_sceneAnimation->GetTimeSpan(startTime, endTime);\r\n\r\n\t\tif (endTime > startTime)\r\n\t\t\twhile (currTime > endTime)\r\n\t\t\t\tcurrTime = startTime + (currTime - endTime);\r\n\r\n\t\t_sceneAnimation->SetTime(currTime);\r\n\r\n\t\tapplyAnimation();\r\n\t}\r\n\r\n}\r\n\r\nvoid AnimationController::JumpNextKeyframe() {\r\n\t\r\n\tsize_t keyIdx;\r\n\tif (_activeAnimation->GetNextKeyframe(_sceneAnimation->GetTime(), keyIdx)) {\r\n\r\n\t\tfloat keyTime = _activeAnimation->GetKeyframeTime(keyIdx);\r\n\r\n\t\tPlay();\r\n\t\t_sceneAnimation->SetTime(keyTime);\r\n\t\tapplyAnimation();\r\n\t\tPause();\r\n\t}\r\n}\r\n\r\nvoid AnimationController::JumpPrevKeyframe() {\r\n\r\n\tsize_t keyIdx;\r\n\tif (_activeAnimation->GetLastKeyframe(_sceneAnimation->GetTime() - 0.0001f, keyIdx)) {\r\n\r\n\t\tfloat keyTime = _activeAnimation->GetKeyframeTime(keyIdx);\r\n\r\n\t\tPlay();\r\n\t\t_sceneAnimation->SetTime(keyTime);\r\n\t\tapplyAnimation();\r\n\t\tPause();\r\n\t}\r\n}\r\n\r\nvoid AnimationController::DeleteLastKeyframe() {\r\n\r\n\tsize_t keyIdx;\r\n\tif (_activeAnimation->GetLastKeyframe(_sceneAnimation->GetTime(), keyIdx)) {\r\n\t\t_activeAnimation->DeleteKeyframe(keyIdx);\r\n\t}\r\n\r\n\tapplyAnimation();\r\n}\r\n\r\nvoid AnimationController::InsertKeyframe() {\r\n\tif (!_targetCamera) return;\r\n\r\n\tART_ASSERT(_activeBindingIdx < _animBindings.size());\r\n\tBindingDesc& desc = _animBindings[_activeBindingIdx];\r\n\tswitch (desc.Type) {\r\n\tcase AnimationController::ETargetType_Camera:\r\n\t{\r\n\t\tauto& camAnimation = _sceneAnimation->GetCameraAnimation();\r\n\r\n\t\t// capture camera frame\r\n\t\tCameraFrame camFrame;\r\n\t\tcamFrame.Pos = _targetCamera->GetPosition();\r\n\t\tcamFrame.Forward = _targetCamera->GetForwardVec();\r\n\t\tcamFrame.Up = _targetCamera->GetUpVec();\r\n\r\n\t\tsize_t keyIdx = camAnimation.InsertKeyframe(_sceneAnimation->GetTime());\r\n\t\tcamAnimation.SetKeyframeValue(keyIdx, camFrame);\r\n\t}\r\n\t\tbreak;\r\n\tcase AnimationController::ETargetType_Float:\r\n\t{\r\n\t\tauto& it = _floatAnimBindings.find(desc.Name);\r\n\t\tART_ASSERT(it != _floatAnimBindings.end());\r\n\r\n\t\tFloatBinding& binding = it->second;\r\n\r\n\t\tfloat value = *binding.Var;\r\n\t\tsize_t keyIdx = binding.Animation->InsertKeyframe(_sceneAnimation->GetTime());\r\n\t\tbinding.Animation->SetKeyframeValue(keyIdx, value);\r\n\t}\r\n\t\tbreak;\r\n\tcase AnimationController::ETargetType_Bool:\r\n\t{\r\n\t\tauto& it = _boolAnimBindings.find(desc.Name);\r\n\t\tART_ASSERT(it != _boolAnimBindings.end());\r\n\r\n\t\tBoolBinding& binding = it->second;\r\n\r\n\t\tbool value = *binding.Var;\r\n\t\tsize_t keyIdx = binding.Animation->InsertKeyframe(_sceneAnimation->GetTime());\r\n\t\tbinding.Animation->SetKeyframeValue(keyIdx, value);\r\n\t}\r\n\tbreak;\r\n\tdefault:\r\n\t\tART_ASSERT(false);\r\n\t\tbreak;\r\n\t}\r\n\t\r\n\r\n\tapplyAnimation();\r\n}\r\n\r\nvoid AnimationController::applyAnimation() {\r\n\r\n\tif (!_sceneAnimation)\r\n\t\treturn;\r\n\r\n\tSetDirty(true);\r\n\r\n\t// update animation targets\r\n\tif (_targetCamera) {\r\n\t\tauto& camAnimation = _sceneAnimation->GetCameraAnimation();\r\n\r\n\t\tCameraFrame camFrame;\r\n\t\tif (camAnimation.GetLastInterpolatedValue(camFrame)) {\r\n\r\n\t\t\t_targetCamera->SetPosition(camFrame.Pos);\r\n\t\t\t_targetCamera->SetLookDirection(camFrame.Forward, camFrame.Up);\r\n\t\t}\r\n\t\t\r\n\t\t// TMP: we expect the application to do this every frame anyway\r\n\t\t// turns out that multiple calls to the Update() method will make the camera\r\n\t\t// \"forget\" the correct reprojection matrix.\r\n\r\n\t\t//_targetCamera->Update();\r\n\t}\r\n\r\n\t// animate all linked engine vars\r\n\tfor (auto it = _floatAnimBindings.begin(); it != _floatAnimBindings.end(); it++) {\r\n\t\tFloatBinding& binding = it->second;\r\n\r\n\t\tfloat interpolatedValue;\r\n\t\tif (binding.Animation->GetLastInterpolatedValue(interpolatedValue))\r\n\t\t\t*binding.Var = interpolatedValue;\r\n\t}\r\n\r\n\tfor (auto it = _boolAnimBindings.begin(); it != _boolAnimBindings.end(); it++) {\r\n\t\tBoolBinding& binding = it->second;\r\n\r\n\t\tbool interpolatedValue;\r\n\t\tif (binding.Animation->GetLastInterpolatedValue(interpolatedValue))\r\n\t\t\t*binding.Var = interpolatedValue;\r\n\t}\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\tstd::string subtitle;\r\n\t_sceneAnimation->GetSubtitleAnimation().GetLastInterpolatedValue(subtitle);\r\n\tARTGUI::SetText(subtitle);\r\n#endif\r\n}\r\n\r\nsize_t AnimationController::GetNumAnimationTargets() const {\r\n\treturn _animBindings.size();\r\n}\r\n\r\nvoid AnimationController::GetAnimationTargetName(size_t index, std::string& name) const {\r\n\tART_ASSERT(index < _animBindings.size());\r\n\tname = _animBindings[index].Name;\r\n}\r\n\r\nvoid AnimationController::SetActiveTargetIndex(size_t index) {\r\n\tART_ASSERT(index < _animBindings.size());\r\n\t_activeBindingIdx = index;\r\n\t_activeAnimation = GetActiveAnimationFromScene();\r\n}\r\n\r\nsize_t AnimationController::GetActiveTargetIndex() const {\r\n\treturn _activeBindingIdx;\r\n}\r\n\r\nAnimatedValueBase* AnimationController::GetActiveAnimationFromScene() {\r\n\t\r\n\tART_ASSERT(_activeBindingIdx < _animBindings.size());\r\n\tBindingDesc& desc = _animBindings[_activeBindingIdx];\r\n\tswitch (desc.Type) {\r\n\tcase AnimationController::ETargetType_Camera:\r\n\t{\r\n\t\tauto& camAnimation = _sceneAnimation->GetCameraAnimation();\r\n\t\treturn &camAnimation;\r\n\t}\r\n\tbreak;\r\n\tcase AnimationController::ETargetType_Float:\r\n\t{\r\n\t\tauto& it = _floatAnimBindings.find(desc.Name);\r\n\t\tART_ASSERT(it != _floatAnimBindings.end());\r\n\r\n\t\tFloatBinding& binding = it->second;\r\n\t\treturn binding.Animation;\r\n\t}\r\n\tbreak;\r\n\tcase AnimationController::ETargetType_Bool:\r\n\t{\r\n\t\tauto& it = _boolAnimBindings.find(desc.Name);\r\n\t\tART_ASSERT(it != _boolAnimBindings.end());\r\n\r\n\t\tBoolBinding& binding = it->second;\r\n\t\treturn binding.Animation;\r\n\t}\r\n\tbreak;\r\n\tdefault:\r\n\t\tART_ASSERT(false);\r\n\t\tbreak;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/AnimationController.h",
    "content": "#pragma once\r\n\r\n#include \"SceneAnimation.h\"\r\n\r\n#include \"Camera.h\"\r\n#include \"EngineTuning.h\"\r\n\r\n#include <map>\r\n\r\nnamespace ART {\r\n\r\n\t// in its limited form the animation controller targets only a camera\r\n\t// Later on we will extend it to custom animation targets\r\n\tclass AnimationController {\r\n\tpublic:\r\n\r\n\t\tAnimationController();\r\n\r\n\t\tvoid SetSceneAnimation(SceneAnimation_ptr& animation);\r\n\t\tSceneAnimation_ptr& GetSceneAnimation();\r\n\r\n\t\tvoid SetTargetCamera(Math::BaseCamera* targetCamera);\r\n\t\tMath::BaseCamera* GetTargetCamera();\r\n\r\n\t\t// creates a link between an engine var and a named float animation track\r\n\t\t// if the track does not exist yet, it creates a new one\r\n\t\tvoid AnimateFloatVar(NumVar* engineVar, const char* trackName);\r\n\t\tvoid AnimateBoolVar(BoolVar* engineVar, const char* trackName);\r\n\r\n\t\t// replay controls\r\n\t\t// TO DO: support off-line animation with fixed frame rate\r\n\t\tbool IsPlaying() const;\r\n\r\n\t\tvoid TogglePlaying();\r\n\r\n\t\tbool IsDirty() const {\r\n\t\t\treturn _isDirty;\r\n\t\t}\r\n\t\tvoid SetDirty(bool dirty) {\r\n\t\t\t_isDirty = dirty;\r\n\t\t}\r\n\r\n\t\tvoid Play();\r\n\t\t\r\n\t\t// stops playing\r\n\t\tvoid Pause();\r\n\t\t// stops playing and resets the time\r\n\t\tvoid Stop();\r\n\r\n\t\t// If the animation is playing, updates the state of the animation in real-time\r\n\t\t// At the end of the animation time frame, it loops the animation sequence from the beginning\r\n\t\t// TO DO: make this behavior more flexible\r\n\t\tvoid Update(float elapsedTime);\r\n\r\n\t\t// keyframe manipulation: the controller establishes the connection between a scene object or parameter\r\n\t\t// and the animation data. Therefore only this class is able to capture new keyframes\r\n\t\t// NOTE: later these methods will take effect on the active animation track. Right now we only have a single track for the camera\r\n\t\t\r\n\t\tvoid JumpPrevKeyframe();\r\n\r\n\t\tvoid JumpNextKeyframe();\r\n\t\t\r\n\t\tvoid DeleteLastKeyframe();\r\n\r\n\t\tvoid InsertKeyframe();\r\n\r\n\t\t// GUI interop\r\n\t\tsize_t GetNumAnimationTargets() const;\r\n\t\tvoid GetAnimationTargetName(size_t index, std::string& name) const;\r\n\t\t\r\n\t\t// The active animation target is the one we capture keyframes from. \r\n\t\t// We assume that the GUI will also display the keyframes of this target\r\n\t\tvoid SetActiveTargetIndex(size_t index);\r\n\t\tsize_t GetActiveTargetIndex() const;\r\n\r\n\t\tAnimatedValueBase* GetActiveAnimationFromScene();\r\n\r\n\tprotected:\r\n\r\n\t\tstruct FloatBinding {\r\n\t\t\tNumVar*\t\t\t\t\tVar;\r\n\t\t\tAnimatedValue<float>*\tAnimation;\r\n\t\t};\r\n\r\n\t\tstruct BoolBinding {\r\n\t\t\tBoolVar*\t\t\t\tVar;\r\n\t\t\tAnimatedValue<bool>*\tAnimation;\r\n\t\t};\r\n\r\n\t\tenum ETargetType {\r\n\t\t\tETargetType_Camera = 0,\r\n\t\t\tETargetType_Float,\r\n\t\t\tETargetType_Bool,\r\n\t\t\tETargetType_Count\r\n\t\t};\r\n\r\n\t\tstruct BindingDesc {\r\n\t\t\tstd::string\t\t\t\tName;\r\n\t\t\tETargetType\t\t\t\tType;\r\n\t\t};\r\n\r\n\t\tvoid applyAnimation();\r\n\r\n\t\tbool\t\t\t\t\t\t\t\t\t\t_isPlaying;\r\n\t\tbool\t\t\t\t\t\t\t\t\t\t_isDirty;\r\n\t\t\r\n\t\tSceneAnimation_ptr\t\t\t\t\t\t\t_sceneAnimation;\r\n\r\n\t\tMath::BaseCamera*\t\t\t\t\t\t\t_targetCamera;\r\n\r\n\t\tstd::vector<BindingDesc>\t\t\t\t\t_animBindings;\r\n\t\tsize_t\t\t\t\t\t\t\t\t\t\t_activeBindingIdx;\r\n\t\tAnimatedValueBase*\t\t\t\t\t\t\t_activeAnimation;\r\n\r\n\t\tstd::map<std::string, FloatBinding>\t\t\t_floatAnimBindings;\r\n\t\tstd::map<std::string, BoolBinding>\t\t\t_boolAnimBindings;\r\n\r\n\t};\r\n\r\n\tDECLARE_PTR_TYPES(AnimationController);\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/CameraAnimation.cpp",
    "content": "\r\n#include \"pch.h\"\r\n\r\n#include \"CameraAnimation.h\"\r\n\r\nusing namespace Math;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CameraFrame\r\n\r\nnamespace ART {\r\n\r\n\tCameraFrame operator + (const CameraFrame& a, const CameraFrame& b) {\r\n\t\tCameraFrame res(a);\r\n\t\tres += b;\r\n\t\treturn res;\r\n\t}\r\n\r\n\tCameraFrame operator * (const CameraFrame& a, float f) {\r\n\t\tCameraFrame res(a);\r\n\t\tres *= f;\r\n\t\treturn res;\r\n\t}\r\n\r\n\tCameraFrame operator * (float f, const CameraFrame& a) {\r\n\t\tCameraFrame res(a);\r\n\t\tres *= f;\r\n\t\treturn res;\r\n\t}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/CameraAnimation.h",
    "content": "#pragma once\r\n\r\n#include \"AnimatedValue.h\"\r\n#include \"SerializationUtil.h\"\r\n\r\n#include \"document.h\"\r\n\r\n#include \"VectorMath.h\"\r\n\r\nnamespace ART {\r\n\r\n\t// Utilites to animate camera keyframes\r\n\r\n\t///////////////////////////////////////////////////////////////////////////////\r\n\t// CameraFrame\r\n\t//\r\n\t// Currently we animate the three vectors that define the camera transformation together\r\n\t// it would be more elegant to use quaternions in the future\r\n\t\r\n\tstruct CameraFrame {\r\n\t\tMath::Vector3\t\tPos;\r\n\t\tMath::Vector3\t\tUp;\r\n\t\tMath::Vector3\t\tForward;\r\n\r\n\t\tconst CameraFrame& operator = (const CameraFrame& other) {\r\n\t\t\tPos = other.Pos;\r\n\t\t\tUp = other.Up;\r\n\t\t\tForward = other.Forward;\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tconst CameraFrame& operator += (const CameraFrame& other) {\r\n\t\t\tPos += other.Pos;\r\n\t\t\tUp += other.Up;\r\n\t\t\tForward += other.Forward;\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t\tconst CameraFrame& operator *= (float value) {\r\n\t\t\tPos = value * Pos;\r\n\t\t\tUp = value * Up;\r\n\t\t\tForward = value * Forward;\r\n\t\t\treturn *this;\r\n\t\t}\r\n\r\n\t};\r\n\r\n\r\n\tCameraFrame operator + (const CameraFrame& a, const CameraFrame& b);\r\n\r\n\tCameraFrame operator * (const CameraFrame& a, float f);\r\n\r\n\tCameraFrame operator * (float f, const CameraFrame& a);\r\n\r\n}\r\n\r\n// Template specialization to support the serialization of this type in keyframes\r\n\r\ntemplate<>\r\ntemplate<class TWriter>\r\nvoid JSONSerializableValue<ART::CameraFrame>::SerializeJSON(TWriter& writer) const {\r\n\tusing namespace Math;\r\n\t\r\n\tJSONSerializableValue<Vector3> jsonPos(Value.Pos);\r\n\tJSONSerializableValue<Vector3> jsonUp(Value.Up);\r\n\tJSONSerializableValue<Vector3> jsonForward(Value.Forward);\r\n\r\n\twriter.StartObject();\r\n\r\n\twriter.String(\"pos\");\r\n\tjsonPos.SerializeJSON(writer);\r\n\twriter.String(\"up\");\r\n\tjsonUp.SerializeJSON(writer);\r\n\twriter.String(\"forward\");\r\n\tjsonForward.SerializeJSON(writer);\r\n\r\n\twriter.EndObject();\r\n}\r\n\r\ntemplate<>\r\nvoid JSONSerializableValue<ART::CameraFrame>::DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\tif (!jsonValue.IsObject()) {\r\n\t\tthrow SerializationException(\"CameraFrame : expected JSON OBJECT\");\r\n\t}\r\n\r\n\tfor (auto it = jsonValue.MemberBegin(); it != jsonValue.MemberEnd(); it++) {\r\n\r\n\t\tJSONSerializableValue<Math::Vector3> vecVal;\r\n\t\tvecVal.DeserializeJSON(it->value);\r\n\r\n\t\tconst char* name = it->name.GetString();\r\n\t\tif (STRMATCH(name, \"pos\")) {\r\n\t\t\tValue.Pos = vecVal.Value;\r\n\t\t}\r\n\t\telse if (STRMATCH(name, \"up\")) {\r\n\t\t\tValue.Up = vecVal.Value;\r\n\t\t}\r\n\t\telse if (STRMATCH(name, \"forward\")) {\r\n\t\t\tValue.Forward = vecVal.Value;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/SceneAnimation.cpp",
    "content": "#include \"pch.h\"\r\n\r\n\r\n#include \"SceneAnimation.h\"\r\n#include \"AnimatedValue.inl\"\r\n\r\n#include \"Utility.h\"\r\n\r\n#include \"document.h\"\r\n#include \"writer.h\"\r\n#include \"stringbuffer.h\"\r\n#include \"filereadstream.h\"\r\n#include \"error/en.h\"\r\n#include \"prettywriter.h\"\r\n\r\n#include <iostream>\r\n#include <fstream>\r\n#include <sstream>\r\n\r\n#define STRMATCH(x, y) (strcmp(x, y) == 0)\r\n\r\nusing namespace ART;\r\nusing namespace Math;\r\n\r\nSceneAnimation::SceneAnimation() {\r\n\tSetTimeSpan(0, 0);\r\n\tSetTime(0);\r\n}\r\n\r\nSceneAnimation::SceneAnimation(float startTime, float endTime) {\r\n\tSetTimeSpan(startTime, endTime);\r\n\tSetTime(startTime);\r\n}\r\n\r\nbool SceneAnimation::LoadJson(const char *filename) {\r\n\t\r\n\t_animVarLUT.clear();\r\n\t_floatVars.clear();\r\n\t_float3Vars.clear();\r\n\t_boolVars.clear();\r\n\t\r\n\tstd::ifstream file;\r\n\tfile.open(filename, std::ios::binary);\r\n\tif (!file) {\r\n\t\tstd::cout << \"Failed to open animation file: \" << filename << std::endl;\r\n\t\treturn false;\r\n\t}\r\n\tstd::stringstream ss;\r\n\tss << file.rdbuf();\r\n\tfile.close();\r\n\r\n\trapidjson::Document doc;\r\n\tif (doc.Parse(ss.str().c_str()).HasParseError()) {\r\n\t\tstd::cout << \"Error parsing JSON: document not recognized as object.\" << std::endl;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (rapidjson::Value::MemberIterator it = doc.MemberBegin(); it != doc.MemberEnd(); it++) {\r\n\r\n\t\tconst char* name = it->name.GetString();\r\n\t\trapidjson::Value& val = it->value;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tif (STRMATCH(name, \"StartTime\")) {\r\n\t\t\t\tif (!val.IsDouble())\r\n\t\t\t\t\tthrow SerializationException(\"'StartTime' : expected number\");\r\n\t\t\t\t_startTime = (float) val.GetDouble();\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"EndTime\")) {\r\n\t\t\t\tif (!val.IsDouble())\r\n\t\t\t\t\tthrow SerializationException(\"'EndTime' : expected number\");\r\n\t\t\t\t_endTime = (float)val.GetDouble();\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"CameraAnimation\")) {\r\n\t\t\t\t_camAnimation.DeserializeJSON(val);\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"Subtitles\")) {\r\n\t\t\t\t_subtitleAnimation.DeserializeJSON(val);\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"AnimatedVars\")) {\r\n\t\t\t\tparseVarsJson(val);\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tthrowUnexpectedKeyException(name);\r\n\t\t\t}\r\n\t\t}\r\n\t\tcatch (SerializationException ex) {\r\n\t\t\tstd::stringstream msg;\r\n\t\t\tmsg << \"Error parsing scene animation: \" << ex.Message;\r\n\t\t\tUtility::Print(msg.str().c_str());\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tSetTime(_startTime);\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid SceneAnimation::parseVarsJson(rapidjson::Value& rootVal) {\r\n\tif (!rootVal.IsArray())\r\n\t\tthrow SerializationException(\"AnimatedVars: expected an array\");\r\n\r\n\tfor (rapidjson::SizeType iVar = 0; iVar < rootVal.Size(); iVar++) {\r\n\t\tauto& var = rootVal[iVar];\r\n\t\tif (!var.IsObject()) throw SerializationException(\"AnimatedVars: array must contain objects.\");\r\n\r\n\t\tstd::string varName;\r\n\t\tAnimatedVarDesc varDesc;\r\n\t\trapidjson::Value* animValue = nullptr; // we don't know its type yet, so we cannot parse it yet\r\n\r\n\t\tfor (auto iter = var.MemberBegin(); iter != var.MemberEnd(); iter++) {\r\n\t\t\tconst char* name = iter->name.GetString();\r\n\t\t\tauto& value = iter->value;\r\n\t\t\t\r\n\t\t\tif (STRMATCH(name, \"Name\")) {\r\n\t\t\t\tif (!value.IsString()) throw SerializationException(\"AnimatedVars.Name: expected string\");\r\n\t\t\t\tvarName = value.GetString();\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"Type\")) {\r\n\t\t\t\tif (!value.IsUint()) throw SerializationException(\"AnimatedVars.Type: expected uint\");\r\n\t\t\t\tif (value.GetUint() >= EVarType_Undefined) throw SerializationException(\"AnimatedVars.Type: invalid code\");\r\n\t\t\t\tvarDesc.Type = (EVarType)value.GetUint();\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"Animation\")) {\r\n\t\t\t\tanimValue = &value;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tthrowUnexpectedKeyException(name);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (varName == \"\" || varDesc.Type == EVarType_Undefined || animValue == nullptr)\r\n\t\t\tthrow SerializationException(\"AnimatedVars: missing or invalid fields (Name/Type/Animation)\");\r\n\r\n\t\tif (_animVarLUT.find(varName) != _animVarLUT.end()) {\r\n\t\t\tstd::string errMsg = std::string(\"Duplicate animated var name \") + varName;\r\n\t\t\tthrow SerializationException(errMsg.c_str());\r\n\t\t}\r\n\r\n\t\t// everything looks OK, let's parse the animated value\r\n\t\tswitch (varDesc.Type)\r\n\t\t{\r\n\t\tcase EVarType_Float:\r\n\t\t\t{\r\n\t\t\t\tAnimatedValue<float> animFloat;\r\n\t\t\t\tanimFloat.DeserializeJSON(*animValue);\r\n\r\n\t\t\t\tvarDesc.TrackID = (uint32_t) _floatVars.size();\r\n\t\t\t\t_floatVars.push_back(animFloat);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase EVarType_Float3:\r\n\t\t{\r\n\t\t\tAnimatedValue<Math::Vector3> animFloat3;\r\n\t\t\tanimFloat3.DeserializeJSON(*animValue);\r\n\r\n\t\t\tvarDesc.TrackID = (uint32_t) _float3Vars.size();\r\n\t\t\t_float3Vars.push_back(animFloat3);\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase EVarType_Bool:\r\n\t\t{\r\n\t\t\tAnimatedValue<bool> animBool;\r\n\t\t\tanimBool.DeserializeJSON(*animValue);\r\n\r\n\t\t\tvarDesc.TrackID = (uint32_t)_boolVars.size();\r\n\t\t\t_boolVars.push_back(animBool);\r\n\t\t}\r\n\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tthrow SerializationException(\"Unsupported animated var type\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\t_animVarLUT[varName] = varDesc;\r\n\t} // for\r\n\r\n}\r\n\r\nvoid SceneAnimation::throwUnexpectedKeyException(const char* name) {\r\n\tstd::string errMsg = std::string(\"Unexpected key: \") + name;\r\n\tthrow SerializationException(errMsg.c_str());\r\n}\r\n\r\nbool SceneAnimation::SaveJson(const char *filename) {\r\n\r\n\trapidjson::StringBuffer buf;\r\n\trapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);\r\n\r\n\twriter.StartObject();\r\n\t\r\n\twriter.Key(\"StartTime\");\r\n\twriter.Double(_startTime);\r\n\twriter.Key(\"EndTime\");\r\n\twriter.Double(_endTime);\r\n\r\n\twriter.Key(\"CameraAnimation\");\r\n\t_camAnimation.SerializeJSON(writer);\r\n\r\n\twriter.Key(\"Subtitles\");\r\n\t_subtitleAnimation.SerializeJSON(writer);\r\n\t\r\n\twriter.Key(\"AnimatedVars\");\r\n\twriter.StartArray();\r\n\tfor (auto& lutEntry : _animVarLUT) {\r\n\t\tAnimatedVarDesc& varDesc = lutEntry.second;\r\n\t\t\r\n\t\twriter.StartObject();\r\n\t\t\twriter.Key(\"Name\");\r\n\t\t\twriter.String(lutEntry.first.c_str());\r\n\r\n\t\t\twriter.Key(\"Type\");\r\n\t\t\twriter.Uint((uint32_t)varDesc.Type);\r\n\r\n\t\t\twriter.Key(\"Animation\");\r\n\t\t\tswitch (varDesc.Type)\r\n\t\t\t{\r\n\t\t\tcase EVarType_Float:\r\n\t\t\t\t_floatVars[varDesc.TrackID].SerializeJSON(writer);\r\n\t\t\t\tbreak;\r\n\t\t\tcase EVarType_Float3:\r\n\t\t\t\t_float3Vars[varDesc.TrackID].SerializeJSON(writer);\r\n\t\t\t\tbreak;\r\n\t\t\tcase EVarType_Bool:\r\n\t\t\t\t_boolVars[varDesc.TrackID].SerializeJSON(writer);\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tART_ASSERT(false); // should never happed\r\n\t\t\t\tthrow SerializationException(\"Failed to serialize animated var: unsupported type\");\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\twriter.EndObject();\r\n\t}\r\n\twriter.EndArray();\r\n\r\n\twriter.EndObject();\r\n\r\n\r\n\tstd::ofstream of(filename);\r\n\tif (!of) {\r\n\t\tstd::cerr << \"Unable to write file: \" << filename << std::endl;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tof << buf.GetString();\r\n\tof.close();\r\n\treturn true;\r\n}\r\n\r\nvoid SceneAnimation::SetTimeSpan(float startTime, float endTime) {\r\n\t_startTime = startTime;\r\n\t_endTime = endTime;\r\n}\r\n\r\nvoid SceneAnimation::GetTimeSpan(float& startTime, float& endTime) {\r\n\tstartTime = _startTime;\r\n\tendTime = _endTime;\r\n}\r\n\r\nvoid SceneAnimation::SetTime(float t) {\r\n\t_currTime = t;\r\n\r\n\tif (_currTime > _endTime)\r\n\t\t_currTime = _endTime;\r\n\telse if (_currTime < _startTime)\r\n\t\t_currTime = _startTime;\r\n\r\n\t_camAnimation.EvaluateAt(_currTime);\r\n\t_subtitleAnimation.EvaluateAt(_currTime);\r\n\r\n\tfor (auto& animVar : _floatVars)\r\n\t\tanimVar.EvaluateAt(_currTime);\r\n\tfor (auto& animVar : _float3Vars)\r\n\t\tanimVar.EvaluateAt(_currTime);\r\n\tfor (auto& animVar : _boolVars)\r\n\t\tanimVar.EvaluateAt(_currTime);\r\n}\r\n\r\nfloat SceneAnimation::GetTime() const {\r\n\treturn _currTime;\r\n}\r\n\r\nAnimatedValue<float>* SceneAnimation::GetFloatAnimation(const char* name) {\r\n\tauto it = _animVarLUT.find(name);\r\n\tif (it == _animVarLUT.end() || it->second.Type != EVarType_Float)\r\n\t\treturn nullptr;\r\n\r\n\treturn &_floatVars[it->second.TrackID];\r\n}\r\n\r\nAnimatedValue<Math::Vector3>* SceneAnimation::GetFloat3Animation(const char* name) {\r\n\tauto it = _animVarLUT.find(name);\r\n\tif (it == _animVarLUT.end() || it->second.Type != EVarType_Float3)\r\n\t\treturn nullptr;\r\n\r\n\treturn &_float3Vars[it->second.TrackID];\r\n}\r\n\r\nAnimatedValue<bool>* SceneAnimation::GetBoolAnimation(const char* name) {\r\n\tauto it = _animVarLUT.find(name);\r\n\tif (it == _animVarLUT.end() || it->second.Type != EVarType_Bool)\r\n\t\treturn nullptr;\r\n\r\n\treturn &_boolVars[it->second.TrackID];\r\n}\r\n\r\nbool SceneAnimation::CreateAnimation(const char* name, EVarType type) {\r\n\tif (_animVarLUT.find(name) != _animVarLUT.end())\r\n\t\treturn false;\r\n\r\n\tAnimatedVarDesc varDesc;\r\n\tvarDesc.Type = type;\r\n\r\n\tswitch (type) {\r\n\tcase EVarType_Float:\r\n\t\tvarDesc.TrackID = (uint32_t) _floatVars.size();\r\n\t\t_floatVars.push_back(AnimatedValue<float>());\r\n\t\tbreak;\r\n\tcase EVarType_Float3:\r\n\t\tvarDesc.TrackID = (uint32_t) _float3Vars.size();\r\n\t\t_float3Vars.push_back(AnimatedValue<Math::Vector3>());\r\n\t\tbreak;\r\n\tcase EVarType_Bool: {\r\n\t\tvarDesc.TrackID = (uint32_t) _boolVars.size();\r\n\t\tAnimatedValue<bool> anim;\r\n\t\tanim.SetInterpolationMode(INTERPOLATION_MODE_CONSTANT);\r\n\t\t_boolVars.push_back(anim);\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\tART_ASSERT(false);\r\n\t\treturn false;\r\n\t}\r\n\r\n\t_animVarLUT[name] = varDesc;\r\n\r\n\treturn true;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/SceneAnimation.h",
    "content": "#pragma once\r\n\r\n#include \"CameraAnimation.h\"\r\n#include \"../CommonDefs.h\"\r\n\r\n#include <string>\r\n#include <vector>\r\n#include <map>\r\n\r\n#include \"document.h\"\r\n\r\nnamespace ART {\r\n\r\n\tclass SceneAnimation {\r\n\tpublic:\r\n\r\n\t\tenum EVarType {\r\n\t\t\tEVarType_Float = 0,\r\n\t\t\tEVarType_Float3,\r\n\t\t\tEVarType_Bool,\r\n\t\t\tEVarType_Undefined,\r\n\t\t\tEVarType_Count\r\n\t\t};\r\n\r\n\t\tstruct AnimatedVarDesc {\r\n\t\t\tEVarType\t\tType;\r\n\t\t\tuint32_t\t\tTrackID;\r\n\r\n\t\t\tAnimatedVarDesc() :\r\n\t\t\t\tType(EVarType_Undefined),\r\n\t\t\t\tTrackID(uint32_t(-1)) {}\r\n\t\t};\r\n\r\n\t\tSceneAnimation();\r\n\t\tSceneAnimation(float startTime, float endTime);\r\n\r\n\t\tbool LoadJson(const char *filename);\r\n\t\tbool SaveJson(const char *filename);\r\n\r\n\t\tvoid SetTimeSpan(float startTime, float endTime);\r\n\t\tvoid GetTimeSpan(float& startTime, float& endTime);\r\n\r\n\t\t// sets the animation's global time and evaluates the animation tracks at this time\r\n\t\tvoid SetTime(float t);\r\n\t\tfloat GetTime() const;\r\n\r\n\t\tAnimatedValue<CameraFrame>& GetCameraAnimation() {\r\n\t\t\treturn _camAnimation;\r\n\t\t}\r\n\r\n\t\tPointAnimatedValue<std::string>& GetSubtitleAnimation() {\r\n\t\t\treturn _subtitleAnimation;\r\n\t\t}\r\n\r\n\t\t// returns null if does not exist\r\n\t\tAnimatedValue<float>* GetFloatAnimation(const char* name);\r\n\t\tAnimatedValue<Math::Vector3>* GetFloat3Animation(const char* name);\r\n\t\tAnimatedValue<bool>* GetBoolAnimation(const char* name);\r\n\r\n\t\t// creates a new animation track with the given name, but returns false if the name is already used\r\n\t\tbool CreateAnimation(const char* name, EVarType type);\r\n\r\n\tprotected:\r\n\r\n\t\tvoid parseVarsJson(rapidjson::Value& rootVal);\r\n\r\n\t\tinline void throwUnexpectedKeyException(const char* key);\r\n\r\n\t\tfloat\t\t\t\t\t\t\t_startTime;\r\n\t\tfloat\t\t\t\t\t\t\t_endTime;\r\n\t\tfloat\t\t\t\t\t\t\t_currTime;\r\n\r\n\t\t// currently we only animate a camera, but later this class will be extended to support\r\n\t\t// arbitrary animation tracks\r\n\t\tAnimatedValue<CameraFrame>\t\t_camAnimation;\r\n\t\tPointAnimatedValue<std::string>\t_subtitleAnimation;\r\n\r\n\t\t// additional, arbitrary variables can be animated using typed animated values\r\n\t\t// These will be identified from the engine side using a key-index lookup table\r\n\t\tstd::map<std::string, AnimatedVarDesc>\t_animVarLUT;\r\n\r\n\t\tstd::vector<AnimatedValue<float>>\t\t\t_floatVars;\r\n\t\tstd::vector<AnimatedValue<Math::Vector3>>\t_float3Vars;\r\n\t\tstd::vector<AnimatedValue<bool>>\t\t\t_boolVars;\r\n\r\n\t};\r\n\r\n\tDECLARE_PTR_TYPES(SceneAnimation);\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Animation/SerializationUtil.h",
    "content": "#pragma once\r\n\r\n#include \"../CommonDefs.h\"\r\n#include \"Math/Vector.h\"\r\n\r\n#include <string>\r\n\r\nstruct SerializationException {\r\n\tstd::string\t\tMessage;\r\n\r\n\tSerializationException(const char* message) : Message(message) {\r\n\t}\r\n};\r\n\r\n// The keyframe value must support serialization\r\n// For C++ primitve types we provide this base class that takes care of it\r\ntemplate<typename T>\r\nstruct JSONSerializableValue {\r\n\r\n\t// Serialization methods are template-specialized, sincw we don't know the JSON\r\n\t// layout of T. Therefore the default methods should always fail\r\n\r\n\tJSONSerializableValue() {}\r\n\tJSONSerializableValue(const T& val) : Value(val) {}\r\n\r\n\ttemplate<class TWriter>\r\n\tvoid SerializeJSON(TWriter& writer) const {\r\n\t\tART_ASSERT(false);\r\n\t}\r\n\r\n\tvoid DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\t\tART_ASSERT(false);\r\n\t}\r\n\r\n\tT Value;\r\n};\r\n\r\n// The following are template-specializations of SerializableValue for basic types that we want to JSON serialize with the wrapper class\r\n\r\ntemplate<>\r\ntemplate<class TWriter>\r\nvoid JSONSerializableValue<uint32_t>::SerializeJSON(TWriter& writer) const {\r\n\twriter.Uint(Value);\r\n}\r\n\r\ntemplate<>\r\nvoid JSONSerializableValue<uint32_t>::DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\tif (!jsonValue.IsUint())\r\n\t\tthrow SerializationException(\"expected UINT value\");\r\n\tValue = jsonValue.GetUint();\r\n}\r\n\r\n\r\ntemplate<>\r\ntemplate<class TWriter>\r\nvoid JSONSerializableValue<float>::SerializeJSON(TWriter& writer) const {\r\n\twriter.Double(Value);\r\n}\r\n\r\ntemplate<>\r\nvoid JSONSerializableValue<float>::DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\tif (!jsonValue.IsDouble())\r\n\t\tthrow SerializationException(\"expected FLOAT value\");\r\n\tValue = (float) jsonValue.GetDouble();\r\n}\r\n\r\ntemplate<>\r\ntemplate<class TWriter>\r\nvoid JSONSerializableValue<bool>::SerializeJSON(TWriter& writer) const {\r\n\twriter.Bool(Value);\r\n}\r\n\r\ntemplate<>\r\nvoid JSONSerializableValue<bool>::DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\tif (!jsonValue.IsBool())\r\n\t\tthrow SerializationException(\"expected BOOL value\");\r\n\tValue = (float)jsonValue.GetBool();\r\n}\r\n\r\ntemplate<>\r\ntemplate<class TWriter>\r\nvoid JSONSerializableValue<std::string>::SerializeJSON(TWriter& writer) const {\r\n\twriter.String(Value.c_str());\r\n}\r\n\r\ntemplate<>\r\nvoid JSONSerializableValue<std::string>::DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\tif (!jsonValue.IsString())\r\n\t\tthrow SerializationException(\"expected STRING value\");\r\n\tValue = jsonValue.GetString();\r\n}\r\n\r\ntemplate<>\r\ntemplate<class TWriter>\r\nvoid JSONSerializableValue<Math::Vector3>::SerializeJSON(TWriter& writer) const {\r\n\twriter.StartArray();\r\n\t\twriter.Double(Value.GetX());\r\n\t\twriter.Double(Value.GetY());\r\n\t\twriter.Double(Value.GetZ());\r\n\twriter.EndArray();\r\n}\r\n\r\ntemplate<>\r\nvoid JSONSerializableValue<Math::Vector3>::DeserializeJSON(rapidjson::Value& jsonValue) {\r\n\tif (!jsonValue.IsArray() || jsonValue.Size() != 3)\r\n\t\tthrow SerializationException(\"Vector3: expected Array of 3 floats\");\r\n\r\n\tfor (int i = 0; i < 3; i++) {\r\n\t\tif (!jsonValue[i].IsDouble())\r\n\t\t\tthrow SerializationException(\"Vector3: all array members must be float values\");\r\n\t\tswitch (i) {\r\n\t\tcase 0:\r\n\t\t\tValue.SetX((float) jsonValue[i].GetDouble());\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tValue.SetY((float) jsonValue[i].GetDouble());\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tValue.SetZ((float) jsonValue[i].GetDouble());\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/CommonDefs.h",
    "content": "#pragma once\r\n\r\n#include <memory>\r\n\r\n#define ART_ENABLE_GUI\r\n\r\n// Assertion that can be disabled using a compiled macro\r\n#   ifdef ART_NOASSERT\r\n#       define ART_ASSERT(x)\r\n#   else\r\n#       include <cassert>\r\n#       define ART_ASSERT(x) assert(x)\r\n#   endif\r\n\r\n\r\n// Declare shared ptr types for non-templated type\r\n#define DECLARE_PTR_TYPES(typeName) \\\r\n\ttypedef std::shared_ptr<typeName>\t\t\ttypeName ## _ptr; \\\r\n\ttypedef std::shared_ptr<const typeName>\t\ttypeName ## _cptr;\r\n\r\n// Declare shared ptr types for templated type\r\n#define DECLARE_PTR_TYPES_T1(typeName) \\\r\n\ttemplate<typename T> using typeName ## _ptr = std::shared_ptr<typeName<T>>; \\\r\n\ttemplate<typename T> using typeName ## _cptr = std::shared_ptr<const typeName<T>>;\r\n\r\n#define DECLARE_PTR_TYPES_T2(typeName) \\\r\n\ttemplate<typename T1, typename T2> using typeName ## _ptr = std::shared_ptr<typeName<T1, T2>>; \\\r\n\ttemplate<typename T1, typename T2> using typeName ## _cptr = std::shared_ptr<const typeName<T1, T2>>;\r\n\r\n#define STRMATCH(x, y) (strcmp(x, y) == 0)\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/AnimationWidget.cpp",
    "content": "\r\n#include \"pch.h\"\r\n\r\n#include \"AnimationWidget.h\"\r\n\r\n#include \"..\\CommonDefs.h\"\r\n\r\n#include \"imgui\\imgui.h\"\r\n#include \"imgui\\imgui_impl_dx11.h\"\r\n\r\n#include \"..\\..\\GameInput.h\"\r\n\r\n#include \"GUICore.h\"\r\n#include \"GUIUtil.h\"\r\n\r\nusing namespace ART;\r\n\r\n// NOTE: while this widget is implemented as a class, due to the stateless immediate manner of ImGUI\r\n// we currently store all states in a static variable\r\n// This means that only one instance of thie widget can work properly at once\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\nnamespace ARTGUI {\r\n\r\n\tAnimationWidget::AnimationWidget(const AnimationController_ptr& controller) {\r\n\t\t_controller = controller;\r\n\t\t_showHelp = true;\r\n\t\t_timeElapsed = 0;\r\n\t\t_lastAnimStart = 0;\r\n\t\t_lastAnimEnd = 0;\r\n\r\n\t\t_trackNames.resize(controller->GetNumAnimationTargets());\r\n\t\t_trackNameChrs.resize(_trackNames.size());\r\n\t\tfor (size_t i = 0; i < _trackNames.size(); i++) {\r\n\t\t\tcontroller->GetAnimationTargetName(i, _trackNames[i]);\r\n\t\t\t_trackNameChrs[i] = _trackNames[i].c_str();\r\n\t\t}\r\n\t}\r\n\r\n\tvoid AnimationWidget::Init() {\r\n\r\n\t}\r\n\r\n\tvoid AnimationWidget::Update(float elapsedTime) {\r\n\r\n\t\tif(ARTGUI::IsVisible())\r\n\t\t\t_timeElapsed += elapsedTime;\r\n\r\n\t\tif (_timeElapsed > 3.0f)\r\n\t\t\t_showHelp = false;\r\n\r\n\t\t_controller->Update(0);\r\n\r\n\t}\r\n\r\n\tvoid AnimationWidget::Render() {\r\n\r\n\t\tstatic bool isOpen = true;\r\n\t\tstatic float time = 0;\r\n\r\n\t\tauto& io = ImGui::GetIO();\r\n\r\n\t\tfloat width = io.DisplaySize.x - 200;\r\n\t\tfloat height = 110;\r\n\r\n\t\tImGui::SetNextWindowSize(ImVec2(width, height));\r\n\t\tImGui::SetNextWindowPos(ImVec2(100, io.DisplaySize.y - height - 90));\r\n\r\n\t\tImGui::Begin(\"Animation\", &isOpen);\r\n\r\n\t\tImGui::BeginChild(\"AnimButtons\", ImVec2(200, 100), true);\r\n\r\n\t\tImGui::PushItemWidth(300);\r\n\t\t\r\n\t\tstatic int selectedTrackIdx = 0;\r\n\t\tImGui::Combo(\"##cmbActiveTarget\", &selectedTrackIdx, &_trackNameChrs[0], (int) _trackNameChrs.size());\r\n\r\n\t\tif (selectedTrackIdx != _controller->GetActiveTargetIndex())\r\n\t\t\t_controller->SetActiveTargetIndex(selectedTrackIdx);\r\n\r\n\t\tImGui::PopItemWidth();\r\n\t\t\r\n\t\tImGui::PushItemWidth(100);\r\n\t\t\r\n\t\tif (_controller->IsPlaying()) {\r\n\t\t\tif (ImGui::Button(\"Pause\"))\r\n\t\t\t\t_controller->Pause();\r\n\t\t}\r\n\t\telse if (ImGui::Button(\"Play\"))\r\n\t\t\t_controller->Play();\r\n\r\n\t\tImGui::SameLine();\r\n\t\tif (ImGui::Button(\"Key->>\"))\r\n\t\t\t_controller->JumpNextKeyframe();\r\n\t\tif (ImGui::IsItemHovered())\r\n\t\t\tImGui::SetTooltip(\"Jump to next keyframe\");\r\n\r\n\t\tImGui::SameLine();\r\n\t\tif (ImGui::Button(\"+ Key\"))\r\n\t\t\t_controller->InsertKeyframe();\r\n\t\tif (ImGui::IsItemHovered())\r\n\t\t\tImGui::SetTooltip(\"Insert keyframe at current time\");\r\n\r\n\t\tif (ImGui::Button(\"Stop\"))\r\n\t\t\t_controller->Stop();\r\n\r\n\t\tImGui::SameLine();\r\n\t\tif (ImGui::Button(\"<<-Key\"))\r\n\t\t\t_controller->JumpPrevKeyframe();\r\n\t\tif (ImGui::IsItemHovered())\r\n\t\t\tImGui::SetTooltip(\"Jump to previous keyframe\");\r\n\r\n\t\tImGui::SameLine();\r\n\t\tif (ImGui::Button(\"- Key\"))\r\n\t\t\t_controller->DeleteLastKeyframe();\r\n\t\tif (ImGui::IsItemHovered())\r\n\t\t\tImGui::SetTooltip(\"Delete last keyframe\");\r\n\r\n\t\tImGui::PopItemWidth();\r\n\r\n\t\tImGui::EndChild();\r\n\r\n\t\tImGui::SameLine();\r\n\r\n\t\tImGui::BeginChild(\"AnimTimeLine\", ImVec2(ImGui::GetWindowContentRegionWidth() - 200, 80), true);\r\n\r\n\t\tauto sceneAnimation = _controller->GetSceneAnimation();\r\n\t\tfloat start, end;\r\n\t\tsceneAnimation->GetTimeSpan(start, end);\r\n\t\ttime = sceneAnimation->GetTime();\r\n\r\n\t\tstatic char txtInputStart[16] = \"0.0\";\r\n\t\tstatic char txtInputEnd[16] = \"0.0\";\r\n\t\tif (_lastAnimStart != start || _lastAnimEnd != end) {\r\n\t\t\tGUIUtil::CopyFloatToCharArray(start, txtInputStart);\r\n\t\t\tGUIUtil::CopyFloatToCharArray(end, txtInputEnd);\r\n\t\t\t_lastAnimStart = start;\r\n\t\t\t_lastAnimEnd = end;\r\n\t\t}\r\n\r\n\t\tconst float timeLineWidth = ImGui::GetWindowContentRegionWidth();\r\n\t\t\r\n\t\tImGui::PushItemWidth(60);\r\n\t\tif (ImGui::InputText(\"##start\", txtInputStart, 16, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_EnterReturnsTrue)) {\r\n\t\t\tfloat f = std::atof(txtInputStart);\r\n\t\t\tif (f < _lastAnimEnd)\r\n\t\t\t\t_lastAnimStart = f;\r\n\t\t\telse\r\n\t\t\t\tGUIUtil::CopyFloatToCharArray(_lastAnimStart, txtInputStart);\r\n\t\t}\r\n\t\tif (ImGui::IsItemHovered())\r\n\t\t\tImGui::SetTooltip(\"Animation start time\");\r\n\t\tImGui::PopItemWidth();\r\n\t\tImGui::SameLine();\r\n\r\n\t\tImGui::PushItemWidth(timeLineWidth - 120);\r\n\t\tif (ImGui::SliderFloat(\"##sldTime\", &time, start, end)) {\r\n\t\t\t// if the value changed we pause the animation and let the slider control the time\r\n\t\t\t_controller->Play();\r\n\t\t\tsceneAnimation->SetTime(time);\r\n\t\t\t_controller->Update(0);\r\n\t\t\t_controller->Pause();\r\n\t\t}\r\n\t\tImGui::PopItemWidth();\r\n\r\n\t\tImGui::SameLine();\r\n\r\n\t\tImGui::PushItemWidth(60);\r\n\t\tif (ImGui::InputText(\"##end\", txtInputEnd, 16, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_EnterReturnsTrue)) {\r\n\t\t\tfloat f = std::atof(txtInputEnd);\r\n\t\t\tif (f > _lastAnimStart)\r\n\t\t\t\t_lastAnimEnd = f;\r\n\t\t\telse\r\n\t\t\t\tGUIUtil::CopyFloatToCharArray(_lastAnimEnd, txtInputEnd);\r\n\t\t}\r\n\t\tif (ImGui::IsItemHovered())\r\n\t\t\tImGui::SetTooltip(\"Animation end time\");\r\n\t\tImGui::PopItemWidth();\r\n\r\n\t\tImGui::Separator();\r\n\r\n\t\t{\r\n\t\t\tImDrawList* draw_list = ImGui::GetWindowDrawList();\r\n\r\n\t\t\tauto animation = _controller->GetActiveAnimationFromScene();\r\n\t\t\tART_ASSERT(animation);\r\n\r\n\t\t\t// use custom drawing to render keyframes\r\n\t\t\tconst ImVec2 p = ImGui::GetCursorScreenPos();\r\n\t\t\tconst ImU32 backColor = ImColor(ImVec4(0.2f, 0.2f, 0.2f, 1.0f));\r\n\t\t\tconst ImU32 keyColor = ImColor(ImVec4(1.0f, 1.0f, 1.0f, 1.0f));\r\n\t\t\tconst ImU32 timeColor = ImColor(ImVec4(1.0f, 0.0f, 0.0f, 1.0f));\r\n\t\t\tstatic float sz = 12.0f;\r\n\r\n\t\t\tdraw_list->AddRectFilled(ImVec2(p.x, p.y + 2.0f), ImVec2(p.x + timeLineWidth, p.y + 6.0f + sz), backColor);\r\n\r\n\t\t\tfor (size_t iKeyframe = 0; iKeyframe < animation->GetKeyframeCount(); iKeyframe++) {\r\n\t\t\t\t\r\n\t\t\t\tfloat keyTime = animation->GetKeyframeTime(iKeyframe);\r\n\r\n\t\t\t\tfloat relOffset = (keyTime - start) / (end - start);\r\n\t\t\t\t\r\n\t\t\t\tfloat x = p.x + relOffset * timeLineWidth, y = p.y + 4.0f;\r\n\r\n\t\t\t\t//draw_list->AddCircleFilled(ImVec2(x, y + sz*0.5f), sz*0.5f, keyColor);;\r\n\t\t\t\tdraw_list->AddRectFilled(ImVec2(x-1, y), ImVec2(x + 1, y + sz), keyColor);\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// render current time\r\n\t\t\tfloat relOffset = (time - start) / (end - start);\r\n\t\t\tfloat x = p.x + relOffset * timeLineWidth, y = p.y + 4.0f;\r\n\r\n\t\t\t//draw_list->AddCircleFilled(ImVec2(x, y + sz*0.5f), sz*0.5f, keyColor);;\r\n\t\t\tdraw_list->AddRectFilled(ImVec2(p.x, p.y + 0.5 * sz + 2), ImVec2(x, p.y + 0.5 * sz + 6), timeColor);\r\n\t\t\tdraw_list->AddRectFilled(ImVec2(x - 1, y), ImVec2(x + 1, y + sz), timeColor);\r\n\r\n\t\t}\r\n\r\n\t\tImGui::EndChild();\r\n\r\n\t\tImGui::End();\r\n\t\tif (_lastAnimStart != start || _lastAnimEnd != end) {\r\n\t\t\tif (time < _lastAnimStart)\r\n\t\t\t\ttime = _lastAnimStart;\r\n\t\t\tif (time > _lastAnimEnd)\r\n\t\t\t\ttime = _lastAnimEnd;\r\n\r\n\t\t\tsceneAnimation->SetTimeSpan(_lastAnimStart, _lastAnimEnd);\r\n\t\t\tsceneAnimation->SetTime(time);\r\n\t\t}\r\n\r\n\r\n\t\tif(_showHelp)\r\n\t\t\tshowHelpOverlay();\r\n\t}\r\n\r\n\tvoid AnimationWidget::showHelpOverlay() {\r\n\t\tImGui::SetNextWindowPos(ImVec2(50, 50));\r\n\t\tImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));\r\n\r\n\t\tImGui::Begin(\"Animation Keyboard Shortcuts\", NULL, \r\n\t\t\tImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings);\r\n\r\n\t\tImGui::Text(\"Animation Controls\");\r\n\t\tImGui::Separator();\r\n\t\tImGui::Text(\"PAUSE       toggle playing\");\r\n\t\tImGui::Text(\"LCTRL + >   jump to next keyframe\");\r\n\t\tImGui::Text(\"LCTRL + <   jump to prev keyframe\");\r\n\t\tImGui::Separator();\r\n\t\tImGui::Text(\"LCTRL + INS insert new keyframe at current time\");\r\n\t\tImGui::Text(\"LCTRL + DEL insert new keyframe at current time\");\r\n\t\tImGui::Separator();\r\n\t\tImGui::Text(\"LCTRL + S\t save animation\");\r\n\t\tImGui::Text(\"LCTRL + R   reload animation\");\r\n\r\n\t\tImGui::End();\r\n\t\tImGui::PopStyleColor();\r\n\t}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/AnimationWidget.h",
    "content": "#pragma once\r\n\r\n#include \"..\\CommonDefs.h\"\r\n#include \"..\\Animation\\AnimationController.h\"\r\n\r\n#include \"IGUIWidget.h\"\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\nnamespace ARTGUI {\r\n\r\n\r\n\tclass AnimationWidget;\r\n\tDECLARE_PTR_TYPES(AnimationWidget);\r\n\r\n\r\n\tclass AnimationWidget : public IGUIWidget {\r\n\tpublic:\r\n\r\n\t\tAnimationWidget(const ART::AnimationController_ptr& controller);\r\n\r\n\t\tvirtual ~AnimationWidget() {}\r\n\r\n\t\tvirtual void Init() override;\r\n\t\t\r\n\t\tvirtual void Update(float elapsedTime) override;\r\n\t\t\r\n\t\tvirtual void Render() override;\r\n\r\n\t\tstatic AnimationWidget_ptr Create(const ART::AnimationController_ptr& controller) {\r\n\t\t\treturn std::make_shared<AnimationWidget>(controller);\r\n\t\t}\r\n\r\n\tprotected:\r\n\r\n\t\tvoid showHelpOverlay();\r\n\r\n\t\tART::AnimationController_ptr\t\t\t_controller;\r\n\r\n\t\tbool\t\t\t\t\t\t\t\t\t\t\t_showHelp;\r\n\t\tfloat\t\t\t\t\t\t\t\t\t\t\t_timeElapsed; // just to time the help screen\r\n\r\n\t\tfloat\t\t\t\t\t\t\t\t\t\t\t_lastAnimStart;\r\n\t\tfloat\t\t\t\t\t\t\t\t\t\t\t_lastAnimEnd;\r\n\r\n\t\tstd::vector<std::string>\t\t\t\t\t\t_trackNames;\r\n\t\tstd::vector<const char*>\t\t\t\t\t\t_trackNameChrs;\r\n\r\n\t};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/GUICore.cpp",
    "content": "\r\n#include \"pch.h\"\r\n\r\n#include \"GUICore.h\"\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\n#include \"imgui\\imgui.h\"\r\n#include \"imgui\\imgui_impl_dx11.h\"\r\n\r\n#include \"..\\..\\CommandContext.h\"\r\n#include \"..\\..\\GraphicsCore.h\"\r\n#include \"..\\..\\CommandListManager.h\"\r\n#include \"..\\..\\ColorBuffer.h\"\r\n#include \"..\\..\\Utility.h\"\r\n#include \"..\\..\\GameInput.h\"\r\n\r\n#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))\r\n#define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))\r\n\r\n#include <vector>\r\n#include <string>\r\n\r\nusing namespace Graphics;\r\nusing namespace std;\r\n\r\nnamespace ARTGUI {\r\n\r\n\tID3D11DeviceContext*\t\tg_DeviceContext11 = nullptr;\r\n\tComPtr<ID3D11Device>\t\tg_Device11;\r\n\tComPtr<ID3D11On12Device>\tg_Device11on12;\r\n\tComPtr<ID2D1Factory3>\t\tg_D2DFactory;\r\n\tComPtr<ID2D1Device2>\t\tg_D2DDevice;\r\n\tComPtr<ID2D1DeviceContext2>\tg_D2DDeviceContext;\r\n\tComPtr<IDWriteFactory>\t\tg_DWriteFactory;\r\n\r\n\tvector<ComPtr<ID3D11Texture2D>>\t\t\tg_WrappedBackbuffers;\r\n\tvector<ComPtr<ID2D1Bitmap1>>\t\t\tg_D2DRenderTargets;\r\n\tvector<ComPtr<ID3D11RenderTargetView>>\tg_D3D11RTV;\r\n\r\n\t// temporary GUI objects for testing\r\n\tComPtr<ID2D1SolidColorBrush>\tg_TestBrush;\r\n\tComPtr<IDWriteTextFormat>\t\tg_TestText;\r\n\r\n\tvector<IGUIWidget_ptr>\t\t\tg_Widgets;\r\n\r\n\tHWND\t\t\t\t\t\t\tg_hWnd = NULL;\r\n\r\n\tGameInput::DigitalInput\t\t\tg_KeyCodeLUT[512];\r\n\r\n\tbool\t\t\t\t\t\t\tg_IsVisible = false;\r\n\tbool\t\t\t\t\t\t\tg_IsFocused = true;\r\n\r\n\tstd::wstring\t\t\t\t\tg_Text;\r\n\r\n\tvoid initKeyCodes() {\r\n\t\tusing namespace GameInput;\r\n\r\n\t\tfor (uint32_t i = 0; i < 512; i++) {\r\n\t\t\tg_KeyCodeLUT[i] = kNumKeys;\r\n\t\t}\r\n\t\t\r\n\t\tg_KeyCodeLUT['a'] = kKey_a;\r\n\t\tg_KeyCodeLUT['b'] = kKey_b;\r\n\t\tg_KeyCodeLUT['c'] = kKey_c;\r\n\t\tg_KeyCodeLUT['d'] = kKey_d;\r\n\t\tg_KeyCodeLUT['e'] = kKey_e;\r\n\t\tg_KeyCodeLUT['f'] = kKey_f;\r\n\t\tg_KeyCodeLUT['g'] = kKey_g;\r\n\t\tg_KeyCodeLUT['h'] = kKey_h;\r\n\t\tg_KeyCodeLUT['i'] = kKey_i;\r\n\t\tg_KeyCodeLUT['j'] = kKey_j;\r\n\t\tg_KeyCodeLUT['k'] = kKey_k;\r\n\t\tg_KeyCodeLUT['l'] = kKey_l;\r\n\t\tg_KeyCodeLUT['m'] = kKey_m;\r\n\t\tg_KeyCodeLUT['n'] = kKey_n;\r\n\t\tg_KeyCodeLUT['o'] = kKey_o;\r\n\t\tg_KeyCodeLUT['p'] = kKey_p;\r\n\t\tg_KeyCodeLUT['q'] = kKey_q;\r\n\t\tg_KeyCodeLUT['r'] = kKey_r;\r\n\t\tg_KeyCodeLUT['s'] = kKey_s;\r\n\t\tg_KeyCodeLUT['t'] = kKey_t;\r\n\t\tg_KeyCodeLUT['u'] = kKey_u;\r\n\t\tg_KeyCodeLUT['v'] = kKey_v;\r\n\t\tg_KeyCodeLUT['w'] = kKey_w;\r\n\t\tg_KeyCodeLUT['x'] = kKey_x;\r\n\t\tg_KeyCodeLUT['y'] = kKey_y;\r\n\t\tg_KeyCodeLUT['z'] = kKey_z;\r\n\r\n\t\tg_KeyCodeLUT['0'] = kKey_0;\r\n\t\tg_KeyCodeLUT['1'] = kKey_1;\r\n\t\tg_KeyCodeLUT['2'] = kKey_2;\r\n\t\tg_KeyCodeLUT['3'] = kKey_3;\r\n\t\tg_KeyCodeLUT['4'] = kKey_4;\r\n\t\tg_KeyCodeLUT['5'] = kKey_5;\r\n\t\tg_KeyCodeLUT['6'] = kKey_6;\r\n\t\tg_KeyCodeLUT['7'] = kKey_7;\r\n\t\tg_KeyCodeLUT['8'] = kKey_8;\r\n\t\tg_KeyCodeLUT['9'] = kKey_9;\r\n\r\n\t}\r\n\r\n\tvoid SetHwnd(HWND hWnd) {\r\n\t\tg_hWnd = hWnd;\r\n\t}\r\n\t\t\r\n\tvoid Initialize() {\r\n\t\t// Must be called after the DX12 device and the swapchain already exist\r\n\r\n\t\tinitKeyCodes();\r\n\r\n\t\tconst uint32_t numBackbuffers = Graphics::GetNumBackbuffers();\r\n\r\n\t\tFinalize();\r\n\r\n\t\tART_ASSERT(g_Device);\r\n\t\tART_ASSERT(g_hWnd);\r\n\r\n\t\tUINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;\r\n\r\n#ifdef _DEBUG\r\n\t\td3d11DeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;\r\n#endif\r\n\r\n\t\tID3D12CommandQueue* graphicsQueue = g_CommandManager.GetGraphicsQueue().GetCommandQueue();\r\n\r\n\t\tASSERT_SUCCEEDED(D3D11On12CreateDevice(\r\n\t\t\tg_Device,\r\n\t\t\td3d11DeviceFlags,\r\n\t\t\tnullptr,\r\n\t\t\t0,\r\n\t\t\treinterpret_cast<IUnknown**>(&graphicsQueue),\r\n\t\t\t1,\r\n\t\t\t0,\r\n\t\t\t&g_Device11,\r\n\t\t\t&g_DeviceContext11,\r\n\t\t\tnullptr\r\n\t\t));\r\n\r\n\t\tASSERT_SUCCEEDED(g_Device11.As(&g_Device11on12));\r\n\r\n\t\t// D2D / DWrite resources\r\n\t\tD2D1_FACTORY_OPTIONS d2dFactoryOptions = {};\r\n\t\tD2D1_DEVICE_CONTEXT_OPTIONS deviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE;\r\n\t\tASSERT_SUCCEEDED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3),\r\n\t\t\t&d2dFactoryOptions, &g_D2DFactory));\r\n\r\n\t\tComPtr<IDXGIDevice> dxgiDevice;\r\n\t\tASSERT_SUCCEEDED(g_Device11on12.As(&dxgiDevice));\r\n\t\tASSERT_SUCCEEDED(g_D2DFactory->CreateDevice(dxgiDevice.Get(), &g_D2DDevice));\r\n\t\tASSERT_SUCCEEDED(g_D2DDevice->CreateDeviceContext(deviceOptions, &g_D2DDeviceContext));\r\n\t\tASSERT_SUCCEEDED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &g_DWriteFactory));\r\n\r\n\t\tg_WrappedBackbuffers.resize(numBackbuffers);\r\n\t\tg_D2DRenderTargets.resize(numBackbuffers);\r\n\t\tg_D3D11RTV.resize(numBackbuffers);\r\n\r\n\t\t\t// initialize test GUI objects\r\n\t\t\tASSERT_SUCCEEDED(g_D2DDeviceContext->CreateSolidColorBrush(\r\n\t\t\t\tD2D1::ColorF(D2D1::ColorF::AntiqueWhite), &g_TestBrush\r\n\t\t\t\t ));\r\n\t\t\r\n\t\t\tASSERT_SUCCEEDED(g_DWriteFactory->CreateTextFormat(\r\n\t\t\t\tL\"Verdana\",\r\n\t\t\t\tNULL,\r\n\t\t\t\tDWRITE_FONT_WEIGHT_NORMAL,\r\n\t\t\t\tDWRITE_FONT_STYLE_NORMAL,\r\n\t\t\t\tDWRITE_FONT_STRETCH_NORMAL,\r\n\t\t\t\t36,\r\n\t\t\t\tL\"en-us\",\r\n\t\t\t\t&g_TestText\r\n\t\t\t\t));\r\n\t\tASSERT_SUCCEEDED(g_TestText->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));\r\n\t\tASSERT_SUCCEEDED(g_TestText->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER));\r\n\r\n\t\tImGui_ImplDX11_Init(g_hWnd, g_Device11.Get(), g_DeviceContext11);\r\n\r\n\t\tImGuiIO& io = ImGui::GetIO();\r\n\t\tio.MousePos.x = 100;\r\n\t\tio.MousePos.y = 100;\r\n\r\n\t\tUtility::Print(\"Basic GUI controls: [F1] toggle visibility, [TAB] toggle focus\");\r\n\r\n\t}\r\n\r\n\tvoid Finalize() {\r\n\r\n\t\tImGui_ImplDX11_Shutdown();\r\n\r\n\t\tReleaseSwapchainResources();\r\n\t\t\r\n\t\tif (g_DeviceContext11) {\r\n\t\t\tg_DeviceContext11->Release();\r\n\t\t\tg_DeviceContext11 = nullptr;\r\n\t\t}\r\n\r\n\t\tg_D2DDeviceContext.Reset();\r\n\t\tg_DWriteFactory.Reset();\r\n\t\tg_D2DFactory.Reset();\r\n\t\tg_D2DDevice.Reset();\r\n\r\n\t\tg_Device11on12.Reset();\r\n\t\tg_Device11.Reset();\r\n\t}\r\n\r\n\tvoid ReleaseSwapchainResources() {\r\n\r\n\t\tfor (auto& rtv : g_D3D11RTV)\r\n\t\t\trtv.Reset();\r\n\t\tfor (auto& d2dRT : g_D2DRenderTargets)\r\n\t\t\td2dRT.Reset();\r\n\t\tfor (auto& wrappedBackbuffer : g_WrappedBackbuffers)\r\n\t\t\twrappedBackbuffer.Reset();\r\n\t\r\n\t\tImGui_ImplDX11_InvalidateDeviceObjects();\r\n\t}\r\n\r\n\tvoid Resize(uint32_t width, uint32_t height) {\r\n\r\n\t\t// get render targets as DX11 wrapped resources\r\n\t\tsize_t numRTs = g_WrappedBackbuffers.size();\r\n\t\tfor (size_t iRT = 0; iRT < numRTs; iRT++) {\r\n\r\n\t\t\tauto rtv = Graphics::GetFramebufferByIdx((uint32_t) iRT).GetResource();\r\n\r\n\t\t\tD3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };\r\n\t\t\tASSERT_SUCCEEDED(g_Device11on12->CreateWrappedResource(\r\n\t\t\t\trtv,\r\n\t\t\t\t&d3d11Flags,\r\n\t\t\t\tD3D12_RESOURCE_STATE_RENDER_TARGET,\r\n\t\t\t\tD3D12_RESOURCE_STATE_RENDER_TARGET,\r\n\t\t\t\tIID_PPV_ARGS(&g_WrappedBackbuffers[iRT])\r\n\t\t\t));\r\n\r\n\t\t\t// Query the desktop's dpi settings, which will be used to create\r\n\t\t\t// D2D's render targets.\r\n\t\t\tfloat dpiX;\r\n\t\t\tfloat dpiY;\r\n\t\t\tg_D2DFactory->GetDesktopDpi(&dpiX, &dpiY);\r\n\t\t\tD2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(\r\n\t\t\t\tD2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,\r\n\t\t\t\tD2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),\r\n\t\t\t\tdpiX,\r\n\t\t\t\tdpiY\r\n\t\t\t);\r\n\r\n\t\t\t// create a render target for D3D11 to draw into\r\n\t\t\t// (we currently use this for ImGUI)\r\n\t\t\tD3D11_TEXTURE2D_DESC rtTexDesc;\r\n\t\t\tg_WrappedBackbuffers[iRT]->GetDesc(&rtTexDesc);\r\n\r\n\t\t\tD3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;\r\n\t\t\tZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));\r\n\t\t\trender_target_view_desc.Format = rtTexDesc.Format;\r\n\t\t\trender_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;\r\n\t\t\trender_target_view_desc.Texture2D.MipSlice = 0;\r\n\r\n\t\t\tASSERT_SUCCEEDED(g_Device11->CreateRenderTargetView(g_WrappedBackbuffers[iRT].Get(), &render_target_view_desc, g_D3D11RTV[iRT].ReleaseAndGetAddressOf()));\r\n\r\n\t\t\tASSERT(ImGui_ImplDX11_CreateDeviceObjects());\r\n\r\n\t\t\t// create a render target for D2D to draw into this back buffer\r\n\t\t\tComPtr<IDXGISurface> surface;\r\n\t\t\tASSERT_SUCCEEDED(g_WrappedBackbuffers[iRT].As(&surface));\r\n\t\t\tASSERT_SUCCEEDED(g_D2DDeviceContext->CreateBitmapFromDxgiSurface(\r\n\t\t\t\tsurface.Get(),\r\n\t\t\t\t&bitmapProperties,\r\n\t\t\t\t&g_D2DRenderTargets[iRT]\r\n\t\t\t));\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tvoid Update(float elapsedTime) {\r\n\r\n\t\tGameInput::AllowReadInputs(true);\r\n\r\n\t\t// to detect first key stroke.\r\n\t\t// we cannot rely on GameInput::FirstKeyPressed, since we clear the key states if the GUI is in focus\r\n\t\t// to prevent the game from intercepting the keystrokes\r\n\t\tstatic bool toggleFocused[2] = { false, false };\r\n\r\n\t\ttoggleFocused[0] = GameInput::IsPressed(GameInput::kKey_tab);\r\n\r\n\t\t// toggle visible / focused status\r\n\t\tif (GameInput::IsFirstPressed(GameInput::kKey_f1)) {\r\n\t\t\tif (!g_IsVisible) {\r\n\t\t\t\tg_IsVisible = true;\r\n\t\t\t\tg_IsFocused = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tg_IsVisible = false;\r\n\t\t}\r\n\r\n\t\tif (GameInput::IsFirstPressed(GameInput::kKey_escape))\r\n\t\t\tg_IsVisible = false;\r\n\r\n\t\tif (!IsVisible())\r\n\t\t\treturn;\r\n\r\n\t\tif (toggleFocused[0] && !toggleFocused[1]) {\r\n\t\t\tg_IsFocused = !g_IsFocused;\r\n\t\t\tGameInput::ClearDigitalInput(GameInput::kKey_tab);\r\n\t\t}\r\n\t\ttoggleFocused[1] = toggleFocused[0];\r\n\r\n\t\tif (!IsFocused())\r\n\t\t\treturn;\r\n\r\n\t\tImGuiIO& io = ImGui::GetIO();\r\n\r\n\t\t// mouse deltas\r\n\t\t// For some reason MiniEngine scales the analog values quite aggressively\r\n\t\tconst float sensitivity = 1200;\r\n\t\tfloat dMouseX = GameInput::GetAnalogInput(GameInput::kAnalogMouseX) * sensitivity;\r\n\t\tfloat dMouseY = GameInput::GetAnalogInput(GameInput::kAnalogMouseY) * -sensitivity;\r\n\r\n\t\tio.MousePos.x += dMouseX;\r\n\t\tio.MousePos.y += dMouseY;\r\n\r\n\t\tio.MouseDown[0] = GameInput::IsPressed(GameInput::kMouse0);\r\n\t\tio.MouseDown[1] = GameInput::IsPressed(GameInput::kMouse1);\r\n\t\tio.MouseDown[2] = GameInput::IsPressed(GameInput::kMouse2);\r\n\r\n\t\tfor (unsigned short i = 0; i < 512; i++) {\r\n\t\t\tif (g_KeyCodeLUT[i] != GameInput::kNumKeys) {\r\n\t\t\t\tio.KeysDown[i] = GameInput::IsPressed(g_KeyCodeLUT[i]) ? 1 : 0;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (auto& widget : g_Widgets) {\r\n\t\t\twidget->Update(elapsedTime);\r\n\t\t}\r\n\r\n\t\t// block all keyboard and mouse events from game\r\n\t\tGameInput::AllowReadInputs(false);\r\n\t}\r\n\r\n\tvoid Display(GraphicsContext& Context) {\r\n\t\tif (!IsVisible() && g_Text.size() == 0) return;\r\n\r\n\t\tconst uint32_t fbIndex = Graphics::GetActiveFramebufferIdx();\r\n\r\n\t\tContext.TransitionResource(Graphics::GetFramebufferByIdx(fbIndex), D3D12_RESOURCE_STATE_RENDER_TARGET, true);\r\n\t\tContext.Flush();\r\n\r\n\t\tID3D11Resource* backBufferResource = g_WrappedBackbuffers[fbIndex].Get();\r\n\t\tg_Device11on12->AcquireWrappedResources(&backBufferResource, 1);\r\n\r\n\t\t// Text display\r\n\t\tif (g_Text.size() > 0) {\r\n\t\t\tD2D1_SIZE_F rtSize = g_D2DRenderTargets[fbIndex]->GetSize();\r\n\t\t\tD2D1_RECT_F rect = D2D1::RectF(0, 50, rtSize.width - 100, rtSize.height - 50);\r\n\r\n\t\t\tg_D2DDeviceContext->SetTarget(g_D2DRenderTargets[fbIndex].Get());\r\n\t\t\tg_D2DDeviceContext->BeginDraw();\r\n\r\n\t\t\tg_D2DDeviceContext->SetTransform(D2D1::Matrix3x2F::Translation(0, -0.5f * rtSize.height + 50));\r\n\t\t\tg_TestText->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING);\r\n\t\t\tg_D2DDeviceContext->DrawTextW(\r\n\t\t\t\tg_Text.c_str(),\r\n\t\t\t\t(UINT32) g_Text.size(),\r\n\t\t\t\tg_TestText.Get(),\r\n\t\t\t\t&rect,\r\n\t\t\t\tg_TestBrush.Get()\r\n\t\t\t);\r\n\r\n\t\t\tg_D2DDeviceContext->EndDraw();\r\n\t\t}\r\n\r\n\t\tif (g_IsVisible) {\r\n\t\t\tImGui_ImplDX11_NewFrame();\r\n\r\n\t\t\tfor (auto& widget : g_Widgets)\r\n\t\t\t\twidget->Render();\r\n\r\n\t\t\tauto* rtv = g_D3D11RTV[fbIndex].Get();\r\n\t\t\tg_DeviceContext11->OMSetRenderTargets(1, &rtv, NULL);\r\n\r\n\t\t\tImGui::Render();\r\n\r\n\t\t}\r\n\r\n\t\tID3D11RenderTargetView* pNullRTV = nullptr;\r\n\t\tg_DeviceContext11->OMSetRenderTargets(1, &pNullRTV, NULL);\r\n\t\tg_DeviceContext11->Flush();\r\n\r\n\t\tg_Device11on12->ReleaseWrappedResources(&backBufferResource, 1);\r\n\r\n\t\tContext.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\r\n\t}\r\n\r\n\tbool IsFocused() {\r\n\t\treturn g_IsVisible && g_IsFocused; // tmp\r\n\t}\r\n\r\n\tbool IsVisible() {\r\n\t\treturn g_IsVisible;\r\n\t}\r\n\r\n\tvoid AddWidgetBase(const IGUIWidget_ptr& widget) {\r\n\t\tg_Widgets.push_back(widget);\r\n\t}\r\n\r\n\tLRESULT WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r\n\t\tif (!IsFocused())\r\n\t\t\treturn 0;\r\n\r\n\t\treturn ImGui_ImplDX11_WndProcHandler(hWnd, msg, wParam, lParam);\r\n\t}\r\n\r\n\tvoid SetText(const std::string& text) {\r\n\t\tg_Text = std::wstring(text.begin(), text.end());\r\n\t}\r\n\r\n}\r\n\r\n#endif // ART_ENABLE_GUI\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/GUICore.h",
    "content": "#pragma once\r\n\r\n#include \"..\\CommonDefs.h\"\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\n#include \"AnimationWidget.h\"\r\n\r\n// to avoid re-including these to all GUI classes\r\n#include <d3d11.h>\r\n#include <d3d11on12.h>\r\n#include <dwrite.h>\r\n#include <d2d1_3.h>\r\n#include <wrl.h>\r\n\r\n#include \"..\\..\\GraphicsCommon.h\"\r\n\r\nclass GraphicsContext;\r\n\r\nnamespace ARTGUI {\r\n\r\n\tusing namespace Microsoft::WRL;\r\n\r\n\t// GUI has three states:\r\n\t// 1 - hidden\r\n\t// 2 - visible\r\n\t// 3 - focused (visible and capturing input)\r\n\r\n\tvoid SetHwnd(HWND hWnd);\r\n\tvoid Initialize();\r\n\tvoid Finalize();\r\n\tvoid ReleaseSwapchainResources();\r\n\tvoid Resize(uint32_t width, uint32_t height);\r\n\tvoid Update(float frameTime);\r\n\tvoid Display(GraphicsContext& Context);\r\n\tbool IsVisible();\r\n\tbool IsFocused();\r\n\r\n\tvoid SetText(const std::string& text);\r\n\r\n\tvoid AddWidgetBase(const IGUIWidget_ptr& widget);\r\n\r\n\t// convenience method to avoid shared ptr conversions\r\n\ttemplate<class T>\r\n\tvoid AddWidget(const std::shared_ptr<T>& widget) {\r\n\t\tIGUIWidget_ptr iWidget = std::dynamic_pointer_cast<IGUIWidget, T>(widget);\r\n\t\tAddWidgetBase(widget);\r\n\t}\r\n\r\n\tLRESULT WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);\r\n\r\n\textern ID3D11DeviceContext*\t\t\tg_DeviceContext11;\r\n\textern ComPtr<ID3D11On12Device>\t\tg_Device11on12;\r\n\textern ComPtr<ID2D1Factory3>\t\tg_D2DFactory;\r\n\textern ComPtr<ID2D1Device2>\t\t\tg_D2DDevice;\r\n\textern ComPtr<ID2D1DeviceContext2>\tg_D2DDeviceContext;\r\n\textern ComPtr<IDWriteFactory>\t\tg_DWriteFactory;\r\n}\r\n\r\n#endif // ART_ENABLE_GUI\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/GUIUtil.h",
    "content": "#pragma once\r\n\r\n#pragma warning(disable: 4996)\r\n\r\n#include <sstream>\r\n\r\nnamespace ART {\r\n\r\n\tstruct GUIUtil {\r\n\t\t// helper function\r\n\t\tstatic void CopyFloatToCharArray(float f, char* buffer) {\r\n\t\t\tstd::stringstream strm;\r\n\t\t\tstrm << f;\r\n\r\n\t\t\tstrm.str().copy(buffer, strm.str().length());\r\n\t\t\tbuffer[strm.str().length()] = '\\0';\r\n\t\t}\r\n\t};\r\n\r\n}\r\n\r\n#pragma warning(default: 4996)\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/IGUIWidget.h",
    "content": "#pragma once\r\n\r\n#pragma once\r\n\r\n#include \"..\\CommonDefs.h\"\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\nnamespace ARTGUI {\r\n\t\r\n\tstruct IGUIWidget {\r\n\t\tvirtual ~IGUIWidget() {};\r\n\r\n\t\tvirtual void Init() = 0;\r\n\r\n\t\tvirtual void Update(float elapsedTime) = 0;\r\n\r\n\t\t// called by the GUI framework, this makes the widget to render\r\n\t\t// later on we can extend this by defining the parent frame, right now this is very minimalistic\r\n\t\tvirtual void Render() = 0;\r\n\t};\r\n\r\n\tDECLARE_PTR_TYPES(IGUIWidget);\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/SequencerWidget.cpp",
    "content": "\r\n#include \"pch.h\"\r\n\r\n#include \"SequencerWidget.h\"\r\n\r\n#include \"..\\CommonDefs.h\"\r\n\r\n#include \"imgui\\imgui.h\"\r\n#include \"imgui\\imgui_impl_dx11.h\"\r\n\r\n#include \"..\\..\\GameInput.h\"\r\n\r\n#include \"GUICore.h\"\r\n#include \"GUIUtil.h\"\r\n\r\nusing namespace ART;\r\n\r\n#pragma warning(disable: 4996)\r\n\r\n\r\n// NOTE: while this widget is implemented as a class, due to the stateless immediate manner of ImGUI\r\n// we currently store all states in a static variable\r\n// This means that only one instance of thie widget can work properly at once\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\nnamespace ARTGUI {\r\n\r\n\tSequencerWidget::SequencerWidget(ART::FrameSequencer* sequencer, const ART::AnimationController_ptr& controller):\r\n\t\t_sequencer(sequencer),\r\n\t\t_controller(controller)\r\n\t{\r\n\t\t_nextSequence.Name = \"MySequence\";\r\n\t\t//_nextSequence.FPS = 24.0f;\r\n\t\t//_nextSequence.CaptureFPS = 24.0f;\r\n\t\t_nextSequence.FPS = 60.0f;\r\n\t\t_nextSequence.CaptureFPS = 60.0f;\r\n\t}\r\n\r\n\tvoid SequencerWidget::Init() {\r\n\r\n\t}\r\n\r\n\tvoid SequencerWidget::Update(float elapsedTime) {\r\n\t\tif (_sequencer->IsCapturing() && _sequencer->GetCurrFrameID() == 0)\r\n\t\t\t_controller->Play();\r\n\t}\r\n\r\n\t// helper method\r\n\tvoid updateFloatFromCharArray(float& f, char* txt) {\r\n\t\tfloat tmp = std::atof(txt);\r\n\t\tif (f > 0.0f) {\r\n\t\t\tf = tmp;\r\n\t\t}\r\n\t\telse\r\n\t\t\tGUIUtil::CopyFloatToCharArray(f, txt);\r\n\t}\r\n\r\n\tvoid SequencerWidget::Render() {\r\n\t\tstatic bool isOpen = true;\r\n\r\n\t\tauto& io = ImGui::GetIO();\r\n\r\n\t\tfloat width = 350;\r\n\t\tfloat height = 150;\r\n\r\n\t\tImGui::SetNextWindowSize(ImVec2(width, height));\r\n\t\tImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x - width - 100, 100));\r\n\r\n\t\tImGui::Begin(\"Sequencer\", &isOpen);\r\n\r\n\t\tImGui::Text(\"Sequence Name: \");\r\n\t\tImGui::SameLine();\r\n\r\n\t\tImGui::PushItemWidth(200);\r\n\r\n\t\tstatic char txtSeqName[24] = \"MySequence\";\r\n\t\tif (ImGui::InputText(\"##txtSeqName\", txtSeqName, 24, ImGuiInputTextFlags_EnterReturnsTrue)) {\r\n\t\t\tstd::string name(txtSeqName);\r\n\t\t\tif (name.size() > 0)\r\n\t\t\t\t_nextSequence.Name = name;\r\n\t\t\telse\r\n\t\t\t\t_nextSequence.Name.copy(txtSeqName, _nextSequence.Name.size());\r\n\t\t}\r\n\t\tImGui::PopItemWidth();\r\n\r\n\t\tImGui::Text(\"Render Frame Rate: \");\r\n\t\tImGui::SameLine();\r\n\r\n\t\tImGui::PushItemWidth(200);\r\n\r\n\t\t//static char txtSequenceFPS[8] = \"24.0\";\r\n\t\t//static char txtCaptureFPS[8] = \"24.0\";\r\n\t\tstatic char txtSequenceFPS[8] = \"60.0\";\r\n\t\tstatic char txtCaptureFPS[8] = \"1.0\";\r\n\t\tif (ImGui::InputText(\"##txtSeqFPS\", txtSequenceFPS, 8, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_EnterReturnsTrue)) {\r\n\t\t\tfloat f = std::atof(txtSequenceFPS);\r\n\t\t\tif (f > 0.0f) {\r\n\t\t\t\t_nextSequence.FPS = f;\r\n\t\t\t\tif (f < _nextSequence.CaptureFPS) {\r\n\t\t\t\t\t_nextSequence.CaptureFPS = f;\r\n\t\t\t\t\tGUIUtil::CopyFloatToCharArray(f, txtCaptureFPS);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tGUIUtil::CopyFloatToCharArray(_nextSequence.FPS, txtSequenceFPS);\r\n\t\t}\r\n\t\tImGui::PopItemWidth();\r\n\r\n\t\tImGui::Text(\"Capture Frame Rate: \");\r\n\t\tImGui::SameLine();\r\n\r\n\t\tImGui::PushItemWidth(200);\r\n\r\n\t\tif (ImGui::InputText(\"##txtCapFPS\", txtCaptureFPS, 8, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_EnterReturnsTrue)) {\r\n\t\t\tfloat f = std::atof(txtCaptureFPS);\r\n\t\t\tif (f > 0.0f) {\r\n\t\t\t\t_nextSequence.CaptureFPS = f;\r\n\t\t\t\tif (f > _nextSequence.FPS) {\r\n\t\t\t\t\t_nextSequence.FPS = f;\r\n\t\t\t\t\tGUIUtil::CopyFloatToCharArray(f, txtSequenceFPS);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t\tGUIUtil::CopyFloatToCharArray(_nextSequence.CaptureFPS, txtCaptureFPS);\r\n\t\t}\r\n\t\tImGui::PopItemWidth();\r\n\r\n\r\n\t\tImGui::PushItemWidth(300);\r\n\t\tif (_sequencer->IsCapturing()) {\r\n\t\t\tif (ImGui::Button(\"Stop\")) {\r\n\t\t\t\tendSequence();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\tif (ImGui::Button(\"Render\")) {\r\n\r\n\t\t\t\tstd::string name(txtSeqName);\r\n\t\t\t\tif (name.size() > 0) _nextSequence.Name = name;\r\n\t\t\t\tupdateFloatFromCharArray(_nextSequence.FPS, txtSequenceFPS);\r\n\t\t\t\tupdateFloatFromCharArray(_nextSequence.CaptureFPS, txtCaptureFPS);\r\n\t\t\t\tif (_nextSequence.CaptureFPS > _nextSequence.FPS)\r\n\t\t\t\t\t_nextSequence.CaptureFPS = _nextSequence.FPS;\r\n\r\n\t\t\t\tbeginSequence();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tImGui::PopItemWidth();\r\n\r\n\t\tImGui::Separator();\r\n\r\n\t\tif (_sequencer->IsCapturing()) {\r\n\r\n\t\t\tint frameCnt = _sequencer->GetTotalFrameCnt();\r\n\t\t\tint currFrameIdx = _sequencer->GetCurrFrameID();\r\n\r\n\t\t\tfloat progress = currFrameIdx / (float)frameCnt;\r\n\r\n\t\t\tstd::stringstream progressStrm;\r\n\t\t\tprogressStrm << \"[\" << currFrameIdx << \"/\" << frameCnt << \"]\";\r\n\t\t\tImGui::ProgressBar(progress, ImVec2(-1, 0), progressStrm.str().c_str());\r\n\t\t}\r\n\r\n\t\tImGui::End();\r\n\r\n\t}\r\n\r\n\tvoid SequencerWidget::beginSequence() {\r\n\r\n\t\tauto sceneAnimation = _controller->GetSceneAnimation();\r\n\t\tsceneAnimation->GetTimeSpan(_nextSequence.StartTime, _nextSequence.EndTime);\r\n\r\n\t\t_controller->Stop();\r\n\t\t_sequencer->BeginCapture(_nextSequence);\r\n\r\n\t}\r\n\r\n\tvoid SequencerWidget::endSequence() {\r\n\t\t_controller->Stop();\r\n\t\t_sequencer->EndCapture();\r\n\t}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/SequencerWidget.h",
    "content": "#pragma once\r\n\r\n#include \"..\\CommonDefs.h\"\r\n#include \"..\\Sequencer\\FrameSequencer.h\"\r\n#include \"..\\Animation\\AnimationController.h\"\r\n\r\n#include \"IGUIWidget.h\"\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\r\nnamespace ARTGUI {\r\n\r\n\tclass SequencerWidget;\r\n\tDECLARE_PTR_TYPES(SequencerWidget);\r\n\r\n\tclass SequencerWidget : public IGUIWidget {\r\n\tpublic:\r\n\r\n\t\tSequencerWidget(ART::FrameSequencer* sequencer, const ART::AnimationController_ptr& controller);\r\n\r\n\t\tvirtual ~SequencerWidget() {}\r\n\r\n\t\tvirtual void Init() override;\r\n\r\n\t\tvirtual void Update(float elapsedTime) override;\r\n\r\n\t\tvirtual void Render() override;\r\n\r\n\t\tstatic SequencerWidget_ptr Create(ART::FrameSequencer* sequencer, const ART::AnimationController_ptr& controller) {\r\n\t\t\treturn std::make_shared<SequencerWidget>(sequencer, controller);\r\n\t\t}\r\n\r\n\tprotected:\r\n\r\n\t\tvoid beginSequence();\r\n\t\tvoid endSequence();\r\n\r\n\t\tART::FrameSequencer*\t\t\t\t_sequencer;\r\n\t\tART::AnimationController_ptr\t\t_controller;\r\n\r\n\t\tART::FrameSequence\t\t\t\t\t_nextSequence;\r\n\r\n\t};\r\n\r\n}\r\n\r\n#endif // ART_ENABLE_GUI\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/LICENSE.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014-2017 Omar Cornut and ImGui contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/README.md",
    "content": "dear imgui,\n=====\n[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui)\n[![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720)\n\n(This library is free but needs your support to sustain its development. There are lots of desirable new features and maintenance to do. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for private support, custom development etc. E-mail: omarcornut at gmail.)\n\nMonthly donations via Patreon:\n<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)\n\nOne-off donations via PayPal:\n<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)\n\ndear imgui (AKA ImGui), is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).\n\nImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.\n\nImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard. \n\nImGui is self-contained within a few files that you can easily copy and compile into your application/engine:\n\n  - imgui.cpp\n  - imgui.h\n  - imgui_demo.cpp\n  - imgui_draw.cpp\n  - imgui_internal.h\n  - imconfig.h (empty by default, user-editable)\n  - stb_rect_pack.h\n  - stb_textedit.h\n  - stb_truetype.h\n\nNo specific build process is required. You can add the .cpp files to your project or #include them from an existing file.\n\nYour code passes mouse/keyboard inputs and settings to ImGui (see example applications for more details). After ImGui is setup, you can use it like in this example:\n\n![screenshot of sample code alongside its output with ImGui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png)\n\nImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase. \n\n_A common misunderstanding is to think that immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions are called by the user. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._\n\nImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc.  \n\nBinaries/Demo\n-------------\n\nYou should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some ImGui features, you can download Windows binaries of the demo app here:\n- [imgui-demo-binaries-20170723.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20170723.zip) (Windows binaries, ImGui 1.51+ 2017/07/23, 5 executables, 808 KB)\n\nBindings\n--------\n\n_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_\n\n_Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation!_\n\nLanguages:\n- C - cimgui: thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui\n- C#/.Net - ImGui.NET: An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET\n- D - DerelictImgui: Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui\n- Go - go-imgui https://github.com/Armored-Dragon/go-imgui\n- Lua - https://github.com/patrickriordan/imgui_lua_bindings\n- Pascal - imgui-pas https://github.com/dpethes/imgui-pas\n- Python - CyImGui: Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui\n- Python - pyimgui: Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui\n- Rust - imgui-rs: Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs\n\nFrameworks:\n- Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples\n- Unmerged PR: DirectX12 example (with issues) https://github.com/ocornut/imgui/pull/301\n- Unmerged PR: SDL2 + OpenGLES + Emscripten example https://github.com/ocornut/imgui/pull/336\n- Unmerged PR: FreeGlut + OpenGL2 example https://github.com/ocornut/imgui/pull/801\n- Unmerged PR: Native Win32 and OSX example https://github.com/ocornut/imgui/pull/281\n- Unmerged PR: Android Example https://github.com/ocornut/imgui/pull/421\n- Cinder backend for dear imgui https://github.com/simongeilfus/Cinder-ImGui\n- FlexGUI: Flexium/SFML backend for dear imgui https://github.com/DXsmiley/FlexGUI\n- IrrIMGUI: Irrlicht backend for dear imgui https://github.com/ZahlGraf/IrrIMGUI\n- UnrealEngine_ImGui: Unreal Engine 4 backend for dear imgui https://github.com/sronsse/UnrealEngine_ImGui\n- LÖVE backend for dear imgui https://github.com/slages/love-imgui\n- Ogre backend for dear imgui https://bitbucket.org/LMCrashy/ogreimgui/src\n- ofxImGui: openFrameworks backend for dear imgui https://github.com/jvcleave/ofxImGui\n- SFML backend for dear imgui https://github.com/EliasD/imgui-sfml\n- SFML backend for dear imgui https://github.com/Mischa-Alff/imgui-backends\n- cocos2d-x with imgui https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551\n- NanoRT: software raytraced version https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example\n\nFor other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/).\nPlease contact me with the Issues tracker or Twitter to fix/update this list.\n\nGallery\n-------\n\nSee the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for some user creations.\n\n![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png)\n[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png)\n![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_02.png)\n\n[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png)\n\n![screenshot 3](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_01.png)\n![screenshot 4](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/test_window_03.png)\n![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v140/test_window_05_menus.png)\n![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png)\n![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png)\n\nImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with:\n```\nImGuiIO& io = ImGui::GetIO();\nio.Fonts->AddFontFromFileTTF(\"ArialUni.ttf\", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());\n\n// For Microsoft IME, pass your HWND to enable IME positioning:\nio.ImeWindowHandle = my_hwnd;\n```\n![Japanese screenshot](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01_jp.png)\n\nReferences\n----------\n\nThe Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because \"Retained Mode\" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works. \n- [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html).\n- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf).\n- [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/).\n- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861).\n- [Nicolas Guillemot's CppCon'16 flashtalk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k).\n- [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/).\n\nSee the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks.\n\nFrequently Asked Question (FAQ)\n-------------------------------\n\n<b>Where is the documentation?</b>\n\n- The documentation is at the top of imgui.cpp + effectively imgui.h. \n- Example code is in imgui_demo.cpp and particularly the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output. \n- Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder. \n- We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.\n\n<b>Why the odd dual naming, \"dear imgui\" vs \"ImGui\"?</b>\n\nThe library started its life and is best known as \"ImGui\" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name \"dear imgui\" that people can use to refer to this specific library in ambiguous situations.\n\n<br><b>What is ImTextureID and how do I display an image?</b>\n<br><b>I integrated ImGui in my engine and the text or lines are blurry..</b>\n<br><b>I integrated ImGui in my engine and some elements are disappearing when I move windows around..</b>\n<br><b>How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs.</b>\n<br><b>How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?</b>\n<br><b>How can I load a different font than the default?</b>\n<br><b>How can I easily use icons in my application?</b>\n<br><b>How can I load multiple fonts?</b>\n<br><b>How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?</b>\n<br><b>How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables)</b>\n<br><b>How can I use the drawing facilities without an ImGui window? (using ImDrawList API)</b>\n\nSee the FAQ in imgui.cpp for answers.\n\n<b>How do you use ImGui on a platform that may not have a mouse or keyboard?</b>\n\nI recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate.\n\n<b>Can you create elaborate/serious tools with ImGui?</b>\n\nYes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more \"offline\" UI toolkits where only a fraction of your team effectively creates tools).\n\nImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make unnecessarily complicated things. ImGui is about making things that are simple, efficient and powerful.\n\n<b>Is ImGui fast?</b>\n\nProbably fast enough for most uses. Down to the foundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it.\n\nMileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended).\n\n![performance screenshot](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v138/performance_01.png)\n\nThis is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint.\n\nIf you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - one way is using helpers such as ImGuiListClipper - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem.\n\n<b>Can you reskin the look of ImGui?</b>\n\nYou can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. \n\nThis is [LumixEngine](https://github.com/nem0/LumixEngine) with a minor skinning hack + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged).\n\n[![Skinning in LumixEngine](https://cloud.githubusercontent.com/assets/8225057/13198792/92808c5c-d812-11e5-9507-16b63918b05b.jpg)](https://cloud.githubusercontent.com/assets/8225057/13044612/59f07aec-d3cf-11e5-8ccb-39adf2e13e69.png)\n\n<b>Why using C++ (as opposed to C)?</b>\n\nImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience.\n\nThere is an unofficial but reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly. I would suggest using your target language functionality to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. It was really designed with C++ in mind and may not make the same amount of sense with another language. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages.\n\nSupport dear imgui\n------------------\n\n<b>How can I help financing further development of Dear ImGui?</b>\n\nYour contributions are keeping the library alive. If you are an individual using dear imgui, please consider donating to enable me to spend more time improving the library.\n\nMonthly donations via Patreon:\n<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)\n\nOne-off donations via PayPal:\n<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)\n\nIf your company uses dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for private support, custom development etc. E-mail: omarcornut at gmail. Thanks!\n\nCredits\n-------\n\nDeveloped by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect contributors to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com). \n\nI first discovered imgui principles at [Q-Games](http://www.q-games.com) where Atman had dropped his own simple imgui implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating on it. \n\nEmbeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license).\n\nEmbeds [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).\n\nInspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub.\n\nOngoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui).\n\nDouble-chocolate sponsors:\n- Media Molecule\n- Mobigame\n- Insomniac Games (sponsored the gamepad/keyboard navigation branch)\n- Aras Pranckevičius\n\nSalty caramel supporters:\n- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko.\n\nCaramel supporters:\n- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, [Kit framework](http://svkonsult.se/kit), Josh Faust, Martin Donlon, Quinton, Felix.\n\nAnd other supporters; thanks!\n\nLicense\n-------\n\nDear ImGui is licensed under the MIT License, see LICENSE for more information.\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imconfig.h",
    "content": "//-----------------------------------------------------------------------------\r\n// USER IMPLEMENTATION\r\n// This file contains compile-time options for ImGui.\r\n// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO().\r\n//-----------------------------------------------------------------------------\r\n\r\n#pragma once\r\n\r\n//---- Define assertion handler. Defaults to calling assert().\r\n//#define IM_ASSERT(_EXPR)  MyAssert(_EXPR)\r\n\r\n//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.\r\n//#define IMGUI_API __declspec( dllexport )\r\n//#define IMGUI_API __declspec( dllimport )\r\n\r\n//---- Include imgui_user.h at the end of imgui.h\r\n//#define IMGUI_INCLUDE_IMGUI_USER_H\r\n\r\n//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)\r\n//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS\r\n//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS\r\n\r\n//---- Don't implement test window functionality (ShowTestWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)\r\n//---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why.\r\n//#define IMGUI_DISABLE_TEST_WINDOWS\r\n\r\n//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names\r\n//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS\r\n\r\n//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)\r\n//#define IMGUI_USE_BGRA_PACKED_COLOR\r\n\r\n//---- Implement STB libraries in a namespace to avoid conflicts\r\n//#define IMGUI_STB_NAMESPACE     ImGuiStb\r\n\r\n//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.\r\n/*\r\n#define IM_VEC2_CLASS_EXTRA                                                 \\\r\n        ImVec2(const MyVec2& f) { x = f.x; y = f.y; }                       \\\r\n        operator MyVec2() const { return MyVec2(x,y); }\r\n\r\n#define IM_VEC4_CLASS_EXTRA                                                 \\\r\n        ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; }     \\\r\n        operator MyVec4() const { return MyVec4(x,y,z,w); }\r\n*/\r\n\r\n//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices\r\n//#define ImDrawIdx unsigned int\r\n\r\n//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.\r\n//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers.\r\n/*\r\nnamespace ImGui\r\n{\r\n    void    Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL);\r\n}\r\n*/\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui.cpp",
    "content": "// dear imgui, v1.52 WIP\r\n// (main code and documentation)\r\n\r\n// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.\r\n// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase.\r\n// Get latest version at https://github.com/ocornut/imgui\r\n// Releases change-log at https://github.com/ocornut/imgui/releases\r\n// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269\r\n// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.\r\n// This library is free but I need your support to sustain development and maintenance.\r\n// If you work for a company, please consider financial support, e.g: https://www.patreon.com/imgui\r\n\r\n/*\r\n\r\n Index\r\n - MISSION STATEMENT\r\n - END-USER GUIDE\r\n - PROGRAMMER GUIDE (read me!)\r\n   - Read first\r\n   - How to update to a newer version of ImGui\r\n   - Getting started with integrating ImGui in your code/engine\r\n - API BREAKING CHANGES (read me when you update!)\r\n - ISSUES & TODO LIST\r\n - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS\r\n   - How can I help?\r\n   - What is ImTextureID and how do I display an image?\r\n   - I integrated ImGui in my engine and the text or lines are blurry..\r\n   - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around..\r\n   - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs.\r\n   - How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?\r\n   - How can I load a different font than the default?\r\n   - How can I easily use icons in my application?\r\n   - How can I load multiple fonts?\r\n   - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?\r\n   - How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables)\r\n   - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)\r\n - ISSUES & TODO-LIST\r\n - CODE\r\n\r\n\r\n MISSION STATEMENT\r\n =================\r\n\r\n - Easy to use to create code-driven and data-driven tools\r\n - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools\r\n - Easy to hack and improve\r\n - Minimize screen real-estate usage\r\n - Minimize setup and maintenance\r\n - Minimize state storage on user side\r\n - Portable, minimize dependencies, run on target (consoles, phones, etc.)\r\n - Efficient runtime and memory consumption (NB- we do allocate when \"growing\" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything)\r\n\r\n Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:\r\n - Doesn't look fancy, doesn't animate\r\n - Limited layout features, intricate layouts are typically crafted in code\r\n\r\n\r\n END-USER GUIDE\r\n ==============\r\n\r\n - Double-click title bar to collapse window\r\n - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin()\r\n - Click and drag on lower right corner to resize window\r\n - Click and drag on any empty space to move window\r\n - Double-click/double-tap on lower right corner grip to auto-fit to content\r\n - TAB/SHIFT+TAB to cycle through keyboard editable fields\r\n - Use mouse wheel to scroll\r\n - Use CTRL+mouse wheel to zoom window contents (if io.FontAllowScaling is true)\r\n - CTRL+Click on a slider or drag box to input value as text\r\n - Text editor:\r\n   - Hold SHIFT or use mouse to select text.\r\n   - CTRL+Left/Right to word jump\r\n   - CTRL+Shift+Left/Right to select words\r\n   - CTRL+A our Double-Click to select all\r\n   - CTRL+X,CTRL+C,CTRL+V to use OS clipboard\r\n   - CTRL+Z,CTRL+Y to undo/redo\r\n   - ESCAPE to revert text to its original value\r\n   - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)\r\n   - Controls are automatically adjusted for OSX to match standard OSX text editing operations.\r\n\r\n\r\n PROGRAMMER GUIDE\r\n ================\r\n\r\n READ FIRST\r\n\r\n - Read the FAQ below this section!\r\n - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.\r\n - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features.\r\n - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861\r\n\r\n HOW TO UPDATE TO A NEWER VERSION OF IMGUI\r\n\r\n - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)\r\n - Read the \"API BREAKING CHANGES\" section (below). This is where we list occasional API breaking changes. \r\n   If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed from the public API.\r\n   If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it. \r\n   Please report any issue to the GitHub page!\r\n - Try to keep your copy of dear imgui reasonably up to date.\r\n\r\n GETTING STARTED WITH INTEGRATING IMGUI IN YOUR CODE/ENGINE\r\n\r\n - Add the ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library.\r\n - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.\r\n - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because it is short, \r\n   then switch to the one more appropriate to your use case.\r\n - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/.\r\n - When using ImGui, your programming IDE if your friend: follow the declaration of variables, functions and types to find comments about them.\r\n\r\n - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize (application resolution).\r\n   Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic integration you don't need to worry about it all.\r\n - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory.\r\n - Every frame:\r\n    - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.)\r\n    - Call ImGui::NewFrame() to begin the imgui frame\r\n    - You can use any ImGui function you want between NewFrame() and Render()\r\n    - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler.\r\n       (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.)\r\n - All rendering information are stored into command-lists until ImGui::Render() is called.\r\n - ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide.\r\n - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in \"update\" vs \"render\" phases of your own application.\r\n - Refer to the examples applications in the examples/ folder for instruction on how to setup your code.\r\n - A minimal application skeleton may be:\r\n\r\n     // Application init\r\n     ImGuiIO& io = ImGui::GetIO();\r\n     io.DisplaySize.x = 1920.0f;\r\n     io.DisplaySize.y = 1280.0f;\r\n     io.RenderDrawListsFn = MyRenderFunction;  // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data.\r\n     // TODO: Fill others settings of the io structure later.\r\n\r\n     // Load texture atlas (there is a default font so you don't need to care about choosing a font yet)\r\n     unsigned char* pixels;\r\n     int width, height;\r\n     io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height);\r\n     // TODO: At this points you've got the texture data and you need to upload that your your graphic system:\r\n     MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA)\r\n     // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'. This will be passed back to your via the renderer.\r\n     io.Fonts->TexID = (void*)texture;\r\n\r\n     // Application main loop\r\n     while (true)\r\n     {\r\n        // Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)\r\n        ImGuiIO& io = ImGui::GetIO();\r\n        io.DeltaTime = 1.0f/60.0f;\r\n        io.MousePos = mouse_pos;\r\n        io.MouseDown[0] = mouse_button_0;\r\n        io.MouseDown[1] = mouse_button_1;\r\n\r\n        // Call NewFrame(), after this point you can use ImGui::* functions anytime\r\n        ImGui::NewFrame();\r\n\r\n        // Most of your application code here\r\n        MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin(\"My window\"); ImGui::Text(\"Hello, world!\"); ImGui::End();\r\n        MyGameRender(); // may use any ImGui functions as well!\r\n     \r\n        // Render & swap video buffers\r\n        ImGui::Render();\r\n        SwapBuffers();\r\n     }\r\n\r\n - A minimal render function skeleton may be:\r\n\r\n    void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data)\r\n    {\r\n       // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled\r\n       // TODO: Setup viewport, orthographic projection matrix\r\n       // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.\r\n       for (int n = 0; n < draw_data->CmdListsCount; n++)\r\n       {\r\n          const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;  // vertex buffer generated by ImGui\r\n          const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;   // index buffer generated by ImGui\r\n          for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)\r\n          {\r\n             const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];\r\n             if (pcmd->UserCallback)\r\n             {\r\n                 pcmd->UserCallback(cmd_list, pcmd);\r\n             }\r\n             else\r\n             {\r\n                 // Render 'pcmd->ElemCount/3' texture triangles\r\n                 MyEngineBindTexture(pcmd->TextureId);\r\n                 MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));\r\n                 MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);\r\n             }\r\n             idx_buffer += pcmd->ElemCount;\r\n          }\r\n       }\r\n    }\r\n\r\n - The examples/ folders contains many functional implementation of the pseudo-code above.\r\n - When calling NewFrame(), the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags are updated. \r\n   They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide \r\n   mouse inputs from the rest of your application. Read the FAQ below for more information about those flags.\r\n\r\n\r\n\r\n API BREAKING CHANGES\r\n ====================\r\n\r\n Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.\r\n Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.\r\n Also read releases logs https://github.com/ocornut/imgui/releases for more details.\r\n\r\n - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace \"io.MousePos = ImVec2(-1,-1)\" with \"io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)\".\r\n - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete).\r\n                     - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).\r\n                     - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).\r\n - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.\r\n - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an \"ambiguous call\" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.\r\n - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.\r\n - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.\r\n - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).\r\n - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).\r\n - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().\r\n - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.\r\n                     - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under \"Color/Picker Widgets\", to understand the various new options.\r\n                     - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))'\r\n - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse\r\n - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.\r\n - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.\r\n - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().\r\n - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.\r\n - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.\r\n - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.\r\n - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. \r\n                       If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. \r\n                       However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.\r\n                       This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color.\r\n                           ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)\r\n                           {\r\n                               float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;\r\n                               return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a);\r\n                           }\r\n                       If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.\r\n - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().\r\n - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.\r\n - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the \"default_open = true\" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).\r\n - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.\r\n - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).\r\n - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)\r\n - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).\r\n - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.\r\n - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.\r\n - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.\r\n - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.\r\n - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.\r\n                       GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.\r\n                       GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out!\r\n - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize\r\n - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project.\r\n - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason\r\n - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.\r\n                       you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.\r\n - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.\r\n                       this necessary change will break your rendering function! the fix should be very easy. sorry for that :(\r\n                     - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.\r\n                     - the signature of the io.RenderDrawListsFn handler has changed!\r\n                            ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)\r\n                       became:\r\n                            ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).\r\n                              argument   'cmd_lists'        -> 'draw_data->CmdLists'\r\n                              argument   'cmd_lists_count'  -> 'draw_data->CmdListsCount'\r\n                              ImDrawList 'commands'         -> 'CmdBuffer'\r\n                              ImDrawList 'vtx_buffer'       -> 'VtxBuffer'\r\n                              ImDrawList  n/a               -> 'IdxBuffer' (new)\r\n                              ImDrawCmd  'vtx_count'        -> 'ElemCount'\r\n                              ImDrawCmd  'clip_rect'        -> 'ClipRect'\r\n                              ImDrawCmd  'user_callback'    -> 'UserCallback'\r\n                              ImDrawCmd  'texture_id'       -> 'TextureId'\r\n                     - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.\r\n                     - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!\r\n                     - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!\r\n - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.\r\n - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).\r\n - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.\r\n - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence\r\n - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry!\r\n - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).\r\n - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).\r\n - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.\r\n - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the \"open\" state of a popup. BeginPopup() returns true if the popup is opened.\r\n - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).\r\n - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.\r\n - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API\r\n - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.\r\n - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.\r\n - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.\r\n - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing\r\n - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.\r\n - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)\r\n - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.\r\n - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.\r\n - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.\r\n - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior\r\n - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()\r\n - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)\r\n - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.\r\n - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.\r\n              (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.\r\n                       this sequence:\r\n                           const void* png_data;\r\n                           unsigned int png_size;\r\n                           ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);\r\n                           // <Copy to GPU>\r\n                       became:\r\n                           unsigned char* pixels;\r\n                           int width, height;\r\n                           io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);\r\n                           // <Copy to GPU>\r\n                           io.Fonts->TexID = (your_texture_identifier);\r\n                       you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.\r\n                       it is now recommended that you sample the font texture with bilinear interpolation.\r\n              (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.\r\n              (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)\r\n              (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets\r\n - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)\r\n - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)\r\n - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility\r\n - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()\r\n - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly)\r\n - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)\r\n - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()\r\n - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn\r\n - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)\r\n - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite\r\n - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes\r\n\r\n\r\n ISSUES & TODO-LIST\r\n ==================\r\n See TODO.txt\r\n\r\n\r\n FREQUENTLY ASKED QUESTIONS (FAQ), TIPS\r\n ======================================\r\n\r\n Q: How can I help?\r\n A: - If you are experienced enough with ImGui and with C/C++, look at the todo list and see how you want/can help!\r\n    - Become a Patron/donate! Convince your company to become a Patron or provide serious funding for development time! See http://www.patreon.com/imgui\r\n\r\n Q: What is ImTextureID and how do I display an image?\r\n A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function.\r\n    ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry!\r\n    It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc.\r\n    At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render.\r\n    Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing.\r\n    (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!)\r\n    To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions.\r\n    ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use.\r\n    It is your responsibility to get textures uploaded to your GPU.\r\n\r\n Q: I integrated ImGui in my engine and the text or lines are blurry..\r\n A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).\r\n    Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.\r\n\r\n Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around..\r\n A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).\r\n\r\n Q: Can I have multiple widgets with the same label? Can I have widget without a label?\r\n A: Yes. A primer on the use of labels/IDs in ImGui..\r\n\r\n   - Elements that are not clickable, such as Text() items don't need an ID.\r\n\r\n   - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the \"active\" widget).\r\n     to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer.\r\n\r\n       Button(\"OK\");        // Label = \"OK\",     ID = hash of \"OK\"\r\n       Button(\"Cancel\");    // Label = \"Cancel\", ID = hash of \"Cancel\"\r\n\r\n   - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called \"OK\" in two different windows\r\n     or in two different locations of a tree.\r\n\r\n   - If you have a same ID twice in the same location, you'll have a conflict:\r\n\r\n       Button(\"OK\");\r\n       Button(\"OK\");           // ID collision! Both buttons will be treated as the same.\r\n\r\n     Fear not! this is easy to solve and there are many ways to solve it!\r\n\r\n   - When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases.\r\n     use \"##\" to pass a complement to the ID that won't be visible to the end-user:\r\n\r\n       Button(\"Play\");         // Label = \"Play\",   ID = hash of \"Play\"\r\n       Button(\"Play##foo1\");   // Label = \"Play\",   ID = hash of \"Play##foo1\" (different from above)\r\n       Button(\"Play##foo2\");   // Label = \"Play\",   ID = hash of \"Play##foo2\" (different from above)\r\n\r\n   - If you want to completely hide the label, but still need an ID:\r\n\r\n       Checkbox(\"##On\", &b);   // Label = \"\",       ID = hash of \"##On\" (no label!)\r\n\r\n   - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels.\r\n     For example you may want to include varying information in a window title bar (and windows are uniquely identified by their ID.. obviously)\r\n     Use \"###\" to pass a label that isn't part of ID:\r\n\r\n       Button(\"Hello###ID\";   // Label = \"Hello\",  ID = hash of \"ID\"\r\n       Button(\"World###ID\";   // Label = \"World\",  ID = hash of \"ID\" (same as above)\r\n\r\n       sprintf(buf, \"My game (%f FPS)###MyGame\");\r\n       Begin(buf);            // Variable label,   ID = hash of \"MyGame\"\r\n\r\n   - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.\r\n     This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements.\r\n     You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the ID stack!\r\n\r\n       for (int i = 0; i < 100; i++)\r\n       {\r\n         PushID(i);\r\n         Button(\"Click\");   // Label = \"Click\",  ID = hash of integer + \"label\" (unique)\r\n         PopID();\r\n       }\r\n\r\n       for (int i = 0; i < 100; i++)\r\n       {\r\n         MyObject* obj = Objects[i];\r\n         PushID(obj);\r\n         Button(\"Click\");   // Label = \"Click\",  ID = hash of pointer + \"label\" (unique)\r\n         PopID();\r\n       }\r\n\r\n       for (int i = 0; i < 100; i++)\r\n       {\r\n         MyObject* obj = Objects[i];\r\n         PushID(obj->Name);\r\n         Button(\"Click\");   // Label = \"Click\",  ID = hash of string + \"label\" (unique)\r\n         PopID();\r\n       }\r\n\r\n   - More example showing that you can stack multiple prefixes into the ID stack:\r\n\r\n       Button(\"Click\");     // Label = \"Click\",  ID = hash of \"Click\"\r\n       PushID(\"node\");\r\n       Button(\"Click\");     // Label = \"Click\",  ID = hash of \"node\" + \"Click\"\r\n         PushID(my_ptr);\r\n           Button(\"Click\"); // Label = \"Click\",  ID = hash of \"node\" + ptr + \"Click\"\r\n         PopID();\r\n       PopID();\r\n\r\n   - Tree nodes implicitly creates a scope for you by calling PushID().\r\n\r\n       Button(\"Click\");     // Label = \"Click\",  ID = hash of \"Click\"\r\n       if (TreeNode(\"node\"))\r\n       {\r\n         Button(\"Click\");   // Label = \"Click\",  ID = hash of \"node\" + \"Click\"\r\n         TreePop();\r\n       }\r\n\r\n   - When working with trees, ID are used to preserve the open/close state of each tree node.\r\n     Depending on your use cases you may want to use strings, indices or pointers as ID.\r\n      e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change.\r\n      e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense!\r\n\r\n Q: How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?\r\n A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure. \r\n    - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application.\r\n    - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console without a keyboard).\r\n    Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is also generally ok, \r\n    as the bool toggles fairly rarely and you don't generally expect to interact with either ImGui or your application during the same frame when that transition occurs.\r\n    ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered.\r\n    (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantCaptureKeyboard=false'. \r\n     Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.)\r\n\r\n Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)\r\n A: Use the font atlas to load the TTF/OTF file you want:\r\n\r\n      ImGuiIO& io = ImGui::GetIO();\r\n      io.Fonts->AddFontFromFileTTF(\"myfontfile.ttf\", size_in_pixels);\r\n      io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()\r\n\r\n Q: How can I easily use icons in my application?\r\n A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings.\r\n    Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions.\r\n\r\n Q: How can I load multiple fonts?\r\n A: Use the font atlas to pack them into a single texture:\r\n    (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.)\r\n\r\n      ImGuiIO& io = ImGui::GetIO();\r\n      ImFont* font0 = io.Fonts->AddFontDefault();\r\n      ImFont* font1 = io.Fonts->AddFontFromFileTTF(\"myfontfile.ttf\", size_in_pixels);\r\n      ImFont* font2 = io.Fonts->AddFontFromFileTTF(\"myfontfile2.ttf\", size_in_pixels);\r\n      io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()\r\n      // the first loaded font gets used by default\r\n      // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime\r\n\r\n      // Options\r\n      ImFontConfig config;\r\n      config.OversampleH = 3;\r\n      config.OversampleV = 1;\r\n      config.GlyphOffset.y -= 2.0f;      // Move everything by 2 pixels up\r\n      config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters\r\n      io.Fonts->LoadFromFileTTF(\"myfontfile.ttf\", size_pixels, &config);\r\n\r\n      // Combine multiple fonts into one (e.g. for icon fonts)\r\n      ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };\r\n      ImFontConfig config;\r\n      config.MergeMode = true;\r\n      io.Fonts->AddFontDefault();\r\n      io.Fonts->LoadFromFileTTF(\"fontawesome-webfont.ttf\", 16.0f, &config, ranges); // Merge icon font\r\n      io.Fonts->LoadFromFileTTF(\"myfontfile.ttf\", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs\r\n\r\n Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?\r\n A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. \r\n\r\n      // Add default Japanese ranges\r\n      io.Fonts->AddFontFromFileTTF(\"myfontfile.ttf\", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());\r\n   \r\n      // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)\r\n      ImVector<ImWchar> ranges;\r\n      ImFontAtlas::GlyphRangesBuilder builder;\r\n      builder.AddText(\"Hello world\");                        // Add a string (here \"Hello world\" contains 7 unique characters)\r\n      builder.AddChar(0x7262);                               // Add a specific character\r\n      builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges\r\n      builder.BuildRanges(&ranges);                          // Build the final result (ordered ranges with all the unique characters submitted)\r\n      io.Fonts->AddFontFromFileTTF(\"myfontfile.ttf\", size_in_pixels, NULL, ranges.Data);\r\n\r\n    All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 by using the u8\"hello\" syntax. \r\n    Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!\r\n    Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.\r\n\r\n    Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that.\r\n    For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly.\r\n\r\n Q: How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables)\r\n A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' so you don't rely on the default globals.\r\n\r\n Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)\r\n A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, \r\n    then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.\r\n    You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui data to retrieve the coordinates of the white pixel.\r\n\r\n - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code.\r\n - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called \"Debug\"\r\n - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings)\r\n - tip: you can call Render() multiple times (e.g for VR renders).\r\n - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui!\r\n\r\n*/\r\n\r\n#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)\r\n#define _CRT_SECURE_NO_WARNINGS\r\n#endif\r\n\r\n#include \"imgui.h\"\r\n#define IMGUI_DEFINE_MATH_OPERATORS\r\n#define IMGUI_DEFINE_PLACEMENT_NEW\r\n#include \"imgui_internal.h\"\r\n\r\n#include <ctype.h>      // toupper, isprint\r\n#include <stdlib.h>     // NULL, malloc, free, qsort, atoi\r\n#include <stdio.h>      // vsnprintf, sscanf, printf\r\n#include <limits.h>     // INT_MIN, INT_MAX\r\n#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier\r\n#include <stddef.h>     // intptr_t\r\n#else\r\n#include <stdint.h>     // intptr_t\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (disable: 4127) // condition expression is constant\r\n#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)\r\n#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen\r\n#endif\r\n\r\n// Clang warnings with -Weverything\r\n#ifdef __clang__\r\n#pragma clang diagnostic ignored \"-Wunknown-pragmas\"        // warning : unknown warning group '-Wformat-pedantic *'        // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great!\r\n#pragma clang diagnostic ignored \"-Wold-style-cast\"         // warning : use of old-style cast                              // yes, they are more terse.\r\n#pragma clang diagnostic ignored \"-Wfloat-equal\"            // warning : comparing floating point with == or != is unsafe   // storing and comparing against same constants (typically 0.0f) is ok.\r\n#pragma clang diagnostic ignored \"-Wformat-nonliteral\"      // warning : format string is not a string literal              // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.\r\n#pragma clang diagnostic ignored \"-Wexit-time-destructors\"  // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.\r\n#pragma clang diagnostic ignored \"-Wglobal-constructors\"    // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.\r\n#pragma clang diagnostic ignored \"-Wsign-conversion\"        // warning : implicit conversion changes signedness             //\r\n#pragma clang diagnostic ignored \"-Wformat-pedantic\"        // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. \r\n#pragma clang diagnostic ignored \"-Wint-to-void-pointer-cast\" // warning : cast to 'void *' from smaller integer type 'int' //\r\n#elif defined(__GNUC__)\r\n#pragma GCC diagnostic ignored \"-Wunused-function\"          // warning: 'xxxx' defined but not used\r\n#pragma GCC diagnostic ignored \"-Wint-to-pointer-cast\"      // warning: cast to pointer from integer of different size\r\n#pragma GCC diagnostic ignored \"-Wformat\"                   // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'\r\n#pragma GCC diagnostic ignored \"-Wdouble-promotion\"         // warning: implicit conversion from 'float' to 'double' when passing argument to function\r\n#pragma GCC diagnostic ignored \"-Wconversion\"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value\r\n#pragma GCC diagnostic ignored \"-Wcast-qual\"                // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers\r\n#pragma GCC diagnostic ignored \"-Wformat-nonliteral\"        // warning: format not a string literal, format string not checked\r\n#endif\r\n\r\n//-------------------------------------------------------------------------\r\n// Forward Declarations\r\n//-------------------------------------------------------------------------\r\n\r\nstatic void             LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);\r\n\r\nstatic void             PushMultiItemsWidths(int components, float w_full = 0.0f);\r\nstatic float            GetDraggedColumnOffset(int column_index);\r\n\r\nstatic bool             IsKeyPressedMap(ImGuiKey key, bool repeat = true);\r\n\r\nstatic ImFont*          GetDefaultFont();\r\nstatic void             SetCurrentFont(ImFont* font);\r\nstatic void             SetCurrentWindow(ImGuiWindow* window);\r\nstatic void             SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);\r\nstatic void             SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);\r\nstatic void             SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);\r\nstatic void             SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);\r\nstatic ImGuiWindow*     FindHoveredWindow(ImVec2 pos, bool excluding_childs);\r\nstatic ImGuiWindow*     CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);\r\nstatic inline bool      IsWindowContentHoverable(ImGuiWindow* window);\r\nstatic void             ClearSetNextWindowData();\r\nstatic void             CheckStacksSize(ImGuiWindow* window, bool write);\r\nstatic void             Scrollbar(ImGuiWindow* window, bool horizontal);\r\nstatic ImVec2           CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);\r\n\r\nstatic void             AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDrawList* draw_list);\r\nstatic void             AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window);\r\nstatic void             AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window);\r\n\r\nstatic ImGuiIniData*    FindWindowSettings(const char* name);\r\nstatic ImGuiIniData*    AddWindowSettings(const char* name);\r\nstatic void             LoadIniSettingsFromDisk(const char* ini_filename);\r\nstatic void             SaveIniSettingsToDisk(const char* ini_filename);\r\nstatic void             MarkIniSettingsDirty(ImGuiWindow* window);\r\n\r\nstatic ImRect           GetVisibleRect();\r\n\r\nstatic bool             BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);\r\nstatic void             CloseInactivePopups();\r\nstatic void             ClosePopupToLevel(int remaining);\r\nstatic void             ClosePopup(ImGuiID id);\r\nstatic ImGuiWindow*     GetFrontMostModalRootWindow();\r\nstatic ImVec2           FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid);\r\n\r\nstatic bool             InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data);\r\nstatic int              InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);\r\nstatic ImVec2           InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);\r\n\r\nstatic inline void      DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size);\r\nstatic inline void      DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size);\r\nstatic void             DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2);\r\nstatic bool             DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Platform dependent default implementations\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic const char*      GetClipboardTextFn_DefaultImpl(void* user_data);\r\nstatic void             SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);\r\nstatic void             ImeSetInputScreenPosFn_DefaultImpl(int x, int y);\r\n\r\n//-----------------------------------------------------------------------------\r\n// Context\r\n//-----------------------------------------------------------------------------\r\n\r\n// Default font atlas storage.\r\n// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable.\r\nstatic ImFontAtlas      GImDefaultFontAtlas;\r\n\r\n// Default context storage + current context pointer.\r\n// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext()\r\n// If you are hot-reloading this code in a DLL you will lose the static/global variables. Create your own context+font atlas instead of relying on those default (see FAQ entry \"How can I preserve my ImGui context across reloading a DLL?\").\r\n// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by:\r\n// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)\r\n// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586\r\n#ifndef GImGui\r\nstatic ImGuiContext     GImDefaultContext;\r\nImGuiContext*           GImGui = &GImDefaultContext;\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// User facing structures\r\n//-----------------------------------------------------------------------------\r\n\r\nImGuiStyle::ImGuiStyle()\r\n{\r\n    Alpha                   = 1.0f;             // Global alpha applies to everything in ImGui\r\n    WindowPadding           = ImVec2(8,8);      // Padding within a window\r\n    WindowMinSize           = ImVec2(32,32);    // Minimum window size\r\n    WindowRounding          = 9.0f;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows\r\n    WindowTitleAlign        = ImVec2(0.0f,0.5f);// Alignment for title bar text\r\n    ChildWindowRounding     = 0.0f;             // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows\r\n    FramePadding            = ImVec2(4,3);      // Padding within a framed rectangle (used by most widgets)\r\n    FrameRounding           = 0.0f;             // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).\r\n    ItemSpacing             = ImVec2(8,4);      // Horizontal and vertical spacing between widgets/lines\r\n    ItemInnerSpacing        = ImVec2(4,4);      // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)\r\n    TouchExtraPadding       = ImVec2(0,0);      // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!\r\n    IndentSpacing           = 21.0f;            // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).\r\n    ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns\r\n    ScrollbarSize           = 16.0f;            // Width of the vertical scrollbar, Height of the horizontal scrollbar\r\n    ScrollbarRounding       = 9.0f;             // Radius of grab corners rounding for scrollbar\r\n    GrabMinSize             = 10.0f;            // Minimum width/height of a grab box for slider/scrollbar\r\n    GrabRounding            = 0.0f;             // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.\r\n    ButtonTextAlign         = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.\r\n    DisplayWindowPadding    = ImVec2(22,22);    // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.\r\n    DisplaySafeAreaPadding  = ImVec2(4,4);      // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.\r\n    AntiAliasedLines        = true;             // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.\r\n    AntiAliasedShapes       = true;             // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)\r\n    CurveTessellationTol    = 1.25f;            // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.\r\n\r\n    Colors[ImGuiCol_Text]                   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);\r\n    Colors[ImGuiCol_TextDisabled]           = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);\r\n    Colors[ImGuiCol_WindowBg]               = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);\r\n    Colors[ImGuiCol_ChildWindowBg]          = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\r\n    Colors[ImGuiCol_PopupBg]                = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);\r\n    Colors[ImGuiCol_Border]                 = ImVec4(0.70f, 0.70f, 0.70f, 0.40f);\r\n    Colors[ImGuiCol_BorderShadow]           = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);\r\n    Colors[ImGuiCol_FrameBg]                = ImVec4(0.80f, 0.80f, 0.80f, 0.30f);   // Background of checkbox, radio button, plot, slider, text input\r\n    Colors[ImGuiCol_FrameBgHovered]         = ImVec4(0.90f, 0.80f, 0.80f, 0.40f);\r\n    Colors[ImGuiCol_FrameBgActive]          = ImVec4(0.90f, 0.65f, 0.65f, 0.45f);\r\n    Colors[ImGuiCol_TitleBg]                = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);\r\n    Colors[ImGuiCol_TitleBgCollapsed]       = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);\r\n    Colors[ImGuiCol_TitleBgActive]          = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);\r\n    Colors[ImGuiCol_MenuBarBg]              = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);\r\n    Colors[ImGuiCol_ScrollbarBg]            = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);\r\n    Colors[ImGuiCol_ScrollbarGrab]          = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);\r\n    Colors[ImGuiCol_ScrollbarGrabHovered]   = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);\r\n    Colors[ImGuiCol_ScrollbarGrabActive]    = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);\r\n    Colors[ImGuiCol_ComboBg]                = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);\r\n    Colors[ImGuiCol_CheckMark]              = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);\r\n    Colors[ImGuiCol_SliderGrab]             = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);\r\n    Colors[ImGuiCol_SliderGrabActive]       = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);\r\n    Colors[ImGuiCol_Button]                 = ImVec4(0.67f, 0.40f, 0.40f, 0.60f);\r\n    Colors[ImGuiCol_ButtonHovered]          = ImVec4(0.67f, 0.40f, 0.40f, 1.00f);\r\n    Colors[ImGuiCol_ButtonActive]           = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);\r\n    Colors[ImGuiCol_Header]                 = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);\r\n    Colors[ImGuiCol_HeaderHovered]          = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);\r\n    Colors[ImGuiCol_HeaderActive]           = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);\r\n    Colors[ImGuiCol_Separator]              = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);\r\n    Colors[ImGuiCol_SeparatorHovered]       = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);\r\n    Colors[ImGuiCol_SeparatorActive]        = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);\r\n    Colors[ImGuiCol_ResizeGrip]             = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);\r\n    Colors[ImGuiCol_ResizeGripHovered]      = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);\r\n    Colors[ImGuiCol_ResizeGripActive]       = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);\r\n    Colors[ImGuiCol_CloseButton]            = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);\r\n    Colors[ImGuiCol_CloseButtonHovered]     = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);\r\n    Colors[ImGuiCol_CloseButtonActive]      = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);\r\n    Colors[ImGuiCol_PlotLines]              = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);\r\n    Colors[ImGuiCol_PlotLinesHovered]       = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);\r\n    Colors[ImGuiCol_PlotHistogram]          = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);\r\n    Colors[ImGuiCol_PlotHistogramHovered]   = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);\r\n    Colors[ImGuiCol_TextSelectedBg]         = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);\r\n    Colors[ImGuiCol_ModalWindowDarkening]   = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);\r\n}\r\n\r\nImGuiIO::ImGuiIO()\r\n{\r\n    // Most fields are initialized with zero\r\n    memset(this, 0, sizeof(*this));\r\n\r\n    // Settings\r\n    DisplaySize = ImVec2(-1.0f, -1.0f);\r\n    DeltaTime = 1.0f/60.0f;\r\n    IniSavingRate = 5.0f;\r\n    IniFilename = \"imgui.ini\";\r\n    LogFilename = \"imgui_log.txt\";\r\n    MouseDoubleClickTime = 0.30f;\r\n    MouseDoubleClickMaxDist = 6.0f;\r\n    for (int i = 0; i < ImGuiKey_COUNT; i++)\r\n        KeyMap[i] = -1;\r\n    KeyRepeatDelay = 0.250f;\r\n    KeyRepeatRate = 0.050f;\r\n    UserData = NULL;\r\n\r\n    Fonts = &GImDefaultFontAtlas;\r\n    FontGlobalScale = 1.0f;\r\n    FontDefault = NULL;\r\n    FontAllowUserScaling = false;\r\n    DisplayFramebufferScale = ImVec2(1.0f, 1.0f);\r\n    DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f);\r\n\r\n    // User functions\r\n    RenderDrawListsFn = NULL;\r\n    MemAllocFn = malloc;\r\n    MemFreeFn = free;\r\n    GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;   // Platform dependent default implementations\r\n    SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;\r\n    ClipboardUserData = NULL;\r\n    ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;\r\n    ImeWindowHandle = NULL;\r\n\r\n    // Input (NB: we already have memset zero the entire structure)\r\n    MousePos = ImVec2(-FLT_MAX, -FLT_MAX);\r\n    MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);\r\n    MouseDragThreshold = 6.0f;\r\n    for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;\r\n    for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;\r\n\r\n    // Set OS X style defaults based on __APPLE__ compile time flag\r\n#ifdef __APPLE__\r\n    OSXBehaviors = true;\r\n#endif\r\n}\r\n\r\n// Pass in translated ASCII characters for text input.\r\n// - with glfw you can get those from the callback set in glfwSetCharCallback()\r\n// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message\r\nvoid ImGuiIO::AddInputCharacter(ImWchar c)\r\n{\r\n    const int n = ImStrlenW(InputCharacters);\r\n    if (n + 1 < IM_ARRAYSIZE(InputCharacters))\r\n    {\r\n        InputCharacters[n] = c;\r\n        InputCharacters[n+1] = '\\0';\r\n    }\r\n}\r\n\r\nvoid ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)\r\n{\r\n    // We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more\r\n    const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar);\r\n    ImWchar wchars[wchars_buf_len];\r\n    ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL);\r\n    for (int i = 0; i < wchars_buf_len && wchars[i] != 0; i++)\r\n        AddInputCharacter(wchars[i]);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// HELPERS\r\n//-----------------------------------------------------------------------------\r\n\r\n#define IM_F32_TO_INT8_UNBOUND(_VAL)    ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f)))   // Unsaturated, for display purpose \r\n#define IM_F32_TO_INT8_SAT(_VAL)        ((int)(ImSaturate(_VAL) * 255.0f + 0.5f))               // Saturated, always output 0..255\r\n\r\n// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \\n.\r\n#ifdef _WIN32\r\n#define IM_NEWLINE \"\\r\\n\"\r\n#else\r\n#define IM_NEWLINE \"\\n\"\r\n#endif\r\n\r\nImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)\r\n{\r\n    ImVec2 ap = p - a;\r\n    ImVec2 ab_dir = b - a;\r\n    float ab_len = sqrtf(ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y);\r\n    ab_dir *= 1.0f / ab_len;\r\n    float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;\r\n    if (dot < 0.0f)\r\n        return a;\r\n    if (dot > ab_len)\r\n        return b;\r\n    return a + ab_dir * dot;\r\n}\r\n\r\nbool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)\r\n{\r\n    bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;\r\n    bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;\r\n    bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;\r\n    return ((b1 == b2) && (b2 == b3));\r\n}\r\n\r\nvoid ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)\r\n{\r\n    ImVec2 v0 = b - a;\r\n    ImVec2 v1 = c - a;\r\n    ImVec2 v2 = p - a;\r\n    const float denom = v0.x * v1.y - v1.x * v0.y;\r\n    out_v = (v2.x * v1.y - v1.x * v2.y) / denom;\r\n    out_w = (v0.x * v2.y - v2.x * v0.y) / denom;\r\n    out_u = 1.0f - out_v - out_w;\r\n}\r\n\r\nImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)\r\n{\r\n    ImVec2 proj_ab = ImLineClosestPoint(a, b, p);\r\n    ImVec2 proj_bc = ImLineClosestPoint(b, c, p);\r\n    ImVec2 proj_ca = ImLineClosestPoint(c, a, p);\r\n    float dist2_ab = ImLengthSqr(p - proj_ab);\r\n    float dist2_bc = ImLengthSqr(p - proj_bc);\r\n    float dist2_ca = ImLengthSqr(p - proj_ca);\r\n    float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));\r\n    if (m == dist2_ab)\r\n        return proj_ab;\r\n    if (m == dist2_bc)\r\n        return proj_bc;\r\n    return proj_ca;\r\n}\r\n\r\nint ImStricmp(const char* str1, const char* str2)\r\n{\r\n    int d;\r\n    while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }\r\n    return d;\r\n}\r\n\r\nint ImStrnicmp(const char* str1, const char* str2, int count)\r\n{\r\n    int d = 0;\r\n    while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }\r\n    return d;\r\n}\r\n\r\nvoid ImStrncpy(char* dst, const char* src, int count)\r\n{\r\n    if (count < 1) return;\r\n    strncpy(dst, src, (size_t)count);\r\n    dst[count-1] = 0;\r\n}\r\n\r\nchar* ImStrdup(const char *str)\r\n{\r\n    size_t len = strlen(str) + 1;\r\n    void* buff = ImGui::MemAlloc(len);\r\n    return (char*)memcpy(buff, (const void*)str, len);\r\n}\r\n\r\nint ImStrlenW(const ImWchar* str)\r\n{\r\n    int n = 0;\r\n    while (*str++) n++;\r\n    return n;\r\n}\r\n\r\nconst ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line\r\n{\r\n    while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\\n')\r\n        buf_mid_line--;\r\n    return buf_mid_line;\r\n}\r\n\r\nconst char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)\r\n{\r\n    if (!needle_end)\r\n        needle_end = needle + strlen(needle);\r\n\r\n    const char un0 = (char)toupper(*needle);\r\n    while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))\r\n    {\r\n        if (toupper(*haystack) == un0)\r\n        {\r\n            const char* b = needle + 1;\r\n            for (const char* a = haystack + 1; b < needle_end; a++, b++)\r\n                if (toupper(*a) != toupper(*b))\r\n                    break;\r\n            if (b == needle_end)\r\n                return haystack;\r\n        }\r\n        haystack++;\r\n    }\r\n    return NULL;\r\n}\r\n\r\nstatic const char* ImAtoi(const char* src, int* output)\r\n{\r\n    int negative = 0;\r\n    if (*src == '-') { negative = 1; src++; }\r\n    if (*src == '+') { src++; }\r\n    int v = 0;\r\n    while (*src >= '0' && *src <= '9')\r\n        v = (v * 10) + (*src++ - '0');\r\n    *output = negative ? -v : v;\r\n    return src;\r\n}\r\n\r\n// MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). \r\n// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm.\r\nint ImFormatString(char* buf, int buf_size, const char* fmt, ...)\r\n{\r\n    IM_ASSERT(buf_size > 0);\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    int w = vsnprintf(buf, buf_size, fmt, args);\r\n    va_end(args);\r\n    if (w == -1 || w >= buf_size)\r\n        w = buf_size - 1;\r\n    buf[w] = 0;\r\n    return w;\r\n}\r\n\r\nint ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)\r\n{\r\n    IM_ASSERT(buf_size > 0);\r\n    int w = vsnprintf(buf, buf_size, fmt, args);\r\n    if (w == -1 || w >= buf_size)\r\n        w = buf_size - 1;\r\n    buf[w] = 0;\r\n    return w;\r\n}\r\n\r\n// Pass data_size==0 for zero-terminated strings\r\n// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.\r\nImU32 ImHash(const void* data, int data_size, ImU32 seed)\r\n{\r\n    static ImU32 crc32_lut[256] = { 0 };\r\n    if (!crc32_lut[1])\r\n    {\r\n        const ImU32 polynomial = 0xEDB88320;\r\n        for (ImU32 i = 0; i < 256; i++)\r\n        {\r\n            ImU32 crc = i;\r\n            for (ImU32 j = 0; j < 8; j++)\r\n                crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);\r\n            crc32_lut[i] = crc;\r\n        }\r\n    }\r\n\r\n    seed = ~seed;\r\n    ImU32 crc = seed;\r\n    const unsigned char* current = (const unsigned char*)data;\r\n\r\n    if (data_size > 0)\r\n    {\r\n        // Known size\r\n        while (data_size--)\r\n            crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];\r\n    }\r\n    else\r\n    {\r\n        // Zero-terminated string\r\n        while (unsigned char c = *current++)\r\n        {\r\n            // We support a syntax of \"label###id\" where only \"###id\" is included in the hash, and only \"label\" gets displayed.\r\n            // Because this syntax is rarely used we are optimizing for the common case.\r\n            // - If we reach ### in the string we discard the hash so far and reset to the seed.\r\n            // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.\r\n            if (c == '#' && current[0] == '#' && current[1] == '#')\r\n                crc = seed;\r\n            crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];\r\n        }\r\n    }\r\n    return ~crc;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImText* helpers\r\n//-----------------------------------------------------------------------------\r\n\r\n// Convert UTF-8 to 32-bits character, process single character input.\r\n// Based on stb_from_utf8() from github.com/nothings/stb/\r\n// We handle UTF-8 decoding error by skipping forward.\r\nint ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)\r\n{\r\n    unsigned int c = (unsigned int)-1;\r\n    const unsigned char* str = (const unsigned char*)in_text;\r\n    if (!(*str & 0x80))\r\n    {\r\n        c = (unsigned int)(*str++);\r\n        *out_char = c;\r\n        return 1;\r\n    }\r\n    if ((*str & 0xe0) == 0xc0)\r\n    {\r\n        *out_char = 0xFFFD; // will be invalid but not end of string\r\n        if (in_text_end && in_text_end - (const char*)str < 2) return 1;\r\n        if (*str < 0xc2) return 2;\r\n        c = (unsigned int)((*str++ & 0x1f) << 6);\r\n        if ((*str & 0xc0) != 0x80) return 2;\r\n        c += (*str++ & 0x3f);\r\n        *out_char = c;\r\n        return 2;\r\n    }\r\n    if ((*str & 0xf0) == 0xe0)\r\n    {\r\n        *out_char = 0xFFFD; // will be invalid but not end of string\r\n        if (in_text_end && in_text_end - (const char*)str < 3) return 1;\r\n        if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;\r\n        if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below\r\n        c = (unsigned int)((*str++ & 0x0f) << 12);\r\n        if ((*str & 0xc0) != 0x80) return 3;\r\n        c += (unsigned int)((*str++ & 0x3f) << 6);\r\n        if ((*str & 0xc0) != 0x80) return 3;\r\n        c += (*str++ & 0x3f);\r\n        *out_char = c;\r\n        return 3;\r\n    }\r\n    if ((*str & 0xf8) == 0xf0)\r\n    {\r\n        *out_char = 0xFFFD; // will be invalid but not end of string\r\n        if (in_text_end && in_text_end - (const char*)str < 4) return 1;\r\n        if (*str > 0xf4) return 4;\r\n        if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;\r\n        if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below\r\n        c = (unsigned int)((*str++ & 0x07) << 18);\r\n        if ((*str & 0xc0) != 0x80) return 4;\r\n        c += (unsigned int)((*str++ & 0x3f) << 12);\r\n        if ((*str & 0xc0) != 0x80) return 4;\r\n        c += (unsigned int)((*str++ & 0x3f) << 6);\r\n        if ((*str & 0xc0) != 0x80) return 4;\r\n        c += (*str++ & 0x3f);\r\n        // utf-8 encodings of values used in surrogate pairs are invalid\r\n        if ((c & 0xFFFFF800) == 0xD800) return 4;\r\n        *out_char = c;\r\n        return 4;\r\n    }\r\n    *out_char = 0;\r\n    return 0;\r\n}\r\n\r\nint ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)\r\n{\r\n    ImWchar* buf_out = buf;\r\n    ImWchar* buf_end = buf + buf_size;\r\n    while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)\r\n    {\r\n        unsigned int c;\r\n        in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);\r\n        if (c == 0)\r\n            break;\r\n        if (c < 0x10000)    // FIXME: Losing characters that don't fit in 2 bytes\r\n            *buf_out++ = (ImWchar)c;\r\n    }\r\n    *buf_out = 0;\r\n    if (in_text_remaining)\r\n        *in_text_remaining = in_text;\r\n    return (int)(buf_out - buf);\r\n}\r\n\r\nint ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)\r\n{\r\n    int char_count = 0;\r\n    while ((!in_text_end || in_text < in_text_end) && *in_text)\r\n    {\r\n        unsigned int c;\r\n        in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);\r\n        if (c == 0)\r\n            break;\r\n        if (c < 0x10000)\r\n            char_count++;\r\n    }\r\n    return char_count;\r\n}\r\n\r\n// Based on stb_to_utf8() from github.com/nothings/stb/\r\nstatic inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)\r\n{\r\n    if (c < 0x80)\r\n    {\r\n        buf[0] = (char)c;\r\n        return 1;\r\n    }\r\n    if (c < 0x800)\r\n    {\r\n        if (buf_size < 2) return 0;\r\n        buf[0] = (char)(0xc0 + (c >> 6));\r\n        buf[1] = (char)(0x80 + (c & 0x3f));\r\n        return 2;\r\n    }\r\n    if (c >= 0xdc00 && c < 0xe000)\r\n    {\r\n        return 0;\r\n    }\r\n    if (c >= 0xd800 && c < 0xdc00)\r\n    {\r\n        if (buf_size < 4) return 0;\r\n        buf[0] = (char)(0xf0 + (c >> 18));\r\n        buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));\r\n        buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));\r\n        buf[3] = (char)(0x80 + ((c ) & 0x3f));\r\n        return 4;\r\n    }\r\n    //else if (c < 0x10000)\r\n    {\r\n        if (buf_size < 3) return 0;\r\n        buf[0] = (char)(0xe0 + (c >> 12));\r\n        buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));\r\n        buf[2] = (char)(0x80 + ((c ) & 0x3f));\r\n        return 3;\r\n    }\r\n}\r\n\r\nstatic inline int ImTextCountUtf8BytesFromChar(unsigned int c)\r\n{\r\n    if (c < 0x80) return 1;\r\n    if (c < 0x800) return 2;\r\n    if (c >= 0xdc00 && c < 0xe000) return 0;\r\n    if (c >= 0xd800 && c < 0xdc00) return 4;\r\n    return 3;\r\n}\r\n\r\nint ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)\r\n{\r\n    char* buf_out = buf;\r\n    const char* buf_end = buf + buf_size;\r\n    while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)\r\n    {\r\n        unsigned int c = (unsigned int)(*in_text++);\r\n        if (c < 0x80)\r\n            *buf_out++ = (char)c;\r\n        else\r\n            buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c);\r\n    }\r\n    *buf_out = 0;\r\n    return (int)(buf_out - buf);\r\n}\r\n\r\nint ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)\r\n{\r\n    int bytes_count = 0;\r\n    while ((!in_text_end || in_text < in_text_end) && *in_text)\r\n    {\r\n        unsigned int c = (unsigned int)(*in_text++);\r\n        if (c < 0x80)\r\n            bytes_count++;\r\n        else\r\n            bytes_count += ImTextCountUtf8BytesFromChar(c);\r\n    }\r\n    return bytes_count;\r\n}\r\n\r\nImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)\r\n{\r\n    float s = 1.0f/255.0f;\r\n    return ImVec4(\r\n        ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,\r\n        ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,\r\n        ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,\r\n        ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);\r\n}\r\n\r\nImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)\r\n{\r\n    ImU32 out;\r\n    out  = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;\r\n    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;\r\n    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;\r\n    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;\r\n    return out;\r\n}\r\n\r\nImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)  \r\n{ \r\n    ImGuiStyle& style = GImGui->Style;\r\n    ImVec4 c = style.Colors[idx]; \r\n    c.w *= style.Alpha * alpha_mul; \r\n    return ColorConvertFloat4ToU32(c); \r\n}\r\n\r\nImU32 ImGui::GetColorU32(const ImVec4& col)\r\n{ \r\n    ImGuiStyle& style = GImGui->Style;\r\n    ImVec4 c = col; \r\n    c.w *= style.Alpha; \r\n    return ColorConvertFloat4ToU32(c); \r\n}\r\n\r\nconst ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)\r\n{ \r\n    ImGuiStyle& style = GImGui->Style;\r\n    return style.Colors[idx];\r\n}\r\n\r\nImU32 ImGui::GetColorU32(ImU32 col)\r\n{ \r\n    float style_alpha = GImGui->Style.Alpha;\r\n    if (style_alpha >= 1.0f)\r\n        return col;\r\n    int a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;\r\n    a = (int)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.\r\n    return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);\r\n}\r\n\r\n// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592\r\n// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv\r\nvoid ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)\r\n{\r\n    float K = 0.f;\r\n    if (g < b)\r\n    {\r\n        ImSwap(g, b);\r\n        K = -1.f;\r\n    }\r\n    if (r < g)\r\n    {\r\n        ImSwap(r, g);\r\n        K = -2.f / 6.f - K;\r\n    }\r\n\r\n    const float chroma = r - (g < b ? g : b);\r\n    out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f));\r\n    out_s = chroma / (r + 1e-20f);\r\n    out_v = r;\r\n}\r\n\r\n// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593\r\n// also http://en.wikipedia.org/wiki/HSL_and_HSV\r\nvoid ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)\r\n{\r\n    if (s == 0.0f)\r\n    {\r\n        // gray\r\n        out_r = out_g = out_b = v;\r\n        return;\r\n    }\r\n\r\n    h = fmodf(h, 1.0f) / (60.0f/360.0f);\r\n    int   i = (int)h;\r\n    float f = h - (float)i;\r\n    float p = v * (1.0f - s);\r\n    float q = v * (1.0f - s * f);\r\n    float t = v * (1.0f - s * (1.0f - f));\r\n\r\n    switch (i)\r\n    {\r\n    case 0: out_r = v; out_g = t; out_b = p; break;\r\n    case 1: out_r = q; out_g = v; out_b = p; break;\r\n    case 2: out_r = p; out_g = v; out_b = t; break;\r\n    case 3: out_r = p; out_g = q; out_b = v; break;\r\n    case 4: out_r = t; out_g = p; out_b = v; break;\r\n    case 5: default: out_r = v; out_g = p; out_b = q; break;\r\n    }\r\n}\r\n\r\nFILE* ImFileOpen(const char* filename, const char* mode)\r\n{\r\n#if defined(_WIN32) && !defined(__CYGWIN__)\r\n    // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can)\r\n    const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;\r\n    const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;\r\n    ImVector<ImWchar> buf;\r\n    buf.resize(filename_wsize + mode_wsize);\r\n    ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);\r\n    ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);\r\n    return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);\r\n#else\r\n    return fopen(filename, mode);\r\n#endif\r\n}\r\n\r\n// Load file content into memory\r\n// Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()\r\nvoid* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size, int padding_bytes)\r\n{\r\n    IM_ASSERT(filename && file_open_mode);\r\n    if (out_file_size)\r\n        *out_file_size = 0;\r\n\r\n    FILE* f;\r\n    if ((f = ImFileOpen(filename, file_open_mode)) == NULL)\r\n        return NULL;\r\n\r\n    long file_size_signed;\r\n    if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))\r\n    {\r\n        fclose(f);\r\n        return NULL;\r\n    }\r\n\r\n    int file_size = (int)file_size_signed;\r\n    void* file_data = ImGui::MemAlloc(file_size + padding_bytes);\r\n    if (file_data == NULL)\r\n    {\r\n        fclose(f);\r\n        return NULL;\r\n    }\r\n    if (fread(file_data, 1, (size_t)file_size, f) != (size_t)file_size)\r\n    {\r\n        fclose(f);\r\n        ImGui::MemFree(file_data);\r\n        return NULL;\r\n    }\r\n    if (padding_bytes > 0)\r\n        memset((void *)(((char*)file_data) + file_size), 0, padding_bytes);\r\n\r\n    fclose(f);\r\n    if (out_file_size)\r\n        *out_file_size = file_size;\r\n\r\n    return file_data;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImGuiStorage\r\n//-----------------------------------------------------------------------------\r\n\r\n// Helper: Key->value storage\r\nvoid ImGuiStorage::Clear()\r\n{\r\n    Data.clear();\r\n}\r\n\r\n// std::lower_bound but without the bullshit\r\nstatic ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::Pair>& data, ImGuiID key)\r\n{\r\n    ImVector<ImGuiStorage::Pair>::iterator first = data.begin();\r\n    ImVector<ImGuiStorage::Pair>::iterator last = data.end();\r\n    int count = (int)(last - first);\r\n    while (count > 0)\r\n    {\r\n        int count2 = count / 2;\r\n        ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;\r\n        if (mid->key < key)\r\n        {\r\n            first = ++mid;\r\n            count -= count2 + 1;\r\n        }\r\n        else\r\n        {\r\n            count = count2;\r\n        }\r\n    }\r\n    return first;\r\n}\r\n\r\nint ImGuiStorage::GetInt(ImGuiID key, int default_val) const\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);\r\n    if (it == Data.end() || it->key != key)\r\n        return default_val;\r\n    return it->val_i;\r\n}\r\n\r\nbool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const\r\n{\r\n    return GetInt(key, default_val ? 1 : 0) != 0;\r\n}\r\n\r\nfloat ImGuiStorage::GetFloat(ImGuiID key, float default_val) const\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);\r\n    if (it == Data.end() || it->key != key)\r\n        return default_val;\r\n    return it->val_f;\r\n}\r\n\r\nvoid* ImGuiStorage::GetVoidPtr(ImGuiID key) const\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);\r\n    if (it == Data.end() || it->key != key)\r\n        return NULL;\r\n    return it->val_p;\r\n}\r\n\r\n// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.\r\nint* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(Data, key);\r\n    if (it == Data.end() || it->key != key)\r\n        it = Data.insert(it, Pair(key, default_val));\r\n    return &it->val_i;\r\n}\r\n\r\nbool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)\r\n{\r\n    return (bool*)GetIntRef(key, default_val ? 1 : 0);\r\n}\r\n\r\nfloat* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(Data, key);\r\n    if (it == Data.end() || it->key != key)\r\n        it = Data.insert(it, Pair(key, default_val));\r\n    return &it->val_f;\r\n}\r\n\r\nvoid** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(Data, key);\r\n    if (it == Data.end() || it->key != key)\r\n        it = Data.insert(it, Pair(key, default_val));\r\n    return &it->val_p;\r\n}\r\n\r\n// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)\r\nvoid ImGuiStorage::SetInt(ImGuiID key, int val)\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(Data, key);\r\n    if (it == Data.end() || it->key != key)\r\n    {\r\n        Data.insert(it, Pair(key, val));\r\n        return;\r\n    }\r\n    it->val_i = val;\r\n}\r\n\r\nvoid ImGuiStorage::SetBool(ImGuiID key, bool val)\r\n{\r\n    SetInt(key, val ? 1 : 0);\r\n}\r\n\r\nvoid ImGuiStorage::SetFloat(ImGuiID key, float val)\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(Data, key);\r\n    if (it == Data.end() || it->key != key)\r\n    {\r\n        Data.insert(it, Pair(key, val));\r\n        return;\r\n    }\r\n    it->val_f = val;\r\n}\r\n\r\nvoid ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)\r\n{\r\n    ImVector<Pair>::iterator it = LowerBound(Data, key);\r\n    if (it == Data.end() || it->key != key)\r\n    {\r\n        Data.insert(it, Pair(key, val));\r\n        return;\r\n    }\r\n    it->val_p = val;\r\n}\r\n\r\nvoid ImGuiStorage::SetAllInt(int v)\r\n{\r\n    for (int i = 0; i < Data.Size; i++)\r\n        Data[i].val_i = v;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImGuiTextFilter\r\n//-----------------------------------------------------------------------------\r\n\r\n// Helper: Parse and apply text filters. In format \"aaaaa[,bbbb][,ccccc]\"\r\nImGuiTextFilter::ImGuiTextFilter(const char* default_filter)\r\n{\r\n    if (default_filter)\r\n    {\r\n        ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));\r\n        Build();\r\n    }\r\n    else\r\n    {\r\n        InputBuf[0] = 0;\r\n        CountGrep = 0;\r\n    }\r\n}\r\n\r\nbool ImGuiTextFilter::Draw(const char* label, float width)\r\n{\r\n    if (width != 0.0f)\r\n        ImGui::PushItemWidth(width);\r\n    bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));\r\n    if (width != 0.0f)\r\n        ImGui::PopItemWidth();\r\n    if (value_changed)\r\n        Build();\r\n    return value_changed;\r\n}\r\n\r\nvoid ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>& out)\r\n{\r\n    out.resize(0);\r\n    const char* wb = b;\r\n    const char* we = wb;\r\n    while (we < e)\r\n    {\r\n        if (*we == separator)\r\n        {\r\n            out.push_back(TextRange(wb, we));\r\n            wb = we + 1;\r\n        }\r\n        we++;\r\n    }\r\n    if (wb != we)\r\n        out.push_back(TextRange(wb, we));\r\n}\r\n\r\nvoid ImGuiTextFilter::Build()\r\n{\r\n    Filters.resize(0);\r\n    TextRange input_range(InputBuf, InputBuf+strlen(InputBuf));\r\n    input_range.split(',', Filters);\r\n\r\n    CountGrep = 0;\r\n    for (int i = 0; i != Filters.Size; i++)\r\n    {\r\n        Filters[i].trim_blanks();\r\n        if (Filters[i].empty())\r\n            continue;\r\n        if (Filters[i].front() != '-')\r\n            CountGrep += 1;\r\n    }\r\n}\r\n\r\nbool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const\r\n{\r\n    if (Filters.empty())\r\n        return true;\r\n\r\n    if (text == NULL)\r\n        text = \"\";\r\n\r\n    for (int i = 0; i != Filters.Size; i++)\r\n    {\r\n        const TextRange& f = Filters[i];\r\n        if (f.empty())\r\n            continue;\r\n        if (f.front() == '-')\r\n        {\r\n            // Subtract\r\n            if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL)\r\n                return false;\r\n        }\r\n        else\r\n        {\r\n            // Grep\r\n            if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)\r\n                return true;\r\n        }\r\n    }\r\n\r\n    // Implicit * grep\r\n    if (CountGrep == 0)\r\n        return true;\r\n\r\n    return false;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImGuiTextBuffer\r\n//-----------------------------------------------------------------------------\r\n\r\n// On some platform vsnprintf() takes va_list by reference and modifies it.\r\n// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.\r\n#ifndef va_copy\r\n#define va_copy(dest, src) (dest = src)\r\n#endif\r\n\r\n// Helper: Text buffer for logging/accumulating text\r\nvoid ImGuiTextBuffer::appendv(const char* fmt, va_list args)\r\n{\r\n    va_list args_copy;\r\n    va_copy(args_copy, args);\r\n\r\n    int len = vsnprintf(NULL, 0, fmt, args);         // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.\r\n    if (len <= 0)\r\n        return;\r\n\r\n    const int write_off = Buf.Size;\r\n    const int needed_sz = write_off + len;\r\n    if (write_off + len >= Buf.Capacity)\r\n    {\r\n        int double_capacity = Buf.Capacity * 2;\r\n        Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity);\r\n    }\r\n\r\n    Buf.resize(needed_sz);\r\n    ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args_copy);\r\n}\r\n\r\nvoid ImGuiTextBuffer::append(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    appendv(fmt, args);\r\n    va_end(args);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImGuiSimpleColumns\r\n//-----------------------------------------------------------------------------\r\n\r\nImGuiSimpleColumns::ImGuiSimpleColumns()\r\n{\r\n    Count = 0;\r\n    Spacing = Width = NextWidth = 0.0f;\r\n    memset(Pos, 0, sizeof(Pos));\r\n    memset(NextWidths, 0, sizeof(NextWidths));\r\n}\r\n\r\nvoid ImGuiSimpleColumns::Update(int count, float spacing, bool clear)\r\n{\r\n    IM_ASSERT(Count <= IM_ARRAYSIZE(Pos));\r\n    Count = count;\r\n    Width = NextWidth = 0.0f;\r\n    Spacing = spacing;\r\n    if (clear) memset(NextWidths, 0, sizeof(NextWidths));\r\n    for (int i = 0; i < Count; i++)\r\n    {\r\n        if (i > 0 && NextWidths[i] > 0.0f)\r\n            Width += Spacing;\r\n        Pos[i] = (float)(int)Width;\r\n        Width += NextWidths[i];\r\n        NextWidths[i] = 0.0f;\r\n    }\r\n}\r\n\r\nfloat ImGuiSimpleColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double\r\n{\r\n    NextWidth = 0.0f;\r\n    NextWidths[0] = ImMax(NextWidths[0], w0);\r\n    NextWidths[1] = ImMax(NextWidths[1], w1);\r\n    NextWidths[2] = ImMax(NextWidths[2], w2);\r\n    for (int i = 0; i < 3; i++)\r\n        NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);\r\n    return ImMax(Width, NextWidth);\r\n}\r\n\r\nfloat ImGuiSimpleColumns::CalcExtraSpace(float avail_w)\r\n{\r\n    return ImMax(0.0f, avail_w - Width);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImGuiListClipper\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)\r\n{\r\n    // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. \r\n    // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. Consider moving within SetCursorXXX functions?\r\n    ImGui::SetCursorPosY(pos_y);\r\n    ImGuiWindow* window = ImGui::GetCurrentWindow();\r\n    window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;      // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage.\r\n    window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y);    // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.\r\n    if (window->DC.ColumnsCount > 1)\r\n        window->DC.ColumnsCellMinY = window->DC.CursorPos.y;                    // Setting this so that cell Y position are set properly\r\n}\r\n\r\n// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1\r\n// Use case B: Begin() called from constructor with items_height>0\r\n// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style.\r\nvoid ImGuiListClipper::Begin(int count, float items_height)\r\n{\r\n    StartPosY = ImGui::GetCursorPosY();\r\n    ItemsHeight = items_height;\r\n    ItemsCount = count;\r\n    StepNo = 0;\r\n    DisplayEnd = DisplayStart = -1;\r\n    if (ItemsHeight > 0.0f)\r\n    {\r\n        ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display\r\n        if (DisplayStart > 0)\r\n            SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor\r\n        StepNo = 2;\r\n    }\r\n}\r\n\r\nvoid ImGuiListClipper::End()\r\n{\r\n    if (ItemsCount < 0)\r\n        return;\r\n    // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user.\r\n    if (ItemsCount < INT_MAX)\r\n        SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor\r\n    ItemsCount = -1;\r\n    StepNo = 3;\r\n}\r\n\r\nbool ImGuiListClipper::Step()\r\n{\r\n    if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)\r\n    {\r\n        ItemsCount = -1; \r\n        return false; \r\n    }\r\n    if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height.\r\n    {\r\n        DisplayStart = 0;\r\n        DisplayEnd = 1;\r\n        StartPosY = ImGui::GetCursorPosY();\r\n        StepNo = 1;\r\n        return true;\r\n    }\r\n    if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.\r\n    {\r\n        if (ItemsCount == 1) { ItemsCount = -1; return false; }\r\n        float items_height = ImGui::GetCursorPosY() - StartPosY;\r\n        IM_ASSERT(items_height > 0.0f);   // If this triggers, it means Item 0 hasn't moved the cursor vertically\r\n        Begin(ItemsCount-1, items_height);\r\n        DisplayStart++;\r\n        DisplayEnd++;\r\n        StepNo = 3;\r\n        return true;\r\n    }\r\n    if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3.\r\n    {\r\n        IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0);\r\n        StepNo = 3;\r\n        return true;\r\n    }\r\n    if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.\r\n        End();\r\n    return false;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImGuiWindow\r\n//-----------------------------------------------------------------------------\r\n\r\nImGuiWindow::ImGuiWindow(const char* name)\r\n{\r\n    Name = ImStrdup(name);\r\n    ID = ImHash(name, 0);\r\n    IDStack.push_back(ID);\r\n    Flags = 0;\r\n    OrderWithinParent = 0;\r\n    PosFloat = Pos = ImVec2(0.0f, 0.0f);\r\n    Size = SizeFull = ImVec2(0.0f, 0.0f);\r\n    SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);\r\n    WindowPadding = ImVec2(0.0f, 0.0f);\r\n    MoveId = GetID(\"#MOVE\");\r\n    Scroll = ImVec2(0.0f, 0.0f);\r\n    ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);\r\n    ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);\r\n    ScrollbarX = ScrollbarY = false;\r\n    ScrollbarSizes = ImVec2(0.0f, 0.0f);\r\n    BorderSize = 0.0f;\r\n    Active = WasActive = false;\r\n    Accessed = false;\r\n    Collapsed = false;\r\n    SkipItems = false;\r\n    Appearing = false;\r\n    BeginCount = 0;\r\n    PopupId = 0;\r\n    AutoFitFramesX = AutoFitFramesY = -1;\r\n    AutoFitOnlyGrows = false;\r\n    AutoFitChildAxises = 0x00;\r\n    AutoPosLastDirection = -1;\r\n    HiddenFrames = 0;\r\n    SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;\r\n    SetWindowPosCenterWanted = false;\r\n\r\n    LastFrameActive = -1;\r\n    ItemWidthDefault = 0.0f;\r\n    FontWindowScale = 1.0f;\r\n\r\n    DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));\r\n    IM_PLACEMENT_NEW(DrawList) ImDrawList();\r\n    DrawList->_OwnerName = Name;\r\n    ParentWindow = NULL;\r\n    RootWindow = NULL;\r\n    RootNonPopupWindow = NULL;\r\n\r\n    FocusIdxAllCounter = FocusIdxTabCounter = -1;\r\n    FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;\r\n    FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;\r\n}\r\n\r\nImGuiWindow::~ImGuiWindow()\r\n{\r\n    DrawList->~ImDrawList();\r\n    ImGui::MemFree(DrawList);\r\n    DrawList = NULL;\r\n    ImGui::MemFree(Name);\r\n    Name = NULL;\r\n}\r\n\r\nImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)\r\n{\r\n    ImGuiID seed = IDStack.back();\r\n    ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed);\r\n    ImGui::KeepAliveID(id);\r\n    return id;\r\n}\r\n\r\nImGuiID ImGuiWindow::GetID(const void* ptr)\r\n{\r\n    ImGuiID seed = IDStack.back();\r\n    ImGuiID id = ImHash(&ptr, sizeof(void*), seed);\r\n    ImGui::KeepAliveID(id);\r\n    return id;\r\n}\r\n\r\nImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)\r\n{\r\n    ImGuiID seed = IDStack.back();\r\n    return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Internal API exposed in imgui_internal.h\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic void SetCurrentWindow(ImGuiWindow* window)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.CurrentWindow = window;\r\n    if (window)\r\n        g.FontSize = window->CalcFontSize();\r\n}\r\n\r\nImGuiWindow* ImGui::GetParentWindow()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(g.CurrentWindowStack.Size >= 2);\r\n    return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2];\r\n}\r\n\r\nvoid ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.ActiveIdIsJustActivated = (g.ActiveId != id);\r\n    g.ActiveId = id;\r\n    g.ActiveIdAllowOverlap = false;\r\n    g.ActiveIdIsAlive |= (id != 0);\r\n    g.ActiveIdWindow = window;\r\n}\r\n\r\nvoid ImGui::ClearActiveID()\r\n{\r\n    SetActiveID(0, NULL);\r\n}\r\n\r\nvoid ImGui::SetHoveredID(ImGuiID id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.HoveredId = id;\r\n    g.HoveredIdAllowOverlap = false;\r\n}\r\n\r\nvoid ImGui::KeepAliveID(ImGuiID id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.ActiveId == id)\r\n        g.ActiveIdIsAlive = true;\r\n}\r\n\r\n// Advance cursor given item size for layout.\r\nvoid ImGui::ItemSize(const ImVec2& size, float text_offset_y)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    // Always align ourselves on pixel boundaries\r\n    ImGuiContext& g = *GImGui;\r\n    const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);\r\n    const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);\r\n    window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);\r\n    window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y));\r\n    window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);\r\n    window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);\r\n\r\n    //window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // Debug\r\n\r\n    window->DC.PrevLineHeight = line_height;\r\n    window->DC.PrevLineTextBaseOffset = text_base_offset;\r\n    window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f;\r\n}\r\n\r\nvoid ImGui::ItemSize(const ImRect& bb, float text_offset_y)\r\n{\r\n    ItemSize(bb.GetSize(), text_offset_y);\r\n}\r\n\r\n// Declare item bounding box for clipping and interaction.\r\n// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface\r\n// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().\r\nbool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n    window->DC.LastItemId = id ? *id : 0;\r\n    window->DC.LastItemRect = bb;\r\n    window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;\r\n    if (IsClippedEx(bb, id, false))\r\n        return false;\r\n\r\n    // Setting LastItemHoveredAndUsable for IsItemHovered(). This is a sensible default, but widgets are free to override it.\r\n    if (IsMouseHoveringRect(bb.Min, bb.Max))\r\n    {\r\n        // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background)\r\n        // So that clicking on items with no active id such as Text() still returns true with IsItemHovered()\r\n        window->DC.LastItemHoveredRect = true;\r\n        if (g.HoveredRootWindow == window->RootWindow)\r\n            if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId))\r\n                if (IsWindowContentHoverable(window))\r\n                    window->DC.LastItemHoveredAndUsable = true;\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\nbool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (!bb.Overlaps(window->ClipRect))\r\n        if (!id || *id != g.ActiveId)\r\n            if (clip_even_when_logged || !g.LogEnabled)\r\n                return true;\r\n    return false;\r\n}\r\n\r\n// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic.\r\nbool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap)\r\n    {\r\n        ImGuiWindow* window = GetCurrentWindowRead();\r\n        if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))\r\n            if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max))\r\n                if (IsWindowContentHoverable(g.HoveredRootWindow))\r\n                    return true;\r\n    }\r\n    return false;\r\n}\r\n\r\nbool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    const bool allow_keyboard_focus = (window->DC.ItemFlags & ImGuiItemFlags_AllowKeyboardFocus) != 0;\r\n    window->FocusIdxAllCounter++;\r\n    if (allow_keyboard_focus)\r\n        window->FocusIdxTabCounter++;\r\n\r\n    // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.\r\n    // Note that we can always TAB out of a widget that doesn't allow tabbing in.\r\n    if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))\r\n        window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.\r\n\r\n    if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)\r\n        return true;\r\n\r\n    if (allow_keyboard_focus)\r\n        if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)\r\n            return true;\r\n\r\n    return false;\r\n}\r\n\r\nvoid ImGui::FocusableItemUnregister(ImGuiWindow* window)\r\n{\r\n    window->FocusIdxAllCounter--;\r\n    window->FocusIdxTabCounter--;\r\n}\r\n\r\nImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImVec2 content_max;\r\n    if (size.x < 0.0f || size.y < 0.0f)\r\n        content_max = g.CurrentWindow->Pos + GetContentRegionMax();\r\n    if (size.x <= 0.0f)\r\n        size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;\r\n    if (size.y <= 0.0f)\r\n        size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;\r\n    return size;\r\n}\r\n\r\nfloat ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)\r\n{\r\n    if (wrap_pos_x < 0.0f)\r\n        return 0.0f;\r\n\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (wrap_pos_x == 0.0f)\r\n        wrap_pos_x = GetContentRegionMax().x + window->Pos.x;\r\n    else if (wrap_pos_x > 0.0f)\r\n        wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space\r\n\r\n    return ImMax(wrap_pos_x - pos.x, 1.0f);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid* ImGui::MemAlloc(size_t sz)\r\n{\r\n    GImGui->IO.MetricsAllocs++;\r\n    return GImGui->IO.MemAllocFn(sz);\r\n}\r\n\r\nvoid ImGui::MemFree(void* ptr)\r\n{\r\n    if (ptr) GImGui->IO.MetricsAllocs--;\r\n    return GImGui->IO.MemFreeFn(ptr);\r\n}\r\n\r\nconst char* ImGui::GetClipboardText()\r\n{\r\n    return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : \"\";\r\n}\r\n\r\nvoid ImGui::SetClipboardText(const char* text)\r\n{\r\n    if (GImGui->IO.SetClipboardTextFn)\r\n        GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);\r\n}\r\n\r\nconst char* ImGui::GetVersion()\r\n{\r\n    return IMGUI_VERSION;\r\n}\r\n\r\n// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself\r\n// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module\r\nImGuiContext* ImGui::GetCurrentContext()\r\n{\r\n    return GImGui;\r\n}\r\n\r\nvoid ImGui::SetCurrentContext(ImGuiContext* ctx)\r\n{\r\n#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC\r\n    IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.\r\n#else\r\n    GImGui = ctx;\r\n#endif\r\n}\r\n\r\nImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*))\r\n{\r\n    if (!malloc_fn) malloc_fn = malloc;\r\n    ImGuiContext* ctx = (ImGuiContext*)malloc_fn(sizeof(ImGuiContext));\r\n    IM_PLACEMENT_NEW(ctx) ImGuiContext();\r\n    ctx->IO.MemAllocFn = malloc_fn;\r\n    ctx->IO.MemFreeFn = free_fn ? free_fn : free;\r\n    return ctx;\r\n}\r\n\r\nvoid ImGui::DestroyContext(ImGuiContext* ctx)\r\n{\r\n    void (*free_fn)(void*) = ctx->IO.MemFreeFn;\r\n    ctx->~ImGuiContext();\r\n    free_fn(ctx);\r\n    if (GImGui == ctx)\r\n        SetCurrentContext(NULL);\r\n}\r\n\r\nImGuiIO& ImGui::GetIO()\r\n{\r\n    return GImGui->IO;\r\n}\r\n\r\nImGuiStyle& ImGui::GetStyle()\r\n{\r\n    return GImGui->Style;\r\n}\r\n\r\n// Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame()\r\nImDrawData* ImGui::GetDrawData()\r\n{\r\n    return GImGui->RenderDrawData.Valid ? &GImGui->RenderDrawData : NULL;\r\n}\r\n\r\nfloat ImGui::GetTime()\r\n{\r\n    return GImGui->Time;\r\n}\r\n\r\nint ImGui::GetFrameCount()\r\n{\r\n    return GImGui->FrameCount;\r\n}\r\n\r\nvoid ImGui::NewFrame()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    // Check user data\r\n    IM_ASSERT(g.IO.DeltaTime >= 0.0f);               // Need a positive DeltaTime (zero is tolerated but will cause some timing issues)\r\n    IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);\r\n    IM_ASSERT(g.IO.Fonts->Fonts.Size > 0);           // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?\r\n    IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded());     // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?\r\n    IM_ASSERT(g.Style.CurveTessellationTol > 0.0f);  // Invalid style setting\r\n    IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f);  // Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)\r\n\r\n    // Initialize on first frame\r\n    if (!g.Initialized)\r\n        ImGui::Initialize();\r\n\r\n    SetCurrentFont(GetDefaultFont());\r\n    IM_ASSERT(g.Font->IsLoaded());\r\n\r\n    g.Time += g.IO.DeltaTime;\r\n    g.FrameCount += 1;\r\n    g.TooltipOverrideCount = 0;\r\n    g.OverlayDrawList.Clear();\r\n    g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID);\r\n    g.OverlayDrawList.PushClipRectFullScreen();\r\n\r\n    // Mark rendering data as invalid to prevent user who may have a handle on it to use it\r\n    g.RenderDrawData.Valid = false;\r\n    g.RenderDrawData.CmdLists = NULL;\r\n    g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0;\r\n\r\n    // Clear reference to active widget if the widget isn't alive anymore\r\n    g.HoveredIdPreviousFrame = g.HoveredId;\r\n    g.HoveredId = 0;\r\n    g.HoveredIdAllowOverlap = false;\r\n    if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)\r\n        ClearActiveID();\r\n    g.ActiveIdPreviousFrame = g.ActiveId;\r\n    g.ActiveIdIsAlive = false;\r\n    g.ActiveIdIsJustActivated = false;\r\n    if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)\r\n        g.ScalarAsInputTextId = 0;\r\n\r\n    // Update keyboard input state\r\n    memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));\r\n    for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)\r\n        g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f;\r\n\r\n    // Update mouse input state\r\n    // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta\r\n    if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev))\r\n        g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;\r\n    else\r\n        g.IO.MouseDelta = ImVec2(0.0f, 0.0f);\r\n    g.IO.MousePosPrev = g.IO.MousePos;\r\n    for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)\r\n    {\r\n        g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;\r\n        g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;\r\n        g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];\r\n        g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;\r\n        g.IO.MouseDoubleClicked[i] = false;\r\n        if (g.IO.MouseClicked[i])\r\n        {\r\n            if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime)\r\n            {\r\n                if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)\r\n                    g.IO.MouseDoubleClicked[i] = true;\r\n                g.IO.MouseClickedTime[i] = -FLT_MAX;    // so the third click isn't turned into a double-click\r\n            }\r\n            else\r\n            {\r\n                g.IO.MouseClickedTime[i] = g.Time;\r\n            }\r\n            g.IO.MouseClickedPos[i] = g.IO.MousePos;\r\n            g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;\r\n        }\r\n        else if (g.IO.MouseDown[i])\r\n        {\r\n            g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]));\r\n        }\r\n    }\r\n\r\n    // Calculate frame-rate for the user, as a purely luxurious feature\r\n    g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];\r\n    g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;\r\n    g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);\r\n    g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame));\r\n\r\n    // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows.\r\n    if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId)\r\n    {\r\n        KeepAliveID(g.MovedWindowMoveId);\r\n        IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow);\r\n        IM_ASSERT(g.MovedWindow->RootWindow->MoveId == g.MovedWindowMoveId);\r\n        if (g.IO.MouseDown[0])\r\n        {\r\n            if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove))\r\n            {\r\n                g.MovedWindow->PosFloat += g.IO.MouseDelta;\r\n                if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)\r\n                    MarkIniSettingsDirty(g.MovedWindow);\r\n            }\r\n            FocusWindow(g.MovedWindow);\r\n        }\r\n        else\r\n        {\r\n            ClearActiveID();\r\n            g.MovedWindow = NULL;\r\n            g.MovedWindowMoveId = 0;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        g.MovedWindow = NULL;\r\n        g.MovedWindowMoveId = 0;\r\n    }\r\n\r\n    // Delay saving settings so we don't spam disk too much\r\n    if (g.SettingsDirtyTimer > 0.0f)\r\n    {\r\n        g.SettingsDirtyTimer -= g.IO.DeltaTime;\r\n        if (g.SettingsDirtyTimer <= 0.0f)\r\n            SaveIniSettingsToDisk(g.IO.IniFilename);\r\n    }\r\n\r\n    // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow\r\n    g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false);\r\n    if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow))\r\n        g.HoveredRootWindow = g.HoveredWindow->RootWindow;\r\n    else\r\n        g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true);\r\n\r\n    if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow())\r\n    {\r\n        g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f);\r\n        ImGuiWindow* window = g.HoveredRootWindow;\r\n        while (window && window != modal_window)\r\n            window = window->ParentWindow;\r\n        if (!window)\r\n            g.HoveredRootWindow = g.HoveredWindow = NULL;\r\n    }\r\n    else\r\n    {\r\n        g.ModalWindowDarkeningRatio = 0.0f;\r\n    }\r\n\r\n    // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application.\r\n    // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership.\r\n    int mouse_earliest_button_down = -1;\r\n    bool mouse_any_down = false;\r\n    for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)\r\n    {\r\n        if (g.IO.MouseClicked[i])\r\n            g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());\r\n        mouse_any_down |= g.IO.MouseDown[i];\r\n        if (g.IO.MouseDown[i])\r\n            if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i])\r\n                mouse_earliest_button_down = i;\r\n    }\r\n    bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];\r\n    if (g.WantCaptureMouseNextFrame != -1)\r\n        g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);\r\n    else\r\n        g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty());\r\n    g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != -1) ? (g.WantCaptureKeyboardNextFrame != 0) : (g.ActiveId != 0);\r\n    g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0;\r\n    g.MouseCursor = ImGuiMouseCursor_Arrow;\r\n    g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;\r\n    g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default\r\n\r\n    // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.\r\n    if (!mouse_avail_to_imgui)\r\n        g.HoveredWindow = g.HoveredRootWindow = NULL;\r\n\r\n    // Scale & Scrolling\r\n    if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed)\r\n    {\r\n        ImGuiWindow* window = g.HoveredWindow;\r\n        if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling)\r\n        {\r\n            // Zoom / Scale window\r\n            const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);\r\n            const float scale = new_font_scale / window->FontWindowScale;\r\n            window->FontWindowScale = new_font_scale;\r\n\r\n            const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;\r\n            window->Pos += offset;\r\n            window->PosFloat += offset;\r\n            window->Size *= scale;\r\n            window->SizeFull *= scale;\r\n        }\r\n        else if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse))\r\n        {\r\n            // Scroll\r\n            const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5;\r\n            SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * window->CalcFontSize() * scroll_lines);\r\n        }\r\n    }\r\n\r\n    // Pressing TAB activate widget focus\r\n    // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus.\r\n    if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false))\r\n        g.NavWindow->FocusIdxTabRequestNext = 0;\r\n\r\n    // Mark all windows as not visible\r\n    for (int i = 0; i != g.Windows.Size; i++)\r\n    {\r\n        ImGuiWindow* window = g.Windows[i];\r\n        window->WasActive = window->Active;\r\n        window->Active = false;\r\n        window->Accessed = false;\r\n    }\r\n\r\n    // Closing the focused window restore focus to the first active root window in descending z-order\r\n    if (g.NavWindow && !g.NavWindow->WasActive)\r\n        for (int i = g.Windows.Size-1; i >= 0; i--)\r\n            if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow))\r\n            {\r\n                FocusWindow(g.Windows[i]);\r\n                break;\r\n            }\r\n\r\n    // No window should be open at the beginning of the frame.\r\n    // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.\r\n    g.CurrentWindowStack.resize(0);\r\n    g.CurrentPopupStack.resize(0);\r\n    CloseInactivePopups();\r\n\r\n    // Create implicit window - we will only render it if the user has added something to it.\r\n    ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);\r\n    ImGui::Begin(\"Debug\");\r\n}\r\n\r\nvoid ImGui::Initialize()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer));\r\n    IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer();\r\n\r\n    IM_ASSERT(g.Settings.empty());\r\n    LoadIniSettingsFromDisk(g.IO.IniFilename);\r\n    g.Initialized = true;\r\n}\r\n\r\n// This function is merely here to free heap allocations.\r\nvoid ImGui::Shutdown()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)\r\n    if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky.\r\n        g.IO.Fonts->Clear();\r\n\r\n    // Cleanup of other data are conditional on actually having initialize ImGui.\r\n    if (!g.Initialized)\r\n        return;\r\n\r\n    SaveIniSettingsToDisk(g.IO.IniFilename);\r\n\r\n    for (int i = 0; i < g.Windows.Size; i++)\r\n    {\r\n        g.Windows[i]->~ImGuiWindow();\r\n        ImGui::MemFree(g.Windows[i]);\r\n    }\r\n    g.Windows.clear();\r\n    g.WindowsSortBuffer.clear();\r\n    g.CurrentWindow = NULL;\r\n    g.CurrentWindowStack.clear();\r\n    g.NavWindow = NULL;\r\n    g.HoveredWindow = NULL;\r\n    g.HoveredRootWindow = NULL;\r\n    g.ActiveIdWindow = NULL;\r\n    g.MovedWindow = NULL;\r\n    for (int i = 0; i < g.Settings.Size; i++)\r\n        ImGui::MemFree(g.Settings[i].Name);\r\n    g.Settings.clear();\r\n    g.ColorModifiers.clear();\r\n    g.StyleModifiers.clear();\r\n    g.FontStack.clear();\r\n    g.OpenPopupStack.clear();\r\n    g.CurrentPopupStack.clear();\r\n    g.SetNextWindowSizeConstraintCallback = NULL;\r\n    g.SetNextWindowSizeConstraintCallbackUserData = NULL;\r\n    for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)\r\n        g.RenderDrawLists[i].clear();\r\n    g.OverlayDrawList.ClearFreeMemory();\r\n    g.PrivateClipboard.clear();\r\n    g.InputTextState.Text.clear();\r\n    g.InputTextState.InitialText.clear();\r\n    g.InputTextState.TempTextBuffer.clear();\r\n\r\n    if (g.LogFile && g.LogFile != stdout)\r\n    {\r\n        fclose(g.LogFile);\r\n        g.LogFile = NULL;\r\n    }\r\n    if (g.LogClipboard)\r\n    {\r\n        g.LogClipboard->~ImGuiTextBuffer();\r\n        ImGui::MemFree(g.LogClipboard);\r\n    }\r\n\r\n    g.Initialized = false;\r\n}\r\n\r\nstatic ImGuiIniData* FindWindowSettings(const char* name)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiID id = ImHash(name, 0);\r\n    for (int i = 0; i != g.Settings.Size; i++)\r\n    {\r\n        ImGuiIniData* ini = &g.Settings[i];\r\n        if (ini->Id == id)\r\n            return ini;\r\n    }\r\n    return NULL;\r\n}\r\n\r\nstatic ImGuiIniData* AddWindowSettings(const char* name)\r\n{\r\n    GImGui->Settings.resize(GImGui->Settings.Size + 1);\r\n    ImGuiIniData* ini = &GImGui->Settings.back();\r\n    ini->Name = ImStrdup(name);\r\n    ini->Id = ImHash(name, 0);\r\n    ini->Collapsed = false;\r\n    ini->Pos = ImVec2(FLT_MAX,FLT_MAX);\r\n    ini->Size = ImVec2(0,0);\r\n    return ini;\r\n}\r\n\r\n// Zero-tolerance, poor-man .ini parsing\r\n// FIXME: Write something less rubbish\r\nstatic void LoadIniSettingsFromDisk(const char* ini_filename)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (!ini_filename)\r\n        return;\r\n\r\n    int file_size;\r\n    char* file_data = (char*)ImFileLoadToMemory(ini_filename, \"rb\", &file_size, 1);\r\n    if (!file_data)\r\n        return;\r\n\r\n    ImGuiIniData* settings = NULL;\r\n    const char* buf_end = file_data + file_size;\r\n    for (const char* line_start = file_data; line_start < buf_end; )\r\n    {\r\n        const char* line_end = line_start;\r\n        while (line_end < buf_end && *line_end != '\\n' && *line_end != '\\r')\r\n            line_end++;\r\n\r\n        if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')\r\n        {\r\n            char name[64];\r\n            ImFormatString(name, IM_ARRAYSIZE(name), \"%.*s\", (int)(line_end-line_start-2), line_start+1);\r\n            settings = FindWindowSettings(name);\r\n            if (!settings)\r\n                settings = AddWindowSettings(name);\r\n        }\r\n        else if (settings)\r\n        {\r\n            float x, y;\r\n            int i;\r\n            if (sscanf(line_start, \"Pos=%f,%f\", &x, &y) == 2)\r\n                settings->Pos = ImVec2(x, y);\r\n            else if (sscanf(line_start, \"Size=%f,%f\", &x, &y) == 2)\r\n                settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize);\r\n            else if (sscanf(line_start, \"Collapsed=%d\", &i) == 1)\r\n                settings->Collapsed = (i != 0);\r\n        }\r\n\r\n        line_start = line_end+1;\r\n    }\r\n\r\n    ImGui::MemFree(file_data);\r\n}\r\n\r\nstatic void SaveIniSettingsToDisk(const char* ini_filename)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SettingsDirtyTimer = 0.0f;\r\n    if (!ini_filename)\r\n        return;\r\n\r\n    // Gather data from windows that were active during this session\r\n    for (int i = 0; i != g.Windows.Size; i++)\r\n    {\r\n        ImGuiWindow* window = g.Windows[i];\r\n        if (window->Flags & ImGuiWindowFlags_NoSavedSettings)\r\n            continue;\r\n        ImGuiIniData* settings = FindWindowSettings(window->Name);\r\n        if (!settings)  // This will only return NULL in the rare instance where the window was first created with ImGuiWindowFlags_NoSavedSettings then had the flag disabled later on. We don't bind settings in this case (bug #1000).\r\n            continue;\r\n        settings->Pos = window->Pos;\r\n        settings->Size = window->SizeFull;\r\n        settings->Collapsed = window->Collapsed;\r\n    }\r\n\r\n    // Write .ini file\r\n    // If a window wasn't opened in this session we preserve its settings\r\n    FILE* f = ImFileOpen(ini_filename, \"wt\");\r\n    if (!f)\r\n        return;\r\n    for (int i = 0; i != g.Settings.Size; i++)\r\n    {\r\n        const ImGuiIniData* settings = &g.Settings[i];\r\n        if (settings->Pos.x == FLT_MAX)\r\n            continue;\r\n        const char* name = settings->Name;\r\n        if (const char* p = strstr(name, \"###\"))  // Skip to the \"###\" marker if any. We don't skip past to match the behavior of GetID()\r\n            name = p;\r\n        fprintf(f, \"[%s]\\n\", name);\r\n        fprintf(f, \"Pos=%d,%d\\n\", (int)settings->Pos.x, (int)settings->Pos.y);\r\n        fprintf(f, \"Size=%d,%d\\n\", (int)settings->Size.x, (int)settings->Size.y);\r\n        fprintf(f, \"Collapsed=%d\\n\", settings->Collapsed);\r\n        fprintf(f, \"\\n\");\r\n    }\r\n\r\n    fclose(f);\r\n}\r\n\r\nstatic void MarkIniSettingsDirty(ImGuiWindow* window)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))\r\n        if (g.SettingsDirtyTimer <= 0.0f)\r\n            g.SettingsDirtyTimer = g.IO.IniSavingRate;\r\n}\r\n\r\n// FIXME: Add a more explicit sort order in the window structure.\r\nstatic int ChildWindowComparer(const void* lhs, const void* rhs)\r\n{\r\n    const ImGuiWindow* a = *(const ImGuiWindow**)lhs;\r\n    const ImGuiWindow* b = *(const ImGuiWindow**)rhs;\r\n    if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))\r\n        return d;\r\n    if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))\r\n        return d;\r\n    if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox))\r\n        return d;\r\n    return (a->OrderWithinParent - b->OrderWithinParent);\r\n}\r\n\r\nstatic void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window)\r\n{\r\n    out_sorted_windows.push_back(window);\r\n    if (window->Active)\r\n    {\r\n        int count = window->DC.ChildWindows.Size;\r\n        if (count > 1)\r\n            qsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);\r\n        for (int i = 0; i < count; i++)\r\n        {\r\n            ImGuiWindow* child = window->DC.ChildWindows[i];\r\n            if (child->Active)\r\n                AddWindowToSortedBuffer(out_sorted_windows, child);\r\n        }\r\n    }\r\n}\r\n\r\nstatic void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDrawList* draw_list)\r\n{\r\n    if (draw_list->CmdBuffer.empty())\r\n        return;\r\n\r\n    // Remove trailing command if unused\r\n    ImDrawCmd& last_cmd = draw_list->CmdBuffer.back();\r\n    if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL)\r\n    {\r\n        draw_list->CmdBuffer.pop_back();\r\n        if (draw_list->CmdBuffer.empty())\r\n            return;\r\n    }\r\n\r\n    // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly.\r\n    IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);\r\n    IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);\r\n    IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);\r\n\r\n    // Check that draw_list doesn't use more vertices than indexable in a single draw call (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per window)\r\n    // If this assert triggers because you are drawing lots of stuff manually, you can:\r\n    // A) Add '#define ImDrawIdx unsigned int' in imconfig.h to set the index size to 4 bytes. You'll need to handle the 4-bytes indices to your renderer.\r\n    //    For example, the OpenGL example code detect index size at compile-time by doing:\r\n    //    'glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);'\r\n    //    Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API.\r\n    // B) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists.\r\n    IM_ASSERT(((ImU64)draw_list->_VtxCurrentIdx >> (sizeof(ImDrawIdx)*8)) == 0);  // Too many vertices in same ImDrawList. See comment above.\r\n    \r\n    out_render_list.push_back(draw_list);\r\n    GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;\r\n    GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;\r\n}\r\n\r\nstatic void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window)\r\n{\r\n    AddDrawListToRenderList(out_render_list, window->DrawList);\r\n    for (int i = 0; i < window->DC.ChildWindows.Size; i++)\r\n    {\r\n        ImGuiWindow* child = window->DC.ChildWindows[i];\r\n        if (!child->Active) // clipped children may have been marked not active\r\n            continue;\r\n        if ((child->Flags & ImGuiWindowFlags_Popup) && child->HiddenFrames > 0)\r\n            continue;\r\n        AddWindowToRenderList(out_render_list, child);\r\n    }\r\n}\r\n\r\nstatic void AddWindowToRenderListSelectLayer(ImGuiWindow* window)\r\n{\r\n    // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, ..\r\n    ImGuiContext& g = *GImGui;\r\n    g.IO.MetricsActiveWindows++;\r\n    if (window->Flags & ImGuiWindowFlags_Popup)\r\n        AddWindowToRenderList(g.RenderDrawLists[1], window);\r\n    else if (window->Flags & ImGuiWindowFlags_Tooltip)\r\n        AddWindowToRenderList(g.RenderDrawLists[2], window);\r\n    else\r\n        AddWindowToRenderList(g.RenderDrawLists[0], window);\r\n}\r\n\r\n// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result.\r\nvoid ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);\r\n    window->ClipRect = window->DrawList->_ClipRectStack.back();\r\n}\r\n\r\nvoid ImGui::PopClipRect()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DrawList->PopClipRect();\r\n    window->ClipRect = window->DrawList->_ClipRectStack.back();\r\n}\r\n\r\n// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.\r\nvoid ImGui::EndFrame()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(g.Initialized);                       // Forgot to call ImGui::NewFrame()\r\n    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again\r\n\r\n    // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)\r\n    if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f)\r\n    {\r\n        g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y);\r\n        g.OsImePosSet = g.OsImePosRequest;\r\n    }\r\n\r\n    // Hide implicit \"Debug\" window if it hasn't been used\r\n    IM_ASSERT(g.CurrentWindowStack.Size == 1);    // Mismatched Begin()/End() calls\r\n    if (g.CurrentWindow && !g.CurrentWindow->Accessed)\r\n        g.CurrentWindow->Active = false;\r\n    ImGui::End();\r\n\r\n    // Click to focus window and start moving (after we're done with all our widgets)\r\n    if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])\r\n    {\r\n        if (!(g.NavWindow && !g.NavWindow->WasActive && g.NavWindow->Active)) // Unless we just made a popup appear\r\n        {\r\n            if (g.HoveredRootWindow != NULL)\r\n            {\r\n                FocusWindow(g.HoveredWindow);\r\n                if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))\r\n                {\r\n                    g.MovedWindow = g.HoveredWindow;\r\n                    g.MovedWindowMoveId = g.HoveredRootWindow->MoveId;\r\n                    SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow);\r\n                }\r\n            }\r\n            else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL)\r\n            {\r\n                // Clicking on void disable focus\r\n                FocusWindow(NULL);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Sort the window list so that all child windows are after their parent\r\n    // We cannot do that on FocusWindow() because childs may not exist yet\r\n    g.WindowsSortBuffer.resize(0);\r\n    g.WindowsSortBuffer.reserve(g.Windows.Size);\r\n    for (int i = 0; i != g.Windows.Size; i++)\r\n    {\r\n        ImGuiWindow* window = g.Windows[i];\r\n        if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))       // if a child is active its parent will add it\r\n            continue;\r\n        AddWindowToSortedBuffer(g.WindowsSortBuffer, window);\r\n    }\r\n\r\n    IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);  // we done something wrong\r\n    g.Windows.swap(g.WindowsSortBuffer);\r\n\r\n    // Clear Input data for next frame\r\n    g.IO.MouseWheel = 0.0f;\r\n    memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));\r\n\r\n    g.FrameCountEnded = g.FrameCount;\r\n}\r\n\r\nvoid ImGui::Render()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(g.Initialized);   // Forgot to call ImGui::NewFrame()\r\n\r\n    if (g.FrameCountEnded != g.FrameCount)\r\n        ImGui::EndFrame();\r\n    g.FrameCountRendered = g.FrameCount;\r\n\r\n    // Skip render altogether if alpha is 0.0\r\n    // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false.\r\n    if (g.Style.Alpha > 0.0f)\r\n    {\r\n        // Gather windows to render\r\n        g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0;\r\n        for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)\r\n            g.RenderDrawLists[i].resize(0);\r\n        for (int i = 0; i != g.Windows.Size; i++)\r\n        {\r\n            ImGuiWindow* window = g.Windows[i];\r\n            if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0)\r\n                AddWindowToRenderListSelectLayer(window);\r\n        }\r\n\r\n        // Flatten layers\r\n        int n = g.RenderDrawLists[0].Size;\r\n        int flattened_size = n;\r\n        for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)\r\n            flattened_size += g.RenderDrawLists[i].Size;\r\n        g.RenderDrawLists[0].resize(flattened_size);\r\n        for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)\r\n        {\r\n            ImVector<ImDrawList*>& layer = g.RenderDrawLists[i];\r\n            if (layer.empty())\r\n                continue;\r\n            memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));\r\n            n += layer.Size;\r\n        }\r\n\r\n        // Draw software mouse cursor if requested\r\n        if (g.IO.MouseDrawCursor)\r\n        {\r\n            const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor];\r\n            const ImVec2 pos = g.IO.MousePos - cursor_data.HotOffset;\r\n            const ImVec2 size = cursor_data.Size;\r\n            const ImTextureID tex_id = g.IO.Fonts->TexID;\r\n            g.OverlayDrawList.PushTextureID(tex_id);\r\n            g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48));        // Shadow\r\n            g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48));        // Shadow\r\n            g.OverlayDrawList.AddImage(tex_id, pos,             pos + size,             cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,255));       // Black border\r\n            g.OverlayDrawList.AddImage(tex_id, pos,             pos + size,             cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], IM_COL32(255,255,255,255)); // White fill\r\n            g.OverlayDrawList.PopTextureID();\r\n        }\r\n        if (!g.OverlayDrawList.VtxBuffer.empty())\r\n            AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList);\r\n\r\n        // Setup draw data\r\n        g.RenderDrawData.Valid = true;\r\n        g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL;\r\n        g.RenderDrawData.CmdListsCount = g.RenderDrawLists[0].Size;\r\n        g.RenderDrawData.TotalVtxCount = g.IO.MetricsRenderVertices;\r\n        g.RenderDrawData.TotalIdxCount = g.IO.MetricsRenderIndices;\r\n\r\n        // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()\r\n        if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)\r\n            g.IO.RenderDrawListsFn(&g.RenderDrawData);\r\n    }\r\n}\r\n\r\nconst char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)\r\n{\r\n    const char* text_display_end = text;\r\n    if (!text_end)\r\n        text_end = (const char*)-1;\r\n\r\n    while (text_display_end < text_end && *text_display_end != '\\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))\r\n        text_display_end++;\r\n    return text_display_end;\r\n}\r\n\r\n// Pass text data straight to log (without being displayed)\r\nvoid ImGui::LogText(const char* fmt, ...)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (!g.LogEnabled)\r\n        return;\r\n\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    if (g.LogFile)\r\n    {\r\n        vfprintf(g.LogFile, fmt, args);\r\n    }\r\n    else\r\n    {\r\n        g.LogClipboard->appendv(fmt, args);\r\n    }\r\n    va_end(args);\r\n}\r\n\r\n// Internal version that takes a position to decide on newline placement and pad items according to their depth.\r\n// We split text into individual lines to add current tree level padding\r\nstatic void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = ImGui::GetCurrentWindowRead();\r\n\r\n    if (!text_end)\r\n        text_end = ImGui::FindRenderedTextEnd(text, text_end);\r\n\r\n    const bool log_new_line = ref_pos.y > window->DC.LogLinePosY+1;\r\n    window->DC.LogLinePosY = ref_pos.y;\r\n\r\n    const char* text_remaining = text;\r\n    if (g.LogStartDepth > window->DC.TreeDepth)  // Re-adjust padding if we have popped out of our starting depth\r\n        g.LogStartDepth = window->DC.TreeDepth;\r\n    const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);\r\n    for (;;)\r\n    {\r\n        // Split the string. Each new line (after a '\\n') is followed by spacing corresponding to the current depth of our log entry.\r\n        const char* line_end = text_remaining;\r\n        while (line_end < text_end)\r\n            if (*line_end == '\\n')\r\n                break;\r\n            else\r\n                line_end++;\r\n        if (line_end >= text_end)\r\n            line_end = NULL;\r\n\r\n        const bool is_first_line = (text == text_remaining);\r\n        bool is_last_line = false;\r\n        if (line_end == NULL)\r\n        {\r\n            is_last_line = true;\r\n            line_end = text_end;\r\n        }\r\n        if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0))\r\n        {\r\n            const int char_count = (int)(line_end - text_remaining);\r\n            if (log_new_line || !is_first_line)\r\n                ImGui::LogText(IM_NEWLINE \"%*s%.*s\", tree_depth*4, \"\", char_count, text_remaining);\r\n            else\r\n                ImGui::LogText(\" %.*s\", char_count, text_remaining);\r\n        }\r\n\r\n        if (is_last_line)\r\n            break;\r\n        text_remaining = line_end + 1;\r\n    }\r\n}\r\n\r\n// Internal ImGui functions to render text\r\n// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()\r\nvoid ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    // Hide anything after a '##' string\r\n    const char* text_display_end;\r\n    if (hide_text_after_hash)\r\n    {\r\n        text_display_end = FindRenderedTextEnd(text, text_end);\r\n    }\r\n    else\r\n    {\r\n        if (!text_end)\r\n            text_end = text + strlen(text); // FIXME-OPT\r\n        text_display_end = text_end;\r\n    }\r\n\r\n    const int text_len = (int)(text_display_end - text);\r\n    if (text_len > 0)\r\n    {\r\n        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);\r\n        if (g.LogEnabled)\r\n            LogRenderedText(pos, text, text_display_end);\r\n    }\r\n}\r\n\r\nvoid ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    if (!text_end)\r\n        text_end = text + strlen(text); // FIXME-OPT\r\n\r\n    const int text_len = (int)(text_end - text);\r\n    if (text_len > 0)\r\n    {\r\n        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);\r\n        if (g.LogEnabled)\r\n            LogRenderedText(pos, text, text_end);\r\n    }\r\n}\r\n\r\n// Default clip_rect uses (pos_min,pos_max)\r\n// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)\r\nvoid ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)\r\n{\r\n    // Hide anything after a '##' string\r\n    const char* text_display_end = FindRenderedTextEnd(text, text_end);\r\n    const int text_len = (int)(text_display_end - text);\r\n    if (text_len == 0)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    // Perform CPU side clipping for single clipped element to avoid using scissor state\r\n    ImVec2 pos = pos_min;\r\n    const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);\r\n\r\n    const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;\r\n    const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;\r\n    bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);\r\n    if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min\r\n        need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);\r\n\r\n    // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.\r\n    if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);\r\n    if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);\r\n\r\n    // Render\r\n    if (need_clipping)\r\n    {\r\n        ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);\r\n        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);\r\n    }\r\n    else\r\n    {\r\n        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);\r\n    }\r\n    if (g.LogEnabled)\r\n        LogRenderedText(pos, text, text_display_end);\r\n}\r\n\r\n// Render a rectangle shaped with optional rounding and borders\r\nvoid ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);\r\n    if (border && (window->Flags & ImGuiWindowFlags_ShowBorders))\r\n    {\r\n        window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding);\r\n        window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding);\r\n    }\r\n}\r\n\r\nvoid ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->Flags & ImGuiWindowFlags_ShowBorders)\r\n    {\r\n        window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding);\r\n        window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding);\r\n    }\r\n}\r\n\r\n// Render a triangle to denote expanded/collapsed state\r\nvoid ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    const float h = g.FontSize * 1.00f;\r\n    const float r = h * 0.40f * scale;\r\n    ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale);\r\n\r\n    ImVec2 a, b, c;\r\n    if (is_open)\r\n    {\r\n        center.y -= r*0.25f;\r\n        a = center + ImVec2(0,1)*r;\r\n        b = center + ImVec2(-0.866f,-0.5f)*r;\r\n        c = center + ImVec2(0.866f,-0.5f)*r;\r\n    }\r\n    else\r\n    {\r\n        a = center + ImVec2(1,0)*r;\r\n        b = center + ImVec2(-0.500f,0.866f)*r;\r\n        c = center + ImVec2(-0.500f,-0.866f)*r;\r\n    }\r\n\r\n    window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text));\r\n}\r\n\r\nvoid ImGui::RenderBullet(ImVec2 pos)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);\r\n}\r\n\r\nvoid ImGui::RenderCheckMark(ImVec2 pos, ImU32 col)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f);\r\n    float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f);\r\n    float bx = pos.x + 0.5f + start_x + rem_third;\r\n    float by = pos.y - 1.0f + (float)(int)(g.Font->Ascent * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y);\r\n    window->DrawList->PathLineTo(ImVec2(bx - rem_third, by - rem_third));\r\n    window->DrawList->PathLineTo(ImVec2(bx, by));\r\n    window->DrawList->PathLineTo(ImVec2(bx + rem_third*2, by - rem_third*2));\r\n    window->DrawList->PathStroke(col, false);\r\n}\r\n\r\n// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.\r\n// CalcTextSize(\"\") should return ImVec2(0.0f, GImGui->FontSize)\r\nImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    const char* text_display_end;\r\n    if (hide_text_after_double_hash)\r\n        text_display_end = FindRenderedTextEnd(text, text_end);      // Hide anything after a '##' string\r\n    else\r\n        text_display_end = text_end;\r\n\r\n    ImFont* font = g.Font;\r\n    const float font_size = g.FontSize;\r\n    if (text == text_display_end)\r\n        return ImVec2(0.0f, font_size);\r\n    ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);\r\n\r\n    // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field)\r\n    const float font_scale = font_size / font->FontSize;\r\n    const float character_spacing_x = 1.0f * font_scale;\r\n    if (text_size.x > 0.0f)\r\n        text_size.x -= character_spacing_x;\r\n    text_size.x = (float)(int)(text_size.x + 0.95f);\r\n\r\n    return text_size;\r\n}\r\n\r\n// Helper to calculate coarse clipping of large list of evenly sized items.\r\n// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.\r\n// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX\r\nvoid ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (g.LogEnabled)\r\n    {\r\n        // If logging is active, do not perform any clipping\r\n        *out_items_display_start = 0;\r\n        *out_items_display_end = items_count;\r\n        return;\r\n    }\r\n    if (window->SkipItems)\r\n    {\r\n        *out_items_display_start = *out_items_display_end = 0;\r\n        return;\r\n    }\r\n\r\n    const ImVec2 pos = window->DC.CursorPos;\r\n    int start = (int)((window->ClipRect.Min.y - pos.y) / items_height);\r\n    int end = (int)((window->ClipRect.Max.y - pos.y) / items_height);\r\n    start = ImClamp(start, 0, items_count);\r\n    end = ImClamp(end + 1, start, items_count);\r\n    *out_items_display_start = start;\r\n    *out_items_display_end = end;\r\n}\r\n\r\n// Find window given position, search front-to-back\r\n// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected.\r\nstatic ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    for (int i = g.Windows.Size-1; i >= 0; i--)\r\n    {\r\n        ImGuiWindow* window = g.Windows[i];\r\n        if (!window->Active)\r\n            continue;\r\n        if (window->Flags & ImGuiWindowFlags_NoInputs)\r\n            continue;\r\n        if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)\r\n            continue;\r\n\r\n        // Using the clipped AABB so a child window will typically be clipped by its parent.\r\n        ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding);\r\n        if (bb.Contains(pos))\r\n            return window;\r\n    }\r\n    return NULL;\r\n}\r\n\r\n// Test if mouse cursor is hovering given rectangle\r\n// NB- Rectangle is clipped by our current clip setting\r\n// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)\r\nbool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n\r\n    // Clip\r\n    ImRect rect_clipped(r_min, r_max);\r\n    if (clip)\r\n        rect_clipped.ClipWith(window->ClipRect);\r\n\r\n    // Expand for touch input\r\n    const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);\r\n    return rect_for_touch.Contains(g.IO.MousePos);\r\n}\r\n\r\nbool ImGui::IsAnyWindowHovered()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.HoveredWindow != NULL;\r\n}\r\n\r\nstatic bool IsKeyPressedMap(ImGuiKey key, bool repeat)\r\n{\r\n    const int key_index = GImGui->IO.KeyMap[key];\r\n    return (key_index >= 0) ? ImGui::IsKeyPressed(key_index, repeat) : false;\r\n}\r\n\r\nint ImGui::GetKeyIndex(ImGuiKey imgui_key)\r\n{\r\n    IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);\r\n    return GImGui->IO.KeyMap[imgui_key];\r\n}\r\n\r\n// Note that imgui doesn't know the semantic of each entry of io.KeyDown[]. Use your own indices/enums according to how your backend/engine stored them into KeyDown[]!\r\nbool ImGui::IsKeyDown(int user_key_index)\r\n{\r\n    if (user_key_index < 0) return false;\r\n    IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown));\r\n    return GImGui->IO.KeysDown[user_key_index];\r\n}\r\n\r\nint ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate)\r\n{\r\n    if (t == 0.0f)\r\n        return 1;\r\n    if (t <= repeat_delay || repeat_rate <= 0.0f)\r\n        return 0;\r\n    const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate);\r\n    return (count > 0) ? count : 0;\r\n}\r\n\r\nint ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (key_index < 0) return false;\r\n    IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));\r\n    const float t = g.IO.KeysDownDuration[key_index];\r\n    return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate);\r\n}\r\n\r\nbool ImGui::IsKeyPressed(int user_key_index, bool repeat)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (user_key_index < 0) return false;\r\n    IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));\r\n    const float t = g.IO.KeysDownDuration[user_key_index];\r\n    if (t == 0.0f)\r\n        return true;\r\n    if (repeat && t > g.IO.KeyRepeatDelay)\r\n        return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;\r\n    return false;\r\n}\r\n\r\nbool ImGui::IsKeyReleased(int user_key_index)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (user_key_index < 0) return false;\r\n    IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));\r\n    if (g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index])\r\n        return true;\r\n    return false;\r\n}\r\n\r\nbool ImGui::IsMouseDown(int button)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    return g.IO.MouseDown[button];\r\n}\r\n\r\nbool ImGui::IsMouseClicked(int button, bool repeat)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    const float t = g.IO.MouseDownDuration[button];\r\n    if (t == 0.0f)\r\n        return true;\r\n\r\n    if (repeat && t > g.IO.KeyRepeatDelay)\r\n    {\r\n        float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate;\r\n        if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f))\r\n            return true;\r\n    }\r\n\r\n    return false;\r\n}\r\n\r\nbool ImGui::IsMouseReleased(int button)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    return g.IO.MouseReleased[button];\r\n}\r\n\r\nbool ImGui::IsMouseDoubleClicked(int button)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    return g.IO.MouseDoubleClicked[button];\r\n}\r\n\r\nbool ImGui::IsMouseDragging(int button, float lock_threshold)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    if (!g.IO.MouseDown[button])\r\n        return false;\r\n    if (lock_threshold < 0.0f)\r\n        lock_threshold = g.IO.MouseDragThreshold;\r\n    return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;\r\n}\r\n\r\nImVec2 ImGui::GetMousePos()\r\n{\r\n    return GImGui->IO.MousePos;\r\n}\r\n\r\n// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!\r\nImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.CurrentPopupStack.Size > 0)\r\n        return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen;\r\n    return g.IO.MousePos;\r\n}\r\n\r\n// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position\r\nbool ImGui::IsMousePosValid(const ImVec2* mouse_pos)\r\n{\r\n    if (mouse_pos == NULL)\r\n        mouse_pos = &GImGui->IO.MousePos;\r\n    const float MOUSE_INVALID = -256000.0f;\r\n    return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID;\r\n}\r\n\r\nImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    if (lock_threshold < 0.0f)\r\n        lock_threshold = g.IO.MouseDragThreshold;\r\n    if (g.IO.MouseDown[button])\r\n        if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)\r\n            return g.IO.MousePos - g.IO.MouseClickedPos[button];     // Assume we can only get active with left-mouse button (at the moment).\r\n    return ImVec2(0.0f, 0.0f);\r\n}\r\n\r\nvoid ImGui::ResetMouseDragDelta(int button)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));\r\n    // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr\r\n    g.IO.MouseClickedPos[button] = g.IO.MousePos;\r\n}\r\n\r\nImGuiMouseCursor ImGui::GetMouseCursor()\r\n{\r\n    return GImGui->MouseCursor;\r\n}\r\n\r\nvoid ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)\r\n{\r\n    GImGui->MouseCursor = cursor_type;\r\n}\r\n\r\nvoid ImGui::CaptureKeyboardFromApp(bool capture)\r\n{\r\n    GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0;\r\n}\r\n\r\nvoid ImGui::CaptureMouseFromApp(bool capture)\r\n{\r\n    GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0;\r\n}\r\n\r\nbool ImGui::IsItemHovered()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.LastItemHoveredAndUsable;\r\n}\r\n\r\nbool ImGui::IsItemRectHovered()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.LastItemHoveredRect;\r\n}\r\n\r\nbool ImGui::IsItemActive()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.ActiveId)\r\n    {\r\n        ImGuiWindow* window = GetCurrentWindowRead();\r\n        return g.ActiveId == window->DC.LastItemId;\r\n    }\r\n    return false;\r\n}\r\n\r\nbool ImGui::IsItemClicked(int mouse_button)\r\n{\r\n    return IsMouseClicked(mouse_button) && IsItemHovered();\r\n}\r\n\r\nbool ImGui::IsAnyItemHovered()\r\n{\r\n    return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0;\r\n}\r\n\r\nbool ImGui::IsAnyItemActive()\r\n{\r\n    return GImGui->ActiveId != 0;\r\n}\r\n\r\nbool ImGui::IsItemVisible()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->ClipRect.Overlaps(window->DC.LastItemRect);\r\n}\r\n\r\n// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.\r\nvoid ImGui::SetItemAllowOverlap()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.HoveredId == g.CurrentWindow->DC.LastItemId)\r\n        g.HoveredIdAllowOverlap = true;\r\n    if (g.ActiveId == g.CurrentWindow->DC.LastItemId)\r\n        g.ActiveIdAllowOverlap = true;\r\n}\r\n\r\nImVec2 ImGui::GetItemRectMin()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.LastItemRect.Min;\r\n}\r\n\r\nImVec2 ImGui::GetItemRectMax()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.LastItemRect.Max;\r\n}\r\n\r\nImVec2 ImGui::GetItemRectSize()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.LastItemRect.GetSize();\r\n}\r\n\r\nImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, float outward)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    ImRect rect = window->DC.LastItemRect;\r\n    rect.Expand(outward);\r\n    return rect.GetClosestPoint(pos, on_edge);\r\n}\r\n\r\nstatic ImRect GetVisibleRect()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)\r\n        return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax);\r\n    return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);\r\n}\r\n\r\n// Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first.\r\nstatic void BeginTooltipEx(bool override_previous_tooltip)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    char window_name[16];\r\n    ImFormatString(window_name, IM_ARRAYSIZE(window_name), \"##Tooltip%02d\", g.TooltipOverrideCount);\r\n    if (override_previous_tooltip)\r\n        if (ImGuiWindow* window = ImGui::FindWindowByName(window_name))\r\n            if (window->Active)\r\n            {\r\n                // Hide previous tooltips. We can't easily \"reset\" the content of a window so we create a new one.\r\n                window->HiddenFrames = 1;\r\n                ImFormatString(window_name, IM_ARRAYSIZE(window_name), \"##Tooltip%02d\", ++g.TooltipOverrideCount);\r\n            }\r\n    ImGui::Begin(window_name, NULL, ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize);\r\n}\r\n\r\nvoid ImGui::SetTooltipV(const char* fmt, va_list args)\r\n{\r\n    BeginTooltipEx(true);\r\n    TextV(fmt, args);\r\n    EndTooltip();\r\n}\r\n\r\nvoid ImGui::SetTooltip(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    SetTooltipV(fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nvoid ImGui::BeginTooltip()\r\n{\r\n    BeginTooltipEx(false);\r\n}\r\n\r\nvoid ImGui::EndTooltip()\r\n{\r\n    IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);   // Mismatched BeginTooltip()/EndTooltip() calls\r\n    ImGui::End();\r\n}\r\n\r\n// Mark popup as open (toggle toward open state).\r\n// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.\r\n// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).\r\n// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)\r\nvoid ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n    int current_stack_size = g.CurrentPopupStack.Size;\r\n    ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID(\"##menus\"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here)\r\n    if (g.OpenPopupStack.Size < current_stack_size + 1)\r\n        g.OpenPopupStack.push_back(popup_ref);\r\n    else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id)\r\n    {\r\n        g.OpenPopupStack.resize(current_stack_size+1);\r\n        g.OpenPopupStack[current_stack_size] = popup_ref;\r\n    }\r\n}\r\n\r\nvoid ImGui::OpenPopup(const char* str_id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    OpenPopupEx(g.CurrentWindow->GetID(str_id), false);\r\n}\r\n\r\nstatic void CloseInactivePopups()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.OpenPopupStack.empty())\r\n        return;\r\n\r\n    // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.\r\n    // Don't close our own child popup windows\r\n    int n = 0;\r\n    if (g.NavWindow)\r\n    {\r\n        for (n = 0; n < g.OpenPopupStack.Size; n++)\r\n        {\r\n            ImGuiPopupRef& popup = g.OpenPopupStack[n];\r\n            if (!popup.Window)\r\n                continue;\r\n            IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);\r\n            if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)\r\n                continue;\r\n\r\n            bool has_focus = false;\r\n            for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++)\r\n                has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.NavWindow->RootWindow);\r\n            if (!has_focus)\r\n                break;\r\n        }\r\n    }\r\n    if (n < g.OpenPopupStack.Size)   // This test is not required but it allows to set a useful breakpoint on the line below\r\n        g.OpenPopupStack.resize(n);\r\n}\r\n\r\nstatic ImGuiWindow* GetFrontMostModalRootWindow()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    for (int n = g.OpenPopupStack.Size-1; n >= 0; n--)\r\n        if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window)\r\n            if (front_most_popup->Flags & ImGuiWindowFlags_Modal)\r\n                return front_most_popup;\r\n    return NULL;\r\n}\r\n\r\nstatic void ClosePopupToLevel(int remaining)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (remaining > 0)\r\n        ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window);\r\n    else\r\n        ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow);\r\n    g.OpenPopupStack.resize(remaining);\r\n}\r\n\r\nstatic void ClosePopup(ImGuiID id)\r\n{\r\n    if (!ImGui::IsPopupOpen(id))\r\n        return;\r\n    ImGuiContext& g = *GImGui;\r\n    ClosePopupToLevel(g.OpenPopupStack.Size - 1);\r\n}\r\n\r\n// Close the popup we have begin-ed into.\r\nvoid ImGui::CloseCurrentPopup()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    int popup_idx = g.CurrentPopupStack.Size - 1;\r\n    if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)\r\n        return;\r\n    while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu))\r\n        popup_idx--;\r\n    ClosePopupToLevel(popup_idx);\r\n}\r\n\r\nstatic inline void ClearSetNextWindowData()\r\n{\r\n    // FIXME-OPT\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0;\r\n    g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false;\r\n}\r\n\r\nstatic bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n    if (!ImGui::IsPopupOpen(id))\r\n    {\r\n        ClearSetNextWindowData(); // We behave like Begin() and need to consume those values\r\n        return false;\r\n    }\r\n\r\n    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);\r\n    ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;\r\n\r\n    char name[20];\r\n    if (flags & ImGuiWindowFlags_ChildMenu)\r\n        ImFormatString(name, IM_ARRAYSIZE(name), \"##menu_%d\", g.CurrentPopupStack.Size);    // Recycle windows based on depth\r\n    else\r\n        ImFormatString(name, IM_ARRAYSIZE(name), \"##popup_%08x\", id); // Not recycling, so we can close/open during the same frame\r\n\r\n    bool is_open = ImGui::Begin(name, NULL, flags);\r\n    if (!(window->Flags & ImGuiWindowFlags_ShowBorders))\r\n        g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders;\r\n    if (!is_open) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)\r\n        ImGui::EndPopup();\r\n\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::BeginPopup(const char* str_id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance\r\n    {\r\n        ClearSetNextWindowData(); // We behave like Begin() and need to consume those values\r\n        return false;\r\n    }\r\n    return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_ShowBorders);\r\n}\r\n\r\nbool ImGui::IsPopupOpen(ImGuiID id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == id;\r\n}\r\n\r\nbool ImGui::IsPopupOpen(const char* str_id)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);\r\n}\r\n\r\nbool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n    const ImGuiID id = window->GetID(name);\r\n    if (!IsPopupOpen(id))\r\n    {\r\n        ClearSetNextWindowData(); // We behave like Begin() and need to consume those values\r\n        return false;\r\n    }\r\n\r\n    ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings;\r\n    bool is_open = ImGui::Begin(name, p_open, flags);\r\n    if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)\r\n    {\r\n        ImGui::EndPopup();\r\n        if (is_open)\r\n            ClosePopup(id);\r\n        return false;\r\n    }\r\n\r\n    return is_open;\r\n}\r\n\r\nvoid ImGui::EndPopup()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);  // Mismatched BeginPopup()/EndPopup() calls\r\n    IM_ASSERT(GImGui->CurrentPopupStack.Size > 0);\r\n    ImGui::End();\r\n    if (!(window->Flags & ImGuiWindowFlags_Modal))\r\n        ImGui::PopStyleVar();\r\n}\r\n\r\n// This is a helper to handle the most simple case of associating one named popup to one given widget.\r\n// 1. If you have many possible popups (for different \"instances\" of a same widget, or for wholly different widgets), you may be better off handling\r\n//    this yourself so you can store data relative to the widget that opened the popup instead of choosing different popup identifiers.\r\n// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() with IsItemRectHovered()\r\n//    and passing true to the OpenPopupEx().\r\n//    Because: hovering an item in a window below the popup won't normally trigger is hovering behavior/coloring. The pattern of ignoring the fact that\r\n//    the item can be interacted with (because it is blocked by the active popup) may useful in some situation when e.g. large canvas as one item, content of menu\r\n//    driven by click position.\r\nbool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button)\r\n{\r\n    if (IsItemHovered() && IsMouseClicked(mouse_button))\r\n        OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), false);\r\n    return BeginPopup(str_id);\r\n}\r\n\r\nbool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items)\r\n{\r\n    if (!str_id)\r\n        str_id = \"window_context\";\r\n    if (IsWindowRectHovered() && IsMouseClicked(mouse_button))\r\n        if (also_over_items || !IsAnyItemHovered())\r\n            OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), true);\r\n    return BeginPopup(str_id);\r\n}\r\n\r\nbool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)\r\n{\r\n    if (!str_id) \r\n        str_id = \"void_context\";\r\n    if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button))\r\n        OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), true);\r\n    return BeginPopup(str_id);\r\n}\r\n\r\nstatic bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)\r\n{\r\n    ImGuiWindow* parent_window = ImGui::GetCurrentWindow();\r\n    ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;\r\n\r\n    const ImVec2 content_avail = ImGui::GetContentRegionAvail();\r\n    ImVec2 size = ImFloor(size_arg);\r\n    const int auto_fit_axises = ((size.x == 0.0f) ? 0x01 : 0x00) | ((size.y == 0.0f) ? 0x02 : 0x00);\r\n    if (size.x <= 0.0f)\r\n        size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues)\r\n    if (size.y <= 0.0f)\r\n        size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y);\r\n    if (border)\r\n        flags |= ImGuiWindowFlags_ShowBorders;\r\n    flags |= extra_flags;\r\n\r\n    char title[256];\r\n    if (name)\r\n        ImFormatString(title, IM_ARRAYSIZE(title), \"%s.%s.%08X\", parent_window->Name, name, id);\r\n    else\r\n        ImFormatString(title, IM_ARRAYSIZE(title), \"%s.%08X\", parent_window->Name, id);\r\n\r\n    bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags);\r\n    ImGuiWindow* child_window = ImGui::GetCurrentWindow();\r\n    child_window->AutoFitChildAxises = auto_fit_axises;\r\n    if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders))\r\n        child_window->Flags &= ~ImGuiWindowFlags_ShowBorders;\r\n\r\n    return ret;\r\n}\r\n\r\nbool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);\r\n}\r\n\r\nbool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)\r\n{\r\n    return BeginChildEx(NULL, id, size_arg, border, extra_flags);\r\n}\r\n\r\nvoid ImGui::EndChild()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);   // Mismatched BeginChild()/EndChild() callss\r\n    if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)\r\n    {\r\n        ImGui::End();\r\n    }\r\n    else\r\n    {\r\n        // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting.\r\n        ImVec2 sz = GetWindowSize();\r\n        if (window->AutoFitChildAxises & 0x01) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f\r\n            sz.x = ImMax(4.0f, sz.x);\r\n        if (window->AutoFitChildAxises & 0x02)\r\n            sz.y = ImMax(4.0f, sz.y);\r\n        ImGui::End();\r\n\r\n        ImGuiWindow* parent_window = GetCurrentWindow();\r\n        ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);\r\n        ItemSize(sz);\r\n        ItemAdd(bb, NULL);\r\n    }\r\n}\r\n\r\n// Helper to create a child window / scrolling region that looks like a normal widget frame.\r\nbool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]);\r\n    ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding);\r\n    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);\r\n    return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);\r\n}\r\n\r\nvoid ImGui::EndChildFrame()\r\n{\r\n    ImGui::EndChild();\r\n    ImGui::PopStyleVar(2);\r\n    ImGui::PopStyleColor();\r\n}\r\n\r\n// Save and compare stack sizes on Begin()/End() to detect usage errors\r\nstatic void CheckStacksSize(ImGuiWindow* window, bool write)\r\n{\r\n    // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)\r\n    ImGuiContext& g = *GImGui;\r\n    int* p_backup = &window->DC.StackSizesBackup[0];\r\n    { int current = window->IDStack.Size;       if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && \"PushID/PopID or TreeNode/TreePop Mismatch!\");   p_backup++; }    // Too few or too many PopID()/TreePop()\r\n    { int current = window->DC.GroupStack.Size; if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && \"BeginGroup/EndGroup Mismatch!\");                p_backup++; }    // Too few or too many EndGroup()\r\n    { int current = g.CurrentPopupStack.Size;   if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && \"BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch\"); p_backup++;}// Too few or too many EndMenu()/EndPopup()\r\n    { int current = g.ColorModifiers.Size;      if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && \"PushStyleColor/PopStyleColor Mismatch!\");       p_backup++; }    // Too few or too many PopStyleColor()\r\n    { int current = g.StyleModifiers.Size;      if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && \"PushStyleVar/PopStyleVar Mismatch!\");           p_backup++; }    // Too few or too many PopStyleVar()\r\n    { int current = g.FontStack.Size;           if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && \"PushFont/PopFont Mismatch!\");                   p_backup++; }    // Too few or too many PopFont()\r\n    IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));\r\n}\r\n\r\nstatic ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& r_inner)\r\n{\r\n    const ImGuiStyle& style = GImGui->Style;\r\n\r\n    // Clamp into visible area while not overlapping the cursor. Safety padding is optional if our popup size won't fit without it.\r\n    ImVec2 safe_padding = style.DisplaySafeAreaPadding;\r\n    ImRect r_outer(GetVisibleRect());\r\n    r_outer.Expand(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? -safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? -safe_padding.y : 0.0f));\r\n    ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size);\r\n\r\n    for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++)   // Last, Right, down, up, left. (Favor last used direction).\r\n    {\r\n        const int dir = (n == -1) ? *last_dir : n;\r\n        ImRect rect(dir == 0 ? r_inner.Max.x : r_outer.Min.x, dir == 1 ? r_inner.Max.y : r_outer.Min.y, dir == 3 ? r_inner.Min.x : r_outer.Max.x, dir == 2 ? r_inner.Min.y : r_outer.Max.y);\r\n        if (rect.GetWidth() < size.x || rect.GetHeight() < size.y)\r\n            continue;\r\n        *last_dir = dir;\r\n        return ImVec2(dir == 0 ? r_inner.Max.x : dir == 3 ? r_inner.Min.x - size.x : base_pos_clamped.x, dir == 1 ? r_inner.Max.y : dir == 2 ? r_inner.Min.y - size.y : base_pos_clamped.y);\r\n    }\r\n\r\n    // Fallback, try to keep within display\r\n    *last_dir = -1;\r\n    ImVec2 pos = base_pos;\r\n    pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);\r\n    pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);\r\n    return pos;\r\n}\r\n\r\nImGuiWindow* ImGui::FindWindowByName(const char* name)\r\n{\r\n    // FIXME-OPT: Store sorted hashes -> pointers so we can do a bissection in a contiguous block\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiID id = ImHash(name, 0);\r\n    for (int i = 0; i < g.Windows.Size; i++)\r\n        if (g.Windows[i]->ID == id)\r\n            return g.Windows[i];\r\n    return NULL;\r\n}\r\n\r\nstatic ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    // Create window the first time\r\n    ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow));\r\n    IM_PLACEMENT_NEW(window) ImGuiWindow(name);\r\n    window->Flags = flags;\r\n\r\n    if (flags & ImGuiWindowFlags_NoSavedSettings)\r\n    {\r\n        // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.\r\n        window->Size = window->SizeFull = size;\r\n    }\r\n    else\r\n    {\r\n        // Retrieve settings from .ini file\r\n        // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.\r\n        window->PosFloat = ImVec2(60, 60);\r\n        window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);\r\n\r\n        ImGuiIniData* settings = FindWindowSettings(name);\r\n        if (!settings)\r\n        {\r\n            settings = AddWindowSettings(name);\r\n        }\r\n        else\r\n        {\r\n            window->SetWindowPosAllowFlags &= ~ImGuiCond_FirstUseEver;\r\n            window->SetWindowSizeAllowFlags &= ~ImGuiCond_FirstUseEver;\r\n            window->SetWindowCollapsedAllowFlags &= ~ImGuiCond_FirstUseEver;\r\n        }\r\n\r\n        if (settings->Pos.x != FLT_MAX)\r\n        {\r\n            window->PosFloat = settings->Pos;\r\n            window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);\r\n            window->Collapsed = settings->Collapsed;\r\n        }\r\n\r\n        if (ImLengthSqr(settings->Size) > 0.00001f)\r\n            size = settings->Size;\r\n        window->Size = window->SizeFull = size;\r\n    }\r\n\r\n    if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)\r\n    {\r\n        window->AutoFitFramesX = window->AutoFitFramesY = 2;\r\n        window->AutoFitOnlyGrows = false;\r\n    }\r\n    else\r\n    {\r\n        if (window->Size.x <= 0.0f)\r\n            window->AutoFitFramesX = 2;\r\n        if (window->Size.y <= 0.0f)\r\n            window->AutoFitFramesY = 2;\r\n        window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);\r\n    }\r\n\r\n    if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)\r\n        g.Windows.insert(g.Windows.begin(), window); // Quite slow but rare and only once\r\n    else\r\n        g.Windows.push_back(window);\r\n    return window;\r\n}\r\n\r\nstatic void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.SetNextWindowSizeConstraint)\r\n    {\r\n        // Using -1,-1 on either X/Y axis to preserve the current size.\r\n        ImRect cr = g.SetNextWindowSizeConstraintRect;\r\n        new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;\r\n        new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;\r\n        if (g.SetNextWindowSizeConstraintCallback)\r\n        {\r\n            ImGuiSizeConstraintCallbackData data;\r\n            data.UserData = g.SetNextWindowSizeConstraintCallbackUserData;\r\n            data.Pos = window->Pos;\r\n            data.CurrentSize = window->SizeFull;\r\n            data.DesiredSize = new_size;\r\n            g.SetNextWindowSizeConstraintCallback(&data);\r\n            new_size = data.DesiredSize;\r\n        }\r\n    }\r\n    if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))\r\n        new_size = ImMax(new_size, g.Style.WindowMinSize);\r\n    window->SizeFull = new_size;\r\n}\r\n\r\nstatic ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)\r\n{\r\n    ImVec2 scroll = window->Scroll;\r\n    float cr_x = window->ScrollTargetCenterRatio.x;\r\n    float cr_y = window->ScrollTargetCenterRatio.y;\r\n    if (window->ScrollTarget.x < FLT_MAX)\r\n        scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);\r\n    if (window->ScrollTarget.y < FLT_MAX)\r\n        scroll.y = window->ScrollTarget.y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y);\r\n    scroll = ImMax(scroll, ImVec2(0.0f, 0.0f));\r\n    if (!window->Collapsed && !window->SkipItems)\r\n    {\r\n        scroll.x = ImMin(scroll.x, ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x))); // == GetScrollMaxX for that window\r\n        scroll.y = ImMin(scroll.y, ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y))); // == GetScrollMaxY for that window\r\n    }\r\n    return scroll;\r\n}\r\n\r\n// Push a new ImGui window to add widgets to.\r\n// - A default window called \"Debug\" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.\r\n// - Begin/End can be called multiple times during the frame with the same window name to append content.\r\n// - 'size_on_first_use' for a regular window denote the initial size for first-time creation (no saved data) and isn't that useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation.\r\n// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).\r\n//   You can use the \"##\" or \"###\" markers to use the same label with different id, or same id with different label. See documentation at the top of this file.\r\n// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned.\r\n// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed.\r\n// - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiCond_FirstUseEver) prior to calling Begin().\r\nbool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)\r\n{\r\n    return ImGui::Begin(name, p_open, ImVec2(0.f, 0.f), -1.0f, flags);\r\n}\r\n\r\nbool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    IM_ASSERT(name != NULL);                        // Window name required\r\n    IM_ASSERT(g.Initialized);                       // Forgot to call ImGui::NewFrame()\r\n    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet\r\n\r\n    if (flags & ImGuiWindowFlags_NoInputs)\r\n        flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;\r\n\r\n    // Find or create\r\n    bool window_is_new = false;\r\n    ImGuiWindow* window = FindWindowByName(name);\r\n    if (!window)\r\n    {\r\n        window = CreateNewWindow(name, size_on_first_use, flags);\r\n        window_is_new = true;\r\n    }\r\n\r\n    const int current_frame = g.FrameCount;\r\n    const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);\r\n    if (first_begin_of_the_frame)\r\n        window->Flags = (ImGuiWindowFlags)flags;\r\n    else\r\n        flags = window->Flags;\r\n\r\n    // Add to stack\r\n    ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL;\r\n    g.CurrentWindowStack.push_back(window);\r\n    SetCurrentWindow(window);\r\n    CheckStacksSize(window, true);\r\n    IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));\r\n\r\n    bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1);   // Not using !WasActive because the implicit \"Debug\" window would always toggle off->on\r\n    if (flags & ImGuiWindowFlags_Popup)\r\n    {\r\n        ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size];\r\n        window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed\r\n        window_just_activated_by_user |= (window != popup_ref.Window);\r\n        popup_ref.Window = window;\r\n        g.CurrentPopupStack.push_back(popup_ref);\r\n        window->PopupId = popup_ref.PopupId;\r\n    }\r\n\r\n    const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames == 1);\r\n    window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize);\r\n\r\n    // Process SetNextWindow***() calls\r\n    bool window_pos_set_by_api = false, window_size_set_by_api = false;\r\n    if (g.SetNextWindowPosCond)\r\n    {\r\n        if (window->Appearing) \r\n            window->SetWindowPosAllowFlags |= ImGuiCond_Appearing;\r\n        window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0;\r\n        if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f)\r\n        {\r\n            window->SetWindowPosCenterWanted = true;                            // May be processed on the next frame if this is our first frame and we are measuring size\r\n            window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);\r\n        }\r\n        else\r\n        {\r\n            SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond);\r\n        }\r\n        g.SetNextWindowPosCond = 0;\r\n    }\r\n    if (g.SetNextWindowSizeCond)\r\n    {\r\n        if (window->Appearing) \r\n            window->SetWindowSizeAllowFlags |= ImGuiCond_Appearing;\r\n        window_size_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0;\r\n        SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond);\r\n        g.SetNextWindowSizeCond = 0;\r\n    }\r\n    if (g.SetNextWindowContentSizeCond)\r\n    {\r\n        window->SizeContentsExplicit = g.SetNextWindowContentSizeVal;\r\n        g.SetNextWindowContentSizeCond = 0;\r\n    }\r\n    else if (first_begin_of_the_frame)\r\n    {\r\n        window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);\r\n    }\r\n    if (g.SetNextWindowCollapsedCond)\r\n    {\r\n        if (window->Appearing)\r\n            window->SetWindowCollapsedAllowFlags |= ImGuiCond_Appearing;\r\n        SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond);\r\n        g.SetNextWindowCollapsedCond = 0;\r\n    }\r\n    if (g.SetNextWindowFocus)\r\n    {\r\n        SetWindowFocus();\r\n        g.SetNextWindowFocus = false;\r\n    }\r\n\r\n    // Update known root window (if we are a child window, otherwise window == window->RootWindow)\r\n    int root_idx, root_non_popup_idx;\r\n    for (root_idx = g.CurrentWindowStack.Size - 1; root_idx > 0; root_idx--)\r\n        if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow))\r\n            break;\r\n    for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--)\r\n        if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (g.CurrentWindowStack[root_non_popup_idx]->Flags & ImGuiWindowFlags_Modal))\r\n            break;\r\n    window->ParentWindow = parent_window;\r\n    window->RootWindow = g.CurrentWindowStack[root_idx];\r\n    window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx];      // Used to display TitleBgActive color and for selecting which window to use for NavWindowing\r\n\r\n    // When reusing window again multiple times a frame, just append content (don't need to setup again)\r\n    if (first_begin_of_the_frame)\r\n    {\r\n        window->Active = true;\r\n        window->OrderWithinParent = 0;\r\n        window->BeginCount = 0;\r\n        window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);\r\n        window->LastFrameActive = current_frame;\r\n        window->IDStack.resize(1);\r\n\r\n        // Clear draw list, setup texture, outer clipping rectangle\r\n        window->DrawList->Clear();\r\n        window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);\r\n        ImRect fullscreen_rect(GetVisibleRect());\r\n        if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup)))\r\n            PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);\r\n        else\r\n            PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true);\r\n\r\n        if (window_just_activated_by_user)\r\n        {\r\n            // Popup first latch mouse position, will position itself when it appears next frame\r\n            window->AutoPosLastDirection = -1;\r\n            if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)\r\n                window->PosFloat = g.IO.MousePos;\r\n        }\r\n\r\n        // Collapse window by double-clicking on title bar\r\n        // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing\r\n        if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))\r\n        {\r\n            ImRect title_bar_rect = window->TitleBarRect();\r\n            if (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])\r\n            {\r\n                window->Collapsed = !window->Collapsed;\r\n                MarkIniSettingsDirty(window);\r\n                FocusWindow(window);\r\n            }\r\n        }\r\n        else\r\n        {\r\n            window->Collapsed = false;\r\n        }\r\n\r\n        // SIZE\r\n\r\n        // Save contents size from last frame for auto-fitting (unless explicitly specified)\r\n        window->SizeContents.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x));\r\n        window->SizeContents.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y));\r\n\r\n        // Hide popup/tooltip window when first appearing while we measure size (because we recycle them)\r\n        if (window->HiddenFrames > 0)\r\n            window->HiddenFrames--;\r\n        if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_just_activated_by_user)\r\n        {\r\n            window->HiddenFrames = 1;\r\n            if (flags & ImGuiWindowFlags_AlwaysAutoResize)\r\n            {\r\n                if (!window_size_set_by_api)\r\n                    window->Size = window->SizeFull = ImVec2(0.f, 0.f);\r\n                window->SizeContents = ImVec2(0.f, 0.f);\r\n            }\r\n        }\r\n\r\n        // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects.\r\n        window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding;\r\n\r\n        // Calculate auto-fit size\r\n        ImVec2 size_auto_fit;\r\n        if ((flags & ImGuiWindowFlags_Tooltip) != 0)\r\n        {\r\n            // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.\r\n            size_auto_fit = window->SizeContents + window->WindowPadding - ImVec2(0.0f, style.ItemSpacing.y);\r\n        }\r\n        else\r\n        {\r\n            size_auto_fit = ImClamp(window->SizeContents + window->WindowPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - g.Style.DisplaySafeAreaPadding));\r\n\r\n            // Handling case of auto fit window not fitting in screen on one axis, we are growing auto fit size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding.\r\n            if (size_auto_fit.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar))\r\n                size_auto_fit.y += style.ScrollbarSize;\r\n            if (size_auto_fit.y < window->SizeContents.y && !(flags & ImGuiWindowFlags_NoScrollbar))\r\n                size_auto_fit.x += style.ScrollbarSize;\r\n            size_auto_fit.y = ImMax(size_auto_fit.y - style.ItemSpacing.y, 0.0f);\r\n        }\r\n\r\n        // Handle automatic resize\r\n        if (window->Collapsed)\r\n        {\r\n            // We still process initial auto-fit on collapsed windows to get a window width,\r\n            // But otherwise we don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.\r\n            if (window->AutoFitFramesX > 0)\r\n                window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;\r\n            if (window->AutoFitFramesY > 0)\r\n                window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;\r\n        }\r\n        else\r\n        {\r\n            if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window_size_set_by_api)\r\n            {\r\n                window->SizeFull = size_auto_fit;\r\n            }\r\n            else if ((window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) && !window_size_set_by_api)\r\n            {\r\n                // Auto-fit only grows during the first few frames\r\n                if (window->AutoFitFramesX > 0)\r\n                    window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;\r\n                if (window->AutoFitFramesY > 0)\r\n                    window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;\r\n                MarkIniSettingsDirty(window);\r\n            }\r\n        }\r\n\r\n        // Apply minimum/maximum window size constraints and final size\r\n        ApplySizeFullWithConstraint(window, window->SizeFull);\r\n        window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull;\r\n        \r\n        // POSITION\r\n\r\n        // Position child window\r\n        if (flags & ImGuiWindowFlags_ChildWindow)\r\n        {\r\n            window->OrderWithinParent = parent_window->DC.ChildWindows.Size;\r\n            parent_window->DC.ChildWindows.push_back(window);\r\n        }\r\n        if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))\r\n        {\r\n            window->Pos = window->PosFloat = parent_window->DC.CursorPos;\r\n            window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin().\r\n        }\r\n\r\n        bool window_pos_center = false;\r\n        window_pos_center |= (window->SetWindowPosCenterWanted && window->HiddenFrames == 0);\r\n        window_pos_center |= ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize);\r\n        if (window_pos_center)\r\n        {\r\n            // Center (any sort of window)\r\n            SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeFull * 0.5f), 0);\r\n        }\r\n        else if (flags & ImGuiWindowFlags_ChildMenu)\r\n        {\r\n            // Child menus typically request _any_ position within the parent menu item, and then our FindBestPopupWindowPos() function will move the new menu outside the parent bounds.\r\n            // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu.\r\n            IM_ASSERT(window_pos_set_by_api);\r\n            float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value).\r\n            ImRect rect_to_avoid;\r\n            if (parent_window->DC.MenuBarAppending)\r\n                rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight());\r\n            else\r\n                rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);\r\n            window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);\r\n        }\r\n        else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)\r\n        {\r\n            ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1);\r\n            window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);\r\n        }\r\n\r\n        // Position tooltip (always follows mouse)\r\n        if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api)\r\n        {\r\n            ImVec2 ref_pos = g.IO.MousePos;\r\n            ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead?\r\n            window->PosFloat = FindBestPopupWindowPos(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid);\r\n            if (window->AutoPosLastDirection == -1)\r\n                window->PosFloat = ref_pos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.\r\n        }\r\n\r\n        // Clamp position so it stays visible\r\n        if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))\r\n        {\r\n            if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.\r\n            {\r\n                ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);\r\n                window->PosFloat = ImMax(window->PosFloat + window->Size, padding) - window->Size;\r\n                window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding);\r\n            }\r\n        }\r\n        window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);\r\n\r\n        // Default item width. Make it proportional to window size if window manually resizes\r\n        if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))\r\n            window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);\r\n        else\r\n            window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);\r\n\r\n        // Prepare for focus requests\r\n        window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);\r\n        window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);\r\n        window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;\r\n        window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;\r\n\r\n        // Apply scrolling\r\n        window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window);\r\n        window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);\r\n\r\n        // Modal window darkens what is behind them\r\n        if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow())\r\n            window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio));\r\n\r\n        // Draw window + handle manual resize\r\n        ImRect title_bar_rect = window->TitleBarRect();\r\n        const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;\r\n        if (window->Collapsed)\r\n        {\r\n            // Title bar only\r\n            RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding);\r\n        }\r\n        else\r\n        {\r\n            ImU32 resize_col = 0;\r\n            const float resize_corner_size = ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f);\r\n            if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize))\r\n            {\r\n                // Manual resize\r\n                const ImVec2 br = window->Rect().GetBR();\r\n                const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br);\r\n                const ImGuiID resize_id = window->GetID(\"#RESIZE\");\r\n                bool hovered, held;\r\n                ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds);\r\n                resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);\r\n                if (hovered || held)\r\n                    g.MouseCursor = ImGuiMouseCursor_ResizeNWSE;\r\n\r\n                ImVec2 size_target(FLT_MAX,FLT_MAX);\r\n                if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])\r\n                {\r\n                    // Manual auto-fit when double-clicking\r\n                    size_target = size_auto_fit;\r\n                    ClearActiveID();\r\n                }\r\n                else if (held)\r\n                {\r\n                    // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position\r\n                    size_target = (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos;\r\n                }\r\n\r\n                if (size_target.x != FLT_MAX && size_target.y != FLT_MAX)\r\n                {\r\n                    ApplySizeFullWithConstraint(window, size_target);\r\n                    MarkIniSettingsDirty(window);\r\n                }\r\n                window->Size = window->SizeFull;\r\n                title_bar_rect = window->TitleBarRect();\r\n            }\r\n\r\n            // Scrollbars\r\n            window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar));\r\n            window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));\r\n            if (window->ScrollbarX && !window->ScrollbarY)\r\n                window->ScrollbarY = (window->SizeContents.y > window->Size.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);\r\n            window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);\r\n            window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;\r\n\r\n            // Window background, Default Alpha\r\n            ImGuiCol bg_color_idx = ImGuiCol_WindowBg;\r\n            if ((flags & ImGuiWindowFlags_ComboBox) != 0)\r\n                bg_color_idx = ImGuiCol_ComboBg;\r\n            else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0)\r\n                bg_color_idx = ImGuiCol_PopupBg;\r\n            else if ((flags & ImGuiWindowFlags_ChildWindow) != 0)\r\n                bg_color_idx = ImGuiCol_ChildWindowBg;\r\n            ImVec4 bg_color = style.Colors[bg_color_idx]; // We don't use GetColorU32() because bg_alpha is assigned (not multiplied) below\r\n            if (bg_alpha >= 0.0f)\r\n                bg_color.w = bg_alpha;\r\n            bg_color.w *= style.Alpha;\r\n            if (bg_color.w > 0.0f)\r\n                window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight);\r\n\r\n            // Title bar\r\n            const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow;\r\n            if (!(flags & ImGuiWindowFlags_NoTitleBar))\r\n                window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight);\r\n\r\n            // Menu bar\r\n            if (flags & ImGuiWindowFlags_MenuBar)\r\n            {\r\n                ImRect menu_bar_rect = window->MenuBarRect();\r\n                if (flags & ImGuiWindowFlags_ShowBorders)\r\n                    window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border));\r\n                window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImGuiCorner_TopLeft|ImGuiCorner_TopRight);\r\n            }\r\n\r\n            // Scrollbars\r\n            if (window->ScrollbarX)\r\n                Scrollbar(window, true);\r\n            if (window->ScrollbarY)\r\n                Scrollbar(window, false);\r\n\r\n            // Render resize grip\r\n            // (after the input handling so we don't have a frame of latency)\r\n            if (!(flags & ImGuiWindowFlags_NoResize))\r\n            {\r\n                const ImVec2 br = window->Rect().GetBR();\r\n                window->DrawList->PathLineTo(br + ImVec2(-resize_corner_size, -window->BorderSize));\r\n                window->DrawList->PathLineTo(br + ImVec2(-window->BorderSize, -resize_corner_size));\r\n                window->DrawList->PathArcToFast(ImVec2(br.x - window_rounding - window->BorderSize, br.y - window_rounding - window->BorderSize), window_rounding, 0, 3);\r\n                window->DrawList->PathFillConvex(resize_col);\r\n            }\r\n\r\n            // Borders\r\n            if (flags & ImGuiWindowFlags_ShowBorders)\r\n            {\r\n                window->DrawList->AddRect(window->Pos+ImVec2(1,1), window->Pos+window->Size+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), window_rounding);\r\n                window->DrawList->AddRect(window->Pos, window->Pos+window->Size, GetColorU32(ImGuiCol_Border), window_rounding);\r\n                if (!(flags & ImGuiWindowFlags_NoTitleBar))\r\n                    window->DrawList->AddLine(title_bar_rect.GetBL()+ImVec2(1,0), title_bar_rect.GetBR()-ImVec2(1,0), GetColorU32(ImGuiCol_Border));\r\n            }\r\n        }\r\n\r\n        // Update ContentsRegionMax. All the variable it depends on are set above in this function.\r\n        window->ContentsRegionRect.Min.x = -window->Scroll.x + window->WindowPadding.x;\r\n        window->ContentsRegionRect.Min.y = -window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();\r\n        window->ContentsRegionRect.Max.x = -window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x)); \r\n        window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y)); \r\n\r\n        // Setup drawing context\r\n        window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x;\r\n        window->DC.GroupOffsetX = 0.0f;\r\n        window->DC.ColumnsOffsetX = 0.0f;\r\n        window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.IndentX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y);\r\n        window->DC.CursorPos = window->DC.CursorStartPos;\r\n        window->DC.CursorPosPrevLine = window->DC.CursorPos;\r\n        window->DC.CursorMaxPos = window->DC.CursorStartPos;\r\n        window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f;\r\n        window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;\r\n        window->DC.MenuBarAppending = false;\r\n        window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x);\r\n        window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;\r\n        window->DC.ChildWindows.resize(0);\r\n        window->DC.LayoutType = ImGuiLayoutType_Vertical;\r\n        window->DC.ItemFlags = ImGuiItemFlags_Default_;\r\n        window->DC.ItemWidth = window->ItemWidthDefault;\r\n        window->DC.TextWrapPos = -1.0f; // disabled\r\n        window->DC.ItemFlagsStack.resize(0);\r\n        window->DC.ItemWidthStack.resize(0);\r\n        window->DC.TextWrapPosStack.resize(0);\r\n        window->DC.ColumnsCurrent = 0;\r\n        window->DC.ColumnsCount = 1;\r\n        window->DC.ColumnsStartPosY = window->DC.CursorPos.y;\r\n        window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x;\r\n        window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY;\r\n        window->DC.TreeDepth = 0;\r\n        window->DC.StateStorage = &window->StateStorage;\r\n        window->DC.GroupStack.resize(0);\r\n        window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);\r\n\r\n        if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags))\r\n        {\r\n            window->DC.ItemFlags = parent_window->DC.ItemFlags;\r\n            window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);\r\n        }\r\n\r\n        if (window->AutoFitFramesX > 0)\r\n            window->AutoFitFramesX--;\r\n        if (window->AutoFitFramesY > 0)\r\n            window->AutoFitFramesY--;\r\n\r\n        // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)\r\n        if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))\r\n            if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup))\r\n                FocusWindow(window);\r\n\r\n        // Title bar\r\n        if (!(flags & ImGuiWindowFlags_NoTitleBar))\r\n        {\r\n            // Close button\r\n            if (p_open != NULL)\r\n            {\r\n                const float PAD = 2.0f;\r\n                const float rad = (window->TitleBarHeight() - PAD*2.0f) * 0.5f;\r\n                if (CloseButton(window->GetID(\"#CLOSE\"), window->Rect().GetTR() + ImVec2(-PAD - rad, PAD + rad), rad))\r\n                    *p_open = false;\r\n            }\r\n\r\n            const ImVec2 text_size = CalcTextSize(name, NULL, true);\r\n            if (!(flags & ImGuiWindowFlags_NoCollapse))\r\n                RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f);\r\n\r\n            ImVec2 text_min = window->Pos;\r\n            ImVec2 text_max = window->Pos + ImVec2(window->Size.x, style.FramePadding.y*2 + text_size.y);\r\n            ImRect clip_rect;\r\n            clip_rect.Max = ImVec2(window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton()\r\n            float pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0 ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x;\r\n            float pad_right = (p_open != NULL) ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x;\r\n            if (style.WindowTitleAlign.x > 0.0f) pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);\r\n            text_min.x += pad_left;\r\n            text_max.x -= pad_right;\r\n            clip_rect.Min = ImVec2(text_min.x, window->Pos.y);\r\n            RenderTextClipped(text_min, text_max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);\r\n        }\r\n\r\n        // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()\r\n        window->WindowRectClipped = window->Rect();\r\n        window->WindowRectClipped.ClipWith(window->ClipRect);\r\n\r\n        // Pressing CTRL+C while holding on a window copy its content to the clipboard\r\n        // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.\r\n        // Maybe we can support CTRL+C on every element?\r\n        /*\r\n        if (g.ActiveId == move_id)\r\n            if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))\r\n                ImGui::LogToClipboard();\r\n        */\r\n    }\r\n\r\n    // Inner clipping rectangle\r\n    // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame\r\n    // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior.\r\n    const ImRect title_bar_rect = window->TitleBarRect();\r\n    const float border_size = window->BorderSize;\r\n\t// Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.\r\n    ImRect clip_rect;\r\n    clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f)));\r\n    clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size);\r\n    clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f)));\r\n    clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size);\r\n    PushClipRect(clip_rect.Min, clip_rect.Max, true);\r\n\r\n    // Clear 'accessed' flag last thing\r\n    if (first_begin_of_the_frame)\r\n        window->Accessed = false;\r\n    window->BeginCount++;\r\n    g.SetNextWindowSizeConstraint = false;\r\n\r\n    // Child window can be out of sight and have \"negative\" clip windows.\r\n    // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar).\r\n    if (flags & ImGuiWindowFlags_ChildWindow)\r\n    {\r\n        IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0);\r\n        window->Collapsed = parent_window && parent_window->Collapsed;\r\n\r\n        if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)\r\n            window->Collapsed |= (window->WindowRectClipped.Min.x >= window->WindowRectClipped.Max.x || window->WindowRectClipped.Min.y >= window->WindowRectClipped.Max.y);\r\n\r\n        // We also hide the window from rendering because we've already added its border to the command list.\r\n        // (we could perform the check earlier in the function but it is simpler at this point)\r\n        if (window->Collapsed)\r\n            window->Active = false;\r\n    }\r\n    if (style.Alpha <= 0.0f)\r\n        window->Active = false;\r\n\r\n    // Return false if we don't intend to display anything to allow user to perform an early out optimization\r\n    window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0;\r\n    return !window->SkipItems;\r\n}\r\n\r\nvoid ImGui::End()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n\r\n    if (window->DC.ColumnsCount != 1) // close columns set if any is open\r\n        EndColumns();\r\n    PopClipRect();   // inner window clip rectangle\r\n\r\n    // Stop logging\r\n    if (!(window->Flags & ImGuiWindowFlags_ChildWindow))    // FIXME: add more options for scope of logging\r\n        LogFinish();\r\n\r\n    // Pop\r\n    // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin().\r\n    g.CurrentWindowStack.pop_back();\r\n    if (window->Flags & ImGuiWindowFlags_Popup)\r\n        g.CurrentPopupStack.pop_back();\r\n    CheckStacksSize(window, false);\r\n    SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());\r\n}\r\n\r\n// Vertical scrollbar\r\n// The entire piece of code below is rather confusing because:\r\n// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)\r\n// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar\r\n// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.\r\nstatic void Scrollbar(ImGuiWindow* window, bool horizontal)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(horizontal ? \"#SCROLLX\" : \"#SCROLLY\");\r\n\r\n    // Render background\r\n    bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);\r\n    float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;\r\n    const ImRect window_rect = window->Rect();\r\n    const float border_size = window->BorderSize;\r\n    ImRect bb = horizontal\r\n        ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size)\r\n        : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size);\r\n    if (!horizontal)\r\n        bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f);\r\n    if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f)\r\n        return;\r\n\r\n    float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;\r\n    int window_rounding_corners;\r\n    if (horizontal)\r\n        window_rounding_corners = ImGuiCorner_BotLeft | (other_scrollbar ? 0 : ImGuiCorner_BotRight);\r\n    else\r\n        window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BotRight);\r\n    window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners);\r\n    bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f)));\r\n\r\n    // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)\r\n    float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();\r\n    float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y;\r\n    float win_size_avail_v = (horizontal ? window->SizeFull.x : window->SizeFull.y) - other_scrollbar_size_w;\r\n    float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y;\r\n\r\n    // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)\r\n    // But we maintain a minimum size in pixel to allow for the user to still aim inside.\r\n    IM_ASSERT(ImMax(win_size_contents_v, win_size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.\r\n    const float win_size_v = ImMax(ImMax(win_size_contents_v, win_size_avail_v), 1.0f);\r\n    const float grab_h_pixels = ImClamp(scrollbar_size_v * (win_size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);\r\n    const float grab_h_norm = grab_h_pixels / scrollbar_size_v;\r\n\r\n    // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().\r\n    bool held = false;\r\n    bool hovered = false;\r\n    const bool previously_held = (g.ActiveId == id);\r\n    ImGui::ButtonBehavior(bb, id, &hovered, &held);\r\n\r\n    float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v);\r\n    float scroll_ratio = ImSaturate(scroll_v / scroll_max);\r\n    float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;\r\n    if (held && grab_h_norm < 1.0f)\r\n    {\r\n        float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y;\r\n        float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;\r\n        float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y;\r\n\r\n        // Click position in scrollbar normalized space (0.0f->1.0f)\r\n        const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);\r\n        ImGui::SetHoveredID(id);\r\n\r\n        bool seek_absolute = false;\r\n        if (!previously_held)\r\n        {\r\n            // On initial click calculate the distance between mouse and the center of the grab\r\n            if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm)\r\n            {\r\n                *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;\r\n            }\r\n            else\r\n            {\r\n                seek_absolute = true;\r\n                *click_delta_to_grab_center_v = 0.0f;\r\n            }\r\n        }\r\n\r\n        // Apply scroll\r\n        // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position\r\n        const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm));\r\n        scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));\r\n        if (horizontal)\r\n            window->Scroll.x = scroll_v;\r\n        else\r\n            window->Scroll.y = scroll_v;\r\n\r\n        // Update values for rendering\r\n        scroll_ratio = ImSaturate(scroll_v / scroll_max);\r\n        grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;\r\n\r\n        // Update distance to grab now that we have seeked and saturated\r\n        if (seek_absolute)\r\n            *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;\r\n    }\r\n\r\n    // Render\r\n    const ImU32 grab_col = ImGui::GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab);\r\n    if (horizontal)\r\n        window->DrawList->AddRectFilled(ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y), ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y), grab_col, style.ScrollbarRounding);\r\n    else\r\n        window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels), grab_col, style.ScrollbarRounding);\r\n}\r\n\r\n// Moving window to front of display (which happens to be back of our sorted list)\r\nvoid ImGui::FocusWindow(ImGuiWindow* window)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing.\r\n    g.NavWindow = window;\r\n\r\n    // Passing NULL allow to disable keyboard focus\r\n    if (!window)\r\n        return;\r\n\r\n    // And move its root window to the top of the pile\r\n    if (window->RootWindow)\r\n        window = window->RootWindow;\r\n\r\n    // Steal focus on active widgets\r\n    if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..\r\n        if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)\r\n            ClearActiveID();\r\n\r\n    // Bring to front\r\n    if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window)\r\n        return;\r\n    for (int i = 0; i < g.Windows.Size; i++)\r\n        if (g.Windows[i] == window)\r\n        {\r\n            g.Windows.erase(g.Windows.begin() + i);\r\n            break;\r\n        }\r\n    g.Windows.push_back(window);\r\n}\r\n\r\nvoid ImGui::PushItemWidth(float item_width)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);\r\n    window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);\r\n}\r\n\r\nstatic void PushMultiItemsWidths(int components, float w_full)\r\n{\r\n    ImGuiWindow* window = ImGui::GetCurrentWindow();\r\n    const ImGuiStyle& style = GImGui->Style;\r\n    if (w_full <= 0.0f)\r\n        w_full = ImGui::CalcItemWidth();\r\n    const float w_item_one  = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));\r\n    const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));\r\n    window->DC.ItemWidthStack.push_back(w_item_last);\r\n    for (int i = 0; i < components-1; i++)\r\n        window->DC.ItemWidthStack.push_back(w_item_one);\r\n    window->DC.ItemWidth = window->DC.ItemWidthStack.back();\r\n}\r\n\r\nvoid ImGui::PopItemWidth()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.ItemWidthStack.pop_back();\r\n    window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();\r\n}\r\n\r\nfloat ImGui::CalcItemWidth()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    float w = window->DC.ItemWidth;\r\n    if (w < 0.0f)\r\n    {\r\n        // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well.\r\n        float width_to_right_edge = GetContentRegionAvail().x;\r\n        w = ImMax(1.0f, width_to_right_edge + w);\r\n    }\r\n    w = (float)(int)w;\r\n    return w;\r\n}\r\n\r\nstatic ImFont* GetDefaultFont()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0];\r\n}\r\n\r\nstatic void SetCurrentFont(ImFont* font)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(font && font->IsLoaded());    // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?\r\n    IM_ASSERT(font->Scale > 0.0f);\r\n    g.Font = font;\r\n    g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;\r\n    g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;\r\n    g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel;\r\n}\r\n\r\nvoid ImGui::PushFont(ImFont* font)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (!font)\r\n        font = GetDefaultFont();\r\n    SetCurrentFont(font);\r\n    g.FontStack.push_back(font);\r\n    g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);\r\n}\r\n\r\nvoid  ImGui::PopFont()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.CurrentWindow->DrawList->PopTextureID();\r\n    g.FontStack.pop_back();\r\n    SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back());\r\n}\r\n\r\nvoid ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (enabled)\r\n        window->DC.ItemFlags |= option;\r\n    else\r\n        window->DC.ItemFlags &= ~option;\r\n    window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);\r\n}\r\n\r\nvoid ImGui::PopItemFlag()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.ItemFlagsStack.pop_back();\r\n    window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();\r\n}\r\n\r\nvoid ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)\r\n{\r\n    PushItemFlag(ImGuiItemFlags_AllowKeyboardFocus, allow_keyboard_focus);\r\n}\r\n\r\nvoid ImGui::PopAllowKeyboardFocus()\r\n{\r\n    PopItemFlag();\r\n}\r\n\r\nvoid ImGui::PushButtonRepeat(bool repeat)\r\n{\r\n    PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat);\r\n}\r\n\r\nvoid ImGui::PopButtonRepeat()\r\n{\r\n    PopItemFlag();\r\n}\r\n\r\nvoid ImGui::PushTextWrapPos(float wrap_pos_x)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.TextWrapPos = wrap_pos_x;\r\n    window->DC.TextWrapPosStack.push_back(wrap_pos_x);\r\n}\r\n\r\nvoid ImGui::PopTextWrapPos()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.TextWrapPosStack.pop_back();\r\n    window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back();\r\n}\r\n\r\n// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32\r\nvoid ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiColMod backup;\r\n    backup.Col = idx;\r\n    backup.BackupValue = g.Style.Colors[idx];\r\n    g.ColorModifiers.push_back(backup);\r\n    g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);\r\n}\r\n\r\nvoid ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiColMod backup;\r\n    backup.Col = idx;\r\n    backup.BackupValue = g.Style.Colors[idx];\r\n    g.ColorModifiers.push_back(backup);\r\n    g.Style.Colors[idx] = col;\r\n}\r\n\r\nvoid ImGui::PopStyleColor(int count)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    while (count > 0)\r\n    {\r\n        ImGuiColMod& backup = g.ColorModifiers.back();\r\n        g.Style.Colors[backup.Col] = backup.BackupValue;\r\n        g.ColorModifiers.pop_back();\r\n        count--;\r\n    }\r\n}\r\n\r\nstruct ImGuiStyleVarInfo\r\n{\r\n    ImGuiDataType   Type;\r\n    ImU32           Offset;\r\n    void*           GetVarPtr() const { return (void*)((unsigned char*)&GImGui->Style + Offset); }\r\n};\r\n\r\nstatic const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] =\r\n{\r\n    { ImGuiDataType_Float,  (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) },                // ImGuiStyleVar_Alpha\r\n    { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) },        // ImGuiStyleVar_WindowPadding\r\n    { ImGuiDataType_Float,  (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) },       // ImGuiStyleVar_WindowRounding\r\n    { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) },        // ImGuiStyleVar_WindowMinSize\r\n    { ImGuiDataType_Float,  (ImU32)IM_OFFSETOF(ImGuiStyle, ChildWindowRounding) },  // ImGuiStyleVar_ChildWindowRounding\r\n    { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) },         // ImGuiStyleVar_FramePadding\r\n    { ImGuiDataType_Float,  (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) },        // ImGuiStyleVar_FrameRounding\r\n    { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) },          // ImGuiStyleVar_ItemSpacing\r\n    { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) },     // ImGuiStyleVar_ItemInnerSpacing\r\n    { ImGuiDataType_Float,  (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) },        // ImGuiStyleVar_IndentSpacing\r\n    { ImGuiDataType_Float,  (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) },          // ImGuiStyleVar_GrabMinSize\r\n    { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) },      // ImGuiStyleVar_ButtonTextAlign\r\n};\r\n\r\nstatic const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)\r\n{\r\n    IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_Count_);\r\n    return &GStyleVarInfo[idx];\r\n}\r\n\r\nvoid ImGui::PushStyleVar(ImGuiStyleVar idx, float val)\r\n{\r\n    const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);\r\n    if (var_info->Type == ImGuiDataType_Float)\r\n    {\r\n        float* pvar = (float*)var_info->GetVarPtr();\r\n        GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));\r\n        *pvar = val;\r\n        return;\r\n    }\r\n    IM_ASSERT(0); // Called function with wrong-type? Variable is not a float.\r\n}\r\n\r\nvoid ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)\r\n{\r\n    const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);\r\n    if (var_info->Type == ImGuiDataType_Float2)\r\n    {\r\n        ImVec2* pvar = (ImVec2*)var_info->GetVarPtr();\r\n        GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));\r\n        *pvar = val;\r\n        return;\r\n    }\r\n    IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2.\r\n}\r\n\r\nvoid ImGui::PopStyleVar(int count)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    while (count > 0)\r\n    {\r\n        ImGuiStyleMod& backup = g.StyleModifiers.back();\r\n        const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);\r\n        if (info->Type == ImGuiDataType_Float)          (*(float*)info->GetVarPtr()) = backup.BackupFloat[0];\r\n        else if (info->Type == ImGuiDataType_Float2)    (*(ImVec2*)info->GetVarPtr()) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]);\r\n        else if (info->Type == ImGuiDataType_Int)       (*(int*)info->GetVarPtr()) = backup.BackupInt[0];\r\n        g.StyleModifiers.pop_back();\r\n        count--;\r\n    }\r\n}\r\n\r\nconst char* ImGui::GetStyleColorName(ImGuiCol idx)\r\n{\r\n    // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\\1: return \"\\1\";\r\n    switch (idx)\r\n    {\r\n    case ImGuiCol_Text: return \"Text\";\r\n    case ImGuiCol_TextDisabled: return \"TextDisabled\";\r\n    case ImGuiCol_WindowBg: return \"WindowBg\";\r\n    case ImGuiCol_ChildWindowBg: return \"ChildWindowBg\";\r\n    case ImGuiCol_PopupBg: return \"PopupBg\";\r\n    case ImGuiCol_Border: return \"Border\";\r\n    case ImGuiCol_BorderShadow: return \"BorderShadow\";\r\n    case ImGuiCol_FrameBg: return \"FrameBg\";\r\n    case ImGuiCol_FrameBgHovered: return \"FrameBgHovered\";\r\n    case ImGuiCol_FrameBgActive: return \"FrameBgActive\";\r\n    case ImGuiCol_TitleBg: return \"TitleBg\";\r\n    case ImGuiCol_TitleBgCollapsed: return \"TitleBgCollapsed\";\r\n    case ImGuiCol_TitleBgActive: return \"TitleBgActive\";\r\n    case ImGuiCol_MenuBarBg: return \"MenuBarBg\";\r\n    case ImGuiCol_ScrollbarBg: return \"ScrollbarBg\";\r\n    case ImGuiCol_ScrollbarGrab: return \"ScrollbarGrab\";\r\n    case ImGuiCol_ScrollbarGrabHovered: return \"ScrollbarGrabHovered\";\r\n    case ImGuiCol_ScrollbarGrabActive: return \"ScrollbarGrabActive\";\r\n    case ImGuiCol_ComboBg: return \"ComboBg\";\r\n    case ImGuiCol_CheckMark: return \"CheckMark\";\r\n    case ImGuiCol_SliderGrab: return \"SliderGrab\";\r\n    case ImGuiCol_SliderGrabActive: return \"SliderGrabActive\";\r\n    case ImGuiCol_Button: return \"Button\";\r\n    case ImGuiCol_ButtonHovered: return \"ButtonHovered\";\r\n    case ImGuiCol_ButtonActive: return \"ButtonActive\";\r\n    case ImGuiCol_Header: return \"Header\";\r\n    case ImGuiCol_HeaderHovered: return \"HeaderHovered\";\r\n    case ImGuiCol_HeaderActive: return \"HeaderActive\";\r\n    case ImGuiCol_Separator: return \"Separator\";\r\n    case ImGuiCol_SeparatorHovered: return \"SeparatorHovered\";\r\n    case ImGuiCol_SeparatorActive: return \"SeparatorActive\";\r\n    case ImGuiCol_ResizeGrip: return \"ResizeGrip\";\r\n    case ImGuiCol_ResizeGripHovered: return \"ResizeGripHovered\";\r\n    case ImGuiCol_ResizeGripActive: return \"ResizeGripActive\";\r\n    case ImGuiCol_CloseButton: return \"CloseButton\";\r\n    case ImGuiCol_CloseButtonHovered: return \"CloseButtonHovered\";\r\n    case ImGuiCol_CloseButtonActive: return \"CloseButtonActive\";\r\n    case ImGuiCol_PlotLines: return \"PlotLines\";\r\n    case ImGuiCol_PlotLinesHovered: return \"PlotLinesHovered\";\r\n    case ImGuiCol_PlotHistogram: return \"PlotHistogram\";\r\n    case ImGuiCol_PlotHistogramHovered: return \"PlotHistogramHovered\";\r\n    case ImGuiCol_TextSelectedBg: return \"TextSelectedBg\";\r\n    case ImGuiCol_ModalWindowDarkening: return \"ModalWindowDarkening\";\r\n    }\r\n    IM_ASSERT(0);\r\n    return \"Unknown\";\r\n}\r\n\r\nbool ImGui::IsWindowHovered()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow);\r\n}\r\n\r\nbool ImGui::IsWindowRectHovered()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.HoveredWindow == g.CurrentWindow;\r\n}\r\n\r\nbool ImGui::IsWindowFocused()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.NavWindow == g.CurrentWindow;\r\n}\r\n\r\nbool ImGui::IsRootWindowFocused()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.NavWindow == g.CurrentWindow->RootWindow;\r\n}\r\n\r\nbool ImGui::IsRootWindowOrAnyChildFocused()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;\r\n}\r\n\r\nbool ImGui::IsRootWindowOrAnyChildHovered()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow);\r\n}\r\n\r\nfloat ImGui::GetWindowWidth()\r\n{\r\n    ImGuiWindow* window = GImGui->CurrentWindow;\r\n    return window->Size.x;\r\n}\r\n\r\nfloat ImGui::GetWindowHeight()\r\n{\r\n    ImGuiWindow* window = GImGui->CurrentWindow;\r\n    return window->Size.y;\r\n}\r\n\r\nImVec2 ImGui::GetWindowPos()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n    return window->Pos;\r\n}\r\n\r\nstatic void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)\r\n{\r\n    window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.\r\n    window->Scroll.y = new_scroll_y;\r\n    window->DC.CursorMaxPos.y -= window->Scroll.y;\r\n}\r\n\r\nstatic void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)\r\n{\r\n    // Test condition (NB: bit 0 is always true) and clear flags for next time\r\n    if (cond && (window->SetWindowPosAllowFlags & cond) == 0)\r\n        return;\r\n    window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);\r\n    window->SetWindowPosCenterWanted = false;\r\n\r\n    // Set\r\n    const ImVec2 old_pos = window->Pos;\r\n    window->PosFloat = pos;\r\n    window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);\r\n    window->DC.CursorPos += (window->Pos - old_pos);    // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor\r\n    window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.\r\n}\r\n\r\nvoid ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    SetWindowPos(window, pos, cond);\r\n}\r\n\r\nvoid ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond)\r\n{\r\n    if (ImGuiWindow* window = FindWindowByName(name))\r\n        SetWindowPos(window, pos, cond);\r\n}\r\n\r\nImVec2 ImGui::GetWindowSize()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->Size;\r\n}\r\n\r\nstatic void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond)\r\n{\r\n    // Test condition (NB: bit 0 is always true) and clear flags for next time\r\n    if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)\r\n        return;\r\n    window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);\r\n\r\n    // Set\r\n    if (size.x > 0.0f)\r\n    {\r\n        window->AutoFitFramesX = 0;\r\n        window->SizeFull.x = size.x;\r\n    }\r\n    else\r\n    {\r\n        window->AutoFitFramesX = 2;\r\n        window->AutoFitOnlyGrows = false;\r\n    }\r\n    if (size.y > 0.0f)\r\n    {\r\n        window->AutoFitFramesY = 0;\r\n        window->SizeFull.y = size.y;\r\n    }\r\n    else\r\n    {\r\n        window->AutoFitFramesY = 2;\r\n        window->AutoFitOnlyGrows = false;\r\n    }\r\n}\r\n\r\nvoid ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond)\r\n{\r\n    SetWindowSize(GImGui->CurrentWindow, size, cond);\r\n}\r\n\r\nvoid ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond)\r\n{\r\n    ImGuiWindow* window = FindWindowByName(name);\r\n    if (window)\r\n        SetWindowSize(window, size, cond);\r\n}\r\n\r\nstatic void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond)\r\n{\r\n    // Test condition (NB: bit 0 is always true) and clear flags for next time\r\n    if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)\r\n        return;\r\n    window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);\r\n\r\n    // Set\r\n    window->Collapsed = collapsed;\r\n}\r\n\r\nvoid ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)\r\n{\r\n    SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);\r\n}\r\n\r\nbool ImGui::IsWindowCollapsed()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->Collapsed;\r\n}\r\n\r\nbool ImGui::IsWindowAppearing()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->Appearing;\r\n}\r\n\r\nvoid ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)\r\n{\r\n    ImGuiWindow* window = FindWindowByName(name);\r\n    if (window)\r\n        SetWindowCollapsed(window, collapsed, cond);\r\n}\r\n\r\nvoid ImGui::SetWindowFocus()\r\n{\r\n    FocusWindow(GImGui->CurrentWindow);\r\n}\r\n\r\nvoid ImGui::SetWindowFocus(const char* name)\r\n{\r\n    if (name)\r\n    {\r\n        if (ImGuiWindow* window = FindWindowByName(name))\r\n            FocusWindow(window);\r\n    }\r\n    else\r\n    {\r\n        FocusWindow(NULL);\r\n    }\r\n}\r\n\r\nvoid ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowPosVal = pos;\r\n    g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::SetNextWindowPosCenter(ImGuiCond cond)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX);\r\n    g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowSizeVal = size;\r\n    g.SetNextWindowSizeCond = cond ? cond : ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowSizeConstraint = true;\r\n    g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max);\r\n    g.SetNextWindowSizeConstraintCallback = custom_callback;\r\n    g.SetNextWindowSizeConstraintCallbackUserData = custom_callback_user_data;\r\n}\r\n\r\nvoid ImGui::SetNextWindowContentSize(const ImVec2& size)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowContentSizeVal = size;\r\n    g.SetNextWindowContentSizeCond = ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::SetNextWindowContentWidth(float width)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowContentSizeVal = ImVec2(width, g.SetNextWindowContentSizeCond ? g.SetNextWindowContentSizeVal.y : 0.0f);\r\n    g.SetNextWindowContentSizeCond = ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowCollapsedVal = collapsed;\r\n    g.SetNextWindowCollapsedCond = cond ? cond : ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::SetNextWindowFocus()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextWindowFocus = true;\r\n}\r\n\r\n// In window space (not screen space!)\r\nImVec2 ImGui::GetContentRegionMax()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    ImVec2 mx = window->ContentsRegionRect.Max;\r\n    if (window->DC.ColumnsCount != 1)\r\n        mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x;\r\n    return mx;\r\n}\r\n\r\nImVec2 ImGui::GetContentRegionAvail()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return GetContentRegionMax() - (window->DC.CursorPos - window->Pos);\r\n}\r\n\r\nfloat ImGui::GetContentRegionAvailWidth()\r\n{\r\n    return GetContentRegionAvail().x;\r\n}\r\n\r\n// In window space (not screen space!)\r\nImVec2 ImGui::GetWindowContentRegionMin()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->ContentsRegionRect.Min;\r\n}\r\n\r\nImVec2 ImGui::GetWindowContentRegionMax()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->ContentsRegionRect.Max;\r\n}\r\n\r\nfloat ImGui::GetWindowContentRegionWidth()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->ContentsRegionRect.Max.x - window->ContentsRegionRect.Min.x;\r\n}\r\n\r\nfloat ImGui::GetTextLineHeight()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.FontSize;\r\n}\r\n\r\nfloat ImGui::GetTextLineHeightWithSpacing()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.FontSize + g.Style.ItemSpacing.y;\r\n}\r\n\r\nfloat ImGui::GetItemsLineHeightWithSpacing()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;\r\n}\r\n\r\nImDrawList* ImGui::GetWindowDrawList()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    return window->DrawList;\r\n}\r\n\r\nImFont* ImGui::GetFont()\r\n{\r\n    return GImGui->Font;\r\n}\r\n\r\nfloat ImGui::GetFontSize()\r\n{\r\n    return GImGui->FontSize;\r\n}\r\n\r\nImVec2 ImGui::GetFontTexUvWhitePixel()\r\n{\r\n    return GImGui->FontTexUvWhitePixel;\r\n}\r\n\r\nvoid ImGui::SetWindowFontScale(float scale)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->FontWindowScale = scale;\r\n    g.FontSize = window->CalcFontSize();\r\n}\r\n\r\n// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.\r\n// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'.\r\nImVec2 ImGui::GetCursorPos()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.CursorPos - window->Pos + window->Scroll;\r\n}\r\n\r\nfloat ImGui::GetCursorPosX()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;\r\n}\r\n\r\nfloat ImGui::GetCursorPosY()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;\r\n}\r\n\r\nvoid ImGui::SetCursorPos(const ImVec2& local_pos)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.CursorPos = window->Pos - window->Scroll + local_pos;\r\n    window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);\r\n}\r\n\r\nvoid ImGui::SetCursorPosX(float x)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;\r\n    window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);\r\n}\r\n\r\nvoid ImGui::SetCursorPosY(float y)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;\r\n    window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);\r\n}\r\n\r\nImVec2 ImGui::GetCursorStartPos()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.CursorStartPos - window->Pos;\r\n}\r\n\r\nImVec2 ImGui::GetCursorScreenPos()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.CursorPos;\r\n}\r\n\r\nvoid ImGui::SetCursorScreenPos(const ImVec2& screen_pos)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.CursorPos = screen_pos;\r\n    window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);\r\n}\r\n\r\nfloat ImGui::GetScrollX()\r\n{\r\n    return GImGui->CurrentWindow->Scroll.x;\r\n}\r\n\r\nfloat ImGui::GetScrollY()\r\n{\r\n    return GImGui->CurrentWindow->Scroll.y;\r\n}\r\n\r\nfloat ImGui::GetScrollMaxX()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));\r\n}\r\n\r\nfloat ImGui::GetScrollMaxY()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));\r\n}\r\n\r\nvoid ImGui::SetScrollX(float scroll_x)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->ScrollTarget.x = scroll_x;\r\n    window->ScrollTargetCenterRatio.x = 0.0f;\r\n}\r\n\r\nvoid ImGui::SetScrollY(float scroll_y)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY\r\n    window->ScrollTargetCenterRatio.y = 0.0f;\r\n}\r\n\r\nvoid ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio)\r\n{\r\n    // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);\r\n    window->ScrollTarget.y = (float)(int)(pos_y + window->Scroll.y);\r\n    if (center_y_ratio <= 0.0f && window->ScrollTarget.y <= window->WindowPadding.y)    // Minor hack to make \"scroll to top\" take account of WindowPadding, else it would scroll to (WindowPadding.y - ItemSpacing.y)\r\n        window->ScrollTarget.y = 0.0f;\r\n    window->ScrollTargetCenterRatio.y = center_y_ratio;\r\n}\r\n\r\n// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.\r\nvoid ImGui::SetScrollHere(float center_y_ratio)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space\r\n    target_y += (window->DC.PrevLineHeight * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line.\r\n    SetScrollFromPosY(target_y, center_y_ratio);\r\n}\r\n\r\nvoid ImGui::SetKeyboardFocusHere(int offset)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;\r\n    window->FocusIdxTabRequestNext = INT_MAX;\r\n}\r\n\r\nvoid ImGui::SetStateStorage(ImGuiStorage* tree)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.StateStorage = tree ? tree : &window->StateStorage;\r\n}\r\n\r\nImGuiStorage* ImGui::GetStateStorage()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.StateStorage;\r\n}\r\n\r\nvoid ImGui::TextV(const char* fmt, va_list args)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);\r\n    TextUnformatted(g.TempBuffer, text_end);\r\n}\r\n\r\nvoid ImGui::Text(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    TextV(fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nvoid ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)\r\n{\r\n    PushStyleColor(ImGuiCol_Text, col);\r\n    TextV(fmt, args);\r\n    PopStyleColor();\r\n}\r\n\r\nvoid ImGui::TextColored(const ImVec4& col, const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    TextColoredV(col, fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nvoid ImGui::TextDisabledV(const char* fmt, va_list args)\r\n{\r\n    PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]);\r\n    TextV(fmt, args);\r\n    PopStyleColor();\r\n}\r\n\r\nvoid ImGui::TextDisabled(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    TextDisabledV(fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nvoid ImGui::TextWrappedV(const char* fmt, va_list args)\r\n{\r\n    bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f);    // Keep existing wrap position is one ia already set\r\n    if (need_wrap) PushTextWrapPos(0.0f);\r\n    TextV(fmt, args);\r\n    if (need_wrap) PopTextWrapPos();\r\n}\r\n\r\nvoid ImGui::TextWrapped(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    TextWrappedV(fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nvoid ImGui::TextUnformatted(const char* text, const char* text_end)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    IM_ASSERT(text != NULL);\r\n    const char* text_begin = text;\r\n    if (text_end == NULL)\r\n        text_end = text + strlen(text); // FIXME-OPT\r\n\r\n    const float wrap_pos_x = window->DC.TextWrapPos;\r\n    const bool wrap_enabled = wrap_pos_x >= 0.0f;\r\n    if (text_end - text > 2000 && !wrap_enabled)\r\n    {\r\n        // Long text!\r\n        // Perform manual coarse clipping to optimize for long multi-line text\r\n        // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.\r\n        // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.\r\n        const char* line = text;\r\n        const float line_height = GetTextLineHeight();\r\n        const ImVec2 text_pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrentLineTextBaseOffset);\r\n        const ImRect clip_rect = window->ClipRect;\r\n        ImVec2 text_size(0,0);\r\n\r\n        if (text_pos.y <= clip_rect.Max.y)\r\n        {\r\n            ImVec2 pos = text_pos;\r\n\r\n            // Lines to skip (can't skip when logging text)\r\n            if (!g.LogEnabled)\r\n            {\r\n                int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);\r\n                if (lines_skippable > 0)\r\n                {\r\n                    int lines_skipped = 0;\r\n                    while (line < text_end && lines_skipped < lines_skippable)\r\n                    {\r\n                        const char* line_end = strchr(line, '\\n');\r\n                        if (!line_end)\r\n                            line_end = text_end;\r\n                        line = line_end + 1;\r\n                        lines_skipped++;\r\n                    }\r\n                    pos.y += lines_skipped * line_height;\r\n                }\r\n            }\r\n\r\n            // Lines to render\r\n            if (line < text_end)\r\n            {\r\n                ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));\r\n                while (line < text_end)\r\n                {\r\n                    const char* line_end = strchr(line, '\\n');\r\n                    if (IsClippedEx(line_rect, NULL, false))\r\n                        break;\r\n\r\n                    const ImVec2 line_size = CalcTextSize(line, line_end, false);\r\n                    text_size.x = ImMax(text_size.x, line_size.x);\r\n                    RenderText(pos, line, line_end, false);\r\n                    if (!line_end)\r\n                        line_end = text_end;\r\n                    line = line_end + 1;\r\n                    line_rect.Min.y += line_height;\r\n                    line_rect.Max.y += line_height;\r\n                    pos.y += line_height;\r\n                }\r\n\r\n                // Count remaining lines\r\n                int lines_skipped = 0;\r\n                while (line < text_end)\r\n                {\r\n                    const char* line_end = strchr(line, '\\n');\r\n                    if (!line_end)\r\n                        line_end = text_end;\r\n                    line = line_end + 1;\r\n                    lines_skipped++;\r\n                }\r\n                pos.y += lines_skipped * line_height;\r\n            }\r\n\r\n            text_size.y += (pos - text_pos).y;\r\n        }\r\n\r\n        ImRect bb(text_pos, text_pos + text_size);\r\n        ItemSize(bb);\r\n        ItemAdd(bb, NULL);\r\n    }\r\n    else\r\n    {\r\n        const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;\r\n        const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);\r\n\r\n        // Account of baseline offset\r\n        ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);\r\n        ImRect bb(text_pos, text_pos + text_size);\r\n        ItemSize(text_size);\r\n        if (!ItemAdd(bb, NULL))\r\n            return;\r\n\r\n        // Render (we don't hide text after ## in this end-user function)\r\n        RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);\r\n    }\r\n}\r\n\r\nvoid ImGui::AlignFirstTextHeightToWidgets()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    // Declare a dummy item size to that upcoming items that are smaller will center-align on the newly expanded line height.\r\n    ImGuiContext& g = *GImGui;\r\n    ItemSize(ImVec2(0, g.FontSize + g.Style.FramePadding.y*2), g.Style.FramePadding.y);\r\n    SameLine(0, 0);\r\n}\r\n\r\n// Add a label+text combo aligned to other label+value widgets\r\nvoid ImGui::LabelTextV(const char* label, const char* fmt, va_list args)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const float w = CalcItemWidth();\r\n\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));\r\n    const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);\r\n    ItemSize(total_bb, style.FramePadding.y);\r\n    if (!ItemAdd(total_bb, NULL))\r\n        return;\r\n\r\n    // Render\r\n    const char* value_text_begin = &g.TempBuffer[0];\r\n    const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);\r\n    RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));\r\n    if (label_size.x > 0.0f)\r\n        RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);\r\n}\r\n\r\nvoid ImGui::LabelText(const char* label, const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    LabelTextV(label, fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nstatic inline bool IsWindowContentHoverable(ImGuiWindow* window)\r\n{\r\n    // An active popup disable hovering on other windows (apart from its own children)\r\n    // FIXME-OPT: This could be cached/stored within the window.\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.NavWindow)\r\n        if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)\r\n            if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)\r\n                return false;\r\n\r\n    return true;\r\n}\r\n\r\nbool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    if (flags & ImGuiButtonFlags_Disabled)\r\n    {\r\n        if (out_hovered) *out_hovered = false;\r\n        if (out_held) *out_held = false;\r\n        if (g.ActiveId == id) ClearActiveID();\r\n        return false;\r\n    }\r\n\r\n    // Default behavior requires click+release on same spot\r\n    if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0)\r\n        flags |= ImGuiButtonFlags_PressedOnClickRelease;\r\n\r\n    bool pressed = false;\r\n    bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);\r\n    if (hovered)\r\n    {\r\n        SetHoveredID(id);\r\n        if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))\r\n        {\r\n            //                        | CLICKING        | HOLDING with ImGuiButtonFlags_Repeat\r\n            // PressedOnClickRelease  |  <on release>*  |  <on repeat> <on repeat> .. (NOT on release)  <-- MOST COMMON! (*) only if both click/release were over bounds\r\n            // PressedOnClick         |  <on click>     |  <on click> <on repeat> <on repeat> ..\r\n            // PressedOnRelease       |  <on release>   |  <on repeat> <on repeat> .. (NOT on release)\r\n            // PressedOnDoubleClick   |  <on dclick>    |  <on dclick> <on repeat> <on repeat> ..\r\n            if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0])\r\n            {\r\n                SetActiveID(id, window); // Hold on ID\r\n                FocusWindow(window);\r\n                g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;\r\n            }\r\n            if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]))\r\n            {\r\n                pressed = true;\r\n                ClearActiveID();\r\n                FocusWindow(window);\r\n            }\r\n            if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0])\r\n            {\r\n                if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay))  // Repeat mode trumps <on release>\r\n                    pressed = true;\r\n                ClearActiveID();\r\n            }\r\n\r\n            // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). \r\n            // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings.\r\n            if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true))\r\n                pressed = true;\r\n        }\r\n    }\r\n\r\n    bool held = false;\r\n    if (g.ActiveId == id)\r\n    {\r\n        if (g.IO.MouseDown[0])\r\n        {\r\n            held = true;\r\n        }\r\n        else\r\n        {\r\n            if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease))\r\n                if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay))  // Repeat mode trumps <on release>\r\n                    pressed = true;\r\n            ClearActiveID();\r\n        }\r\n    }\r\n\r\n    // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.\r\n    if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))\r\n        hovered = pressed = held = false;\r\n\r\n    if (out_hovered) *out_hovered = hovered;\r\n    if (out_held) *out_held = held;\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n\r\n    ImVec2 pos = window->DC.CursorPos;\r\n    if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)\r\n        pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;\r\n    ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);\r\n\r\n    const ImRect bb(pos, pos + size);\r\n    ItemSize(bb, style.FramePadding.y);\r\n    if (!ItemAdd(bb, &id))\r\n        return false;\r\n\r\n    if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat;\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);\r\n\r\n    // Render\r\n    const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);\r\n    RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);\r\n    RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);\r\n\r\n    // Automatically close popups\r\n    //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))\r\n    //    CloseCurrentPopup();\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::Button(const char* label, const ImVec2& size_arg)\r\n{\r\n    return ButtonEx(label, size_arg, 0);\r\n}\r\n\r\n// Small buttons fits within text without additional vertical spacing.\r\nbool ImGui::SmallButton(const char* label)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    float backup_padding_y = g.Style.FramePadding.y;\r\n    g.Style.FramePadding.y = 0.0f;\r\n    bool pressed = ButtonEx(label, ImVec2(0,0), ImGuiButtonFlags_AlignTextBaseLine);\r\n    g.Style.FramePadding.y = backup_padding_y;\r\n    return pressed;\r\n}\r\n\r\n// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.\r\n// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id)\r\nbool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    const ImGuiID id = window->GetID(str_id);\r\n    ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);\r\n    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);\r\n    ItemSize(bb);\r\n    if (!ItemAdd(bb, &id))\r\n        return false;\r\n\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(bb, id, &hovered, &held);\r\n\r\n    return pressed;\r\n}\r\n\r\n// Upper-right button to close a window.\r\nbool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius));\r\n\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(bb, id, &hovered, &held);\r\n\r\n    // Render\r\n    const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);\r\n    const ImVec2 center = bb.GetCenter();\r\n    window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12);\r\n\r\n    const float cross_extent = (radius * 0.7071f) - 1.0f;\r\n    if (hovered)\r\n    {\r\n        window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text));\r\n        window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text));\r\n    }\r\n\r\n    return pressed;\r\n}\r\n\r\nvoid ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);\r\n    if (border_col.w > 0.0f)\r\n        bb.Max += ImVec2(2,2);\r\n    ItemSize(bb);\r\n    if (!ItemAdd(bb, NULL))\r\n        return;\r\n\r\n    if (border_col.w > 0.0f)\r\n    {\r\n        window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f);\r\n        window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, GetColorU32(tint_col));\r\n    }\r\n    else\r\n    {\r\n        window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));\r\n    }\r\n}\r\n\r\n// frame_padding < 0: uses FramePadding from style (default)\r\n// frame_padding = 0: no framing\r\n// frame_padding > 0: set framing size\r\n// The color used are the button colors.\r\nbool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    // Default to using texture ID as ID. User can still push string/integer prefixes.\r\n    // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.\r\n    PushID((void *)user_texture_id);\r\n    const ImGuiID id = window->GetID(\"#image\");\r\n    PopID();\r\n\r\n    const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;\r\n    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2);\r\n    const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);\r\n    ItemSize(bb);\r\n    if (!ItemAdd(bb, &id))\r\n        return false;\r\n\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(bb, id, &hovered, &held);\r\n\r\n    // Render\r\n    const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);\r\n    RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));\r\n    if (bg_col.w > 0.0f)\r\n        window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col));\r\n    window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col));\r\n\r\n    return pressed;\r\n}\r\n\r\n// Start logging ImGui output to TTY\r\nvoid ImGui::LogToTTY(int max_depth)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.LogEnabled)\r\n        return;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n\r\n    g.LogEnabled = true;\r\n    g.LogFile = stdout;\r\n    g.LogStartDepth = window->DC.TreeDepth;\r\n    if (max_depth >= 0)\r\n        g.LogAutoExpandMaxDepth = max_depth;\r\n}\r\n\r\n// Start logging ImGui output to given file\r\nvoid ImGui::LogToFile(int max_depth, const char* filename)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.LogEnabled)\r\n        return;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n\r\n    if (!filename)\r\n    {\r\n        filename = g.IO.LogFilename;\r\n        if (!filename)\r\n            return;\r\n    }\r\n\r\n    g.LogFile = ImFileOpen(filename, \"ab\");\r\n    if (!g.LogFile)\r\n    {\r\n        IM_ASSERT(g.LogFile != NULL); // Consider this an error\r\n        return;\r\n    }\r\n    g.LogEnabled = true;\r\n    g.LogStartDepth = window->DC.TreeDepth;\r\n    if (max_depth >= 0)\r\n        g.LogAutoExpandMaxDepth = max_depth;\r\n}\r\n\r\n// Start logging ImGui output to clipboard\r\nvoid ImGui::LogToClipboard(int max_depth)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.LogEnabled)\r\n        return;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n\r\n    g.LogEnabled = true;\r\n    g.LogFile = NULL;\r\n    g.LogStartDepth = window->DC.TreeDepth;\r\n    if (max_depth >= 0)\r\n        g.LogAutoExpandMaxDepth = max_depth;\r\n}\r\n\r\nvoid ImGui::LogFinish()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if (!g.LogEnabled)\r\n        return;\r\n\r\n    LogText(IM_NEWLINE);\r\n    g.LogEnabled = false;\r\n    if (g.LogFile != NULL)\r\n    {\r\n        if (g.LogFile == stdout)\r\n            fflush(g.LogFile);\r\n        else\r\n            fclose(g.LogFile);\r\n        g.LogFile = NULL;\r\n    }\r\n    if (g.LogClipboard->size() > 1)\r\n    {\r\n        SetClipboardText(g.LogClipboard->begin());\r\n        g.LogClipboard->clear();\r\n    }\r\n}\r\n\r\n// Helper to display logging buttons\r\nvoid ImGui::LogButtons()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    PushID(\"LogButtons\");\r\n    const bool log_to_tty = Button(\"Log To TTY\"); SameLine();\r\n    const bool log_to_file = Button(\"Log To File\"); SameLine();\r\n    const bool log_to_clipboard = Button(\"Log To Clipboard\"); SameLine();\r\n    PushItemWidth(80.0f);\r\n    PushAllowKeyboardFocus(false);\r\n    SliderInt(\"Depth\", &g.LogAutoExpandMaxDepth, 0, 9, NULL);\r\n    PopAllowKeyboardFocus();\r\n    PopItemWidth();\r\n    PopID();\r\n\r\n    // Start logging at the end of the function so that the buttons don't appear in the log\r\n    if (log_to_tty)\r\n        LogToTTY(g.LogAutoExpandMaxDepth);\r\n    if (log_to_file)\r\n        LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename);\r\n    if (log_to_clipboard)\r\n        LogToClipboard(g.LogAutoExpandMaxDepth);\r\n}\r\n\r\nbool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)\r\n{\r\n    if (flags & ImGuiTreeNodeFlags_Leaf)\r\n        return true;\r\n\r\n    // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions)\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = g.CurrentWindow;\r\n    ImGuiStorage* storage = window->DC.StateStorage;\r\n\r\n    bool is_open;\r\n    if (g.SetNextTreeNodeOpenCond != 0)\r\n    {\r\n        if (g.SetNextTreeNodeOpenCond & ImGuiCond_Always)\r\n        {\r\n            is_open = g.SetNextTreeNodeOpenVal;\r\n            storage->SetInt(id, is_open);\r\n        }\r\n        else\r\n        {\r\n            // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently.\r\n            const int stored_value = storage->GetInt(id, -1);\r\n            if (stored_value == -1)\r\n            {\r\n                is_open = g.SetNextTreeNodeOpenVal;\r\n                storage->SetInt(id, is_open);\r\n            }\r\n            else\r\n            {\r\n                is_open = stored_value != 0;\r\n            }\r\n        }\r\n        g.SetNextTreeNodeOpenCond = 0;\r\n    }\r\n    else\r\n    {\r\n        is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;\r\n    }\r\n\r\n    // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).\r\n    // NB- If we are above max depth we still allow manually opened nodes to be logged.\r\n    if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)\r\n        is_open = true;\r\n\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;\r\n    const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);\r\n\r\n    if (!label_end)\r\n        label_end = FindRenderedTextEnd(label);\r\n    const ImVec2 label_size = CalcTextSize(label, label_end, false);\r\n\r\n    // We vertically grow up to current line height up the typical widget height.\r\n    const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it\r\n    const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);\r\n    ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));\r\n    if (display_frame)\r\n    {\r\n        // Framed header expand a little outside the default padding\r\n        bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;\r\n        bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;\r\n    }\r\n\r\n    const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2));   // Collapser arrow width + Spacing\r\n    const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f);   // Include collapser\r\n    ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);\r\n\r\n    // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing\r\n    // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not)\r\n    const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y);\r\n    bool is_open = TreeNodeBehaviorIsOpen(id, flags);\r\n    if (!ItemAdd(interact_bb, &id))\r\n    {\r\n        if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))\r\n            TreePushRawID(id);\r\n        return is_open;\r\n    }\r\n\r\n    // Flags that affects opening behavior:\r\n    // - 0(default) ..................... single-click anywhere to open\r\n    // - OpenOnDoubleClick .............. double-click anywhere to open\r\n    // - OpenOnArrow .................... single-click on arrow to open\r\n    // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open\r\n    ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0);\r\n    if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)\r\n        button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0);\r\n    bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);\r\n    if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf))\r\n    {\r\n        bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick));\r\n        if (flags & ImGuiTreeNodeFlags_OpenOnArrow)\r\n            toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y));\r\n        if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)\r\n            toggled |= g.IO.MouseDoubleClicked[0];\r\n        if (toggled)\r\n        {\r\n            is_open = !is_open;\r\n            window->DC.StateStorage->SetInt(id, is_open);\r\n        }\r\n    }\r\n    if (flags & ImGuiTreeNodeFlags_AllowOverlapMode)\r\n        SetItemAllowOverlap();\r\n\r\n    // Render\r\n    const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);\r\n    const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, padding.y + text_base_offset_y);\r\n    if (display_frame)\r\n    {\r\n        // Framed type\r\n        RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);\r\n        RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f);\r\n        if (g.LogEnabled)\r\n        {\r\n            // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.\r\n            const char log_prefix[] = \"\\n##\";\r\n            const char log_suffix[] = \"##\";\r\n            LogRenderedText(text_pos, log_prefix, log_prefix+3);\r\n            RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size);\r\n            LogRenderedText(text_pos, log_suffix+1, log_suffix+3);\r\n        }\r\n        else\r\n        {\r\n            RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        // Unframed typed for tree nodes\r\n        if (hovered || (flags & ImGuiTreeNodeFlags_Selected))\r\n            RenderFrame(bb.Min, bb.Max, col, false);\r\n\r\n        if (flags & ImGuiTreeNodeFlags_Bullet)\r\n            RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y));\r\n        else if (!(flags & ImGuiTreeNodeFlags_Leaf))\r\n            RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f);\r\n        if (g.LogEnabled)\r\n            LogRenderedText(text_pos, \">\");\r\n        RenderText(text_pos, label, label_end, false);\r\n    }\r\n\r\n    if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))\r\n        TreePushRawID(id);\r\n    return is_open;\r\n}\r\n\r\n// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).\r\n// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode().\r\nbool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen, label);\r\n}\r\n\r\nbool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    if (p_open && !*p_open)\r\n        return false;\r\n\r\n    ImGuiID id = window->GetID(label);\r\n    bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label);\r\n    if (p_open)\r\n    {\r\n        // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.\r\n        ImGuiContext& g = *GImGui;\r\n        float button_sz = g.FontSize * 0.5f;\r\n        if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz))\r\n            *p_open = false;\r\n    }\r\n\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    return TreeNodeBehavior(window->GetID(label), flags, label, NULL);\r\n}\r\n\r\nbool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);\r\n    return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);\r\n}\r\n\r\nbool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);\r\n    return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);\r\n}\r\n\r\nbool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)\r\n{\r\n    return TreeNodeExV(str_id, 0, fmt, args);\r\n}\r\n\r\nbool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)\r\n{\r\n    return TreeNodeExV(ptr_id, 0, fmt, args);\r\n}\r\n\r\nbool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    bool is_open = TreeNodeExV(str_id, flags, fmt, args);\r\n    va_end(args);\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    bool is_open = TreeNodeExV(ptr_id, flags, fmt, args);\r\n    va_end(args);\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::TreeNode(const char* str_id, const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    bool is_open = TreeNodeExV(str_id, 0, fmt, args);\r\n    va_end(args);\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    bool is_open = TreeNodeExV(ptr_id, 0, fmt, args);\r\n    va_end(args);\r\n    return is_open;\r\n}\r\n\r\nbool ImGui::TreeNode(const char* label)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n    return TreeNodeBehavior(window->GetID(label), 0, label, NULL);\r\n}\r\n\r\nvoid ImGui::TreeAdvanceToLabelPos()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing();\r\n}\r\n\r\n// Horizontal distance preceding label when using TreeNode() or Bullet()\r\nfloat ImGui::GetTreeNodeToLabelSpacing()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.FontSize + (g.Style.FramePadding.x * 2.0f);\r\n}\r\n\r\nvoid ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.SetNextTreeNodeOpenVal = is_open;\r\n    g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always;\r\n}\r\n\r\nvoid ImGui::PushID(const char* str_id)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    window->IDStack.push_back(window->GetID(str_id));\r\n}\r\n\r\nvoid ImGui::PushID(const char* str_id_begin, const char* str_id_end)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    window->IDStack.push_back(window->GetID(str_id_begin, str_id_end));\r\n}\r\n\r\nvoid ImGui::PushID(const void* ptr_id)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    window->IDStack.push_back(window->GetID(ptr_id));\r\n}\r\n\r\nvoid ImGui::PushID(int int_id)\r\n{\r\n    const void* ptr_id = (void*)(intptr_t)int_id;\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    window->IDStack.push_back(window->GetID(ptr_id));\r\n}\r\n\r\nvoid ImGui::PopID()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    window->IDStack.pop_back();\r\n}\r\n\r\nImGuiID ImGui::GetID(const char* str_id)\r\n{\r\n    return GImGui->CurrentWindow->GetID(str_id);\r\n}\r\n\r\nImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end)\r\n{\r\n    return GImGui->CurrentWindow->GetID(str_id_begin, str_id_end);\r\n}\r\n\r\nImGuiID ImGui::GetID(const void* ptr_id)\r\n{\r\n    return GImGui->CurrentWindow->GetID(ptr_id);\r\n}\r\n\r\nvoid ImGui::Bullet()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);\r\n    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));\r\n    ItemSize(bb);\r\n    if (!ItemAdd(bb, NULL))\r\n    {\r\n        SameLine(0, style.FramePadding.x*2);\r\n        return;\r\n    }\r\n\r\n    // Render and stay on same line\r\n    RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));\r\n    SameLine(0, style.FramePadding.x*2);\r\n}\r\n\r\n// Text with a little bullet aligned to the typical tree node.\r\nvoid ImGui::BulletTextV(const char* fmt, va_list args)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    const char* text_begin = g.TempBuffer;\r\n    const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);\r\n    const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);\r\n    const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it\r\n    const float line_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);\r\n    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y)));  // Empty text doesn't add padding\r\n    ItemSize(bb);\r\n    if (!ItemAdd(bb, NULL))\r\n        return;\r\n\r\n    // Render\r\n    RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));\r\n    RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);\r\n}\r\n\r\nvoid ImGui::BulletText(const char* fmt, ...)\r\n{\r\n    va_list args;\r\n    va_start(args, fmt);\r\n    BulletTextV(fmt, args);\r\n    va_end(args);\r\n}\r\n\r\nstatic inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size)\r\n{\r\n    if (data_type == ImGuiDataType_Int)\r\n        ImFormatString(buf, buf_size, display_format, *(int*)data_ptr);\r\n    else if (data_type == ImGuiDataType_Float)\r\n        ImFormatString(buf, buf_size, display_format, *(float*)data_ptr);\r\n}\r\n\r\nstatic inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size)\r\n{\r\n    if (data_type == ImGuiDataType_Int)\r\n    {\r\n        if (decimal_precision < 0)\r\n            ImFormatString(buf, buf_size, \"%d\", *(int*)data_ptr);\r\n        else\r\n            ImFormatString(buf, buf_size, \"%.*d\", decimal_precision, *(int*)data_ptr);\r\n    }\r\n    else if (data_type == ImGuiDataType_Float)\r\n    {\r\n        if (decimal_precision < 0)\r\n            ImFormatString(buf, buf_size, \"%f\", *(float*)data_ptr);     // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits?\r\n        else\r\n            ImFormatString(buf, buf_size, \"%.*f\", decimal_precision, *(float*)data_ptr);\r\n    }\r\n}\r\n\r\nstatic void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2)// Store into value1\r\n{\r\n    if (data_type == ImGuiDataType_Int)\r\n    {\r\n        if (op == '+')\r\n            *(int*)value1 = *(int*)value1 + *(const int*)value2;\r\n        else if (op == '-')\r\n            *(int*)value1 = *(int*)value1 - *(const int*)value2;\r\n    }\r\n    else if (data_type == ImGuiDataType_Float)\r\n    {\r\n        if (op == '+')\r\n            *(float*)value1 = *(float*)value1 + *(const float*)value2;\r\n        else if (op == '-')\r\n            *(float*)value1 = *(float*)value1 - *(const float*)value2;\r\n    }\r\n}\r\n\r\n// User can input math operators (e.g. +100) to edit a numerical values.\r\nstatic bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format)\r\n{\r\n    while (ImCharIsSpace(*buf))\r\n        buf++;\r\n\r\n    // We don't support '-' op because it would conflict with inputing negative value.\r\n    // Instead you can use +-100 to subtract from an existing value\r\n    char op = buf[0];\r\n    if (op == '+' || op == '*' || op == '/')\r\n    {\r\n        buf++;\r\n        while (ImCharIsSpace(*buf))\r\n            buf++;\r\n    }\r\n    else\r\n    {\r\n        op = 0;\r\n    }\r\n    if (!buf[0])\r\n        return false;\r\n\r\n    if (data_type == ImGuiDataType_Int)\r\n    {\r\n        if (!scalar_format)\r\n            scalar_format = \"%d\";\r\n        int* v = (int*)data_ptr;\r\n        const int old_v = *v;\r\n        int arg0i = *v;\r\n        if (op && sscanf(initial_value_buf, scalar_format, &arg0i) < 1)\r\n            return false;\r\n\r\n        // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision\r\n        float arg1f = 0.0f;\r\n        if (op == '+')      { if (sscanf(buf, \"%f\", &arg1f) == 1) *v = (int)(arg0i + arg1f); }                 // Add (use \"+-\" to subtract)\r\n        else if (op == '*') { if (sscanf(buf, \"%f\", &arg1f) == 1) *v = (int)(arg0i * arg1f); }                 // Multiply\r\n        else if (op == '/') { if (sscanf(buf, \"%f\", &arg1f) == 1 && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }// Divide\r\n        else                { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; }                       // Assign constant (read as integer so big values are not lossy)\r\n        return (old_v != *v);\r\n    }\r\n    else if (data_type == ImGuiDataType_Float)\r\n    {\r\n        // For floats we have to ignore format with precision (e.g. \"%.2f\") because sscanf doesn't take them in\r\n        scalar_format = \"%f\";\r\n        float* v = (float*)data_ptr;\r\n        const float old_v = *v;\r\n        float arg0f = *v;\r\n        if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1)\r\n            return false;\r\n\r\n        float arg1f = 0.0f;\r\n        if (sscanf(buf, scalar_format, &arg1f) < 1)\r\n            return false;\r\n        if (op == '+')      { *v = arg0f + arg1f; }                    // Add (use \"+-\" to subtract)\r\n        else if (op == '*') { *v = arg0f * arg1f; }                    // Multiply\r\n        else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide\r\n        else                { *v = arg1f; }                            // Assign constant\r\n        return (old_v != *v);\r\n    }\r\n\r\n    return false;\r\n}\r\n\r\n// Create text input in place of a slider (when CTRL+Clicking on slider)\r\n// FIXME: Logic is messy and confusing.\r\nbool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen)\r\n    // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id\r\n    SetActiveID(g.ScalarAsInputTextId, window);\r\n    SetHoveredID(0);\r\n    FocusableItemUnregister(window);\r\n\r\n    char buf[32];\r\n    DataTypeFormatString(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf));\r\n    bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll);\r\n    if (g.ScalarAsInputTextId == 0)     // First frame we started displaying the InputText widget\r\n    {\r\n        IM_ASSERT(g.ActiveId == id);    // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible)\r\n        g.ScalarAsInputTextId = g.ActiveId;\r\n        SetHoveredID(id);\r\n    }\r\n    if (text_value_changed)\r\n        return DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, NULL);\r\n    return false;\r\n}\r\n\r\n// Parse display precision back from the display format string\r\nint ImGui::ParseFormatPrecision(const char* fmt, int default_precision)\r\n{\r\n    int precision = default_precision;\r\n    while ((fmt = strchr(fmt, '%')) != NULL)\r\n    {\r\n        fmt++;\r\n        if (fmt[0] == '%') { fmt++; continue; } // Ignore \"%%\"\r\n        while (*fmt >= '0' && *fmt <= '9')\r\n            fmt++;\r\n        if (*fmt == '.')\r\n        {\r\n            fmt = ImAtoi(fmt + 1, &precision);\r\n            if (precision < 0 || precision > 10)\r\n                precision = default_precision;\r\n        }\r\n        if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation\r\n            precision = -1;\r\n        break;\r\n    }\r\n    return precision;\r\n}\r\n\r\nstatic float GetMinimumStepAtDecimalPrecision(int decimal_precision)\r\n{\r\n    static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };\r\n    return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision);\r\n}\r\n\r\nfloat ImGui::RoundScalar(float value, int decimal_precision)\r\n{\r\n    // Round past decimal precision\r\n    // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0\r\n    // FIXME: Investigate better rounding methods\r\n    if (decimal_precision < 0)\r\n        return value;\r\n    const float min_step = GetMinimumStepAtDecimalPrecision(decimal_precision);\r\n    bool negative = value < 0.0f;\r\n    value = fabsf(value);\r\n    float remainder = fmodf(value, min_step);\r\n    if (remainder <= min_step*0.5f)\r\n        value -= remainder;\r\n    else\r\n        value += (min_step - remainder);\r\n    return negative ? -value : value;\r\n}\r\n\r\nstatic inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos)\r\n{\r\n    if (v_min == v_max)\r\n        return 0.0f;\r\n\r\n    const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f);\r\n    const float v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);\r\n    if (is_non_linear)\r\n    {\r\n        if (v_clamped < 0.0f)\r\n        {\r\n            const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min);\r\n            return (1.0f - powf(f, 1.0f/power)) * linear_zero_pos;\r\n        }\r\n        else\r\n        {\r\n            const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min));\r\n            return linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos);\r\n        }\r\n    }\r\n\r\n    // Linear slider\r\n    return (v_clamped - v_min) / (v_max - v_min);\r\n}\r\n\r\nbool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    // Draw frame\r\n    RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);\r\n\r\n    const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f);\r\n    const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0;\r\n\r\n    const float grab_padding = 2.0f;\r\n    const float slider_sz = is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f);\r\n    float grab_sz;\r\n    if (decimal_precision != 0)\r\n        grab_sz = ImMin(style.GrabMinSize, slider_sz);\r\n    else\r\n        grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), slider_sz);  // Integer sliders, if possible have the grab size represent 1 unit\r\n    const float slider_usable_sz = slider_sz - grab_sz;\r\n    const float slider_usable_pos_min = (is_horizontal ? frame_bb.Min.x : frame_bb.Min.y) + grab_padding + grab_sz*0.5f;\r\n    const float slider_usable_pos_max = (is_horizontal ? frame_bb.Max.x : frame_bb.Max.y) - grab_padding - grab_sz*0.5f;\r\n\r\n    // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f\r\n    float linear_zero_pos = 0.0f;   // 0.0->1.0f\r\n    if (v_min * v_max < 0.0f)\r\n    {\r\n        // Different sign\r\n        const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power);\r\n        const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power);\r\n        linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0);\r\n    }\r\n    else\r\n    {\r\n        // Same sign\r\n        linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;\r\n    }\r\n\r\n    // Process clicking on the slider\r\n    bool value_changed = false;\r\n    if (g.ActiveId == id)\r\n    {\r\n        bool set_new_value = false;\r\n        float clicked_t = 0.0f;\r\n        if (g.IO.MouseDown[0])\r\n        {\r\n            const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;\r\n            clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f;\r\n            if (!is_horizontal)\r\n                clicked_t = 1.0f - clicked_t;\r\n            set_new_value = true;\r\n        }\r\n        else\r\n        {\r\n            ClearActiveID();\r\n        }\r\n\r\n        if (set_new_value)\r\n        {\r\n            float new_value;\r\n            if (is_non_linear)\r\n            {\r\n                // Account for logarithmic scale on both sides of the zero\r\n                if (clicked_t < linear_zero_pos)\r\n                {\r\n                    // Negative: rescale to the negative range before powering\r\n                    float a = 1.0f - (clicked_t / linear_zero_pos);\r\n                    a = powf(a, power);\r\n                    new_value = ImLerp(ImMin(v_max,0.0f), v_min, a);\r\n                }\r\n                else\r\n                {\r\n                    // Positive: rescale to the positive range before powering\r\n                    float a;\r\n                    if (fabsf(linear_zero_pos - 1.0f) > 1.e-6f)\r\n                        a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos);\r\n                    else\r\n                        a = clicked_t;\r\n                    a = powf(a, power);\r\n                    new_value = ImLerp(ImMax(v_min,0.0f), v_max, a);\r\n                }\r\n            }\r\n            else\r\n            {\r\n                // Linear slider\r\n                new_value = ImLerp(v_min, v_max, clicked_t);\r\n            }\r\n\r\n            // Round past decimal precision\r\n            new_value = RoundScalar(new_value, decimal_precision);\r\n            if (*v != new_value)\r\n            {\r\n                *v = new_value;\r\n                value_changed = true;\r\n            }\r\n        }\r\n    }\r\n\r\n    // Draw\r\n    float grab_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos);\r\n    if (!is_horizontal)\r\n        grab_t = 1.0f - grab_t;\r\n    const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);\r\n    ImRect grab_bb;\r\n    if (is_horizontal)\r\n        grab_bb = ImRect(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + grab_padding), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - grab_padding));\r\n    else\r\n        grab_bb = ImRect(ImVec2(frame_bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f));\r\n    window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);\r\n\r\n    return value_changed;\r\n}\r\n\r\n// Use power!=1.0 for logarithmic sliders.\r\n// Adjust display_format to decorate the value with a prefix or a suffix.\r\n//   \"%.3f\"         1.234\r\n//   \"%5.2f secs\"   01.23 secs\r\n//   \"Gold: %.0f\"   Gold: 1\r\nbool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n    const float w = CalcItemWidth();\r\n\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));\r\n    const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));\r\n\r\n    // NB- we don't call ItemSize() yet because we may turn into a text edit box below\r\n    if (!ItemAdd(total_bb, &id))\r\n    {\r\n        ItemSize(total_bb, style.FramePadding.y);\r\n        return false;\r\n    }\r\n\r\n    const bool hovered = IsHovered(frame_bb, id);\r\n    if (hovered)\r\n        SetHoveredID(id);\r\n\r\n    if (!display_format)\r\n        display_format = \"%.3f\";\r\n    int decimal_precision = ParseFormatPrecision(display_format, 3);\r\n\r\n    // Tabbing or CTRL-clicking on Slider turns it into an input box\r\n    bool start_text_input = false;\r\n    const bool tab_focus_requested = FocusableItemRegister(window, id);\r\n    if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))\r\n    {\r\n        SetActiveID(id, window);\r\n        FocusWindow(window);\r\n        if (tab_focus_requested || g.IO.KeyCtrl)\r\n        {\r\n            start_text_input = true;\r\n            g.ScalarAsInputTextId = 0;\r\n        }\r\n    }\r\n    if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))\r\n        return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision);\r\n\r\n    // Actual slider behavior + render grab\r\n    ItemSize(total_bb, style.FramePadding.y);\r\n    const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision);\r\n\r\n    // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.\r\n    char value_buf[64];\r\n    const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);\r\n    RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));\r\n\r\n    if (label_size.x > 0.0f)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);\r\n    const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));\r\n\r\n    ItemSize(bb, style.FramePadding.y);\r\n    if (!ItemAdd(frame_bb, &id))\r\n        return false;\r\n\r\n    const bool hovered = IsHovered(frame_bb, id);\r\n    if (hovered)\r\n        SetHoveredID(id);\r\n\r\n    if (!display_format)\r\n        display_format = \"%.3f\";\r\n    int decimal_precision = ParseFormatPrecision(display_format, 3);\r\n\r\n    if (hovered && g.IO.MouseClicked[0])\r\n    {\r\n        SetActiveID(id, window);\r\n        FocusWindow(window);\r\n    }\r\n\r\n    // Actual slider behavior + render grab\r\n    bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, ImGuiSliderFlags_Vertical);\r\n\r\n    // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.\r\n    // For the vertical slider we allow centered text to overlap the frame padding\r\n    char value_buf[64];\r\n    char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);\r\n    RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f));\r\n    if (label_size.x > 0.0f)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max)\r\n{\r\n    float v_deg = (*v_rad) * 360.0f / (2*IM_PI);\r\n    bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, \"%.0f deg\", 1.0f);\r\n    *v_rad = v_deg * (2*IM_PI) / 360.0f;\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format)\r\n{\r\n    if (!display_format)\r\n        display_format = \"%.0f\";\r\n    float v_f = (float)*v;\r\n    bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f);\r\n    *v = (int)v_f;\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format)\r\n{\r\n    if (!display_format)\r\n        display_format = \"%.0f\";\r\n    float v_f = (float)*v;\r\n    bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f);\r\n    *v = (int)v_f;\r\n    return value_changed;\r\n}\r\n\r\n// Add multiple sliders on 1 line for compact edition of multiple components\r\nbool ImGui::SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    bool value_changed = false;\r\n    BeginGroup();\r\n    PushID(label);\r\n    PushMultiItemsWidths(components);\r\n    for (int i = 0; i < components; i++)\r\n    {\r\n        PushID(i);\r\n        value_changed |= SliderFloat(\"##v\", &v[i], v_min, v_max, display_format, power);\r\n        SameLine(0, g.Style.ItemInnerSpacing.x);\r\n        PopID();\r\n        PopItemWidth();\r\n    }\r\n    PopID();\r\n\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    return SliderFloatN(label, v, 2, v_min, v_max, display_format, power);\r\n}\r\n\r\nbool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    return SliderFloatN(label, v, 3, v_min, v_max, display_format, power);\r\n}\r\n\r\nbool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    return SliderFloatN(label, v, 4, v_min, v_max, display_format, power);\r\n}\r\n\r\nbool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    bool value_changed = false;\r\n    BeginGroup();\r\n    PushID(label);\r\n    PushMultiItemsWidths(components);\r\n    for (int i = 0; i < components; i++)\r\n    {\r\n        PushID(i);\r\n        value_changed |= SliderInt(\"##v\", &v[i], v_min, v_max, display_format);\r\n        SameLine(0, g.Style.ItemInnerSpacing.x);\r\n        PopID();\r\n        PopItemWidth();\r\n    }\r\n    PopID();\r\n\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format)\r\n{\r\n    return SliderIntN(label, v, 2, v_min, v_max, display_format);\r\n}\r\n\r\nbool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format)\r\n{\r\n    return SliderIntN(label, v, 3, v_min, v_max, display_format);\r\n}\r\n\r\nbool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format)\r\n{\r\n    return SliderIntN(label, v, 4, v_min, v_max, display_format);\r\n}\r\n\r\nbool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    // Draw frame\r\n    const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);\r\n    RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);\r\n\r\n    bool value_changed = false;\r\n\r\n    // Process clicking on the drag\r\n    if (g.ActiveId == id)\r\n    {\r\n        if (g.IO.MouseDown[0])\r\n        {\r\n            if (g.ActiveIdIsJustActivated)\r\n            {\r\n                // Lock current value on click\r\n                g.DragCurrentValue = *v;\r\n                g.DragLastMouseDelta = ImVec2(0.f, 0.f);\r\n            }\r\n\r\n            if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX)\r\n                v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio;\r\n            float v_cur = g.DragCurrentValue;\r\n            const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f);\r\n            float adjust_delta = 0.0f;\r\n            //if (g.ActiveIdSource == ImGuiInputSource_Mouse)\r\n            {\r\n                adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x;\r\n                if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f)\r\n                    adjust_delta *= g.DragSpeedScaleFast;\r\n                if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f)\r\n                    adjust_delta *= g.DragSpeedScaleSlow;\r\n            }\r\n            adjust_delta *= v_speed;\r\n            g.DragLastMouseDelta.x = mouse_drag_delta.x;\r\n\r\n            if (fabsf(adjust_delta) > 0.0f)\r\n            {\r\n                if (fabsf(power - 1.0f) > 0.001f)\r\n                {\r\n                    // Logarithmic curve on both side of 0.0\r\n                    float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur;\r\n                    float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f;\r\n                    float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign);\r\n                    float v1_abs = v1 >= 0.0f ? v1 : -v1;\r\n                    float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f;          // Crossed sign line\r\n                    v_cur = powf(v1_abs, power) * v0_sign * v1_sign;    // Reapply sign\r\n                }\r\n                else\r\n                {\r\n                    v_cur += adjust_delta;\r\n                }\r\n\r\n                // Clamp\r\n                if (v_min < v_max)\r\n                    v_cur = ImClamp(v_cur, v_min, v_max);\r\n                g.DragCurrentValue = v_cur;\r\n            }\r\n\r\n            // Round to user desired precision, then apply\r\n            v_cur = RoundScalar(v_cur, decimal_precision);\r\n            if (*v != v_cur)\r\n            {\r\n                *v = v_cur;\r\n                value_changed = true;\r\n            }\r\n        }\r\n        else\r\n        {\r\n            ClearActiveID();\r\n        }\r\n    }\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n    const float w = CalcItemWidth();\r\n\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));\r\n    const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);\r\n    const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));\r\n\r\n    // NB- we don't call ItemSize() yet because we may turn into a text edit box below\r\n    if (!ItemAdd(total_bb, &id))\r\n    {\r\n        ItemSize(total_bb, style.FramePadding.y);\r\n        return false;\r\n    }\r\n\r\n    const bool hovered = IsHovered(frame_bb, id);\r\n    if (hovered)\r\n        SetHoveredID(id);\r\n\r\n    if (!display_format)\r\n        display_format = \"%.3f\";\r\n    int decimal_precision = ParseFormatPrecision(display_format, 3);\r\n\r\n    // Tabbing or CTRL-clicking on Drag turns it into an input box\r\n    bool start_text_input = false;\r\n    const bool tab_focus_requested = FocusableItemRegister(window, id);\r\n    if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])))\r\n    {\r\n        SetActiveID(id, window);\r\n        FocusWindow(window);\r\n        if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0])\r\n        {\r\n            start_text_input = true;\r\n            g.ScalarAsInputTextId = 0;\r\n        }\r\n    }\r\n    if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))\r\n        return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision);\r\n\r\n    // Actual drag behavior\r\n    ItemSize(total_bb, style.FramePadding.y);\r\n    const bool value_changed = DragBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power);\r\n\r\n    // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.\r\n    char value_buf[64];\r\n    const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);\r\n    RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));\r\n\r\n    if (label_size.x > 0.0f)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    bool value_changed = false;\r\n    BeginGroup();\r\n    PushID(label);\r\n    PushMultiItemsWidths(components);\r\n    for (int i = 0; i < components; i++)\r\n    {\r\n        PushID(i);\r\n        value_changed |= DragFloat(\"##v\", &v[i], v_speed, v_min, v_max, display_format, power);\r\n        SameLine(0, g.Style.ItemInnerSpacing.x);\r\n        PopID();\r\n        PopItemWidth();\r\n    }\r\n    PopID();\r\n\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    return DragFloatN(label, v, 2, v_speed, v_min, v_max, display_format, power);\r\n}\r\n\r\nbool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    return DragFloatN(label, v, 3, v_speed, v_min, v_max, display_format, power);\r\n}\r\n\r\nbool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* display_format, float power)\r\n{\r\n    return DragFloatN(label, v, 4, v_speed, v_min, v_max, display_format, power);\r\n}\r\n\r\nbool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* display_format, const char* display_format_max, float power)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    PushID(label);\r\n    BeginGroup();\r\n    PushMultiItemsWidths(2);\r\n\r\n    bool value_changed = DragFloat(\"##min\", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power);\r\n    PopItemWidth();\r\n    SameLine(0, g.Style.ItemInnerSpacing.x);\r\n    value_changed |= DragFloat(\"##max\", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power);\r\n    PopItemWidth();\r\n    SameLine(0, g.Style.ItemInnerSpacing.x);\r\n\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n    PopID();\r\n\r\n    return value_changed;\r\n}\r\n\r\n// NB: v_speed is float to allow adjusting the drag speed with more precision\r\nbool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format)\r\n{\r\n    if (!display_format)\r\n        display_format = \"%.0f\";\r\n    float v_f = (float)*v;\r\n    bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format);\r\n    *v = (int)v_f;\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    bool value_changed = false;\r\n    BeginGroup();\r\n    PushID(label);\r\n    PushMultiItemsWidths(components);\r\n    for (int i = 0; i < components; i++)\r\n    {\r\n        PushID(i);\r\n        value_changed |= DragInt(\"##v\", &v[i], v_speed, v_min, v_max, display_format);\r\n        SameLine(0, g.Style.ItemInnerSpacing.x);\r\n        PopID();\r\n        PopItemWidth();\r\n    }\r\n    PopID();\r\n\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* display_format)\r\n{\r\n    return DragIntN(label, v, 2, v_speed, v_min, v_max, display_format);\r\n}\r\n\r\nbool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* display_format)\r\n{\r\n    return DragIntN(label, v, 3, v_speed, v_min, v_max, display_format);\r\n}\r\n\r\nbool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* display_format)\r\n{\r\n    return DragIntN(label, v, 4, v_speed, v_min, v_max, display_format);\r\n}\r\n\r\nbool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* display_format, const char* display_format_max)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    PushID(label);\r\n    BeginGroup();\r\n    PushMultiItemsWidths(2);\r\n\r\n    bool value_changed = DragInt(\"##min\", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format);\r\n    PopItemWidth();\r\n    SameLine(0, g.Style.ItemInnerSpacing.x);\r\n    value_changed |= DragInt(\"##max\", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format);\r\n    PopItemWidth();\r\n    SameLine(0, g.Style.ItemInnerSpacing.x);\r\n\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n    PopID();\r\n\r\n    return value_changed;\r\n}\r\n\r\nvoid ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    if (graph_size.x == 0.0f)\r\n        graph_size.x = CalcItemWidth();\r\n    if (graph_size.y == 0.0f)\r\n        graph_size.y = label_size.y + (style.FramePadding.y * 2);\r\n\r\n    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y));\r\n    const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);\r\n    const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));\r\n    ItemSize(total_bb, style.FramePadding.y);\r\n    if (!ItemAdd(total_bb, NULL))\r\n        return;\r\n\r\n    // Determine scale from values if not specified\r\n    if (scale_min == FLT_MAX || scale_max == FLT_MAX)\r\n    {\r\n        float v_min = FLT_MAX;\r\n        float v_max = -FLT_MAX;\r\n        for (int i = 0; i < values_count; i++)\r\n        {\r\n            const float v = values_getter(data, i);\r\n            v_min = ImMin(v_min, v);\r\n            v_max = ImMax(v_max, v);\r\n        }\r\n        if (scale_min == FLT_MAX)\r\n            scale_min = v_min;\r\n        if (scale_max == FLT_MAX)\r\n            scale_max = v_max;\r\n    }\r\n\r\n    RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);\r\n\r\n    if (values_count > 0)\r\n    {\r\n        int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);\r\n        int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);\r\n\r\n        // Tooltip on hover\r\n        int v_hovered = -1;\r\n        if (IsHovered(inner_bb, 0))\r\n        {\r\n            const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);\r\n            const int v_idx = (int)(t * item_count);\r\n            IM_ASSERT(v_idx >= 0 && v_idx < values_count);\r\n\r\n            const float v0 = values_getter(data, (v_idx + values_offset) % values_count);\r\n            const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);\r\n            if (plot_type == ImGuiPlotType_Lines)\r\n                SetTooltip(\"%d: %8.4g\\n%d: %8.4g\", v_idx, v0, v_idx+1, v1);\r\n            else if (plot_type == ImGuiPlotType_Histogram)\r\n                SetTooltip(\"%d: %8.4g\", v_idx, v0);\r\n            v_hovered = v_idx;\r\n        }\r\n\r\n        const float t_step = 1.0f / (float)res_w;\r\n\r\n        float v0 = values_getter(data, (0 + values_offset) % values_count);\r\n        float t0 = 0.0f;\r\n        ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) );                       // Point in the normalized space of our target rectangle\r\n        float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min / (scale_max - scale_min)) : (scale_min < 0.0f ? 0.0f : 1.0f);   // Where does the zero line stands\r\n\r\n        const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);\r\n        const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);\r\n\r\n        for (int n = 0; n < res_w; n++)\r\n        {\r\n            const float t1 = t0 + t_step;\r\n            const int v1_idx = (int)(t0 * item_count + 0.5f);\r\n            IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);\r\n            const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);\r\n            const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );\r\n\r\n            // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.\r\n            ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);\r\n            ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));\r\n            if (plot_type == ImGuiPlotType_Lines)\r\n            {\r\n                window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);\r\n            }\r\n            else if (plot_type == ImGuiPlotType_Histogram)\r\n            {\r\n                if (pos1.x >= pos0.x + 2.0f)\r\n                    pos1.x -= 1.0f;\r\n                window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);\r\n            }\r\n\r\n            t0 = t1;\r\n            tp0 = tp1;\r\n        }\r\n    }\r\n\r\n    // Text overlay\r\n    if (overlay_text)\r\n        RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f));\r\n\r\n    if (label_size.x > 0.0f)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);\r\n}\r\n\r\nstruct ImGuiPlotArrayGetterData\r\n{\r\n    const float* Values;\r\n    int Stride;\r\n\r\n    ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; }\r\n};\r\n\r\nstatic float Plot_ArrayGetter(void* data, int idx)\r\n{\r\n    ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data;\r\n    const float v = *(float*)(void*)((unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);\r\n    return v;\r\n}\r\n\r\nvoid ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)\r\n{\r\n    ImGuiPlotArrayGetterData data(values, stride);\r\n    PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);\r\n}\r\n\r\nvoid ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)\r\n{\r\n    PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);\r\n}\r\n\r\nvoid ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)\r\n{\r\n    ImGuiPlotArrayGetterData data(values, stride);\r\n    PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);\r\n}\r\n\r\nvoid ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)\r\n{\r\n    PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);\r\n}\r\n\r\n// size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size\r\nvoid ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    ImVec2 pos = window->DC.CursorPos;\r\n    ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f));\r\n    ItemSize(bb, style.FramePadding.y);\r\n    if (!ItemAdd(bb, NULL))\r\n        return;\r\n\r\n    // Render\r\n    fraction = ImSaturate(fraction);\r\n    RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);\r\n    bb.Expand(ImVec2(-window->BorderSize, -window->BorderSize));\r\n    const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);\r\n    RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);\r\n\r\n    // Default displaying the fraction as percentage string, but user can override it\r\n    char overlay_buf[32];\r\n    if (!overlay)\r\n    {\r\n        ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), \"%.0f%%\", fraction*100+0.01f);\r\n        overlay = overlay_buf;\r\n    }\r\n\r\n    ImVec2 overlay_size = CalcTextSize(overlay, NULL);\r\n    if (overlay_size.x > 0.0f)\r\n        RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb);\r\n}\r\n\r\nbool ImGui::Checkbox(const char* label, bool* v)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n\r\n    const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); // We want a square shape to we use Y twice\r\n    ItemSize(check_bb, style.FramePadding.y);\r\n\r\n    ImRect total_bb = check_bb;\r\n    if (label_size.x > 0)\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n    const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size);\r\n    if (label_size.x > 0)\r\n    {\r\n        ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);\r\n        total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));\r\n    }\r\n\r\n    if (!ItemAdd(total_bb, &id))\r\n        return false;\r\n\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);\r\n    if (pressed)\r\n        *v = !(*v);\r\n\r\n    RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);\r\n    if (*v)\r\n    {\r\n        const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());\r\n        const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f));\r\n        window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), style.FrameRounding);\r\n    }\r\n\r\n    if (g.LogEnabled)\r\n        LogRenderedText(text_bb.GetTL(), *v ? \"[x]\" : \"[ ]\");\r\n    if (label_size.x > 0.0f)\r\n        RenderText(text_bb.GetTL(), label);\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)\r\n{\r\n    bool v = ((*flags & flags_value) == flags_value);\r\n    bool pressed = Checkbox(label, &v);\r\n    if (pressed)\r\n    {\r\n        if (v)\r\n            *flags |= flags_value;\r\n        else\r\n            *flags &= ~flags_value;\r\n    }\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::RadioButton(const char* label, bool active)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n\r\n    const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1));\r\n    ItemSize(check_bb, style.FramePadding.y);\r\n\r\n    ImRect total_bb = check_bb;\r\n    if (label_size.x > 0)\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n    const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);\r\n    if (label_size.x > 0)\r\n    {\r\n        ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);\r\n        total_bb.Add(text_bb);\r\n    }\r\n\r\n    if (!ItemAdd(total_bb, &id))\r\n        return false;\r\n\r\n    ImVec2 center = check_bb.GetCenter();\r\n    center.x = (float)(int)center.x + 0.5f;\r\n    center.y = (float)(int)center.y + 0.5f;\r\n    const float radius = check_bb.GetHeight() * 0.5f;\r\n\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);\r\n\r\n    window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);\r\n    if (active)\r\n    {\r\n        const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());\r\n        const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f));\r\n        window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16);\r\n    }\r\n\r\n    if (window->Flags & ImGuiWindowFlags_ShowBorders)\r\n    {\r\n        window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16);\r\n        window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16);\r\n    }\r\n\r\n    if (g.LogEnabled)\r\n        LogRenderedText(text_bb.GetTL(), active ? \"(x)\" : \"( )\");\r\n    if (label_size.x > 0.0f)\r\n        RenderText(text_bb.GetTL(), label);\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::RadioButton(const char* label, int* v, int v_button)\r\n{\r\n    const bool pressed = RadioButton(label, *v == v_button);\r\n    if (pressed)\r\n    {\r\n        *v = v_button;\r\n    }\r\n    return pressed;\r\n}\r\n\r\nstatic int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)\r\n{\r\n    int line_count = 0;\r\n    const char* s = text_begin;\r\n    while (char c = *s++) // We are only matching for \\n so we can ignore UTF-8 decoding\r\n        if (c == '\\n')\r\n            line_count++;\r\n    s--;\r\n    if (s[0] != '\\n' && s[0] != '\\r')\r\n        line_count++;\r\n    *out_text_end = s;\r\n    return line_count;\r\n}\r\n\r\nstatic ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)\r\n{\r\n    ImFont* font = GImGui->Font;\r\n    const float line_height = GImGui->FontSize;\r\n    const float scale = line_height / font->FontSize;\r\n\r\n    ImVec2 text_size = ImVec2(0,0);\r\n    float line_width = 0.0f;\r\n\r\n    const ImWchar* s = text_begin;\r\n    while (s < text_end)\r\n    {\r\n        unsigned int c = (unsigned int)(*s++);\r\n        if (c == '\\n')\r\n        {\r\n            text_size.x = ImMax(text_size.x, line_width);\r\n            text_size.y += line_height;\r\n            line_width = 0.0f;\r\n            if (stop_on_new_line)\r\n                break;\r\n            continue;\r\n        }\r\n        if (c == '\\r')\r\n            continue;\r\n\r\n        const float char_width = font->GetCharAdvance((unsigned short)c) * scale;\r\n        line_width += char_width;\r\n    }\r\n\r\n    if (text_size.x < line_width)\r\n        text_size.x = line_width;\r\n\r\n    if (out_offset)\r\n        *out_offset = ImVec2(line_width, text_size.y + line_height);  // offset allow for the possibility of sitting after a trailing \\n\r\n\r\n    if (line_width > 0 || text_size.y == 0.0f)                        // whereas size.y will ignore the trailing \\n\r\n        text_size.y += line_height;\r\n\r\n    if (remaining)\r\n        *remaining = s;\r\n\r\n    return text_size;\r\n}\r\n\r\n// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar)\r\nnamespace ImGuiStb\r\n{\r\n\r\nstatic int     STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj)                             { return obj->CurLenW; }\r\nstatic ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx)                      { return obj->Text[idx]; }\r\nstatic float   STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx)  { ImWchar c = obj->Text[line_start_idx+char_idx]; if (c == '\\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); }\r\nstatic int     STB_TEXTEDIT_KEYTOTEXT(int key)                                                    { return key >= 0x10000 ? 0 : key; }\r\nstatic ImWchar STB_TEXTEDIT_NEWLINE = '\\n';\r\nstatic void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)\r\n{\r\n    const ImWchar* text = obj->Text.Data;\r\n    const ImWchar* text_remaining = NULL;\r\n    const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);\r\n    r->x0 = 0.0f;\r\n    r->x1 = size.x;\r\n    r->baseline_y_delta = size.y;\r\n    r->ymin = 0.0f;\r\n    r->ymax = size.y;\r\n    r->num_chars = (int)(text_remaining - (text + line_start_idx));\r\n}\r\n\r\nstatic bool is_separator(unsigned int c)                                        { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }\r\nstatic int  is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx)      { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; }\r\nstatic int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)   { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }\r\n#ifdef __APPLE__    // FIXME: Move setting to IO structure\r\nstatic int  is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx)       { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }\r\nstatic int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)  { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }\r\n#else\r\nstatic int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)  { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }\r\n#endif\r\n#define STB_TEXTEDIT_MOVEWORDLEFT   STB_TEXTEDIT_MOVEWORDLEFT_IMPL    // They need to be #define for stb_textedit.h\r\n#define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL\r\n\r\nstatic void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)\r\n{\r\n    ImWchar* dst = obj->Text.Data + pos;\r\n\r\n    // We maintain our buffer length in both UTF-8 and wchar formats\r\n    obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);\r\n    obj->CurLenW -= n;\r\n\r\n    // Offset remaining text\r\n    const ImWchar* src = obj->Text.Data + pos + n;\r\n    while (ImWchar c = *src++)\r\n        *dst++ = c;\r\n    *dst = '\\0';\r\n}\r\n\r\nstatic bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)\r\n{\r\n    const int text_len = obj->CurLenW;\r\n    IM_ASSERT(pos <= text_len);\r\n    if (new_text_len + text_len + 1 > obj->Text.Size)\r\n        return false;\r\n\r\n    const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);\r\n    if (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA)\r\n        return false;\r\n\r\n    ImWchar* text = obj->Text.Data;\r\n    if (pos != text_len)\r\n        memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar));\r\n    memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar));\r\n\r\n    obj->CurLenW += new_text_len;\r\n    obj->CurLenA += new_text_len_utf8;\r\n    obj->Text[obj->CurLenW] = '\\0';\r\n\r\n    return true;\r\n}\r\n\r\n// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)\r\n#define STB_TEXTEDIT_K_LEFT         0x10000 // keyboard input to move cursor left\r\n#define STB_TEXTEDIT_K_RIGHT        0x10001 // keyboard input to move cursor right\r\n#define STB_TEXTEDIT_K_UP           0x10002 // keyboard input to move cursor up\r\n#define STB_TEXTEDIT_K_DOWN         0x10003 // keyboard input to move cursor down\r\n#define STB_TEXTEDIT_K_LINESTART    0x10004 // keyboard input to move cursor to start of line\r\n#define STB_TEXTEDIT_K_LINEEND      0x10005 // keyboard input to move cursor to end of line\r\n#define STB_TEXTEDIT_K_TEXTSTART    0x10006 // keyboard input to move cursor to start of text\r\n#define STB_TEXTEDIT_K_TEXTEND      0x10007 // keyboard input to move cursor to end of text\r\n#define STB_TEXTEDIT_K_DELETE       0x10008 // keyboard input to delete selection or character under cursor\r\n#define STB_TEXTEDIT_K_BACKSPACE    0x10009 // keyboard input to delete selection or character left of cursor\r\n#define STB_TEXTEDIT_K_UNDO         0x1000A // keyboard input to perform undo\r\n#define STB_TEXTEDIT_K_REDO         0x1000B // keyboard input to perform redo\r\n#define STB_TEXTEDIT_K_WORDLEFT     0x1000C // keyboard input to move cursor left one word\r\n#define STB_TEXTEDIT_K_WORDRIGHT    0x1000D // keyboard input to move cursor right one word\r\n#define STB_TEXTEDIT_K_SHIFT        0x20000\r\n\r\n#define STB_TEXTEDIT_IMPLEMENTATION\r\n#include \"stb_textedit.h\"\r\n\r\n}\r\n\r\nvoid ImGuiTextEditState::OnKeyPressed(int key)\r\n{\r\n    stb_textedit_key(this, &StbState, key);\r\n    CursorFollow = true;\r\n    CursorAnimReset();\r\n}\r\n\r\n// Public API to manipulate UTF-8 text\r\n// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)\r\n// FIXME: The existence of this rarely exercised code path is a bit of a nuisance.\r\nvoid ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count)\r\n{\r\n    IM_ASSERT(pos + bytes_count <= BufTextLen);\r\n    char* dst = Buf + pos;\r\n    const char* src = Buf + pos + bytes_count;\r\n    while (char c = *src++)\r\n        *dst++ = c;\r\n    *dst = '\\0';\r\n\r\n    if (CursorPos + bytes_count >= pos)\r\n        CursorPos -= bytes_count;\r\n    else if (CursorPos >= pos)\r\n        CursorPos = pos;\r\n    SelectionStart = SelectionEnd = CursorPos;\r\n    BufDirty = true;\r\n    BufTextLen -= bytes_count;\r\n}\r\n\r\nvoid ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)\r\n{\r\n    const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);\r\n    if (new_text_len + BufTextLen + 1 >= BufSize)\r\n        return;\r\n\r\n    if (BufTextLen != pos)\r\n        memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));\r\n    memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));\r\n    Buf[BufTextLen + new_text_len] = '\\0';\r\n\r\n    if (CursorPos >= pos)\r\n        CursorPos += new_text_len;\r\n    SelectionStart = SelectionEnd = CursorPos;\r\n    BufDirty = true;\r\n    BufTextLen += new_text_len;\r\n}\r\n\r\n// Return false to discard a character.\r\nstatic bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)\r\n{\r\n    unsigned int c = *p_char;\r\n\r\n    if (c < 128 && c != ' ' && !isprint((int)(c & 0xFF)))\r\n    {\r\n        bool pass = false;\r\n        pass |= (c == '\\n' && (flags & ImGuiInputTextFlags_Multiline));\r\n        pass |= (c == '\\t' && (flags & ImGuiInputTextFlags_AllowTabInput));\r\n        if (!pass)\r\n            return false;\r\n    }\r\n\r\n    if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys.\r\n        return false;\r\n\r\n    if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank))\r\n    {\r\n        if (flags & ImGuiInputTextFlags_CharsDecimal)\r\n            if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))\r\n                return false;\r\n\r\n        if (flags & ImGuiInputTextFlags_CharsHexadecimal)\r\n            if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))\r\n                return false;\r\n\r\n        if (flags & ImGuiInputTextFlags_CharsUppercase)\r\n            if (c >= 'a' && c <= 'z')\r\n                *p_char = (c += (unsigned int)('A'-'a'));\r\n\r\n        if (flags & ImGuiInputTextFlags_CharsNoBlank)\r\n            if (ImCharIsSpace(c))\r\n                return false;\r\n    }\r\n\r\n    if (flags & ImGuiInputTextFlags_CallbackCharFilter)\r\n    {\r\n        ImGuiTextEditCallbackData callback_data;\r\n        memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData));\r\n        callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;\r\n        callback_data.EventChar = (ImWchar)c;\r\n        callback_data.Flags = flags;\r\n        callback_data.UserData = user_data;\r\n        if (callback(&callback_data) != 0)\r\n            return false;\r\n        *p_char = callback_data.EventChar;\r\n        if (!callback_data.EventChar)\r\n            return false;\r\n    }\r\n\r\n    return true;\r\n}\r\n\r\n// Edit a string of text\r\n// NB: when active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while active has no effect.\r\n// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188\r\nbool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys)\r\n    IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiIO& io = g.IO;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;\r\n    const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;\r\n    const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;\r\n\r\n    if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn\r\n        BeginGroup();\r\n    const ImGuiID id = window->GetID(label);\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line\r\n    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);\r\n    const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));\r\n\r\n    ImGuiWindow* draw_window = window;\r\n    if (is_multiline)\r\n    {\r\n        if (!BeginChildFrame(id, frame_bb.GetSize()))\r\n        {\r\n            EndChildFrame();\r\n            EndGroup();\r\n            return false;\r\n        }\r\n        draw_window = GetCurrentWindow();\r\n        size.x -= draw_window->ScrollbarSizes.x;\r\n    }\r\n    else\r\n    {\r\n        ItemSize(total_bb, style.FramePadding.y);\r\n        if (!ItemAdd(total_bb, &id))\r\n            return false;\r\n    }\r\n\r\n    // Password pushes a temporary font with only a fallback glyph\r\n    if (is_password)\r\n    {\r\n        const ImFont::Glyph* glyph = g.Font->FindGlyph('*');\r\n        ImFont* password_font = &g.InputTextPasswordFont;\r\n        password_font->FontSize = g.Font->FontSize;\r\n        password_font->Scale = g.Font->Scale;\r\n        password_font->DisplayOffset = g.Font->DisplayOffset;\r\n        password_font->Ascent = g.Font->Ascent;\r\n        password_font->Descent = g.Font->Descent;\r\n        password_font->ContainerAtlas = g.Font->ContainerAtlas;\r\n        password_font->FallbackGlyph = glyph;\r\n        password_font->FallbackXAdvance = glyph->XAdvance;\r\n        IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexXAdvance.empty() && password_font->IndexLookup.empty());\r\n        PushFont(password_font);\r\n    }\r\n\r\n    // NB: we are only allowed to access 'edit_state' if we are the active widget.\r\n    ImGuiTextEditState& edit_state = g.InputTextState;\r\n\r\n    const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0);    // Using completion callback disable keyboard tabbing\r\n    const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);\r\n    const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;\r\n\r\n    const bool hovered = IsHovered(frame_bb, id);\r\n    if (hovered)\r\n    {\r\n        SetHoveredID(id);\r\n        g.MouseCursor = ImGuiMouseCursor_TextInput;\r\n    }\r\n    const bool user_clicked = hovered && io.MouseClicked[0];\r\n    const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive(\"#SCROLLY\");\r\n\r\n    bool clear_active_id = false;\r\n\r\n    bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0;\r\n    if (focus_requested || user_clicked || user_scrolled)\r\n    {\r\n        if (g.ActiveId != id)\r\n        {\r\n            // Start edition\r\n            // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)\r\n            // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)\r\n            const int prev_len_w = edit_state.CurLenW;\r\n            edit_state.Text.resize(buf_size+1);        // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.\r\n            edit_state.InitialText.resize(buf_size+1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.\r\n            ImStrncpy(edit_state.InitialText.Data, buf, edit_state.InitialText.Size);\r\n            const char* buf_end = NULL;\r\n            edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);\r\n            edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.\r\n            edit_state.CursorAnimReset();\r\n\r\n            // Preserve cursor position and undo/redo stack if we come back to same widget\r\n            // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and edit_state.Text (wchar).\r\n            const bool recycle_state = (edit_state.Id == id) && (prev_len_w == edit_state.CurLenW);\r\n            if (recycle_state)\r\n            {\r\n                // Recycle existing cursor/selection/undo stack but clamp position\r\n                // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.\r\n                edit_state.CursorClamp();\r\n            }\r\n            else\r\n            {\r\n                edit_state.Id = id;\r\n                edit_state.ScrollX = 0.0f;\r\n                stb_textedit_initialize_state(&edit_state.StbState, !is_multiline);\r\n                if (!is_multiline && focus_requested_by_code)\r\n                    select_all = true;\r\n            }\r\n            if (flags & ImGuiInputTextFlags_AlwaysInsertMode)\r\n                edit_state.StbState.insert_mode = true;\r\n            if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))\r\n                select_all = true;\r\n        }\r\n        SetActiveID(id, window);\r\n        FocusWindow(window);\r\n    }\r\n    else if (io.MouseClicked[0])\r\n    {\r\n        // Release focus when we click outside\r\n        clear_active_id = true;\r\n    }\r\n\r\n    bool value_changed = false;\r\n    bool enter_pressed = false;\r\n\r\n    if (g.ActiveId == id)\r\n    {\r\n        if (!is_editable && !g.ActiveIdIsJustActivated)\r\n        {\r\n            // When read-only we always use the live data passed to the function\r\n            edit_state.Text.resize(buf_size+1);\r\n            const char* buf_end = NULL;\r\n            edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);\r\n            edit_state.CurLenA = (int)(buf_end - buf);\r\n            edit_state.CursorClamp();\r\n        }\r\n\r\n        edit_state.BufSizeA = buf_size;\r\n\r\n        // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.\r\n        // Down the line we should have a cleaner library-wide concept of Selected vs Active.\r\n        g.ActiveIdAllowOverlap = !io.MouseDown[0];\r\n        g.WantTextInputNextFrame = 1;\r\n\r\n        // Edit in progress\r\n        const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;\r\n        const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));\r\n\r\n        const bool osx_double_click_selects_words = io.OSXBehaviors;      // OS X style: Double click selects by word instead of selecting whole text\r\n        if (select_all || (hovered && !osx_double_click_selects_words && io.MouseDoubleClicked[0]))\r\n        {\r\n            edit_state.SelectAll();\r\n            edit_state.SelectedAllMouseLock = true;\r\n        }\r\n        else if (hovered && osx_double_click_selects_words && io.MouseDoubleClicked[0])\r\n        {\r\n            // Select a word only, OS X style (by simulating keystrokes)\r\n            edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);\r\n            edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);\r\n        }\r\n        else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock)\r\n        {\r\n            stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y);\r\n            edit_state.CursorAnimReset();\r\n        }\r\n        else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))\r\n        {\r\n            stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y);\r\n            edit_state.CursorAnimReset();\r\n            edit_state.CursorFollow = true;\r\n        }\r\n        if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])\r\n            edit_state.SelectedAllMouseLock = false;\r\n\r\n        if (io.InputCharacters[0])\r\n        {\r\n            // Process text input (before we check for Return because using some IME will effectively send a Return?)\r\n            // We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - to input certain characters.\r\n            if (!(io.KeyCtrl && !io.KeyAlt) && is_editable)\r\n            {\r\n                for (int n = 0; n < IM_ARRAYSIZE(io.InputCharacters) && io.InputCharacters[n]; n++)\r\n                    if (unsigned int c = (unsigned int)io.InputCharacters[n])\r\n                    {\r\n                        // Insert character if they pass filtering\r\n                        if (!InputTextFilterCharacter(&c, flags, callback, user_data))\r\n                            continue;\r\n                        edit_state.OnKeyPressed((int)c);\r\n                    }\r\n            }\r\n\r\n            // Consume characters\r\n            memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));\r\n        }\r\n    }\r\n\r\n    bool cancel_edit = false;\r\n    if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id)\r\n    {\r\n        // Handle key-presses\r\n        const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);\r\n        const bool is_shortcut_key_only = (io.OSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl\r\n        const bool is_wordmove_key_down = io.OSXBehaviors ? io.KeyAlt : io.KeyCtrl;                     // OS X style: Text editing cursor movement using Alt instead of Ctrl\r\n        const bool is_startend_key_down = io.OSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt;  // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End\r\n\r\n        if (IsKeyPressedMap(ImGuiKey_LeftArrow))                        { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_RightArrow))                  { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline)     { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline)   { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_Home))                        { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_End))                         { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable)       { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }\r\n        else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable)\r\n        {\r\n            if (!edit_state.HasSelection())\r\n            {\r\n                if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT);\r\n                else if (io.OSXBehaviors && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT);\r\n            }\r\n            edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);\r\n        }\r\n        else if (IsKeyPressedMap(ImGuiKey_Enter))\r\n        {\r\n            bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;\r\n            if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))\r\n            {\r\n                enter_pressed = clear_active_id = true;\r\n            }\r\n            else if (is_editable)\r\n            {\r\n                unsigned int c = '\\n'; // Insert new line\r\n                if (InputTextFilterCharacter(&c, flags, callback, user_data))\r\n                    edit_state.OnKeyPressed((int)c);\r\n            }\r\n        }\r\n        else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && !io.KeyAlt && is_editable)\r\n        {\r\n            unsigned int c = '\\t'; // Insert TAB\r\n            if (InputTextFilterCharacter(&c, flags, callback, user_data))\r\n                edit_state.OnKeyPressed((int)c);\r\n        }\r\n        else if (IsKeyPressedMap(ImGuiKey_Escape))                                      { clear_active_id = cancel_edit = true; }\r\n        else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable)    { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); }\r\n        else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable)    { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); }\r\n        else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A))                   { edit_state.SelectAll(); edit_state.CursorFollow = true; }\r\n        else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection()))\r\n        {\r\n            // Cut, Copy\r\n            const bool cut = IsKeyPressedMap(ImGuiKey_X);\r\n            if (cut && !edit_state.HasSelection())\r\n                edit_state.SelectAll();\r\n\r\n            if (io.SetClipboardTextFn)\r\n            {\r\n                const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;\r\n                const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW;\r\n                edit_state.TempTextBuffer.resize((ie-ib) * 4 + 1);\r\n                ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data+ib, edit_state.Text.Data+ie);\r\n                SetClipboardText(edit_state.TempTextBuffer.Data);\r\n            }\r\n\r\n            if (cut)\r\n            {\r\n                edit_state.CursorFollow = true;\r\n                stb_textedit_cut(&edit_state, &edit_state.StbState);\r\n            }\r\n        }\r\n        else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V) && is_editable)\r\n        {\r\n            // Paste\r\n            if (const char* clipboard = GetClipboardText())\r\n            {\r\n                // Filter pasted buffer\r\n                const int clipboard_len = (int)strlen(clipboard);\r\n                ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar));\r\n                int clipboard_filtered_len = 0;\r\n                for (const char* s = clipboard; *s; )\r\n                {\r\n                    unsigned int c;\r\n                    s += ImTextCharFromUtf8(&c, s, NULL);\r\n                    if (c == 0)\r\n                        break;\r\n                    if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, user_data))\r\n                        continue;\r\n                    clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;\r\n                }\r\n                clipboard_filtered[clipboard_filtered_len] = 0;\r\n                if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation\r\n                {\r\n                    stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);\r\n                    edit_state.CursorFollow = true;\r\n                }\r\n                ImGui::MemFree(clipboard_filtered);\r\n            }\r\n        }\r\n    }\r\n\r\n    if (g.ActiveId == id)\r\n    {\r\n        if (cancel_edit)\r\n        {\r\n            // Restore initial value\r\n            if (is_editable)\r\n            {\r\n                ImStrncpy(buf, edit_state.InitialText.Data, buf_size);\r\n                value_changed = true;\r\n            }\r\n        }\r\n\r\n        // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.\r\n        // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage.\r\n        bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);\r\n        if (apply_edit_back_to_user_buffer)\r\n        {\r\n            // Apply new value immediately - copy modified buffer back\r\n            // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer\r\n            // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.\r\n            // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.\r\n            if (is_editable)\r\n            {\r\n                edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);\r\n                ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data, NULL);\r\n            }\r\n\r\n            // User callback\r\n            if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0)\r\n            {\r\n                IM_ASSERT(callback != NULL);\r\n\r\n                // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.\r\n                ImGuiInputTextFlags event_flag = 0;\r\n                ImGuiKey event_key = ImGuiKey_COUNT;\r\n                if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab))\r\n                {\r\n                    event_flag = ImGuiInputTextFlags_CallbackCompletion;\r\n                    event_key = ImGuiKey_Tab;\r\n                }\r\n                else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow))\r\n                {\r\n                    event_flag = ImGuiInputTextFlags_CallbackHistory;\r\n                    event_key = ImGuiKey_UpArrow;\r\n                }\r\n                else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow))\r\n                {\r\n                    event_flag = ImGuiInputTextFlags_CallbackHistory;\r\n                    event_key = ImGuiKey_DownArrow;\r\n                }\r\n                else if (flags & ImGuiInputTextFlags_CallbackAlways)\r\n                    event_flag = ImGuiInputTextFlags_CallbackAlways;\r\n\r\n                if (event_flag)\r\n                {\r\n                    ImGuiTextEditCallbackData callback_data;\r\n                    memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData));\r\n                    callback_data.EventFlag = event_flag;\r\n                    callback_data.Flags = flags;\r\n                    callback_data.UserData = user_data;\r\n                    callback_data.ReadOnly = !is_editable;\r\n\r\n                    callback_data.EventKey = event_key;\r\n                    callback_data.Buf = edit_state.TempTextBuffer.Data;\r\n                    callback_data.BufTextLen = edit_state.CurLenA;\r\n                    callback_data.BufSize = edit_state.BufSizeA;\r\n                    callback_data.BufDirty = false;\r\n\r\n                    // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)\r\n                    ImWchar* text = edit_state.Text.Data;\r\n                    const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor);\r\n                    const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start);\r\n                    const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end);\r\n\r\n                    // Call user code\r\n                    callback(&callback_data);\r\n\r\n                    // Read back what user may have modified\r\n                    IM_ASSERT(callback_data.Buf == edit_state.TempTextBuffer.Data);  // Invalid to modify those fields\r\n                    IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA);\r\n                    IM_ASSERT(callback_data.Flags == flags);\r\n                    if (callback_data.CursorPos != utf8_cursor_pos)            edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos);\r\n                    if (callback_data.SelectionStart != utf8_selection_start)  edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart);\r\n                    if (callback_data.SelectionEnd != utf8_selection_end)      edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd);\r\n                    if (callback_data.BufDirty)\r\n                    {\r\n                        IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!\r\n                        edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, callback_data.Buf, NULL);\r\n                        edit_state.CurLenA = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()\r\n                        edit_state.CursorAnimReset();\r\n                    }\r\n                }\r\n            }\r\n\r\n            // Copy back to user buffer\r\n            if (is_editable && strcmp(edit_state.TempTextBuffer.Data, buf) != 0)\r\n            {\r\n                ImStrncpy(buf, edit_state.TempTextBuffer.Data, buf_size);\r\n                value_changed = true;\r\n            }\r\n        }\r\n    }\r\n\r\n    // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)\r\n    if (clear_active_id && g.ActiveId == id)\r\n        ClearActiveID();\r\n\r\n    // Render\r\n    // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on.\r\n    const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; \r\n\r\n    if (!is_multiline)\r\n        RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);\r\n\r\n    const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size\r\n    ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;\r\n    ImVec2 text_size(0.f, 0.f);\r\n    const bool is_currently_scrolling = (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetIDNoKeepAlive(\"#SCROLLY\"));\r\n    if (g.ActiveId == id || is_currently_scrolling)\r\n    {\r\n        edit_state.CursorAnim += io.DeltaTime;\r\n\r\n        // This is going to be messy. We need to:\r\n        // - Display the text (this alone can be more easily clipped)\r\n        // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)\r\n        // - Measure text height (for scrollbar)\r\n        // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)\r\n        // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.\r\n        const ImWchar* text_begin = edit_state.Text.Data;\r\n        ImVec2 cursor_offset, select_start_offset;\r\n\r\n        {\r\n            // Count lines + find lines numbers straddling 'cursor' and 'select_start' position.\r\n            const ImWchar* searches_input_ptr[2];\r\n            searches_input_ptr[0] = text_begin + edit_state.StbState.cursor;\r\n            searches_input_ptr[1] = NULL;\r\n            int searches_remaining = 1;\r\n            int searches_result_line_number[2] = { -1, -999 };\r\n            if (edit_state.StbState.select_start != edit_state.StbState.select_end)\r\n            {\r\n                searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);\r\n                searches_result_line_number[1] = -1;\r\n                searches_remaining++;\r\n            }\r\n\r\n            // Iterate all lines to find our line numbers\r\n            // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.\r\n            searches_remaining += is_multiline ? 1 : 0;\r\n            int line_count = 0;\r\n            for (const ImWchar* s = text_begin; *s != 0; s++)\r\n                if (*s == '\\n')\r\n                {\r\n                    line_count++;\r\n                    if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; }\r\n                    if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; }\r\n                }\r\n            line_count++;\r\n            if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count;\r\n            if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count;\r\n\r\n            // Calculate 2d position by finding the beginning of the line and measuring distance\r\n            cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;\r\n            cursor_offset.y = searches_result_line_number[0] * g.FontSize;\r\n            if (searches_result_line_number[1] >= 0)\r\n            {\r\n                select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;\r\n                select_start_offset.y = searches_result_line_number[1] * g.FontSize;\r\n            }\r\n\r\n            // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)\r\n            if (is_multiline)\r\n                text_size = ImVec2(size.x, line_count * g.FontSize);\r\n        }\r\n\r\n        // Scroll\r\n        if (edit_state.CursorFollow)\r\n        {\r\n            // Horizontal scroll in chunks of quarter width\r\n            if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll))\r\n            {\r\n                const float scroll_increment_x = size.x * 0.25f;\r\n                if (cursor_offset.x < edit_state.ScrollX)\r\n                    edit_state.ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x);\r\n                else if (cursor_offset.x - size.x >= edit_state.ScrollX)\r\n                    edit_state.ScrollX = (float)(int)(cursor_offset.x - size.x + scroll_increment_x);\r\n            }\r\n            else\r\n            {\r\n                edit_state.ScrollX = 0.0f;\r\n            }\r\n\r\n            // Vertical scroll\r\n            if (is_multiline)\r\n            {\r\n                float scroll_y = draw_window->Scroll.y;\r\n                if (cursor_offset.y - g.FontSize < scroll_y)\r\n                    scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);\r\n                else if (cursor_offset.y - size.y >= scroll_y)\r\n                    scroll_y = cursor_offset.y - size.y;\r\n                draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y);   // To avoid a frame of lag\r\n                draw_window->Scroll.y = scroll_y;\r\n                render_pos.y = draw_window->DC.CursorPos.y;\r\n            }\r\n        }\r\n        edit_state.CursorFollow = false;\r\n        const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f);\r\n\r\n        // Draw selection\r\n        if (edit_state.StbState.select_start != edit_state.StbState.select_end)\r\n        {\r\n            const ImWchar* text_selected_begin = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);\r\n            const ImWchar* text_selected_end = text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end);\r\n\r\n            float bg_offy_up = is_multiline ? 0.0f : -1.0f;    // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.\r\n            float bg_offy_dn = is_multiline ? 0.0f : 2.0f;\r\n            ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg);\r\n            ImVec2 rect_pos = render_pos + select_start_offset - render_scroll;\r\n            for (const ImWchar* p = text_selected_begin; p < text_selected_end; )\r\n            {\r\n                if (rect_pos.y > clip_rect.w + g.FontSize)\r\n                    break;\r\n                if (rect_pos.y < clip_rect.y)\r\n                {\r\n                    while (p < text_selected_end)\r\n                        if (*p++ == '\\n')\r\n                            break;\r\n                }\r\n                else\r\n                {\r\n                    ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);\r\n                    if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * 0.50f); // So we can see selected empty lines\r\n                    ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn));\r\n                    rect.ClipWith(clip_rect);\r\n                    if (rect.Overlaps(clip_rect))\r\n                        draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);\r\n                }\r\n                rect_pos.x = render_pos.x - render_scroll.x;\r\n                rect_pos.y += g.FontSize;\r\n            }\r\n        }\r\n\r\n        draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect);\r\n\r\n        // Draw blinking cursor\r\n        bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f;\r\n        ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll;\r\n        ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f);\r\n        if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))\r\n            draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));\r\n\r\n        // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)\r\n        if (is_editable)\r\n            g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);\r\n    }\r\n    else\r\n    {\r\n        // Render text only\r\n        const char* buf_end = NULL;\r\n        if (is_multiline)\r\n            text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width\r\n        draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, is_multiline ? NULL : &clip_rect);\r\n    }\r\n\r\n    if (is_multiline)\r\n    {\r\n        Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line\r\n        EndChildFrame();\r\n        EndGroup();\r\n    }\r\n\r\n    if (is_password)\r\n        PopFont();\r\n\r\n    // Log as text\r\n    if (g.LogEnabled && !is_password)\r\n        LogRenderedText(render_pos, buf_display, NULL);\r\n\r\n    if (label_size.x > 0)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);\r\n\r\n    if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)\r\n        return enter_pressed;\r\n    else\r\n        return value_changed;\r\n}\r\n\r\nbool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)\r\n{\r\n    IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()\r\n    return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);\r\n}\r\n\r\nbool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)\r\n{\r\n    return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);\r\n}\r\n\r\n// NB: scalar_format here must be a simple \"%xx\" format string with no prefix/suffix (unlike the Drag/Slider functions \"display_format\" argument)\r\nbool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n\r\n    BeginGroup();\r\n    PushID(label);\r\n    const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding*2.0f;\r\n    if (step_ptr)\r\n        PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2));\r\n\r\n    char buf[64];\r\n    DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf));\r\n\r\n    bool value_changed = false;\r\n    if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal))\r\n        extra_flags |= ImGuiInputTextFlags_CharsDecimal;\r\n    extra_flags |= ImGuiInputTextFlags_AutoSelectAll;\r\n    if (InputText(\"\", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + \"\" gives us the expected ID from outside point of view\r\n        value_changed = DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, scalar_format);\r\n\r\n    // Step buttons\r\n    if (step_ptr)\r\n    {\r\n        PopItemWidth();\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n        if (ButtonEx(\"-\", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))\r\n        {\r\n            DataTypeApplyOp(data_type, '-', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr);\r\n            value_changed = true;\r\n        }\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n        if (ButtonEx(\"+\", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))\r\n        {\r\n            DataTypeApplyOp(data_type, '+', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr);\r\n            value_changed = true;\r\n        }\r\n    }\r\n    PopID();\r\n\r\n    if (label_size.x > 0)\r\n    {\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n        RenderText(ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + style.FramePadding.y), label);\r\n        ItemSize(label_size, style.FramePadding.y);\r\n    }\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags)\r\n{\r\n    char display_format[16];\r\n    if (decimal_precision < 0)\r\n        strcpy(display_format, \"%f\");      // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1\r\n    else\r\n        ImFormatString(display_format, IM_ARRAYSIZE(display_format), \"%%.%df\", decimal_precision);\r\n    return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags);\r\n}\r\n\r\nbool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags)\r\n{\r\n    // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes.\r\n    const char* scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? \"%08X\" : \"%d\";\r\n    return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), scalar_format, extra_flags);\r\n}\r\n\r\nbool ImGui::InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    bool value_changed = false;\r\n    BeginGroup();\r\n    PushID(label);\r\n    PushMultiItemsWidths(components);\r\n    for (int i = 0; i < components; i++)\r\n    {\r\n        PushID(i);\r\n        value_changed |= InputFloat(\"##v\", &v[i], 0, 0, decimal_precision, extra_flags);\r\n        SameLine(0, g.Style.ItemInnerSpacing.x);\r\n        PopID();\r\n        PopItemWidth();\r\n    }\r\n    PopID();\r\n\r\n    window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags)\r\n{\r\n    return InputFloatN(label, v, 2, decimal_precision, extra_flags);\r\n}\r\n\r\nbool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags)\r\n{\r\n    return InputFloatN(label, v, 3, decimal_precision, extra_flags);\r\n}\r\n\r\nbool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags)\r\n{\r\n    return InputFloatN(label, v, 4, decimal_precision, extra_flags);\r\n}\r\n\r\nbool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    bool value_changed = false;\r\n    BeginGroup();\r\n    PushID(label);\r\n    PushMultiItemsWidths(components);\r\n    for (int i = 0; i < components; i++)\r\n    {\r\n        PushID(i);\r\n        value_changed |= InputInt(\"##v\", &v[i], 0, 0, extra_flags);\r\n        SameLine(0, g.Style.ItemInnerSpacing.x);\r\n        PopID();\r\n        PopItemWidth();\r\n    }\r\n    PopID();\r\n\r\n    window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);\r\n    TextUnformatted(label, FindRenderedTextEnd(label));\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags)\r\n{\r\n    return InputIntN(label, v, 2, extra_flags);\r\n}\r\n\r\nbool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags)\r\n{\r\n    return InputIntN(label, v, 3, extra_flags);\r\n}\r\n\r\nbool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags)\r\n{\r\n    return InputIntN(label, v, 4, extra_flags);\r\n}\r\n\r\nstatic bool Items_ArrayGetter(void* data, int idx, const char** out_text)\r\n{\r\n    const char* const* items = (const char* const*)data;\r\n    if (out_text)\r\n        *out_text = items[idx];\r\n    return true;\r\n}\r\n\r\nstatic bool Items_SingleStringGetter(void* data, int idx, const char** out_text)\r\n{\r\n    // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.\r\n    const char* items_separated_by_zeros = (const char*)data;\r\n    int items_count = 0;\r\n    const char* p = items_separated_by_zeros;\r\n    while (*p)\r\n    {\r\n        if (idx == items_count)\r\n            break;\r\n        p += strlen(p) + 1;\r\n        items_count++;\r\n    }\r\n    if (!*p)\r\n        return false;\r\n    if (out_text)\r\n        *out_text = p;\r\n    return true;\r\n}\r\n\r\n// Combo box helper allowing to pass an array of strings.\r\nbool ImGui::Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items)\r\n{\r\n    const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);\r\n    return value_changed;\r\n}\r\n\r\n// Combo box helper allowing to pass all items in a single string.\r\nbool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)\r\n{\r\n    int items_count = 0;\r\n    const char* p = items_separated_by_zeros;       // FIXME-OPT: Avoid computing this, or at least only when combo is open\r\n    while (*p)\r\n    {\r\n        p += strlen(p) + 1;\r\n        items_count++;\r\n    }\r\n    bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::BeginCombo(const char* label, const char* preview_value, float popup_opened_height)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n    const float w = CalcItemWidth();\r\n\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));\r\n    const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));\r\n    ItemSize(total_bb, style.FramePadding.y);\r\n    if (!ItemAdd(total_bb, &id))\r\n        return false;\r\n\r\n    const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f);\r\n    const bool hovered = IsHovered(frame_bb, id);\r\n    bool popup_open = IsPopupOpen(id);\r\n\r\n    const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));\r\n    RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);\r\n    RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING\r\n    RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true);\r\n\r\n    if (preview_value != NULL)\r\n        RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f));\r\n\r\n    if (label_size.x > 0)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);\r\n\r\n    bool popup_toggled = false;\r\n    if (hovered)\r\n    {\r\n        SetHoveredID(id);\r\n        if (g.IO.MouseClicked[0])\r\n        {\r\n            ClearActiveID();\r\n            popup_toggled = true;\r\n        }\r\n    }\r\n    if (popup_toggled)\r\n    {\r\n        if (popup_open)\r\n        {\r\n            ClosePopup(id);\r\n        }\r\n        else\r\n        {\r\n            FocusWindow(window);\r\n            OpenPopupEx(id, false);\r\n        }\r\n        popup_open = !popup_open;\r\n    }\r\n\r\n    if (!popup_open)\r\n        return false;\r\n\r\n    float popup_y1 = frame_bb.Max.y;\r\n    float popup_y2 = ImClamp(popup_y1 + popup_opened_height, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y);\r\n    if ((popup_y2 - popup_y1) < ImMin(popup_opened_height, frame_bb.Min.y - style.DisplaySafeAreaPadding.y))\r\n    {\r\n        // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement)\r\n        popup_y1 = ImClamp(frame_bb.Min.y - popup_opened_height, style.DisplaySafeAreaPadding.y, frame_bb.Min.y);\r\n        popup_y2 = frame_bb.Min.y;\r\n    }\r\n    ImRect popup_rect(ImVec2(frame_bb.Min.x, popup_y1), ImVec2(frame_bb.Max.x, popup_y2));\r\n    SetNextWindowPos(popup_rect.Min);\r\n    SetNextWindowSize(popup_rect.GetSize());\r\n    PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);\r\n\r\n    const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0);\r\n    if (!BeginPopupEx(id, flags))\r\n    {\r\n        IM_ASSERT(0);   // This should never happen as we tested for IsPopupOpen() above\r\n        return false;\r\n    }\r\n    Spacing();\r\n\r\n    return true;\r\n}\r\n\r\nvoid ImGui::EndCombo()\r\n{\r\n    EndPopup();\r\n    PopStyleVar();\r\n}\r\n\r\n// Combo box function.\r\nbool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    const char* preview_text = NULL;\r\n    if (*current_item >= 0 && *current_item < items_count)\r\n        items_getter(data, *current_item, &preview_text);\r\n\r\n    // Size default to hold ~7 items\r\n    if (height_in_items < 0)\r\n        height_in_items = 7;\r\n    float popup_opened_height = (g.FontSize + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3);\r\n\r\n    if (!BeginCombo(label, preview_text, popup_opened_height))\r\n        return false;\r\n\r\n    // Display items\r\n    // FIXME-OPT: Use clipper\r\n    bool value_changed = false;\r\n    for (int i = 0; i < items_count; i++)\r\n    {\r\n        PushID((void*)(intptr_t)i);\r\n        const bool item_selected = (i == *current_item);\r\n        const char* item_text;\r\n        if (!items_getter(data, i, &item_text))\r\n            item_text = \"*Unknown item*\";\r\n        if (Selectable(item_text, item_selected))\r\n        {\r\n            value_changed = true;\r\n            *current_item = i;\r\n        }\r\n        if (item_selected && IsWindowAppearing())\r\n            SetScrollHere();\r\n        PopID();\r\n    }\r\n\r\n    EndCombo();\r\n    return value_changed;\r\n}\r\n\r\n// Tip: pass an empty label (e.g. \"##dummy\") then you can use the space to draw other text or image.\r\n// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID.\r\nbool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n\r\n    if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) // FIXME-OPT: Avoid if vertically clipped.\r\n        PopClipRect();\r\n\r\n    ImGuiID id = window->GetID(label);\r\n    ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);\r\n    ImVec2 pos = window->DC.CursorPos;\r\n    pos.y += window->DC.CurrentLineTextBaseOffset;\r\n    ImRect bb(pos, pos + size);\r\n    ItemSize(bb);\r\n\r\n    // Fill horizontal space.\r\n    ImVec2 window_padding = window->WindowPadding;\r\n    float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x;\r\n    float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x);\r\n    ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y);\r\n    ImRect bb_with_spacing(pos, pos + size_draw);\r\n    if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth))\r\n        bb_with_spacing.Max.x += window_padding.x;\r\n\r\n    // Selectables are tightly packed together, we extend the box to cover spacing between selectable.\r\n    float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f);\r\n    float spacing_U = (float)(int)(style.ItemSpacing.y * 0.5f);\r\n    float spacing_R = style.ItemSpacing.x - spacing_L;\r\n    float spacing_D = style.ItemSpacing.y - spacing_U;\r\n    bb_with_spacing.Min.x -= spacing_L;\r\n    bb_with_spacing.Min.y -= spacing_U;\r\n    bb_with_spacing.Max.x += spacing_R;\r\n    bb_with_spacing.Max.y += spacing_D;\r\n    if (!ItemAdd(bb_with_spacing, &id))\r\n    {\r\n        if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1)\r\n            PushColumnClipRect();\r\n        return false;\r\n    }\r\n\r\n    ImGuiButtonFlags button_flags = 0;\r\n    if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick;\r\n    if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnClick|ImGuiButtonFlags_PressedOnRelease;\r\n    if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled;\r\n    if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, button_flags);\r\n    if (flags & ImGuiSelectableFlags_Disabled)\r\n        selected = false;\r\n\r\n    // Render\r\n    if (hovered || selected)\r\n    {\r\n        const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);\r\n        RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f);\r\n    }\r\n\r\n    if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1)\r\n    {\r\n        PushColumnClipRect();\r\n        bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x);\r\n    }\r\n\r\n    if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);\r\n    RenderTextClipped(bb.Min, bb_with_spacing.Max, label, NULL, &label_size, ImVec2(0.0f,0.0f));\r\n    if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();\r\n\r\n    // Automatically close popups\r\n    if (pressed && !(flags & ImGuiSelectableFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))\r\n        CloseCurrentPopup();\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)\r\n{\r\n    if (Selectable(label, *p_selected, flags, size_arg))\r\n    {\r\n        *p_selected = !*p_selected;\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n// Helper to calculate the size of a listbox and display a label on the right.\r\n// Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label \"##empty\"\r\nbool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    const ImGuiStyle& style = GetStyle();\r\n    const ImGuiID id = GetID(label);\r\n    const ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n\r\n    // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.\r\n    ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y);\r\n    ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));\r\n    ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);\r\n    ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));\r\n    window->DC.LastItemRect = bb;\r\n\r\n    BeginGroup();\r\n    if (label_size.x > 0)\r\n        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);\r\n\r\n    BeginChildFrame(id, frame_bb.GetSize());\r\n    return true;\r\n}\r\n\r\nbool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)\r\n{\r\n    // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.\r\n    // However we don't add +0.40f if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size.\r\n    // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution.\r\n    if (height_in_items < 0)\r\n        height_in_items = ImMin(items_count, 7);\r\n    float height_in_items_f = height_in_items < items_count ? (height_in_items + 0.40f) : (height_in_items + 0.00f);\r\n\r\n    // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild().\r\n    ImVec2 size;\r\n    size.x = 0.0f;\r\n    size.y = GetTextLineHeightWithSpacing() * height_in_items_f + GetStyle().ItemSpacing.y;\r\n    return ListBoxHeader(label, size);\r\n}\r\n\r\nvoid ImGui::ListBoxFooter()\r\n{\r\n    ImGuiWindow* parent_window = GetParentWindow();\r\n    const ImRect bb = parent_window->DC.LastItemRect;\r\n    const ImGuiStyle& style = GetStyle();\r\n\r\n    EndChildFrame();\r\n\r\n    // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect)\r\n    // We call SameLine() to restore DC.CurrentLine* data\r\n    SameLine();\r\n    parent_window->DC.CursorPos = bb.Min;\r\n    ItemSize(bb, style.FramePadding.y);\r\n    EndGroup();\r\n}\r\n\r\nbool ImGui::ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_items)\r\n{\r\n    const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)\r\n{\r\n    if (!ListBoxHeader(label, items_count, height_in_items))\r\n        return false;\r\n\r\n    // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper.\r\n    bool value_changed = false;\r\n    ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.\r\n    while (clipper.Step())\r\n        for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)\r\n        {\r\n            const bool item_selected = (i == *current_item);\r\n            const char* item_text;\r\n            if (!items_getter(data, i, &item_text))\r\n                item_text = \"*Unknown item*\";\r\n\r\n            PushID(i);\r\n            if (Selectable(item_text, item_selected))\r\n            {\r\n                *current_item = i;\r\n                value_changed = true;\r\n            }\r\n            PopID();\r\n        }\r\n    ListBoxFooter();\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    ImVec2 pos = window->DC.CursorPos;\r\n    ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n    ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f);\r\n    float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame\r\n    float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);\r\n\r\n    bool pressed = Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f));\r\n    if (shortcut_size.x > 0.0f)\r\n    {\r\n        PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);\r\n        RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);\r\n        PopStyleColor();\r\n    }\r\n\r\n    if (selected)\r\n        RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled));\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled)\r\n{\r\n    if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled))\r\n    {\r\n        if (p_selected)\r\n            *p_selected = !*p_selected;\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\nbool ImGui::BeginMainMenuBar()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    SetNextWindowPos(ImVec2(0.0f, 0.0f));\r\n    SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.FontBaseSize + g.Style.FramePadding.y * 2.0f));\r\n    PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);\r\n    PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0));\r\n    if (!Begin(\"##MainMenuBar\", NULL, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_MenuBar)\r\n        || !BeginMenuBar())\r\n    {\r\n        End();\r\n        PopStyleVar(2);\r\n        return false;\r\n    }\r\n    g.CurrentWindow->DC.MenuBarOffsetX += g.Style.DisplaySafeAreaPadding.x;\r\n    return true;\r\n}\r\n\r\nvoid ImGui::EndMainMenuBar()\r\n{\r\n    EndMenuBar();\r\n    End();\r\n    PopStyleVar(2);\r\n}\r\n\r\nbool ImGui::BeginMenuBar()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n    if (!(window->Flags & ImGuiWindowFlags_MenuBar))\r\n        return false;\r\n\r\n    IM_ASSERT(!window->DC.MenuBarAppending);\r\n    BeginGroup(); // Save position\r\n    PushID(\"##menubar\");\r\n    ImRect rect = window->MenuBarRect();\r\n    PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false);\r\n    window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y);\r\n    window->DC.LayoutType = ImGuiLayoutType_Horizontal;\r\n    window->DC.MenuBarAppending = true;\r\n    AlignFirstTextHeightToWidgets();\r\n    return true;\r\n}\r\n\r\nvoid ImGui::EndMenuBar()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar);\r\n    IM_ASSERT(window->DC.MenuBarAppending);\r\n    PopClipRect();\r\n    PopID();\r\n    window->DC.MenuBarOffsetX = window->DC.CursorPos.x - window->MenuBarRect().Min.x;\r\n    window->DC.GroupStack.back().AdvanceCursor = false;\r\n    EndGroup();\r\n    window->DC.LayoutType = ImGuiLayoutType_Vertical;\r\n    window->DC.MenuBarAppending = false;\r\n}\r\n\r\nbool ImGui::BeginMenu(const char* label, bool enabled)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const ImGuiID id = window->GetID(label);\r\n\r\n    ImVec2 label_size = CalcTextSize(label, NULL, true);\r\n\r\n    bool pressed;\r\n    bool menu_is_open = IsPopupOpen(id);\r\n    bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID(\"##menus\"));\r\n    ImGuiWindow* backed_nav_window = g.NavWindow;\r\n    if (menuset_is_open)\r\n        g.NavWindow = window;  // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)\r\n\r\n    // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestPopupWindowPos).\r\n    ImVec2 popup_pos, pos = window->DC.CursorPos;\r\n    if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)\r\n    {\r\n        popup_pos = ImVec2(pos.x - window->WindowPadding.x, pos.y - style.FramePadding.y + window->MenuBarHeight());\r\n        window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);\r\n        PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f);\r\n        float w = label_size.x;\r\n        pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));\r\n        PopStyleVar();\r\n        SameLine();\r\n        window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);\r\n    }\r\n    else\r\n    {\r\n        popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);\r\n        float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame\r\n        float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);\r\n        pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));\r\n        if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);\r\n        RenderCollapseTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), false);\r\n        if (!enabled) PopStyleColor();\r\n    }\r\n\r\n    bool hovered = enabled && IsHovered(window->DC.LastItemRect, id);\r\n\r\n    if (menuset_is_open)\r\n        g.NavWindow = backed_nav_window;\r\n\r\n    bool want_open = false, want_close = false;\r\n    if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))\r\n    {\r\n        // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.\r\n        bool moving_within_opened_triangle = false;\r\n        if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window)\r\n        {\r\n            if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window)\r\n            {\r\n                ImRect next_window_rect = next_window->Rect();\r\n                ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;\r\n                ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();\r\n                ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();\r\n                float extra = ImClamp(fabsf(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack.\r\n                ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f;   // to avoid numerical issues\r\n                tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f);            // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?\r\n                tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);\r\n                moving_within_opened_triangle = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);\r\n                //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); window->DrawList->PopClipRect(); // Debug\r\n            }\r\n        }\r\n\r\n        want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle);\r\n        want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed);\r\n    }\r\n    else if (menu_is_open && pressed && menuset_is_open) // Menu bar: click an open menu again to close it\r\n    {\r\n        want_close = true;\r\n        want_open = menu_is_open = false;\r\n    }\r\n    else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others\r\n    {\r\n        want_open = true;\r\n    }\r\n\r\n    if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu(\"options\", has_object)) { ..use object.. }'\r\n        want_close = true;\r\n    if (want_close && IsPopupOpen(id))\r\n        ClosePopupToLevel(GImGui->CurrentPopupStack.Size);\r\n\r\n    if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size)\r\n    {\r\n        // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.\r\n        OpenPopup(label);\r\n        return false;\r\n    }\r\n\r\n    menu_is_open |= want_open;\r\n    if (want_open)\r\n        OpenPopup(label);\r\n\r\n    if (menu_is_open)\r\n    {\r\n        SetNextWindowPos(popup_pos, ImGuiCond_Always);\r\n        ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu);\r\n        menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)\r\n    }\r\n\r\n    return menu_is_open;\r\n}\r\n\r\nvoid ImGui::EndMenu()\r\n{\r\n    EndPopup();\r\n}\r\n\r\n// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.\r\nvoid ImGui::ColorTooltip(const char* text, const float col[4], ImGuiColorEditFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n\r\n    int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);\r\n    BeginTooltipEx(true);\r\n    \r\n    const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;\r\n    if (text_end > text)\r\n    {\r\n        TextUnformatted(text, text_end);\r\n        Separator();\r\n    }\r\n\r\n    ImVec2 sz(g.FontSize * 3, g.FontSize * 3);\r\n    ColorButton(\"##preview\", ImVec4(col[0], col[1], col[2], col[3]), (flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz);\r\n    SameLine();\r\n    if (flags & ImGuiColorEditFlags_NoAlpha)\r\n        Text(\"#%02X%02X%02X\\nR: %d, G: %d, B: %d\\n(%.3f, %.3f, %.3f)\", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);\r\n    else\r\n        Text(\"#%02X%02X%02X%02X\\nR:%d, G:%d, B:%d, A:%d\\n(%.3f, %.3f, %.3f, %.3f)\", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]);\r\n    EndTooltip();\r\n}\r\n\r\nstatic inline float ColorSquareSize()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.FontSize + g.Style.FramePadding.y * 2.0f;\r\n}\r\n\r\nstatic inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b)\r\n{\r\n    float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;\r\n    int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t);\r\n    int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t);\r\n    int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t);\r\n    return IM_COL32(r, g, b, 0xFF);\r\n}\r\n\r\n// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.\r\n// I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether.\r\nvoid ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)\r\n    {\r\n        ImU32 col_bg1 = GetColorU32(ImAlphaBlendColor(IM_COL32(204,204,204,255), col));\r\n        ImU32 col_bg2 = GetColorU32(ImAlphaBlendColor(IM_COL32(128,128,128,255), col));\r\n        window->DrawList->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags);\r\n\r\n        int yi = 0;\r\n        for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)\r\n        {\r\n            float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);\r\n            if (y2 <= y1)\r\n                continue;\r\n            for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)\r\n            {\r\n                float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);\r\n                if (x2 <= x1)\r\n                    continue;\r\n                int rounding_corners_flags_cell = 0;\r\n                if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImGuiCorner_TopLeft;    if (x2 >= p_max.x) rounding_corners_flags_cell |= ImGuiCorner_TopRight; }\r\n                if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImGuiCorner_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImGuiCorner_BotRight; }\r\n                rounding_corners_flags_cell &= rounding_corners_flags;\r\n                window->DrawList->AddRectFilled(ImVec2(x1,y1), ImVec2(x2,y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell);\r\n            }\r\n        }\r\n    }\r\n    else\r\n    {\r\n        window->DrawList->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags);\r\n    }\r\n}\r\n\r\nvoid ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    if ((flags & ImGuiColorEditFlags__InputsMask) == 0)\r\n        flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__InputsMask;\r\n    if ((flags & ImGuiColorEditFlags__DataTypeMask) == 0)\r\n        flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DataTypeMask;\r\n    if ((flags & ImGuiColorEditFlags__PickerMask) == 0)\r\n        flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__PickerMask;\r\n    IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__InputsMask)));   // Check only 1 option is selected\r\n    IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__DataTypeMask))); // Check only 1 option is selected\r\n    IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask)));   // Check only 1 option is selected\r\n    g.ColorEditOptions = flags;\r\n}\r\n\r\n// A little colored square. Return true when clicked.\r\n// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip.\r\n// 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip.\r\nbool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiID id = window->GetID(desc_id);\r\n    float default_size = ColorSquareSize();\r\n    if (size.x == 0.0f)\r\n        size.x = default_size;\r\n    if (size.y == 0.0f)\r\n        size.y = default_size;\r\n    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);\r\n    ItemSize(bb);\r\n    if (!ItemAdd(bb, &id))\r\n        return false;\r\n\r\n    bool hovered, held;\r\n    bool pressed = ButtonBehavior(bb, id, &hovered, &held);\r\n\r\n    if (flags & ImGuiColorEditFlags_NoAlpha)\r\n        flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf);\r\n    \r\n    ImVec4 col_without_alpha(col.x, col.y, col.z, 1.0f);\r\n    float grid_step = ImMin(size.x, size.y) / 2.99f;\r\n    float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);\r\n    if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col.w < 1.0f)\r\n    {\r\n        float mid_x = (float)(int)((bb.Min.x + bb.Max.x) * 0.5f + 0.5f);\r\n        RenderColorRectWithAlphaCheckerboard(ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, GetColorU32(col), grid_step, ImVec2(-grid_step, 0.0f), rounding, ImGuiCorner_TopRight|ImGuiCorner_BotRight);\r\n        window->DrawList->AddRectFilled(bb.Min, ImVec2(mid_x, bb.Max.y), GetColorU32(col_without_alpha), rounding, ImGuiCorner_TopLeft|ImGuiCorner_BotLeft);\r\n    }\r\n    else\r\n    {\r\n        RenderColorRectWithAlphaCheckerboard(bb.Min, bb.Max, GetColorU32((flags & ImGuiColorEditFlags_AlphaPreview) ? col : col_without_alpha), grid_step, ImVec2(0,0), rounding);\r\n    }\r\n    if (window->Flags & ImGuiWindowFlags_ShowBorders)\r\n        RenderFrameBorder(bb.Min, bb.Max, rounding);\r\n    else\r\n        window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border\r\n\r\n    if (hovered && !(flags & ImGuiColorEditFlags_NoTooltip))\r\n        ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));\r\n\r\n    return pressed;\r\n}\r\n\r\nbool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)\r\n{\r\n    return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);\r\n}\r\n\r\nstatic void ColorEditOptionsPopup(ImGuiColorEditFlags flags)\r\n{\r\n    bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__InputsMask);\r\n    bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask);\r\n    if ((!allow_opt_inputs && !allow_opt_datatype) || !ImGui::BeginPopup(\"context\"))\r\n        return;\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiColorEditFlags opts = g.ColorEditOptions;\r\n    if (allow_opt_inputs)\r\n    {\r\n        if (ImGui::RadioButton(\"RGB\", (opts & ImGuiColorEditFlags_RGB) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_RGB;\r\n        if (ImGui::RadioButton(\"HSV\", (opts & ImGuiColorEditFlags_HSV) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HSV;\r\n        if (ImGui::RadioButton(\"HEX\", (opts & ImGuiColorEditFlags_HEX) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HEX;\r\n    }\r\n    if (allow_opt_datatype)\r\n    {\r\n        if (allow_opt_inputs) ImGui::Separator();\r\n        if (ImGui::RadioButton(\"0..255\",     (opts & ImGuiColorEditFlags_Uint8) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8;\r\n        if (ImGui::RadioButton(\"0.00..1.00\", (opts & ImGuiColorEditFlags_Float) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float;\r\n    }\r\n    g.ColorEditOptions = opts;\r\n    ImGui::EndPopup();\r\n}\r\n\r\nstatic void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, float* ref_col)\r\n{\r\n    bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask);\r\n    bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);\r\n    if ((!allow_opt_picker && !allow_opt_alpha_bar) || !ImGui::BeginPopup(\"context\"))\r\n        return;\r\n    ImGuiContext& g = *GImGui;\r\n    if (allow_opt_picker)\r\n    {\r\n        ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (ColorSquareSize() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function\r\n        ImGui::PushItemWidth(picker_size.x);\r\n        for (int picker_type = 0; picker_type < 2; picker_type++)\r\n        {\r\n            // Draw small/thumbnail version of each picker type (over an invisible button for selection)\r\n            if (picker_type > 0) ImGui::Separator();\r\n            ImGui::PushID(picker_type);\r\n            ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoOptions|ImGuiColorEditFlags_NoLabel|ImGuiColorEditFlags_NoSidePreview|(flags & ImGuiColorEditFlags_NoAlpha);\r\n            if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;\r\n            if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;\r\n            ImVec2 backup_pos = ImGui::GetCursorScreenPos();\r\n            if (ImGui::Selectable(\"##selectable\", false, 0, picker_size)) // By default, Selectable() is closing popup\r\n                g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags__PickerMask) | (picker_flags & ImGuiColorEditFlags__PickerMask);\r\n            ImGui::SetCursorScreenPos(backup_pos);\r\n            ImVec4 dummy_ref_col;\r\n            memcpy(&dummy_ref_col.x, ref_col, sizeof(float) * (picker_flags & ImGuiColorEditFlags_NoAlpha ? 3 : 4));\r\n            ImGui::ColorPicker4(\"##dummypicker\", &dummy_ref_col.x, picker_flags);\r\n            ImGui::PopID();\r\n        }\r\n        ImGui::PopItemWidth();\r\n    }\r\n    if (allow_opt_alpha_bar)\r\n    {\r\n        if (allow_opt_picker) ImGui::Separator();\r\n        ImGui::CheckboxFlags(\"Alpha Bar\", (unsigned int*)&g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);\r\n    }\r\n    ImGui::EndPopup();\r\n}\r\n\r\n// Edit colors components (each component in 0.0f..1.0f range). \r\n// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.\r\n// With typical options: Left-click on colored square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item.\r\nbool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return false;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    const ImGuiStyle& style = g.Style;\r\n    const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (ColorSquareSize() + style.ItemInnerSpacing.x);\r\n    const float w_items_all = CalcItemWidth() - w_extra;\r\n    const char* label_display_end = FindRenderedTextEnd(label);\r\n\r\n    const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;\r\n    const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;\r\n    const int components = alpha ? 4 : 3;\r\n    const ImGuiColorEditFlags flags_untouched = flags;\r\n\r\n    BeginGroup();\r\n    PushID(label);\r\n\r\n    // If we're not showing any slider there's no point in doing any HSV conversions\r\n    if (flags & ImGuiColorEditFlags_NoInputs)\r\n        flags = (flags & (~ImGuiColorEditFlags__InputsMask)) | ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_NoOptions;\r\n\r\n    // Context menu: display and modify options (before defaults are applied)\r\n    if (!(flags & ImGuiColorEditFlags_NoOptions))\r\n        ColorEditOptionsPopup(flags);\r\n \r\n    // Read stored options\r\n    if (!(flags & ImGuiColorEditFlags__InputsMask))\r\n        flags |= (g.ColorEditOptions & ImGuiColorEditFlags__InputsMask);\r\n    if (!(flags & ImGuiColorEditFlags__DataTypeMask))\r\n        flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DataTypeMask);\r\n    if (!(flags & ImGuiColorEditFlags__PickerMask))\r\n        flags |= (g.ColorEditOptions & ImGuiColorEditFlags__PickerMask);\r\n    flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask));\r\n\r\n    // Convert to the formats we need\r\n    float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };\r\n    if (flags & ImGuiColorEditFlags_HSV)\r\n        ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);\r\n    int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) };\r\n\r\n    bool value_changed = false;\r\n    bool value_changed_as_float = false;\r\n\r\n    if ((flags & (ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)\r\n    {\r\n        // RGB/HSV 0..255 Sliders\r\n        const float w_item_one  = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));\r\n        const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));\r\n\r\n        const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? \"M:0.000\" : \"M:000\").x);\r\n        const char* ids[4] = { \"##X\", \"##Y\", \"##Z\", \"##W\" };\r\n        const char* fmt_table_int[3][4] =\r\n        {\r\n            {   \"%3.0f\",   \"%3.0f\",   \"%3.0f\",   \"%3.0f\" }, // Short display\r\n            { \"R:%3.0f\", \"G:%3.0f\", \"B:%3.0f\", \"A:%3.0f\" }, // Long display for RGBA\r\n            { \"H:%3.0f\", \"S:%3.0f\", \"V:%3.0f\", \"A:%3.0f\" }  // Long display for HSVA\r\n        };\r\n        const char* fmt_table_float[3][4] =\r\n        {\r\n            {   \"%0.3f\",   \"%0.3f\",   \"%0.3f\",   \"%0.3f\" }, // Short display\r\n            { \"R:%0.3f\", \"G:%0.3f\", \"B:%0.3f\", \"A:%0.3f\" }, // Long display for RGBA\r\n            { \"H:%0.3f\", \"S:%0.3f\", \"V:%0.3f\", \"A:%0.3f\" }  // Long display for HSVA\r\n        };\r\n        const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_HSV) ? 2 : 1;\r\n\r\n        PushItemWidth(w_item_one);\r\n        for (int n = 0; n < components; n++)\r\n        {\r\n            if (n > 0)\r\n                SameLine(0, style.ItemInnerSpacing.x);\r\n            if (n + 1 == components)\r\n                PushItemWidth(w_item_last);\r\n            if (flags & ImGuiColorEditFlags_Float)\r\n                value_changed |= value_changed_as_float |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);\r\n            else\r\n                value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);\r\n            if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))\r\n                OpenPopup(\"context\");\r\n        }\r\n        PopItemWidth();\r\n        PopItemWidth();\r\n    }\r\n    else if ((flags & ImGuiColorEditFlags_HEX) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)\r\n    {\r\n        // RGB Hexadecimal Input\r\n        char buf[64];\r\n        if (alpha)\r\n            ImFormatString(buf, IM_ARRAYSIZE(buf), \"#%02X%02X%02X%02X\", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255));\r\n        else\r\n            ImFormatString(buf, IM_ARRAYSIZE(buf), \"#%02X%02X%02X\", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255));\r\n        PushItemWidth(w_items_all);\r\n        if (InputText(\"##Text\", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))\r\n        {\r\n            value_changed |= true;\r\n            char* p = buf;\r\n            while (*p == '#' || ImCharIsSpace(*p))\r\n                p++;\r\n            i[0] = i[1] = i[2] = i[3] = 0;\r\n            if (alpha)\r\n                sscanf(p, \"%02X%02X%02X%02X\", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)\r\n            else\r\n                sscanf(p, \"%02X%02X%02X\", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);\r\n        }\r\n        if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))\r\n            OpenPopup(\"context\");\r\n        PopItemWidth();\r\n    }\r\n\r\n    bool picker_active = false;\r\n    if (!(flags & ImGuiColorEditFlags_NoSmallPreview))\r\n    {\r\n        if (!(flags & ImGuiColorEditFlags_NoInputs))\r\n            SameLine(0, style.ItemInnerSpacing.x);\r\n\r\n        const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f);\r\n        if (ColorButton(\"##ColorButton\", col_v4, flags))\r\n        {\r\n            if (!(flags & ImGuiColorEditFlags_NoPicker))\r\n            {\r\n                // Store current color and open a picker\r\n                g.ColorPickerRef = col_v4;\r\n                OpenPopup(\"picker\");\r\n                SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y));\r\n            }\r\n        }\r\n        if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))\r\n            OpenPopup(\"context\");\r\n\r\n        if (BeginPopup(\"picker\"))\r\n        {\r\n            picker_active = true;\r\n            if (label != label_display_end)\r\n            {\r\n                TextUnformatted(label, label_display_end);\r\n                Separator();\r\n            }\r\n            float square_sz = ColorSquareSize();\r\n            ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;\r\n            ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;\r\n            PushItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?\r\n            value_changed |= ColorPicker4(\"##picker\", col, picker_flags, &g.ColorPickerRef.x);\r\n            PopItemWidth();\r\n            EndPopup();\r\n        }\r\n    }\r\n\r\n    if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))\r\n    {\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n        TextUnformatted(label, label_display_end);\r\n    }\r\n\r\n    // Convert back\r\n    if (!picker_active)\r\n    {\r\n        if (!value_changed_as_float) \r\n            for (int n = 0; n < 4; n++)\r\n                f[n] = i[n] / 255.0f;\r\n        if (flags & ImGuiColorEditFlags_HSV)\r\n            ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);\r\n        if (value_changed)\r\n        {\r\n            col[0] = f[0];\r\n            col[1] = f[1];\r\n            col[2] = f[2];\r\n            if (alpha)\r\n                col[3] = f[3];\r\n        }\r\n    }\r\n\r\n    PopID();\r\n    EndGroup();\r\n\r\n    return value_changed;\r\n}\r\n\r\nbool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)\r\n{\r\n    float col4[4] = { col[0], col[1], col[2], 1.0f };\r\n    if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha))\r\n        return false;\r\n    col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];\r\n    return true;\r\n}\r\n\r\n// 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.\r\nstatic void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col)\r\n{\r\n    switch (direction)\r\n    {\r\n    case ImGuiDir_Left:  draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return;\r\n    case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return;\r\n    case ImGuiDir_Up:    draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return;\r\n    case ImGuiDir_Down:  draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return;\r\n    default: return; // Fix warning for ImGuiDir_None\r\n    }\r\n}\r\n\r\nstatic void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w)\r\n{\r\n    RenderArrow(draw_list, ImVec2(pos.x + half_sz.x + 1,         pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK);\r\n    RenderArrow(draw_list, ImVec2(pos.x + half_sz.x,             pos.y), half_sz,                              ImGuiDir_Right, IM_COL32_WHITE);\r\n    RenderArrow(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left,  IM_COL32_BLACK);\r\n    RenderArrow(draw_list, ImVec2(pos.x + bar_w - half_sz.x,     pos.y), half_sz,                              ImGuiDir_Left,  IM_COL32_WHITE);\r\n}\r\n\r\nstatic void PaintVertsLinearGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)\r\n{\r\n    ImVec2 gradient_extent = gradient_p1 - gradient_p0;\r\n    float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent);\r\n    for (ImDrawVert* vert = vert_start; vert < vert_end; vert++)\r\n    {\r\n        float d = ImDot(vert->pos - gradient_p0, gradient_extent);\r\n        float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);\r\n        int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t);\r\n        int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t);\r\n        int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t);\r\n        vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK);\r\n    }\r\n}\r\n\r\n// ColorPicker\r\n// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.\r\n// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) \r\nbool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    ImDrawList* draw_list = window->DrawList;\r\n\r\n    ImGuiStyle& style = g.Style;\r\n    ImGuiIO& io = g.IO;\r\n\r\n    PushID(label);\r\n    BeginGroup();\r\n\r\n    if (!(flags & ImGuiColorEditFlags_NoSidePreview))\r\n        flags |= ImGuiColorEditFlags_NoSmallPreview;\r\n\r\n    // Context menu: display and store options.\r\n    if (!(flags & ImGuiColorEditFlags_NoOptions))\r\n        ColorPickerOptionsPopup(flags, col);\r\n\r\n    // Read stored options\r\n    if (!(flags & ImGuiColorEditFlags__PickerMask))\r\n        flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask; \r\n    IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected\r\n    if (!(flags & ImGuiColorEditFlags_NoOptions))\r\n        flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);\r\n\r\n    // Setup\r\n    bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);\r\n    ImVec2 picker_pos = window->DC.CursorPos;\r\n    float bars_width = ColorSquareSize(); // Arbitrary smallish width of Hue/Alpha picking bars\r\n    float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box\r\n    float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;\r\n    float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;\r\n    float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);\r\n\r\n    float wheel_thickness = sv_picker_size * 0.08f;\r\n    float wheel_r_outer = sv_picker_size * 0.50f;\r\n    float wheel_r_inner = wheel_r_outer - wheel_thickness;\r\n    ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f);\r\n    \r\n    // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.\r\n    float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);\r\n    ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.\r\n    ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.\r\n    ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.\r\n\r\n    float H,S,V;\r\n    ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V);\r\n\r\n    bool value_changed = false, value_changed_h = false, value_changed_sv = false;\r\n\r\n    if (flags & ImGuiColorEditFlags_PickerHueWheel)\r\n    {\r\n        // Hue wheel + SV triangle logic\r\n        InvisibleButton(\"hsv\", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));\r\n        if (IsItemActive())\r\n        {\r\n            ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;\r\n            ImVec2 current_off = g.IO.MousePos - wheel_center;\r\n            float initial_dist2 = ImLengthSqr(initial_off);\r\n            if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))\r\n            {\r\n                // Interactive with Hue wheel\r\n                H = atan2f(current_off.y, current_off.x) / IM_PI*0.5f;\r\n                if (H < 0.0f)\r\n                    H += 1.0f;\r\n                value_changed = value_changed_h = true;\r\n            }\r\n            float cos_hue_angle = cosf(-H * 2.0f * IM_PI);\r\n            float sin_hue_angle = sinf(-H * 2.0f * IM_PI);\r\n            if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))\r\n            {\r\n                // Interacting with SV triangle\r\n                ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);\r\n                if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))\r\n                    current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);\r\n                float uu, vv, ww;\r\n                ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);\r\n                V = ImClamp(1.0f - vv, 0.0001f, 1.0f);\r\n                S = ImClamp(uu / V, 0.0001f, 1.0f);\r\n                value_changed = value_changed_sv = true;\r\n            }\r\n        }\r\n        if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))\r\n            OpenPopup(\"context\");\r\n    }\r\n    else if (flags & ImGuiColorEditFlags_PickerHueBar)\r\n    {\r\n        // SV rectangle logic\r\n        InvisibleButton(\"sv\", ImVec2(sv_picker_size, sv_picker_size));\r\n        if (IsItemActive())\r\n        {\r\n            S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));\r\n            V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));\r\n            value_changed = value_changed_sv = true;\r\n        }\r\n        if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1))\r\n            OpenPopup(\"context\");\r\n\r\n        // Hue bar logic\r\n        SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));\r\n        InvisibleButton(\"hue\", ImVec2(bars_width, sv_picker_size));\r\n        if (IsItemActive())\r\n        {\r\n            H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));\r\n            value_changed = value_changed_h = true;\r\n        }\r\n    }\r\n\r\n    // Alpha bar logic\r\n    if (alpha_bar)\r\n    {\r\n        SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));\r\n        InvisibleButton(\"alpha\", ImVec2(bars_width, sv_picker_size));\r\n        if (IsItemActive())\r\n        {\r\n            col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));\r\n            value_changed = true;\r\n        }\r\n    }\r\n\r\n    if (!(flags & ImGuiColorEditFlags_NoSidePreview))\r\n    {\r\n        SameLine(0, style.ItemInnerSpacing.x);\r\n        BeginGroup();\r\n    }\r\n\r\n    if (!(flags & ImGuiColorEditFlags_NoLabel))\r\n    {\r\n        const char* label_display_end = FindRenderedTextEnd(label);\r\n        if (label != label_display_end)\r\n        {\r\n            if ((flags & ImGuiColorEditFlags_NoSidePreview))\r\n                SameLine(0, style.ItemInnerSpacing.x);\r\n            TextUnformatted(label, label_display_end);\r\n        }\r\n    }\r\n\r\n    if (!(flags & ImGuiColorEditFlags_NoSidePreview))\r\n    {\r\n        ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);\r\n        float square_sz = ColorSquareSize();\r\n        if ((flags & ImGuiColorEditFlags_NoLabel))\r\n            Text(\"Current\");\r\n        ColorButton(\"##current\", col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2));\r\n        if (ref_col != NULL)\r\n        {\r\n            Text(\"Original\");\r\n            ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);\r\n            if (ColorButton(\"##original\", ref_col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2)))\r\n            {\r\n                memcpy(col, ref_col, ((flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4) * sizeof(float));\r\n                value_changed = true;\r\n            }\r\n        }\r\n        EndGroup();\r\n    }\r\n\r\n    // Convert back color to RGB\r\n    if (value_changed_h || value_changed_sv)\r\n        ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);\r\n\r\n    // R,G,B and H,S,V slider color editor\r\n    if ((flags & ImGuiColorEditFlags_NoInputs) == 0)\r\n    {\r\n        PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);\r\n        ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;\r\n        ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;\r\n        if (flags & ImGuiColorEditFlags_RGB || (flags & ImGuiColorEditFlags__InputsMask) == 0)\r\n            value_changed |= ColorEdit4(\"##rgb\", col, sub_flags | ImGuiColorEditFlags_RGB);\r\n        if (flags & ImGuiColorEditFlags_HSV || (flags & ImGuiColorEditFlags__InputsMask) == 0)\r\n            value_changed |= ColorEdit4(\"##hsv\", col, sub_flags | ImGuiColorEditFlags_HSV);\r\n        if (flags & ImGuiColorEditFlags_HEX || (flags & ImGuiColorEditFlags__InputsMask) == 0)\r\n            value_changed |= ColorEdit4(\"##hex\", col, sub_flags | ImGuiColorEditFlags_HEX);\r\n        PopItemWidth();\r\n    }\r\n\r\n    // Try to cancel hue wrap (after ColorEdit), if any\r\n    if (value_changed)\r\n    {\r\n        float new_H, new_S, new_V;\r\n        ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);\r\n        if (new_H <= 0 && H > 0) \r\n        {\r\n            if (new_V <= 0 && V != new_V)\r\n                ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);\r\n            else if (new_S <= 0)\r\n                ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);\r\n        }\r\n    }\r\n\r\n    ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);\r\n    ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);\r\n    ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 1.0f));\r\n\r\n    const ImU32 hue_colors[6+1] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) };\r\n    ImVec2 sv_cursor_pos;\r\n    \r\n    if (flags & ImGuiColorEditFlags_PickerHueWheel)\r\n    {\r\n        // Render Hue Wheel\r\n        const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).\r\n        const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);\r\n        for (int n = 0; n < 6; n++)\r\n        {\r\n            const float a0 = (n)     /6.0f * 2.0f * IM_PI - aeps;\r\n            const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;\r\n            int vert_start_idx = draw_list->_VtxCurrentIdx;\r\n            draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);\r\n            draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness);\r\n\r\n            // Paint colors over existing vertices\r\n            ImVec2 gradient_p0(wheel_center.x + cosf(a0) * wheel_r_inner, wheel_center.y + sinf(a0) * wheel_r_inner);\r\n            ImVec2 gradient_p1(wheel_center.x + cosf(a1) * wheel_r_inner, wheel_center.y + sinf(a1) * wheel_r_inner);\r\n            PaintVertsLinearGradientKeepAlpha(draw_list->_VtxWritePtr - (draw_list->_VtxCurrentIdx - vert_start_idx), draw_list->_VtxWritePtr, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]);\r\n        }\r\n\r\n        // Render Cursor + preview on Hue Wheel\r\n        float cos_hue_angle = cosf(H * 2.0f * IM_PI);\r\n        float sin_hue_angle = sinf(H * 2.0f * IM_PI);\r\n        ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f);\r\n        float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;\r\n        int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);\r\n        draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);\r\n        draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments);\r\n        draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments);\r\n\r\n        // Render SV triangle (rotated according to hue)\r\n        ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);\r\n        ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);\r\n        ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);\r\n        ImVec2 uv_white = g.FontTexUvWhitePixel;\r\n        draw_list->PrimReserve(6, 6);\r\n        draw_list->PrimVtx(tra, uv_white, hue_color32);\r\n        draw_list->PrimVtx(trb, uv_white, hue_color32);\r\n        draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);\r\n        draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);\r\n        draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);\r\n        draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);\r\n        draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);\r\n        sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));\r\n    }\r\n    else if (flags & ImGuiColorEditFlags_PickerHueBar)\r\n    {\r\n        // Render SV Square\r\n        draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);\r\n        draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);\r\n        RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f);\r\n        sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S)     * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much\r\n        sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);\r\n\r\n        // Render Hue Bar\r\n        for (int i = 0; i < 6; ++i)\r\n            draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]);\r\n        float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f);\r\n        RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);\r\n        RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);\r\n    }\r\n\r\n    // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)\r\n    float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;\r\n    draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12);\r\n    draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12);\r\n    draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12);\r\n\r\n    // Render alpha bar\r\n    if (alpha_bar)\r\n    {\r\n        float alpha = ImSaturate(col[3]);\r\n        ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);\r\n        RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));\r\n        draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK);\r\n        float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);\r\n        RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);\r\n        RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);\r\n    }\r\n\r\n    EndGroup();\r\n    PopID();\r\n\r\n    return value_changed;\r\n}\r\n\r\n// Horizontal separating line.\r\nvoid ImGui::Separator()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    if (window->DC.ColumnsCount > 1)\r\n        PopClipRect();\r\n\r\n    float x1 = window->Pos.x;\r\n    float x2 = window->Pos.x + window->Size.x;\r\n    if (!window->DC.GroupStack.empty())\r\n        x1 += window->DC.IndentX;\r\n\r\n    const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));\r\n    ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.\r\n    if (!ItemAdd(bb, NULL))\r\n    {\r\n        if (window->DC.ColumnsCount > 1)\r\n            PushColumnClipRect();\r\n        return;\r\n    }\r\n\r\n    window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator));\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.LogEnabled)\r\n        LogText(IM_NEWLINE \"--------------------------------\");\r\n\r\n    if (window->DC.ColumnsCount > 1)\r\n    {\r\n        PushColumnClipRect();\r\n        window->DC.ColumnsCellMinY = window->DC.CursorPos.y;\r\n    }\r\n}\r\n\r\nvoid ImGui::Spacing()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n    ItemSize(ImVec2(0,0));\r\n}\r\n\r\nvoid ImGui::Dummy(const ImVec2& size)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);\r\n    ItemSize(bb);\r\n    ItemAdd(bb, NULL);\r\n}\r\n\r\nbool ImGui::IsRectVisible(const ImVec2& size)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));\r\n}\r\n\r\nbool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));\r\n}\r\n\r\n// Lock horizontal starting position + capture group bounding box into one \"item\" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)\r\nvoid ImGui::BeginGroup()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);\r\n    ImGuiGroupData& group_data = window->DC.GroupStack.back();\r\n    group_data.BackupCursorPos = window->DC.CursorPos;\r\n    group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;\r\n    group_data.BackupIndentX = window->DC.IndentX;\r\n    group_data.BackupGroupOffsetX = window->DC.GroupOffsetX;\r\n    group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight;\r\n    group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;\r\n    group_data.BackupLogLinePosY = window->DC.LogLinePosY;\r\n    group_data.BackupActiveIdIsAlive = GImGui->ActiveIdIsAlive;\r\n    group_data.AdvanceCursor = true;\r\n\r\n    window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX;\r\n    window->DC.IndentX = window->DC.GroupOffsetX;\r\n    window->DC.CursorMaxPos = window->DC.CursorPos;\r\n    window->DC.CurrentLineHeight = 0.0f;\r\n    window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;\r\n}\r\n\r\nvoid ImGui::EndGroup()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    IM_ASSERT(!window->DC.GroupStack.empty());    // Mismatched BeginGroup()/EndGroup() calls\r\n\r\n    ImGuiGroupData& group_data = window->DC.GroupStack.back();\r\n\r\n    ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);\r\n    group_bb.Max.y -= g.Style.ItemSpacing.y;      // Cancel out last vertical spacing because we are adding one ourselves.\r\n    group_bb.Max = ImMax(group_bb.Min, group_bb.Max);\r\n\r\n    window->DC.CursorPos = group_data.BackupCursorPos;\r\n    window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);\r\n    window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight;\r\n    window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;\r\n    window->DC.IndentX = group_data.BackupIndentX;\r\n    window->DC.GroupOffsetX = group_data.BackupGroupOffsetX;\r\n    window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;\r\n\r\n    if (group_data.AdvanceCursor)\r\n    {\r\n        window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset);      // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.\r\n        ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset);\r\n        ItemAdd(group_bb, NULL);\r\n    }\r\n\r\n    // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will function on the entire group.\r\n    // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but if you search for LastItemId you'll notice it is only used in that context.\r\n    const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow);\r\n    if (active_id_within_group)\r\n        window->DC.LastItemId = g.ActiveId;\r\n    if (active_id_within_group && g.HoveredId == g.ActiveId)\r\n        window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = true;\r\n\r\n    window->DC.GroupStack.pop_back();\r\n\r\n    //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255));   // [Debug]\r\n}\r\n\r\n// Gets back to previous line and continue with horizontal layout\r\n//      pos_x == 0      : follow right after previous item\r\n//      pos_x != 0      : align to specified x position (relative to window/group left)\r\n//      spacing_w < 0   : use default spacing if pos_x == 0, no spacing if pos_x != 0\r\n//      spacing_w >= 0  : enforce spacing amount\r\nvoid ImGui::SameLine(float pos_x, float spacing_w)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    if (pos_x != 0.0f)\r\n    {\r\n        if (spacing_w < 0.0f) spacing_w = 0.0f;\r\n        window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffsetX + window->DC.ColumnsOffsetX;\r\n        window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;\r\n    }\r\n    else\r\n    {\r\n        if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x;\r\n        window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;\r\n        window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;\r\n    }\r\n    window->DC.CurrentLineHeight = window->DC.PrevLineHeight;\r\n    window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;\r\n}\r\n\r\nvoid ImGui::NewLine()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems)\r\n        return;\r\n    if (window->DC.CurrentLineHeight > 0.0f)     // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.\r\n        ItemSize(ImVec2(0,0));\r\n    else\r\n        ItemSize(ImVec2(0.0f, GImGui->FontSize));\r\n}\r\n\r\nvoid ImGui::NextColumn()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (window->SkipItems || window->DC.ColumnsCount <= 1)\r\n        return;\r\n\r\n    ImGuiContext& g = *GImGui;\r\n    PopItemWidth();\r\n    PopClipRect();\r\n\r\n    window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);\r\n    if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount)\r\n    {\r\n        // Columns 1+ cancel out IndentX\r\n        window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x;\r\n        window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent);\r\n    }\r\n    else\r\n    {\r\n        window->DC.ColumnsCurrent = 0;\r\n        window->DC.ColumnsOffsetX = 0.0f;\r\n        window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY;\r\n        window->DrawList->ChannelsSetCurrent(0);\r\n    }\r\n    window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX);\r\n    window->DC.CursorPos.y = window->DC.ColumnsCellMinY;\r\n    window->DC.CurrentLineHeight = 0.0f;\r\n    window->DC.CurrentLineTextBaseOffset = 0.0f;\r\n\r\n    PushColumnClipRect();\r\n    PushItemWidth(GetColumnWidth() * 0.65f);  // FIXME: Move on columns setup\r\n}\r\n\r\nint ImGui::GetColumnIndex()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.ColumnsCurrent;\r\n}\r\n\r\nint ImGui::GetColumnsCount()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    return window->DC.ColumnsCount;\r\n}\r\n\r\nstatic float OffsetNormToPixels(ImGuiWindow* window, float offset_norm)\r\n{\r\n    return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX);\r\n}\r\n\r\nstatic float PixelsToOffsetNorm(ImGuiWindow* window, float offset)\r\n{\r\n    return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX);\r\n}\r\n\r\nstatic float GetDraggedColumnOffset(int column_index)\r\n{\r\n    // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing\r\n    // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = ImGui::GetCurrentWindowRead();\r\n    IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets.\r\n    IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index));\r\n\r\n    float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x;\r\n    x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing);\r\n    if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths))\r\n        x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing);\r\n\r\n    return x;\r\n}\r\n\r\nfloat ImGui::GetColumnOffset(int column_index)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (column_index < 0)\r\n        column_index = window->DC.ColumnsCurrent;\r\n\r\n    /*\r\n    if (g.ActiveId)\r\n    {\r\n        ImGuiContext& g = *GImGui;\r\n        const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);\r\n        if (g.ActiveId == column_id)\r\n            return GetDraggedColumnOffset(column_index);\r\n    }\r\n    */\r\n\r\n    IM_ASSERT(column_index < window->DC.ColumnsData.Size);\r\n    const float t = window->DC.ColumnsData[column_index].OffsetNorm;\r\n    const float x_offset = ImLerp(window->DC.ColumnsMinX, window->DC.ColumnsMaxX, t);\r\n    return x_offset;\r\n}\r\n\r\nvoid ImGui::SetColumnOffset(int column_index, float offset)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    if (column_index < 0)\r\n        column_index = window->DC.ColumnsCurrent;\r\n\r\n    IM_ASSERT(column_index < window->DC.ColumnsData.Size);\r\n\r\n    const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1);\r\n    const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f;\r\n\r\n    if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow))\r\n        offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index));\r\n    const float offset_norm = PixelsToOffsetNorm(window, offset);\r\n\r\n    const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);\r\n    window->DC.StateStorage->SetFloat(column_id, offset_norm);\r\n    window->DC.ColumnsData[column_index].OffsetNorm = offset_norm;\r\n\r\n    if (preserve_width)\r\n        SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));\r\n}\r\n\r\nfloat ImGui::GetColumnWidth(int column_index)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (column_index < 0)\r\n        column_index = window->DC.ColumnsCurrent;\r\n\r\n    return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm);\r\n}\r\n\r\nvoid ImGui::SetColumnWidth(int column_index, float width)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (column_index < 0)\r\n        column_index = window->DC.ColumnsCurrent;\r\n\r\n    SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width);\r\n}\r\n\r\nvoid ImGui::PushColumnClipRect(int column_index)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindowRead();\r\n    if (column_index < 0)\r\n        column_index = window->DC.ColumnsCurrent;\r\n\r\n    PushClipRect(window->DC.ColumnsData[column_index].ClipRect.Min, window->DC.ColumnsData[column_index].ClipRect.Max, false);\r\n}\r\n\r\nvoid ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n\r\n    IM_ASSERT(columns_count > 1);\r\n    IM_ASSERT(window->DC.ColumnsCount == 1); // Nested columns are currently not supported\r\n\r\n    // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget.\r\n    // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer.\r\n    PushID(0x11223347 + (id ? 0 : columns_count));\r\n    window->DC.ColumnsSetId = window->GetID(id ? id : \"columns\");\r\n    PopID();\r\n\r\n    // Set state for first column\r\n    window->DC.ColumnsCurrent = 0;\r\n    window->DC.ColumnsCount = columns_count;\r\n    window->DC.ColumnsFlags = flags;\r\n\r\n    const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x);\r\n    window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range\r\n    //window->DC.ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x;\r\n    window->DC.ColumnsMaxX = content_region_width - window->Scroll.x;\r\n    window->DC.ColumnsStartPosY = window->DC.CursorPos.y;\r\n    window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x;\r\n    window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y;\r\n    window->DC.ColumnsOffsetX = 0.0f;\r\n    window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX);\r\n\r\n    // Cache column offsets\r\n    window->DC.ColumnsData.resize(columns_count + 1);\r\n    for (int column_index = 0; column_index < columns_count + 1; column_index++)\r\n    {\r\n        const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index);\r\n        KeepAliveID(column_id);\r\n        const float default_t = column_index / (float)window->DC.ColumnsCount;\r\n        float t = window->DC.StateStorage->GetFloat(column_id, default_t);\r\n        if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow))\r\n            t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)));\r\n        window->DC.ColumnsData[column_index].OffsetNorm = t;\r\n    }\r\n\r\n    // Cache clipping rectangles\r\n    for (int column_index = 0; column_index < columns_count; column_index++)\r\n    {\r\n        float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f);\r\n        float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f);\r\n        window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);\r\n        window->DC.ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect);\r\n    }\r\n\r\n    window->DrawList->ChannelsSplit(window->DC.ColumnsCount);\r\n    PushColumnClipRect();\r\n    PushItemWidth(GetColumnWidth() * 0.65f);\r\n}\r\n\r\nvoid ImGui::EndColumns()\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    IM_ASSERT(window->DC.ColumnsCount > 1);\r\n\r\n    PopItemWidth();\r\n    PopClipRect();\r\n    window->DrawList->ChannelsMerge();\r\n\r\n    window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);\r\n    window->DC.CursorPos.y = window->DC.ColumnsCellMaxY;\r\n    window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX);  // Columns don't grow parent\r\n\r\n    // Draw columns borders and handle resize\r\n    if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)\r\n    {\r\n        const float y1 = window->DC.ColumnsStartPosY;\r\n        const float y2 = window->DC.CursorPos.y;\r\n        int dragging_column = -1;\r\n        for (int i = 1; i < window->DC.ColumnsCount; i++)\r\n        {\r\n            float x = window->Pos.x + GetColumnOffset(i);\r\n            const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i);\r\n            const float column_w = 4.0f; // Width for interaction\r\n            const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2));\r\n            if (IsClippedEx(column_rect, &column_id, false))\r\n                continue;\r\n            \r\n            bool hovered = false, held = false;\r\n            if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize))\r\n            {\r\n                ButtonBehavior(column_rect, column_id, &hovered, &held);\r\n                if (hovered || held)\r\n                    g.MouseCursor = ImGuiMouseCursor_ResizeEW;\r\n                if (held && g.ActiveIdIsJustActivated)\r\n                    g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset().\r\n                if (held)\r\n                    dragging_column = i;\r\n            }\r\n\r\n            // Draw column\r\n            const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);\r\n            const float xi = (float)(int)x;\r\n            window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);\r\n        }\r\n\r\n        // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.\r\n        if (dragging_column != -1)\r\n        {\r\n            float x = GetDraggedColumnOffset(dragging_column);\r\n            SetColumnOffset(dragging_column, x);\r\n        }\r\n    }\r\n\r\n    window->DC.ColumnsSetId = 0;\r\n    window->DC.ColumnsCurrent = 0;\r\n    window->DC.ColumnsCount = 1;\r\n    window->DC.ColumnsFlags = 0;\r\n    window->DC.ColumnsData.resize(0);\r\n    window->DC.ColumnsOffsetX = 0.0f;\r\n    window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX);\r\n}\r\n\r\n// [2017/08: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]\r\nvoid ImGui::Columns(int columns_count, const char* id, bool border)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    IM_ASSERT(columns_count >= 1);\r\n\r\n    if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1)\r\n        EndColumns();\r\n    \r\n    ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);\r\n    //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior\r\n    if (columns_count != 1)\r\n        BeginColumns(id, columns_count, flags);\r\n}\r\n\r\nvoid ImGui::Indent(float indent_w)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.IndentX += (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing;\r\n    window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX;\r\n}\r\n\r\nvoid ImGui::Unindent(float indent_w)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    window->DC.IndentX -= (indent_w > 0.0f) ? indent_w : g.Style.IndentSpacing;\r\n    window->DC.CursorPos.x = window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX;\r\n}\r\n\r\nvoid ImGui::TreePush(const char* str_id)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    Indent();\r\n    window->DC.TreeDepth++;\r\n    PushID(str_id ? str_id : \"#TreePush\");\r\n}\r\n\r\nvoid ImGui::TreePush(const void* ptr_id)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    Indent();\r\n    window->DC.TreeDepth++;\r\n    PushID(ptr_id ? ptr_id : (const void*)\"#TreePush\");\r\n}\r\n\r\nvoid ImGui::TreePushRawID(ImGuiID id)\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    Indent();\r\n    window->DC.TreeDepth++;\r\n    window->IDStack.push_back(id);\r\n}\r\n\r\nvoid ImGui::TreePop()\r\n{\r\n    ImGuiWindow* window = GetCurrentWindow();\r\n    Unindent();\r\n    window->DC.TreeDepth--;\r\n    PopID();\r\n}\r\n\r\nvoid ImGui::Value(const char* prefix, bool b)\r\n{\r\n    Text(\"%s: %s\", prefix, (b ? \"true\" : \"false\"));\r\n}\r\n\r\nvoid ImGui::Value(const char* prefix, int v)\r\n{\r\n    Text(\"%s: %d\", prefix, v);\r\n}\r\n\r\nvoid ImGui::Value(const char* prefix, unsigned int v)\r\n{\r\n    Text(\"%s: %d\", prefix, v);\r\n}\r\n\r\nvoid ImGui::Value(const char* prefix, float v, const char* float_format)\r\n{\r\n    if (float_format)\r\n    {\r\n        char fmt[64];\r\n        ImFormatString(fmt, IM_ARRAYSIZE(fmt), \"%%s: %s\", float_format);\r\n        Text(fmt, prefix, v);\r\n    }\r\n    else\r\n    {\r\n        Text(\"%s: %.3f\", prefix, v);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// PLATFORM DEPENDENT HELPERS\r\n//-----------------------------------------------------------------------------\r\n\r\n#if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS))\r\n#undef WIN32_LEAN_AND_MEAN\r\n#define WIN32_LEAN_AND_MEAN\r\n#include <windows.h>\r\n#endif\r\n\r\n// Win32 API clipboard implementation\r\n#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS)\r\n\r\n#ifdef _MSC_VER\r\n#pragma comment(lib, \"user32\")\r\n#endif\r\n\r\nstatic const char* GetClipboardTextFn_DefaultImpl(void*)\r\n{\r\n    static ImVector<char> buf_local;\r\n    buf_local.clear();\r\n    if (!OpenClipboard(NULL))\r\n        return NULL;\r\n    HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT);\r\n    if (wbuf_handle == NULL)\r\n    {\r\n        CloseClipboard();\r\n        return NULL;\r\n    }\r\n    if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle))\r\n    {\r\n        int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;\r\n        buf_local.resize(buf_len);\r\n        ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL);\r\n    }\r\n    GlobalUnlock(wbuf_handle);\r\n    CloseClipboard();\r\n    return buf_local.Data;\r\n}\r\n\r\nstatic void SetClipboardTextFn_DefaultImpl(void*, const char* text)\r\n{\r\n    if (!OpenClipboard(NULL))\r\n        return;\r\n    const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;\r\n    HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));\r\n    if (wbuf_handle == NULL)\r\n        return;\r\n    ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle);\r\n    ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);\r\n    GlobalUnlock(wbuf_handle);\r\n    EmptyClipboard();\r\n    SetClipboardData(CF_UNICODETEXT, wbuf_handle);\r\n    CloseClipboard();\r\n}\r\n\r\n#else\r\n\r\n// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers\r\nstatic const char* GetClipboardTextFn_DefaultImpl(void*)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin();\r\n}\r\n\r\n// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers\r\nstatic void SetClipboardTextFn_DefaultImpl(void*, const char* text)\r\n{\r\n    ImGuiContext& g = *GImGui;\r\n    g.PrivateClipboard.clear();\r\n    const char* text_end = text + strlen(text);\r\n    g.PrivateClipboard.resize((int)(text_end - text) + 1);\r\n    memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text));\r\n    g.PrivateClipboard[(int)(text_end - text)] = 0;\r\n}\r\n\r\n#endif\r\n\r\n// Win32 API IME support (for Asian languages, etc.)\r\n#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS)\r\n\r\n#include <imm.h>\r\n#ifdef _MSC_VER\r\n#pragma comment(lib, \"imm32\")\r\n#endif\r\n\r\nstatic void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)\r\n{\r\n    // Notify OS Input Method Editor of text input position\r\n    if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle)\r\n        if (HIMC himc = ImmGetContext(hwnd))\r\n        {\r\n            COMPOSITIONFORM cf;\r\n            cf.ptCurrentPos.x = x;\r\n            cf.ptCurrentPos.y = y;\r\n            cf.dwStyle = CFS_FORCE_POSITION;\r\n            ImmSetCompositionWindow(himc, &cf);\r\n        }\r\n}\r\n\r\n#else\r\n\r\nstatic void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}\r\n\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// HELP\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid ImGui::ShowMetricsWindow(bool* p_open)\r\n{\r\n    if (ImGui::Begin(\"ImGui Metrics\", p_open))\r\n    {\r\n        ImGui::Text(\"ImGui %s\", ImGui::GetVersion());\r\n        ImGui::Text(\"Application average %.3f ms/frame (%.1f FPS)\", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);\r\n        ImGui::Text(\"%d vertices, %d indices (%d triangles)\", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3);\r\n        ImGui::Text(\"%d allocations\", ImGui::GetIO().MetricsAllocs);\r\n        static bool show_clip_rects = true;\r\n        ImGui::Checkbox(\"Show clipping rectangles when hovering an ImDrawCmd\", &show_clip_rects);\r\n        ImGui::Separator();\r\n\r\n        struct Funcs\r\n        {\r\n            static void NodeDrawList(ImDrawList* draw_list, const char* label)\r\n            {\r\n                bool node_open = ImGui::TreeNode(draw_list, \"%s: '%s' %d vtx, %d indices, %d cmds\", label, draw_list->_OwnerName ? draw_list->_OwnerName : \"\", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size);\r\n                if (draw_list == ImGui::GetWindowDrawList())\r\n                {\r\n                    ImGui::SameLine();\r\n                    ImGui::TextColored(ImColor(255,100,100), \"CURRENTLY APPENDING\"); // Can't display stats for active draw list! (we don't have the data double-buffered)\r\n                    if (node_open) ImGui::TreePop();\r\n                    return;\r\n                }\r\n                if (!node_open)\r\n                    return;\r\n\r\n                ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList;   // Render additional visuals into the top-most draw list\r\n                overlay_draw_list->PushClipRectFullScreen();\r\n                int elem_offset = 0;\r\n                for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++)\r\n                {\r\n                    if (pcmd->UserCallback)\r\n                    {\r\n                        ImGui::BulletText(\"Callback %p, user_data %p\", pcmd->UserCallback, pcmd->UserCallbackData);\r\n                        continue;\r\n                    }\r\n                    ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;\r\n                    bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), \"Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)\", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? \"indexed\" : \"non-indexed\", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);\r\n                    if (show_clip_rects && ImGui::IsItemHovered())\r\n                    {\r\n                        ImRect clip_rect = pcmd->ClipRect;\r\n                        ImRect vtxs_rect;\r\n                        for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++)\r\n                            vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos);\r\n                        clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255));\r\n                        vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255));\r\n                    }\r\n                    if (!pcmd_node_open)\r\n                        continue;\r\n                    ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.\r\n                    while (clipper.Step())\r\n                        for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)\r\n                        {\r\n                            char buf[300], *buf_p = buf;\r\n                            ImVec2 triangles_pos[3];\r\n                            for (int n = 0; n < 3; n++, vtx_i++)\r\n                            {\r\n                                ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i];\r\n                                triangles_pos[n] = v.pos;\r\n                                buf_p += sprintf(buf_p, \"%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\\n\", (n == 0) ? \"vtx\" : \"   \", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);\r\n                            }\r\n                            ImGui::Selectable(buf, false);\r\n                            if (ImGui::IsItemHovered())\r\n                                overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false);  // Add triangle without AA, more readable for large-thin triangle\r\n                        }\r\n                    ImGui::TreePop();\r\n                }\r\n                overlay_draw_list->PopClipRect();\r\n                ImGui::TreePop();\r\n            }\r\n\r\n            static void NodeWindows(ImVector<ImGuiWindow*>& windows, const char* label)\r\n            {\r\n                if (!ImGui::TreeNode(label, \"%s (%d)\", label, windows.Size))\r\n                    return;\r\n                for (int i = 0; i < windows.Size; i++)\r\n                    Funcs::NodeWindow(windows[i], \"Window\");\r\n                ImGui::TreePop();\r\n            }\r\n\r\n            static void NodeWindow(ImGuiWindow* window, const char* label)\r\n            {\r\n                if (!ImGui::TreeNode(window, \"%s '%s', %d @ 0x%p\", label, window->Name, window->Active || window->WasActive, window))\r\n                    return;\r\n                NodeDrawList(window->DrawList, \"DrawList\");\r\n                ImGui::BulletText(\"Pos: (%.1f,%.1f)\", window->Pos.x, window->Pos.y);\r\n                ImGui::BulletText(\"Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)\", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y);\r\n                ImGui::BulletText(\"Scroll: (%.2f,%.2f)\", window->Scroll.x, window->Scroll.y);\r\n                ImGui::BulletText(\"Active: %d, Accessed: %d\", window->Active, window->Accessed);\r\n                if (window->RootWindow != window) NodeWindow(window->RootWindow, \"RootWindow\");\r\n                if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, \"ChildWindows\");\r\n                ImGui::BulletText(\"Storage: %d bytes\", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));\r\n                ImGui::TreePop();\r\n            }\r\n        };\r\n\r\n        ImGuiContext& g = *GImGui;                // Access private state\r\n        Funcs::NodeWindows(g.Windows, \"Windows\");\r\n        if (ImGui::TreeNode(\"DrawList\", \"Active DrawLists (%d)\", g.RenderDrawLists[0].Size))\r\n        {\r\n            for (int i = 0; i < g.RenderDrawLists[0].Size; i++)\r\n                Funcs::NodeDrawList(g.RenderDrawLists[0][i], \"DrawList\");\r\n            ImGui::TreePop();\r\n        }\r\n        if (ImGui::TreeNode(\"Popups\", \"Open Popups Stack (%d)\", g.OpenPopupStack.Size))\r\n        {\r\n            for (int i = 0; i < g.OpenPopupStack.Size; i++)\r\n            {\r\n                ImGuiWindow* window = g.OpenPopupStack[i].Window;\r\n                ImGui::BulletText(\"PopupID: %08x, Window: '%s'%s%s\", g.OpenPopupStack[i].PopupId, window ? window->Name : \"NULL\", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? \" ChildWindow\" : \"\", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? \" ChildMenu\" : \"\");\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n        if (ImGui::TreeNode(\"Basic state\"))\r\n        {\r\n            ImGui::Text(\"HoveredWindow: '%s'\", g.HoveredWindow ? g.HoveredWindow->Name : \"NULL\");\r\n            ImGui::Text(\"HoveredRootWindow: '%s'\", g.HoveredRootWindow ? g.HoveredRootWindow->Name : \"NULL\");\r\n            ImGui::Text(\"HoveredId: 0x%08X/0x%08X\", g.HoveredId, g.HoveredIdPreviousFrame); // Data is \"in-flight\" so depending on when the Metrics window is called we may see current frame information or not\r\n            ImGui::Text(\"ActiveId: 0x%08X/0x%08X\", g.ActiveId, g.ActiveIdPreviousFrame);\r\n            ImGui::Text(\"ActiveIdWindow: '%s'\", g.ActiveIdWindow ? g.ActiveIdWindow->Name : \"NULL\");\r\n            ImGui::Text(\"NavWindow: '%s'\", g.NavWindow ? g.NavWindow->Name : \"NULL\");\r\n            ImGui::TreePop();\r\n        }\r\n    }\r\n    ImGui::End();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n// Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed.\r\n// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github.\r\n#ifdef IMGUI_INCLUDE_IMGUI_USER_INL\r\n#include \"imgui_user.inl\"\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui.h",
    "content": "// dear imgui, v1.52 WIP\r\n// (headers)\r\n\r\n// See imgui.cpp file for documentation.\r\n// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.\r\n// Read 'Programmer guide' in imgui.cpp for notes on how to setup ImGui in your codebase.\r\n// Get latest version at https://github.com/ocornut/imgui\r\n\r\n#pragma once\r\n\r\n#if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H)\r\n#include \"imconfig.h\"       // User-editable configuration file\r\n#endif\r\n#include <float.h>          // FLT_MAX\r\n#include <stdarg.h>         // va_list\r\n#include <stddef.h>         // ptrdiff_t, NULL\r\n#include <string.h>         // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp\r\n\r\n#define IMGUI_VERSION       \"1.52 WIP\"\r\n\r\n// Define attributes of all API symbols declarations, e.g. for DLL under Windows.\r\n#ifndef IMGUI_API\r\n#define IMGUI_API\r\n#endif\r\n\r\n// Define assertion handler.\r\n#ifndef IM_ASSERT\r\n#include <assert.h>\r\n#define IM_ASSERT(_EXPR)    assert(_EXPR)\r\n#endif\r\n\r\n// Some compilers support applying printf-style warnings to user functions.\r\n#if defined(__clang__) || defined(__GNUC__)\r\n#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1)))\r\n#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))\r\n#else\r\n#define IM_FMTARGS(FMT)\r\n#define IM_FMTLIST(FMT)\r\n#endif\r\n\r\n#if defined(__clang__)\r\n#pragma clang diagnostic push\r\n#pragma clang diagnostic ignored \"-Wold-style-cast\"\r\n#endif\r\n\r\n// Forward declarations\r\nstruct ImDrawChannel;               // Temporary storage for outputting drawing commands out of order, used by ImDrawList::ChannelsSplit()\r\nstruct ImDrawCmd;                   // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call)\r\nstruct ImDrawData;                  // All draw command lists required to render the frame\r\nstruct ImDrawList;                  // A single draw command list (generally one per window)\r\nstruct ImDrawVert;                  // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT)\r\nstruct ImFont;                      // Runtime data for a single font within a parent ImFontAtlas\r\nstruct ImFontAtlas;                 // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader\r\nstruct ImFontConfig;                // Configuration data when adding a font or merging fonts\r\nstruct ImColor;                     // Helper functions to create a color that can be converted to either u32 or float4\r\nstruct ImGuiIO;                     // Main configuration and I/O between your application and ImGui\r\nstruct ImGuiOnceUponAFrame;         // Simple helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro\r\nstruct ImGuiStorage;                // Simple custom key value storage\r\nstruct ImGuiStyle;                  // Runtime data for styling/colors\r\nstruct ImGuiTextFilter;             // Parse and apply text filters. In format \"aaaaa[,bbbb][,ccccc]\"\r\nstruct ImGuiTextBuffer;             // Text buffer for logging/accumulating text\r\nstruct ImGuiTextEditCallbackData;   // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use)\r\nstruct ImGuiSizeConstraintCallbackData;// Structure used to constraint window size in custom ways when using custom ImGuiSizeConstraintCallback (rare/advanced use)\r\nstruct ImGuiListClipper;            // Helper to manually clip large list of items\r\nstruct ImGuiContext;                // ImGui context (opaque)\r\n\r\n// Typedefs and Enumerations (declared as int for compatibility and to not pollute the top of this file)\r\ntypedef unsigned int ImU32;         // 32-bit unsigned integer (typically used to store packed colors)\r\ntypedef unsigned int ImGuiID;       // unique ID used by widgets (typically hashed from a stack of string)\r\ntypedef unsigned short ImWchar;     // character for keyboard input/display\r\ntypedef void* ImTextureID;          // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp)\r\ntypedef int ImGuiCol;               // a color identifier for styling       // enum ImGuiCol_\r\ntypedef int ImGuiStyleVar;          // a variable identifier for styling    // enum ImGuiStyleVar_\r\ntypedef int ImGuiKey;               // a key identifier (ImGui-side enum)   // enum ImGuiKey_\r\ntypedef int ImGuiColorEditFlags;    // color edit flags for Color*()        // enum ImGuiColorEditFlags_\r\ntypedef int ImGuiMouseCursor;       // a mouse cursor identifier            // enum ImGuiMouseCursor_\r\ntypedef int ImGuiWindowFlags;       // window flags for Begin*()            // enum ImGuiWindowFlags_\r\ntypedef int ImGuiCond;              // condition flags for Set*()           // enum ImGuiCond_\r\ntypedef int ImGuiColumnsFlags;      // flags for *Columns*()                // enum ImGuiColumnsFlags_\r\ntypedef int ImGuiInputTextFlags;    // flags for InputText*()               // enum ImGuiInputTextFlags_\r\ntypedef int ImGuiSelectableFlags;   // flags for Selectable()               // enum ImGuiSelectableFlags_\r\ntypedef int ImGuiTreeNodeFlags;     // flags for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_\r\ntypedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data);\r\ntypedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data);\r\n#ifdef _MSC_VER\r\ntypedef unsigned __int64 ImU64;     // 64-bit unsigned integer\r\n#else\r\ntypedef unsigned long long ImU64;   // 64-bit unsigned integer\r\n#endif \r\n\r\n// Others helpers at bottom of the file:\r\n// class ImVector<>                 // Lightweight std::vector like class.\r\n// IMGUI_ONCE_UPON_A_FRAME          // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times)\r\n\r\nstruct ImVec2\r\n{\r\n    float x, y;\r\n    ImVec2() { x = y = 0.0f; }\r\n    ImVec2(float _x, float _y) { x = _x; y = _y; }\r\n#ifdef IM_VEC2_CLASS_EXTRA          // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2.\r\n    IM_VEC2_CLASS_EXTRA\r\n#endif\r\n};\r\n\r\nstruct ImVec4\r\n{\r\n    float x, y, z, w;\r\n    ImVec4() { x = y = z = w = 0.0f; }\r\n    ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }\r\n#ifdef IM_VEC4_CLASS_EXTRA          // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec4.\r\n    IM_VEC4_CLASS_EXTRA\r\n#endif\r\n};\r\n\r\n// ImGui end-user API\r\n// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types)\r\nnamespace ImGui\r\n{\r\n    // Main\r\n    IMGUI_API ImGuiIO&      GetIO();\r\n    IMGUI_API ImGuiStyle&   GetStyle();\r\n    IMGUI_API ImDrawData*   GetDrawData();                              // same value as passed to your io.RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame()\r\n    IMGUI_API void          NewFrame();                                 // start a new ImGui frame, you can submit any command from this point until NewFrame()/Render().\r\n    IMGUI_API void          Render();                                   // ends the ImGui frame, finalize rendering data, then call your io.RenderDrawListsFn() function if set.\r\n    IMGUI_API void          Shutdown();\r\n\r\n    // Demo/Debug/Info\r\n    IMGUI_API void          ShowTestWindow(bool* p_open = NULL);        // create demo/test window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!\r\n    IMGUI_API void          ShowMetricsWindow(bool* p_open = NULL);     // create metrics window. display ImGui internals: browse window list, draw commands, individual vertices, basic internal state, etc.\r\n    IMGUI_API void          ShowStyleEditor(ImGuiStyle* ref = NULL);    // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style)\r\n    IMGUI_API void          ShowUserGuide();                            // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls).\r\n\r\n    // Window\r\n    IMGUI_API bool          Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);                                                   // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false).\r\n    IMGUI_API bool          Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually.\r\n    IMGUI_API void          End();                                                                                                                      // finish appending to current window, pop it off the window stack.\r\n    IMGUI_API bool          BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);    // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).\r\n    IMGUI_API bool          BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);            // \"\r\n    IMGUI_API void          EndChild();\r\n    IMGUI_API ImVec2        GetContentRegionMax();                                              // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates\r\n    IMGUI_API ImVec2        GetContentRegionAvail();                                            // == GetContentRegionMax() - GetCursorPos()\r\n    IMGUI_API float         GetContentRegionAvailWidth();                                       //\r\n    IMGUI_API ImVec2        GetWindowContentRegionMin();                                        // content boundaries min (roughly (0,0)-Scroll), in window coordinates\r\n    IMGUI_API ImVec2        GetWindowContentRegionMax();                                        // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates\r\n    IMGUI_API float         GetWindowContentRegionWidth();                                      //\r\n    IMGUI_API ImDrawList*   GetWindowDrawList();                                                // get rendering command-list if you want to append your own draw primitives\r\n    IMGUI_API ImVec2        GetWindowPos();                                                     // get current window position in screen space (useful if you want to do your own drawing via the DrawList api)\r\n    IMGUI_API ImVec2        GetWindowSize();                                                    // get current window size\r\n    IMGUI_API float         GetWindowWidth();\r\n    IMGUI_API float         GetWindowHeight();\r\n    IMGUI_API bool          IsWindowCollapsed();\r\n    IMGUI_API bool          IsWindowAppearing();\r\n    IMGUI_API void          SetWindowFontScale(float scale);                                    // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows\r\n\r\n    IMGUI_API void          SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0);            // set next window position. call before Begin()\r\n    IMGUI_API void          SetNextWindowPosCenter(ImGuiCond cond = 0);                         // set next window position to be centered on screen. call before Begin()\r\n    IMGUI_API void          SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0);          // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()\r\n    IMGUI_API void          SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints.\r\n    IMGUI_API void          SetNextWindowContentSize(const ImVec2& size);                       // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin()\r\n    IMGUI_API void          SetNextWindowContentWidth(float width);                             // set next window content width (enforce the range of horizontal scrollbar). call before Begin()\r\n    IMGUI_API void          SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0);         // set next window collapsed state. call before Begin()\r\n    IMGUI_API void          SetNextWindowFocus();                                               // set next window to be focused / front-most. call before Begin()\r\n    IMGUI_API void          SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0);                // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects.\r\n    IMGUI_API void          SetWindowSize(const ImVec2& size, ImGuiCond cond = 0);              // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects.    \r\n    IMGUI_API void          SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0);             // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed().\r\n    IMGUI_API void          SetWindowFocus();                                                   // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus().\r\n    IMGUI_API void          SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0);      // set named window position.\r\n    IMGUI_API void          SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0);    // set named window size. set axis to 0.0f to force an auto-fit on this axis.\r\n    IMGUI_API void          SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0);   // set named window collapsed state\r\n    IMGUI_API void          SetWindowFocus(const char* name);                                           // set named window to be focused / front-most. use NULL to remove focus.\r\n\r\n    IMGUI_API float         GetScrollX();                                                       // get scrolling amount [0..GetScrollMaxX()]\r\n    IMGUI_API float         GetScrollY();                                                       // get scrolling amount [0..GetScrollMaxY()]\r\n    IMGUI_API float         GetScrollMaxX();                                                    // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X\r\n    IMGUI_API float         GetScrollMaxY();                                                    // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y\r\n    IMGUI_API void          SetScrollX(float scroll_x);                                         // set scrolling amount [0..GetScrollMaxX()]\r\n    IMGUI_API void          SetScrollY(float scroll_y);                                         // set scrolling amount [0..GetScrollMaxY()]\r\n    IMGUI_API void          SetScrollHere(float center_y_ratio = 0.5f);                         // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom.\r\n    IMGUI_API void          SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f);        // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions.\r\n    IMGUI_API void          SetKeyboardFocusHere(int offset = 0);                               // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use negative 'offset' to access previous widgets.\r\n    IMGUI_API void          SetStateStorage(ImGuiStorage* tree);                                // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it)\r\n    IMGUI_API ImGuiStorage* GetStateStorage();\r\n\r\n    // Parameters stacks (shared)\r\n    IMGUI_API void          PushFont(ImFont* font);                                             // use NULL as a shortcut to push default font\r\n    IMGUI_API void          PopFont();\r\n    IMGUI_API void          PushStyleColor(ImGuiCol idx, ImU32 col);\r\n    IMGUI_API void          PushStyleColor(ImGuiCol idx, const ImVec4& col);\r\n    IMGUI_API void          PopStyleColor(int count = 1);\r\n    IMGUI_API void          PushStyleVar(ImGuiStyleVar idx, float val);\r\n    IMGUI_API void          PushStyleVar(ImGuiStyleVar idx, const ImVec2& val);\r\n    IMGUI_API void          PopStyleVar(int count = 1);\r\n    IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx);                                    // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwhise use GetColorU32() to get style color + style alpha.\r\n    IMGUI_API ImFont*       GetFont();                                                          // get current font\r\n    IMGUI_API float         GetFontSize();                                                      // get current font size (= height in pixels) of current font with current scale applied\r\n    IMGUI_API ImVec2        GetFontTexUvWhitePixel();                                           // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API\r\n    IMGUI_API ImU32         GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f);                  // retrieve given style color with style alpha applied and optional extra alpha multiplier\r\n    IMGUI_API ImU32         GetColorU32(const ImVec4& col);                                     // retrieve given color with style alpha applied\r\n    IMGUI_API ImU32         GetColorU32(ImU32 col);                                             // retrieve given color with style alpha applied\r\n\r\n    // Parameters stacks (current window)\r\n    IMGUI_API void          PushItemWidth(float item_width);                                    // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side)\r\n    IMGUI_API void          PopItemWidth();\r\n    IMGUI_API float         CalcItemWidth();                                                    // width of item given pushed settings and current cursor position\r\n    IMGUI_API void          PushTextWrapPos(float wrap_pos_x = 0.0f);                           // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space\r\n    IMGUI_API void          PopTextWrapPos();\r\n    IMGUI_API void          PushAllowKeyboardFocus(bool allow_keyboard_focus);                  // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets\r\n    IMGUI_API void          PopAllowKeyboardFocus();\r\n    IMGUI_API void          PushButtonRepeat(bool repeat);                                      // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.\r\n    IMGUI_API void          PopButtonRepeat();\r\n\r\n    // Cursor / Layout\r\n    IMGUI_API void          Separator();                                                        // horizontal line\r\n    IMGUI_API void          SameLine(float pos_x = 0.0f, float spacing_w = -1.0f);              // call between widgets or groups to layout them horizontally\r\n    IMGUI_API void          NewLine();                                                          // undo a SameLine()\r\n    IMGUI_API void          Spacing();                                                          // add vertical spacing\r\n    IMGUI_API void          Dummy(const ImVec2& size);                                          // add a dummy item of given size\r\n    IMGUI_API void          Indent(float indent_w = 0.0f);                                      // move content position toward the right, by style.IndentSpacing or indent_w if >0\r\n    IMGUI_API void          Unindent(float indent_w = 0.0f);                                    // move content position back to the left, by style.IndentSpacing or indent_w if >0\r\n    IMGUI_API void          BeginGroup();                                                       // lock horizontal starting position + capture group bounding box into one \"item\" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)\r\n    IMGUI_API void          EndGroup();\r\n    IMGUI_API ImVec2        GetCursorPos();                                                     // cursor position is relative to window position\r\n    IMGUI_API float         GetCursorPosX();                                                    // \"\r\n    IMGUI_API float         GetCursorPosY();                                                    // \"\r\n    IMGUI_API void          SetCursorPos(const ImVec2& local_pos);                              // \"\r\n    IMGUI_API void          SetCursorPosX(float x);                                             // \"\r\n    IMGUI_API void          SetCursorPosY(float y);                                             // \"\r\n    IMGUI_API ImVec2        GetCursorStartPos();                                                // initial cursor position\r\n    IMGUI_API ImVec2        GetCursorScreenPos();                                               // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API)\r\n    IMGUI_API void          SetCursorScreenPos(const ImVec2& pos);                              // cursor position in absolute screen coordinates [0..io.DisplaySize]\r\n    IMGUI_API void          AlignFirstTextHeightToWidgets();                                    // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets\r\n    IMGUI_API float         GetTextLineHeight();                                                // height of font == GetWindowFontSize()\r\n    IMGUI_API float         GetTextLineHeightWithSpacing();                                     // distance (in pixels) between 2 consecutive lines of text == GetWindowFontSize() + GetStyle().ItemSpacing.y\r\n    IMGUI_API float         GetItemsLineHeightWithSpacing();                                    // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y\r\n\r\n    // Columns\r\n    // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking.\r\n    IMGUI_API void          Columns(int count = 1, const char* id = NULL, bool border = true);\r\n    IMGUI_API void          NextColumn();                                                       // next column, defaults to current row or next row if the current row is finished\r\n    IMGUI_API int           GetColumnIndex();                                                   // get current column index\r\n    IMGUI_API float         GetColumnWidth(int column_index = -1);                              // get column width (in pixels). pass -1 to use current column\r\n    IMGUI_API void          SetColumnWidth(int column_index, float width);                      // set column width (in pixels). pass -1 to use current column\r\n    IMGUI_API float         GetColumnOffset(int column_index = -1);                             // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f\r\n    IMGUI_API void          SetColumnOffset(int column_index, float offset_x);                  // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column\r\n    IMGUI_API int           GetColumnsCount();\r\n\r\n    // ID scopes\r\n    // If you are creating widgets in a loop you most likely want to push a unique identifier (e.g. object pointer, loop index) so ImGui can differentiate them.\r\n    // You can also use the \"##foobar\" syntax within widget label to distinguish them from each others. Read \"A primer on the use of labels/IDs\" in the FAQ for more details.\r\n    IMGUI_API void          PushID(const char* str_id);                                         // push identifier into the ID stack. IDs are hash of the entire stack!\r\n    IMGUI_API void          PushID(const char* str_id_begin, const char* str_id_end);\r\n    IMGUI_API void          PushID(const void* ptr_id);\r\n    IMGUI_API void          PushID(int int_id);\r\n    IMGUI_API void          PopID();\r\n    IMGUI_API ImGuiID       GetID(const char* str_id);                                          // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself\r\n    IMGUI_API ImGuiID       GetID(const char* str_id_begin, const char* str_id_end);\r\n    IMGUI_API ImGuiID       GetID(const void* ptr_id);\r\n\r\n    // Widgets: Text\r\n    IMGUI_API void          TextUnformatted(const char* text, const char* text_end = NULL);               // doesn't require null terminated string if 'text_end' is specified. no copy done, no limits, recommended for long chunks of text\r\n    IMGUI_API void          Text(const char* fmt, ...)                                     IM_FMTARGS(1); // simple formatted text\r\n    IMGUI_API void          TextV(const char* fmt, va_list args)                           IM_FMTLIST(1);\r\n    IMGUI_API void          TextColored(const ImVec4& col, const char* fmt, ...)           IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();\r\n    IMGUI_API void          TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2);\r\n    IMGUI_API void          TextDisabled(const char* fmt, ...)                             IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor();\r\n    IMGUI_API void          TextDisabledV(const char* fmt, va_list args)                   IM_FMTLIST(1);\r\n    IMGUI_API void          TextWrapped(const char* fmt, ...)                              IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize().\r\n    IMGUI_API void          TextWrappedV(const char* fmt, va_list args)                    IM_FMTLIST(1);\r\n    IMGUI_API void          LabelText(const char* label, const char* fmt, ...)             IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets\r\n    IMGUI_API void          LabelTextV(const char* label, const char* fmt, va_list args)   IM_FMTLIST(2);\r\n    IMGUI_API void          BulletText(const char* fmt, ...)                               IM_FMTARGS(1); // shortcut for Bullet()+Text()\r\n    IMGUI_API void          BulletTextV(const char* fmt, va_list args)                     IM_FMTLIST(1);\r\n    IMGUI_API void          Bullet();                                                                     // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses\r\n\r\n    // Widgets: Main\r\n    IMGUI_API bool          Button(const char* label, const ImVec2& size = ImVec2(0,0));            // button\r\n    IMGUI_API bool          SmallButton(const char* label);                                         // button with FramePadding=(0,0) to easily embed within text\r\n    IMGUI_API bool          InvisibleButton(const char* str_id, const ImVec2& size);\r\n    IMGUI_API void          Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));\r\n    IMGUI_API bool          ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0),  const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1));    // <0 frame_padding uses default frame padding settings. 0 for no padding\r\n    IMGUI_API bool          Checkbox(const char* label, bool* v);\r\n    IMGUI_API bool          CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);\r\n    IMGUI_API bool          RadioButton(const char* label, bool active);\r\n    IMGUI_API bool          RadioButton(const char* label, int* v, int v_button);\r\n    IMGUI_API bool          Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1);\r\n    IMGUI_API bool          Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1);    // separate items with \\0, end item-list with \\0\\0\r\n    IMGUI_API bool          Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);\r\n    IMGUI_API void          PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float));\r\n    IMGUI_API void          PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));\r\n    IMGUI_API void          PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float));\r\n    IMGUI_API void          PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));\r\n    IMGUI_API void          ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL);\r\n\r\n    // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds)\r\n    // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x\r\n    IMGUI_API bool          DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = \"%.3f\", float power = 1.0f);     // If v_min >= v_max we have no bound\r\n    IMGUI_API bool          DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = \"%.3f\", const char* display_format_max = NULL, float power = 1.0f);\r\n    IMGUI_API bool          DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = \"%.0f\");                                       // If v_min >= v_max we have no bound\r\n    IMGUI_API bool          DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = \"%.0f\", const char* display_format_max = NULL);\r\n\r\n    // Widgets: Input with Keyboard\r\n    IMGUI_API bool          InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);\r\n    IMGUI_API bool          InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);\r\n    IMGUI_API bool          InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0);\r\n    IMGUI_API bool          InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0);\r\n\r\n    // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go off-bounds)\r\n    IMGUI_API bool          SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = \"%.3f\", float power = 1.0f);     // adjust display_format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for logarithmic sliders\r\n    IMGUI_API bool          SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f);\r\n    IMGUI_API bool          SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format = \"%.0f\");\r\n    IMGUI_API bool          VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = \"%.3f\", float power = 1.0f);\r\n    IMGUI_API bool          VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = \"%.0f\");\r\n\r\n    // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.)\r\n    // Note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can the pass the address of a first float element out of a contiguous structure, e.g. &myvector.x\r\n    IMGUI_API bool          ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);\r\n    IMGUI_API bool          ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0);\r\n    IMGUI_API bool          ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);\r\n    IMGUI_API bool          ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);\r\n    IMGUI_API bool          ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0));  // display a colored square/button, hover for details, return true when pressed.\r\n    IMGUI_API void          SetColorEditOptions(ImGuiColorEditFlags flags);                         // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.\r\n\r\n    // Widgets: Trees\r\n    IMGUI_API bool          TreeNode(const char* label);                                            // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop().\r\n    IMGUI_API bool          TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2);       // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet().\r\n    IMGUI_API bool          TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2);       // \"\r\n    IMGUI_API bool          TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2);\r\n    IMGUI_API bool          TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2);\r\n    IMGUI_API bool          TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0);\r\n    IMGUI_API bool          TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);\r\n    IMGUI_API bool          TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);\r\n    IMGUI_API bool          TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);\r\n    IMGUI_API bool          TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);\r\n    IMGUI_API void          TreePush(const char* str_id = NULL);                                    // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose\r\n    IMGUI_API void          TreePush(const void* ptr_id = NULL);                                    // \"\r\n    IMGUI_API void          TreePop();                                                              // ~ Unindent()+PopId()\r\n    IMGUI_API void          TreeAdvanceToLabelPos();                                                // advance cursor x position by GetTreeNodeToLabelSpacing()\r\n    IMGUI_API float         GetTreeNodeToLabelSpacing();                                            // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode\r\n    IMGUI_API void          SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0);               // set next TreeNode/CollapsingHeader open state.\r\n    IMGUI_API bool          CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0);      // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop().\r\n    IMGUI_API bool          CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header\r\n\r\n    // Widgets: Selectable / Lists\r\n    IMGUI_API bool          Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0));  // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height\r\n    IMGUI_API bool          Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0));\r\n    IMGUI_API bool          ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1);\r\n    IMGUI_API bool          ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);\r\n    IMGUI_API bool          ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards.\r\n    IMGUI_API bool          ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // \"\r\n    IMGUI_API void          ListBoxFooter();                                                    // terminate the scrolling region\r\n\r\n    // Widgets: Value() Helpers. Output single value in \"name: value\" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace)\r\n    IMGUI_API void          Value(const char* prefix, bool b);\r\n    IMGUI_API void          Value(const char* prefix, int v);\r\n    IMGUI_API void          Value(const char* prefix, unsigned int v);\r\n    IMGUI_API void          Value(const char* prefix, float v, const char* float_format = NULL);\r\n\r\n    // Tooltips\r\n    IMGUI_API void          SetTooltip(const char* fmt, ...) IM_FMTARGS(1);                     // set text tooltip under mouse-cursor, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip().\r\n    IMGUI_API void          SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);\r\n    IMGUI_API void          BeginTooltip();                                                     // begin/append a tooltip window. to create full-featured tooltip (with any kind of contents).\r\n    IMGUI_API void          EndTooltip();\r\n\r\n    // Menus\r\n    IMGUI_API bool          BeginMainMenuBar();                                                 // create and append to a full screen menu-bar. only call EndMainMenuBar() if this returns true!\r\n    IMGUI_API void          EndMainMenuBar();\r\n    IMGUI_API bool          BeginMenuBar();                                                     // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set). only call EndMenuBar() if this returns true!\r\n    IMGUI_API void          EndMenuBar();\r\n    IMGUI_API bool          BeginMenu(const char* label, bool enabled = true);                  // create a sub-menu entry. only call EndMenu() if this returns true!\r\n    IMGUI_API void          EndMenu();\r\n    IMGUI_API bool          MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true);  // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment\r\n    IMGUI_API bool          MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true);              // return true when activated + toggle (*p_selected) if p_selected != NULL\r\n\r\n    // Popups\r\n    IMGUI_API void          OpenPopup(const char* str_id);                                      // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).\r\n    IMGUI_API bool          BeginPopup(const char* str_id);                                     // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true!\r\n    IMGUI_API bool          BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0);               // modal dialog (block interactions behind the modal window, can't close the modal window by clicking outside)\r\n    IMGUI_API bool          BeginPopupContextItem(const char* str_id, int mouse_button = 1);                                        // helper to open and begin popup when clicked on last item. read comments in .cpp!\r\n    IMGUI_API bool          BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true);  // helper to open and begin popup when clicked on current window.\r\n    IMGUI_API bool          BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1);                                 // helper to open and begin popup when clicked in void (no window).\r\n    IMGUI_API void          EndPopup();\r\n    IMGUI_API bool          IsPopupOpen(const char* str_id);                                    // return true if the popup is open\r\n    IMGUI_API void          CloseCurrentPopup();                                                // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup.\r\n\r\n    // Logging: all text output from interface is redirected to tty/file/clipboard. By default, tree nodes are automatically opened during logging.\r\n    IMGUI_API void          LogToTTY(int max_depth = -1);                                       // start logging to tty\r\n    IMGUI_API void          LogToFile(int max_depth = -1, const char* filename = NULL);         // start logging to file\r\n    IMGUI_API void          LogToClipboard(int max_depth = -1);                                 // start logging to OS clipboard\r\n    IMGUI_API void          LogFinish();                                                        // stop logging (close file, etc.)\r\n    IMGUI_API void          LogButtons();                                                       // helper to display buttons for logging to tty/file/clipboard\r\n    IMGUI_API void          LogText(const char* fmt, ...) IM_FMTARGS(1);                        // pass text data straight to log (without being displayed)\r\n\r\n    // Clipping\r\n    IMGUI_API void          PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect);\r\n    IMGUI_API void          PopClipRect();\r\n\r\n    // Utilities\r\n    IMGUI_API bool          IsItemHovered();                                                    // is the last item hovered by mouse (and usable)?\r\n    IMGUI_API bool          IsItemRectHovered();                                                // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this\r\n    IMGUI_API bool          IsItemActive();                                                     // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false)\r\n    IMGUI_API bool          IsItemClicked(int mouse_button = 0);                                // is the last item clicked? (e.g. button/node just clicked on)\r\n    IMGUI_API bool          IsItemVisible();                                                    // is the last item visible? (aka not out of sight due to clipping/scrolling.)\r\n    IMGUI_API bool          IsAnyItemHovered();\r\n    IMGUI_API bool          IsAnyItemActive();\r\n    IMGUI_API ImVec2        GetItemRectMin();                                                   // get bounding rect of last item in screen space\r\n    IMGUI_API ImVec2        GetItemRectMax();                                                   // \"\r\n    IMGUI_API ImVec2        GetItemRectSize();                                                  // \"\r\n    IMGUI_API void          SetItemAllowOverlap();                                              // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.\r\n    IMGUI_API bool          IsWindowFocused();                                                  // is current window focused\r\n    IMGUI_API bool          IsWindowHovered();                                                  // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others)\r\n    IMGUI_API bool          IsWindowRectHovered();                                              // is current window rectangle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup)\r\n    IMGUI_API bool          IsRootWindowFocused();                                              // is current root window focused (root = top-most parent of a child, otherwise self)\r\n    IMGUI_API bool          IsRootWindowOrAnyChildFocused();                                    // is current root window or any of its child (including current window) focused\r\n    IMGUI_API bool          IsRootWindowOrAnyChildHovered();                                    // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)\r\n    IMGUI_API bool          IsAnyWindowHovered();                                               // is mouse hovering any visible window\r\n    IMGUI_API bool          IsRectVisible(const ImVec2& size);                                  // test if rectangle (of given size, starting from cursor position) is visible / not clipped.\r\n    IMGUI_API bool          IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max);      // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side.\r\n    IMGUI_API float         GetTime();\r\n    IMGUI_API int           GetFrameCount();\r\n    IMGUI_API const char*   GetStyleColorName(ImGuiCol idx);\r\n    IMGUI_API ImVec2        CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f);   // utility to find the closest point the last item bounding rectangle edge. useful to visually link items\r\n    IMGUI_API ImVec2        CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);\r\n    IMGUI_API void          CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end);    // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.\r\n\r\n    IMGUI_API bool          BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0);    // helper to create a child window / scrolling region that looks like a normal widget frame\r\n    IMGUI_API void          EndChildFrame();\r\n\r\n    IMGUI_API ImVec4        ColorConvertU32ToFloat4(ImU32 in);\r\n    IMGUI_API ImU32         ColorConvertFloat4ToU32(const ImVec4& in);\r\n    IMGUI_API void          ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);\r\n    IMGUI_API void          ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);\r\n\r\n    // Inputs\r\n    IMGUI_API int           GetKeyIndex(ImGuiKey imgui_key);                                    // map ImGuiKey_* values into user's key index. == io.KeyMap[key]\r\n    IMGUI_API bool          IsKeyDown(int user_key_index);                                      // is key being held. == io.KeysDown[user_key_index]. note that imgui doesn't know the semantic of each entry of io.KeyDown[]. Use your own indices/enums according to how your backend/engine stored them into KeyDown[]!\r\n    IMGUI_API bool          IsKeyPressed(int user_key_index, bool repeat = true);               // was key pressed (went from !Down to Down). if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate\r\n    IMGUI_API bool          IsKeyReleased(int user_key_index);                                  // was key released (went from Down to !Down)..\r\n    IMGUI_API int           GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate\r\n    IMGUI_API bool          IsMouseDown(int button);                                            // is mouse button held\r\n    IMGUI_API bool          IsMouseClicked(int button, bool repeat = false);                    // did mouse button clicked (went from !Down to Down)\r\n    IMGUI_API bool          IsMouseDoubleClicked(int button);                                   // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime.\r\n    IMGUI_API bool          IsMouseReleased(int button);                                        // did mouse button released (went from Down to !Down)\r\n    IMGUI_API bool          IsMouseDragging(int button = 0, float lock_threshold = -1.0f);      // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold\r\n    IMGUI_API bool          IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);  // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup.\r\n    IMGUI_API bool          IsMousePosValid(const ImVec2* mouse_pos = NULL);                    //\r\n    IMGUI_API ImVec2        GetMousePos();                                                      // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls\r\n    IMGUI_API ImVec2        GetMousePosOnOpeningCurrentPopup();                                 // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into\r\n    IMGUI_API ImVec2        GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f);    // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold\r\n    IMGUI_API void          ResetMouseDragDelta(int button = 0);                                //\r\n    IMGUI_API ImGuiMouseCursor GetMouseCursor();                                                // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you\r\n    IMGUI_API void          SetMouseCursor(ImGuiMouseCursor type);                              // set desired cursor type\r\n    IMGUI_API void          CaptureKeyboardFromApp(bool capture = true);                        // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application handle). e.g. force capture keyboard when your widget is being hovered.\r\n    IMGUI_API void          CaptureMouseFromApp(bool capture = true);                           // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application handle).\r\n\r\n    // Helpers functions to access functions pointers in ImGui::GetIO()\r\n    IMGUI_API void*         MemAlloc(size_t sz);\r\n    IMGUI_API void          MemFree(void* ptr);\r\n    IMGUI_API const char*   GetClipboardText();\r\n    IMGUI_API void          SetClipboardText(const char* text);\r\n\r\n    // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default.\r\n    // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context.\r\n    IMGUI_API const char*   GetVersion();\r\n    IMGUI_API ImGuiContext* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL);\r\n    IMGUI_API void          DestroyContext(ImGuiContext* ctx);\r\n    IMGUI_API ImGuiContext* GetCurrentContext();\r\n    IMGUI_API void          SetCurrentContext(ImGuiContext* ctx);\r\n\r\n    // Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp)\r\n#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS\r\n    static inline bool      IsItemHoveredRect() { return IsItemRectHovered(); }                // OBSOLETE 1.51+\r\n    static inline bool      IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead.\r\n    static inline bool      IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); }        // OBSOLETE 1.51+\r\n    static inline bool      IsMouseHoveringWindow() { return IsWindowRectHovered(); }          // OBSOLETE 1.51+\r\n    static inline bool      CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+\r\n    static inline ImFont*   GetWindowFont() { return GetFont(); }                              // OBSOLETE 1.48+\r\n    static inline float     GetWindowFontSize() { return GetFontSize(); }                      // OBSOLETE 1.48+\r\n    static inline void      SetScrollPosHere() { SetScrollHere(); }                            // OBSOLETE 1.42+\r\n#endif\r\n\r\n} // namespace ImGui\r\n\r\n// Flags for ImGui::Begin()\r\nenum ImGuiWindowFlags_\r\n{\r\n    // Default: 0\r\n    ImGuiWindowFlags_NoTitleBar             = 1 << 0,   // Disable title-bar\r\n    ImGuiWindowFlags_NoResize               = 1 << 1,   // Disable user resizing with the lower-right grip\r\n    ImGuiWindowFlags_NoMove                 = 1 << 2,   // Disable user moving the window\r\n    ImGuiWindowFlags_NoScrollbar            = 1 << 3,   // Disable scrollbars (window can still scroll with mouse or programatically)\r\n    ImGuiWindowFlags_NoScrollWithMouse      = 1 << 4,   // Disable user vertically scrolling with mouse wheel\r\n    ImGuiWindowFlags_NoCollapse             = 1 << 5,   // Disable user collapsing window by double-clicking on it\r\n    ImGuiWindowFlags_AlwaysAutoResize       = 1 << 6,   // Resize every window to its content every frame\r\n    ImGuiWindowFlags_ShowBorders            = 1 << 7,   // Show borders around windows and items\r\n    ImGuiWindowFlags_NoSavedSettings        = 1 << 8,   // Never load/save settings in .ini file\r\n    ImGuiWindowFlags_NoInputs               = 1 << 9,   // Disable catching mouse or keyboard inputs\r\n    ImGuiWindowFlags_MenuBar                = 1 << 10,  // Has a menu-bar\r\n    ImGuiWindowFlags_HorizontalScrollbar    = 1 << 11,  // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the \"Horizontal Scrolling\" section.\r\n    ImGuiWindowFlags_NoFocusOnAppearing     = 1 << 12,  // Disable taking focus when transitioning from hidden to visible state\r\n    ImGuiWindowFlags_NoBringToFrontOnFocus  = 1 << 13,  // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus)\r\n    ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14,  // Always show vertical scrollbar (even if ContentSize.y < Size.y)\r\n    ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15,  // Always show horizontal scrollbar (even if ContentSize.x < Size.x)\r\n    ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16,  // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)\r\n    // [Internal]\r\n    ImGuiWindowFlags_ChildWindow            = 1 << 22,  // Don't use! For internal use by BeginChild()\r\n    ImGuiWindowFlags_ComboBox               = 1 << 23,  // Don't use! For internal use by ComboBox()\r\n    ImGuiWindowFlags_Tooltip                = 1 << 24,  // Don't use! For internal use by BeginTooltip()\r\n    ImGuiWindowFlags_Popup                  = 1 << 25,  // Don't use! For internal use by BeginPopup()\r\n    ImGuiWindowFlags_Modal                  = 1 << 26,  // Don't use! For internal use by BeginPopupModal()\r\n    ImGuiWindowFlags_ChildMenu              = 1 << 27   // Don't use! For internal use by BeginMenu()\r\n};\r\n\r\n// Flags for ImGui::InputText()\r\nenum ImGuiInputTextFlags_\r\n{\r\n    // Default: 0\r\n    ImGuiInputTextFlags_CharsDecimal        = 1 << 0,   // Allow 0123456789.+-*/\r\n    ImGuiInputTextFlags_CharsHexadecimal    = 1 << 1,   // Allow 0123456789ABCDEFabcdef\r\n    ImGuiInputTextFlags_CharsUppercase      = 1 << 2,   // Turn a..z into A..Z\r\n    ImGuiInputTextFlags_CharsNoBlank        = 1 << 3,   // Filter out spaces, tabs\r\n    ImGuiInputTextFlags_AutoSelectAll       = 1 << 4,   // Select entire text when first taking mouse focus\r\n    ImGuiInputTextFlags_EnterReturnsTrue    = 1 << 5,   // Return 'true' when Enter is pressed (as opposed to when the value was modified)\r\n    ImGuiInputTextFlags_CallbackCompletion  = 1 << 6,   // Call user function on pressing TAB (for completion handling)\r\n    ImGuiInputTextFlags_CallbackHistory     = 1 << 7,   // Call user function on pressing Up/Down arrows (for history handling)\r\n    ImGuiInputTextFlags_CallbackAlways      = 1 << 8,   // Call user function every time. User code may query cursor position, modify text buffer.\r\n    ImGuiInputTextFlags_CallbackCharFilter  = 1 << 9,   // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 to discard character.\r\n    ImGuiInputTextFlags_AllowTabInput       = 1 << 10,  // Pressing TAB input a '\\t' character into the text field\r\n    ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11,  // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter).\r\n    ImGuiInputTextFlags_NoHorizontalScroll  = 1 << 12,  // Disable following the cursor horizontally\r\n    ImGuiInputTextFlags_AlwaysInsertMode    = 1 << 13,  // Insert mode\r\n    ImGuiInputTextFlags_ReadOnly            = 1 << 14,  // Read-only mode\r\n    ImGuiInputTextFlags_Password            = 1 << 15,  // Password mode, display all characters as '*'\r\n    // [Internal]\r\n    ImGuiInputTextFlags_Multiline           = 1 << 20   // For internal use by InputTextMultiline()\r\n};\r\n\r\n// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*()\r\nenum ImGuiTreeNodeFlags_\r\n{\r\n    ImGuiTreeNodeFlags_Selected             = 1 << 0,   // Draw as selected\r\n    ImGuiTreeNodeFlags_Framed               = 1 << 1,   // Full colored frame (e.g. for CollapsingHeader)\r\n    ImGuiTreeNodeFlags_AllowOverlapMode     = 1 << 2,   // Hit testing to allow subsequent widgets to overlap this one\r\n    ImGuiTreeNodeFlags_NoTreePushOnOpen     = 1 << 3,   // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack\r\n    ImGuiTreeNodeFlags_NoAutoOpenOnLog      = 1 << 4,   // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)\r\n    ImGuiTreeNodeFlags_DefaultOpen          = 1 << 5,   // Default node to be open\r\n    ImGuiTreeNodeFlags_OpenOnDoubleClick    = 1 << 6,   // Need double-click to open node\r\n    ImGuiTreeNodeFlags_OpenOnArrow          = 1 << 7,   // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open.\r\n    ImGuiTreeNodeFlags_Leaf                 = 1 << 8,   // No collapsing, no arrow (use as a convenience for leaf nodes). \r\n    ImGuiTreeNodeFlags_Bullet               = 1 << 9,   // Display a bullet instead of arrow\r\n    //ImGuITreeNodeFlags_SpanAllAvailWidth  = 1 << 10,  // FIXME: TODO: Extend hit box horizontally even if not framed\r\n    //ImGuiTreeNodeFlags_NoScrollOnOpen     = 1 << 11,  // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible\r\n    ImGuiTreeNodeFlags_CollapsingHeader     = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog\r\n};\r\n\r\n// Flags for ImGui::Selectable()\r\nenum ImGuiSelectableFlags_\r\n{\r\n    // Default: 0\r\n    ImGuiSelectableFlags_DontClosePopups    = 1 << 0,   // Clicking this don't close parent popup window\r\n    ImGuiSelectableFlags_SpanAllColumns     = 1 << 1,   // Selectable frame can span all columns (text will still fit in current column)\r\n    ImGuiSelectableFlags_AllowDoubleClick   = 1 << 2    // Generate press events on double clicks too\r\n};\r\n\r\n// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array\r\nenum ImGuiKey_\r\n{\r\n    ImGuiKey_Tab,       // for tabbing through fields\r\n    ImGuiKey_LeftArrow, // for text edit\r\n    ImGuiKey_RightArrow,// for text edit\r\n    ImGuiKey_UpArrow,   // for text edit\r\n    ImGuiKey_DownArrow, // for text edit\r\n    ImGuiKey_PageUp,\r\n    ImGuiKey_PageDown,\r\n    ImGuiKey_Home,      // for text edit\r\n    ImGuiKey_End,       // for text edit\r\n    ImGuiKey_Delete,    // for text edit\r\n    ImGuiKey_Backspace, // for text edit\r\n    ImGuiKey_Enter,     // for text edit\r\n    ImGuiKey_Escape,    // for text edit\r\n    ImGuiKey_A,         // for text edit CTRL+A: select all\r\n    ImGuiKey_C,         // for text edit CTRL+C: copy\r\n    ImGuiKey_V,         // for text edit CTRL+V: paste\r\n    ImGuiKey_X,         // for text edit CTRL+X: cut\r\n    ImGuiKey_Y,         // for text edit CTRL+Y: redo\r\n    ImGuiKey_Z,         // for text edit CTRL+Z: undo\r\n    ImGuiKey_COUNT\r\n};\r\n\r\n// Enumeration for PushStyleColor() / PopStyleColor()\r\nenum ImGuiCol_\r\n{\r\n    ImGuiCol_Text,\r\n    ImGuiCol_TextDisabled,\r\n    ImGuiCol_WindowBg,              // Background of normal windows\r\n    ImGuiCol_ChildWindowBg,         // Background of child windows\r\n    ImGuiCol_PopupBg,               // Background of popups, menus, tooltips windows\r\n    ImGuiCol_Border,\r\n    ImGuiCol_BorderShadow,\r\n    ImGuiCol_FrameBg,               // Background of checkbox, radio button, plot, slider, text input\r\n    ImGuiCol_FrameBgHovered,\r\n    ImGuiCol_FrameBgActive,\r\n    ImGuiCol_TitleBg,\r\n    ImGuiCol_TitleBgCollapsed,\r\n    ImGuiCol_TitleBgActive,\r\n    ImGuiCol_MenuBarBg,\r\n    ImGuiCol_ScrollbarBg,\r\n    ImGuiCol_ScrollbarGrab,\r\n    ImGuiCol_ScrollbarGrabHovered,\r\n    ImGuiCol_ScrollbarGrabActive,\r\n    ImGuiCol_ComboBg,\r\n    ImGuiCol_CheckMark,\r\n    ImGuiCol_SliderGrab,\r\n    ImGuiCol_SliderGrabActive,\r\n    ImGuiCol_Button,\r\n    ImGuiCol_ButtonHovered,\r\n    ImGuiCol_ButtonActive,\r\n    ImGuiCol_Header,\r\n    ImGuiCol_HeaderHovered,\r\n    ImGuiCol_HeaderActive,\r\n    ImGuiCol_Separator,\r\n    ImGuiCol_SeparatorHovered,\r\n    ImGuiCol_SeparatorActive,\r\n    ImGuiCol_ResizeGrip,\r\n    ImGuiCol_ResizeGripHovered,\r\n    ImGuiCol_ResizeGripActive,\r\n    ImGuiCol_CloseButton,\r\n    ImGuiCol_CloseButtonHovered,\r\n    ImGuiCol_CloseButtonActive,\r\n    ImGuiCol_PlotLines,\r\n    ImGuiCol_PlotLinesHovered,\r\n    ImGuiCol_PlotHistogram,\r\n    ImGuiCol_PlotHistogramHovered,\r\n    ImGuiCol_TextSelectedBg,\r\n    ImGuiCol_ModalWindowDarkening,  // darken entire screen when a modal window is active\r\n    ImGuiCol_COUNT\r\n\r\n    // Obsolete names (will be removed)\r\n#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS\r\n    , ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive\r\n#endif\r\n};\r\n\r\n// Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure.\r\n// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/poped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly.\r\n// NB: if changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.\r\nenum ImGuiStyleVar_\r\n{\r\n    // Enum name ......................// Member in ImGuiStyle structure (see ImGuiStyle for descriptions)\r\n    ImGuiStyleVar_Alpha,               // float     Alpha\r\n    ImGuiStyleVar_WindowPadding,       // ImVec2    WindowPadding\r\n    ImGuiStyleVar_WindowRounding,      // float     WindowRounding\r\n    ImGuiStyleVar_WindowMinSize,       // ImVec2    WindowMinSize\r\n    ImGuiStyleVar_ChildWindowRounding, // float     ChildWindowRounding\r\n    ImGuiStyleVar_FramePadding,        // ImVec2    FramePadding\r\n    ImGuiStyleVar_FrameRounding,       // float     FrameRounding\r\n    ImGuiStyleVar_ItemSpacing,         // ImVec2    ItemSpacing\r\n    ImGuiStyleVar_ItemInnerSpacing,    // ImVec2    ItemInnerSpacing\r\n    ImGuiStyleVar_IndentSpacing,       // float     IndentSpacing\r\n    ImGuiStyleVar_GrabMinSize,         // float     GrabMinSize\r\n    ImGuiStyleVar_ButtonTextAlign,     // ImVec2    ButtonTextAlign\r\n    ImGuiStyleVar_Count_\r\n};\r\n\r\n// Enumeration for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()\r\nenum ImGuiColorEditFlags_\r\n{\r\n    ImGuiColorEditFlags_NoAlpha         = 1 << 1,   //              // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (read 3 components from the input pointer).\r\n    ImGuiColorEditFlags_NoPicker        = 1 << 2,   //              // ColorEdit: disable picker when clicking on colored square.\r\n    ImGuiColorEditFlags_NoOptions       = 1 << 3,   //              // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview.\r\n    ImGuiColorEditFlags_NoSmallPreview  = 1 << 4,   //              // ColorEdit, ColorPicker: disable colored square preview next to the inputs. (e.g. to show only the inputs)\r\n    ImGuiColorEditFlags_NoInputs        = 1 << 5,   //              // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview colored square).\r\n    ImGuiColorEditFlags_NoTooltip       = 1 << 6,   //              // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview.\r\n    ImGuiColorEditFlags_NoLabel         = 1 << 7,   //              // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker).\r\n    ImGuiColorEditFlags_NoSidePreview   = 1 << 8,   //              // ColorPicker: disable bigger color preview on right side of the picker, use small colored square preview instead.\r\n    // User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions(). The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorEditOptions() during startup.\r\n    ImGuiColorEditFlags_AlphaBar        = 1 << 9,   //              // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.\r\n    ImGuiColorEditFlags_AlphaPreview    = 1 << 10,  //              // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque.\r\n    ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 11,  //              // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque.\r\n    ImGuiColorEditFlags_HDR             = 1 << 12,  //              // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).\r\n    ImGuiColorEditFlags_RGB             = 1 << 13,  // [Inputs]     // ColorEdit: choose one among RGB/HSV/HEX. ColorPicker: choose any combination using RGB/HSV/HEX.\r\n    ImGuiColorEditFlags_HSV             = 1 << 14,  // [Inputs]     // \"\r\n    ImGuiColorEditFlags_HEX             = 1 << 15,  // [Inputs]     // \"\r\n    ImGuiColorEditFlags_Uint8           = 1 << 16,  // [DataType]   // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255. \r\n    ImGuiColorEditFlags_Float           = 1 << 17,  // [DataType]   // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.\r\n    ImGuiColorEditFlags_PickerHueBar    = 1 << 18,  // [PickerMode] // ColorPicker: bar for Hue, rectangle for Sat/Value.\r\n    ImGuiColorEditFlags_PickerHueWheel  = 1 << 19,  // [PickerMode] // ColorPicker: wheel for Hue, triangle for Sat/Value.\r\n    // Internals/Masks\r\n    ImGuiColorEditFlags__InputsMask     = ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_HSV|ImGuiColorEditFlags_HEX,\r\n    ImGuiColorEditFlags__DataTypeMask   = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_Float,\r\n    ImGuiColorEditFlags__PickerMask     = ImGuiColorEditFlags_PickerHueWheel|ImGuiColorEditFlags_PickerHueBar,\r\n    ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_PickerHueBar    // Change application default using SetColorEditOptions()\r\n};\r\n\r\n// Enumeration for GetMouseCursor()\r\nenum ImGuiMouseCursor_\r\n{\r\n    ImGuiMouseCursor_None = -1,\r\n    ImGuiMouseCursor_Arrow = 0,\r\n    ImGuiMouseCursor_TextInput,         // When hovering over InputText, etc.\r\n    ImGuiMouseCursor_Move,              // Unused\r\n    ImGuiMouseCursor_ResizeNS,          // Unused\r\n    ImGuiMouseCursor_ResizeEW,          // When hovering over a column\r\n    ImGuiMouseCursor_ResizeNESW,        // Unused\r\n    ImGuiMouseCursor_ResizeNWSE,        // When hovering over the bottom-right corner of a window\r\n    ImGuiMouseCursor_Count_\r\n};\r\n\r\n// Condition flags for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions\r\n// All those functions treat 0 as a shortcut to ImGuiCond_Always\r\nenum ImGuiCond_\r\n{\r\n    ImGuiCond_Always        = 1 << 0, // Set the variable\r\n    ImGuiCond_Once          = 1 << 1, // Set the variable once per runtime session (only the first call with succeed)\r\n    ImGuiCond_FirstUseEver  = 1 << 2, // Set the variable if the window has no saved data (if doesn't exist in the .ini file)\r\n    ImGuiCond_Appearing     = 1 << 3  // Set the variable if the window is appearing after being hidden/inactive (or the first time)\r\n\r\n    // Obsolete names (will be removed)\r\n#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS\r\n    , ImGuiSetCond_Always = ImGuiCond_Always, ImGuiSetCond_Once = ImGuiCond_Once, ImGuiSetCond_FirstUseEver = ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing = ImGuiCond_Appearing\r\n#endif\r\n};\r\n\r\nstruct ImGuiStyle\r\n{\r\n    float       Alpha;                      // Global alpha applies to everything in ImGui\r\n    ImVec2      WindowPadding;              // Padding within a window\r\n    ImVec2      WindowMinSize;              // Minimum window size\r\n    float       WindowRounding;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows\r\n    ImVec2      WindowTitleAlign;           // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.\r\n    float       ChildWindowRounding;        // Radius of child window corners rounding. Set to 0.0f to have rectangular windows\r\n    ImVec2      FramePadding;               // Padding within a framed rectangle (used by most widgets)\r\n    float       FrameRounding;              // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets).\r\n    ImVec2      ItemSpacing;                // Horizontal and vertical spacing between widgets/lines\r\n    ImVec2      ItemInnerSpacing;           // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)\r\n    ImVec2      TouchExtraPadding;          // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!\r\n    float       IndentSpacing;              // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).\r\n    float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns\r\n    float       ScrollbarSize;              // Width of the vertical scrollbar, Height of the horizontal scrollbar\r\n    float       ScrollbarRounding;          // Radius of grab corners for scrollbar\r\n    float       GrabMinSize;                // Minimum width/height of a grab box for slider/scrollbar.\r\n    float       GrabRounding;               // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.\r\n    ImVec2      ButtonTextAlign;            // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered.\r\n    ImVec2      DisplayWindowPadding;       // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.\r\n    ImVec2      DisplaySafeAreaPadding;     // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.\r\n    bool        AntiAliasedLines;           // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU.\r\n    bool        AntiAliasedShapes;          // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)\r\n    float       CurveTessellationTol;       // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.\r\n    ImVec4      Colors[ImGuiCol_COUNT];\r\n\r\n    IMGUI_API ImGuiStyle();\r\n};\r\n\r\n// This is where your app communicate with ImGui. Access via ImGui::GetIO().\r\n// Read 'Programmer guide' section in .cpp file for general usage.\r\nstruct ImGuiIO\r\n{\r\n    //------------------------------------------------------------------\r\n    // Settings (fill once)                 // Default value:\r\n    //------------------------------------------------------------------\r\n\r\n    ImVec2        DisplaySize;              // <unset>              // Display size, in pixels. For clamping windows positions.\r\n    float         DeltaTime;                // = 1.0f/60.0f         // Time elapsed since last frame, in seconds.\r\n    float         IniSavingRate;            // = 5.0f               // Maximum time between saving positions/sizes to .ini file, in seconds.\r\n    const char*   IniFilename;              // = \"imgui.ini\"        // Path to .ini file. NULL to disable .ini saving.\r\n    const char*   LogFilename;              // = \"imgui_log.txt\"    // Path to .log file (default parameter to ImGui::LogToFile when no file is specified).\r\n    float         MouseDoubleClickTime;     // = 0.30f              // Time for a double-click, in seconds.\r\n    float         MouseDoubleClickMaxDist;  // = 6.0f               // Distance threshold to stay in to validate a double-click, in pixels.\r\n    float         MouseDragThreshold;       // = 6.0f               // Distance threshold before considering we are dragging\r\n    int           KeyMap[ImGuiKey_COUNT];   // <unset>              // Map of indices into the KeysDown[512] entries array\r\n    float         KeyRepeatDelay;           // = 0.250f             // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).\r\n    float         KeyRepeatRate;            // = 0.050f             // When holding a key/button, rate at which it repeats, in seconds.\r\n    void*         UserData;                 // = NULL               // Store your own data for retrieval by callbacks.\r\n\r\n    ImFontAtlas*  Fonts;                    // <auto>               // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array.\r\n    float         FontGlobalScale;          // = 1.0f               // Global scale all fonts\r\n    bool          FontAllowUserScaling;     // = false              // Allow user scaling text of individual window with CTRL+Wheel.\r\n    ImFont*       FontDefault;              // = NULL               // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].\r\n    ImVec2        DisplayFramebufferScale;  // = (1.0f,1.0f)        // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.\r\n    ImVec2        DisplayVisibleMin;        // <unset> (0.0f,0.0f)  // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.\r\n    ImVec2        DisplayVisibleMax;        // <unset> (0.0f,0.0f)  // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize\r\n\r\n    // Advanced/subtle behaviors\r\n    bool          OSXBehaviors;             // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl\r\n\r\n    //------------------------------------------------------------------\r\n    // Settings (User Functions)\r\n    //------------------------------------------------------------------\r\n\r\n    // Rendering function, will be called in Render().\r\n    // Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer.\r\n    // See example applications if you are unsure of how to implement this.\r\n    void        (*RenderDrawListsFn)(ImDrawData* data);\r\n\r\n    // Optional: access OS clipboard\r\n    // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)\r\n    const char* (*GetClipboardTextFn)(void* user_data);\r\n    void        (*SetClipboardTextFn)(void* user_data, const char* text);\r\n    void*       ClipboardUserData;\r\n\r\n    // Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer.\r\n    // (default to posix malloc/free)\r\n    void*       (*MemAllocFn)(size_t sz);\r\n    void        (*MemFreeFn)(void* ptr);\r\n\r\n    // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows)\r\n    // (default to use native imm32 api on Windows)\r\n    void        (*ImeSetInputScreenPosFn)(int x, int y);\r\n    void*       ImeWindowHandle;            // (Windows) Set this to your HWND to get automatic IME cursor positioning.\r\n\r\n    //------------------------------------------------------------------\r\n    // Input - Fill before calling NewFrame()\r\n    //------------------------------------------------------------------\r\n\r\n    ImVec2      MousePos;                   // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.)\r\n    bool        MouseDown[5];               // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.\r\n    float       MouseWheel;                 // Mouse wheel: 1 unit scrolls about 5 lines text.\r\n    bool        MouseDrawCursor;            // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).\r\n    bool        KeyCtrl;                    // Keyboard modifier pressed: Control\r\n    bool        KeyShift;                   // Keyboard modifier pressed: Shift\r\n    bool        KeyAlt;                     // Keyboard modifier pressed: Alt\r\n    bool        KeySuper;                   // Keyboard modifier pressed: Cmd/Super/Windows\r\n    bool        KeysDown[512];              // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data)\r\n    ImWchar     InputCharacters[16+1];      // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.\r\n\r\n    // Functions\r\n    IMGUI_API void AddInputCharacter(ImWchar c);                        // Add new character into InputCharacters[]\r\n    IMGUI_API void AddInputCharactersUTF8(const char* utf8_chars);      // Add new characters into InputCharacters[] from an UTF-8 string\r\n    inline void    ClearInputCharacters() { InputCharacters[0] = 0; }   // Clear the text input buffer manually\r\n\r\n    //------------------------------------------------------------------\r\n    // Output - Retrieve after calling NewFrame()\r\n    //------------------------------------------------------------------\r\n\r\n    bool        WantCaptureMouse;           // Mouse is hovering a window or widget is active (= ImGui will use your mouse input). Use to hide mouse from the rest of your application\r\n    bool        WantCaptureKeyboard;        // Widget is active (= ImGui will use your keyboard input). Use to hide keyboard from the rest of your application\r\n    bool        WantTextInput;              // Some text input widget is active, which will read input characters from the InputCharacters array. Use to activate on screen keyboard if your system needs one\r\n    float       Framerate;                  // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames\r\n    int         MetricsAllocs;              // Number of active memory allocations\r\n    int         MetricsRenderVertices;      // Vertices output during last call to Render()\r\n    int         MetricsRenderIndices;       // Indices output during last call to Render() = number of triangles * 3\r\n    int         MetricsActiveWindows;       // Number of visible root windows (exclude child windows)\r\n    ImVec2      MouseDelta;                 // Mouse delta. Note that this is zero if either current or previous position are negative, so a disappearing/reappearing mouse won't have a huge delta for one frame.\r\n\r\n    //------------------------------------------------------------------\r\n    // [Private] ImGui will maintain those fields. Forward compatibility not guaranteed!\r\n    //------------------------------------------------------------------\r\n\r\n    ImVec2      MousePosPrev;               // Previous mouse position temporary storage (nb: not for public use, set to MousePos in NewFrame())\r\n    bool        MouseClicked[5];            // Mouse button went from !Down to Down\r\n    ImVec2      MouseClickedPos[5];         // Position at time of clicking\r\n    float       MouseClickedTime[5];        // Time of last click (used to figure out double-click)\r\n    bool        MouseDoubleClicked[5];      // Has mouse button been double-clicked?\r\n    bool        MouseReleased[5];           // Mouse button went from Down to !Down\r\n    bool        MouseDownOwned[5];          // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds.\r\n    float       MouseDownDuration[5];       // Duration the mouse button has been down (0.0f == just clicked)\r\n    float       MouseDownDurationPrev[5];   // Previous time the mouse button has been down\r\n    float       MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the click point\r\n    float       KeysDownDuration[512];      // Duration the keyboard key has been down (0.0f == just pressed)\r\n    float       KeysDownDurationPrev[512];  // Previous duration the key has been down\r\n\r\n    IMGUI_API   ImGuiIO();\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Helpers\r\n//-----------------------------------------------------------------------------\r\n\r\n// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug).\r\n// Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code!\r\ntemplate<typename T>\r\nclass ImVector\r\n{\r\npublic:\r\n    int                         Size;\r\n    int                         Capacity;\r\n    T*                          Data;\r\n\r\n    typedef T                   value_type;\r\n    typedef value_type*         iterator;\r\n    typedef const value_type*   const_iterator;\r\n\r\n    ImVector()                  { Size = Capacity = 0; Data = NULL; }\r\n    ~ImVector()                 { if (Data) ImGui::MemFree(Data); }\r\n\r\n    inline bool                 empty() const                   { return Size == 0; }\r\n    inline int                  size() const                    { return Size; }\r\n    inline int                  capacity() const                { return Capacity; }\r\n\r\n    inline value_type&          operator[](int i)               { IM_ASSERT(i < Size); return Data[i]; }\r\n    inline const value_type&    operator[](int i) const         { IM_ASSERT(i < Size); return Data[i]; }\r\n\r\n    inline void                 clear()                         { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }\r\n    inline iterator             begin()                         { return Data; }\r\n    inline const_iterator       begin() const                   { return Data; }\r\n    inline iterator             end()                           { return Data + Size; }\r\n    inline const_iterator       end() const                     { return Data + Size; }\r\n    inline value_type&          front()                         { IM_ASSERT(Size > 0); return Data[0]; }\r\n    inline const value_type&    front() const                   { IM_ASSERT(Size > 0); return Data[0]; }\r\n    inline value_type&          back()                          { IM_ASSERT(Size > 0); return Data[Size-1]; }\r\n    inline const value_type&    back() const                    { IM_ASSERT(Size > 0); return Data[Size-1]; }\r\n    inline void                 swap(ImVector<T>& rhs)          { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }\r\n\r\n    inline int                  _grow_capacity(int size) const  { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > size ? new_capacity : size; }\r\n\r\n    inline void                 resize(int new_size)            { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }\r\n    inline void                 reserve(int new_capacity)\r\n    {\r\n        if (new_capacity <= Capacity) return;\r\n        T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type));\r\n        if (Data)\r\n            memcpy(new_data, Data, (size_t)Size * sizeof(value_type));\r\n        ImGui::MemFree(Data);\r\n        Data = new_data;\r\n        Capacity = new_capacity;\r\n    }\r\n\r\n    inline void                 push_back(const value_type& v)  { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; }\r\n    inline void                 pop_back()                      { IM_ASSERT(Size > 0); Size--; }\r\n\r\n    inline iterator             erase(const_iterator it)        { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; }\r\n    inline iterator             insert(const_iterator it, const value_type& v)  { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; }\r\n};\r\n\r\n// Helper: execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame.\r\n// Usage:\r\n//   static ImGuiOnceUponAFrame oaf;\r\n//   if (oaf)\r\n//       ImGui::Text(\"This will be called only once per frame\");\r\nstruct ImGuiOnceUponAFrame\r\n{\r\n    ImGuiOnceUponAFrame() { RefFrame = -1; }\r\n    mutable int RefFrame;\r\n    operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; }\r\n};\r\n\r\n// Helper macro for ImGuiOnceUponAFrame. Attention: The macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces.\r\n#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS    // Will obsolete\r\n#define IMGUI_ONCE_UPON_A_FRAME     static ImGuiOnceUponAFrame imgui_oaf; if (imgui_oaf)\r\n#endif\r\n\r\n// Helper: Parse and apply text filters. In format \"aaaaa[,bbbb][,ccccc]\"\r\nstruct ImGuiTextFilter\r\n{\r\n    struct TextRange\r\n    {\r\n        const char* b;\r\n        const char* e;\r\n\r\n        TextRange() { b = e = NULL; }\r\n        TextRange(const char* _b, const char* _e) { b = _b; e = _e; }\r\n        const char* begin() const { return b; }\r\n        const char* end() const { return e; }\r\n        bool empty() const { return b == e; }\r\n        char front() const { return *b; }\r\n        static bool is_blank(char c) { return c == ' ' || c == '\\t'; }\r\n        void trim_blanks() { while (b < e && is_blank(*b)) b++; while (e > b && is_blank(*(e-1))) e--; }\r\n        IMGUI_API void split(char separator, ImVector<TextRange>& out);\r\n    };\r\n\r\n    char                InputBuf[256];\r\n    ImVector<TextRange> Filters;\r\n    int                 CountGrep;\r\n\r\n    IMGUI_API           ImGuiTextFilter(const char* default_filter = \"\");\r\n                        ~ImGuiTextFilter() {}\r\n    void                Clear() { InputBuf[0] = 0; Build(); }\r\n    IMGUI_API bool      Draw(const char* label = \"Filter (inc,-exc)\", float width = 0.0f);    // Helper calling InputText+Build\r\n    IMGUI_API bool      PassFilter(const char* text, const char* text_end = NULL) const;\r\n    bool                IsActive() const { return !Filters.empty(); }\r\n    IMGUI_API void      Build();\r\n};\r\n\r\n// Helper: Text buffer for logging/accumulating text\r\nstruct ImGuiTextBuffer\r\n{\r\n    ImVector<char>      Buf;\r\n\r\n    ImGuiTextBuffer()   { Buf.push_back(0); }\r\n    inline char         operator[](int i) { return Buf.Data[i]; }\r\n    const char*         begin() const { return &Buf.front(); }\r\n    const char*         end() const { return &Buf.back(); }      // Buf is zero-terminated, so end() will point on the zero-terminator\r\n    int                 size() const { return Buf.Size - 1; }\r\n    bool                empty() { return Buf.Size <= 1; }\r\n    void                clear() { Buf.clear(); Buf.push_back(0); }\r\n    const char*         c_str() const { return Buf.Data; }\r\n    IMGUI_API void      append(const char* fmt, ...) IM_FMTARGS(2);\r\n    IMGUI_API void      appendv(const char* fmt, va_list args) IM_FMTLIST(2);\r\n};\r\n\r\n// Helper: Simple Key->value storage\r\n// Typically you don't have to worry about this since a storage is held within each Window.\r\n// We use it to e.g. store collapse state for a tree (Int 0/1), store color edit options. \r\n// This is optimized for efficient reading (dichotomy into a contiguous buffer), rare writing (typically tied to user interactions)\r\n// You can use it as custom user storage for temporary values. Declare your own storage if, for example:\r\n// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state).\r\n// - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient)\r\n// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types.\r\nstruct ImGuiStorage\r\n{\r\n    struct Pair\r\n    {\r\n        ImGuiID key;\r\n        union { int val_i; float val_f; void* val_p; };\r\n        Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; }\r\n        Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; }\r\n        Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; }\r\n    };\r\n    ImVector<Pair>      Data;\r\n\r\n    // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)\r\n    // - Set***() functions find pair, insertion on demand if missing.\r\n    // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair.\r\n    IMGUI_API void      Clear();\r\n    IMGUI_API int       GetInt(ImGuiID key, int default_val = 0) const;\r\n    IMGUI_API void      SetInt(ImGuiID key, int val);\r\n    IMGUI_API bool      GetBool(ImGuiID key, bool default_val = false) const;\r\n    IMGUI_API void      SetBool(ImGuiID key, bool val);\r\n    IMGUI_API float     GetFloat(ImGuiID key, float default_val = 0.0f) const;\r\n    IMGUI_API void      SetFloat(ImGuiID key, float val);\r\n    IMGUI_API void*     GetVoidPtr(ImGuiID key) const; // default_val is NULL\r\n    IMGUI_API void      SetVoidPtr(ImGuiID key, void* val);\r\n\r\n    // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set.\r\n    // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.\r\n    // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct)\r\n    //      float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat(\"var\", pvar, 0, 100.0f); some_var += *pvar;\r\n    IMGUI_API int*      GetIntRef(ImGuiID key, int default_val = 0);\r\n    IMGUI_API bool*     GetBoolRef(ImGuiID key, bool default_val = false);\r\n    IMGUI_API float*    GetFloatRef(ImGuiID key, float default_val = 0.0f);\r\n    IMGUI_API void**    GetVoidPtrRef(ImGuiID key, void* default_val = NULL);\r\n\r\n    // Use on your own storage if you know only integer are being stored (open/close all tree nodes)\r\n    IMGUI_API void      SetAllInt(int val);\r\n};\r\n\r\n// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered.\r\nstruct ImGuiTextEditCallbackData\r\n{\r\n    ImGuiInputTextFlags EventFlag;      // One of ImGuiInputTextFlags_Callback* // Read-only\r\n    ImGuiInputTextFlags Flags;          // What user passed to InputText()      // Read-only\r\n    void*               UserData;       // What user passed to InputText()      // Read-only\r\n    bool                ReadOnly;       // Read-only mode                       // Read-only\r\n\r\n    // CharFilter event:\r\n    ImWchar             EventChar;      // Character input                      // Read-write (replace character or set to zero)\r\n\r\n    // Completion,History,Always events:\r\n    // If you modify the buffer contents make sure you update 'BufTextLen' and set 'BufDirty' to true.\r\n    ImGuiKey            EventKey;       // Key pressed (Up/Down/TAB)            // Read-only\r\n    char*               Buf;            // Current text buffer                  // Read-write (pointed data only, can't replace the actual pointer)\r\n    int                 BufTextLen;     // Current text length in bytes         // Read-write\r\n    int                 BufSize;        // Maximum text length in bytes         // Read-only\r\n    bool                BufDirty;       // Set if you modify Buf/BufTextLen!!   // Write\r\n    int                 CursorPos;      //                                      // Read-write\r\n    int                 SelectionStart; //                                      // Read-write (== to SelectionEnd when no selection)\r\n    int                 SelectionEnd;   //                                      // Read-write\r\n\r\n    // NB: Helper functions for text manipulation. Calling those function loses selection.\r\n    IMGUI_API void    DeleteChars(int pos, int bytes_count);\r\n    IMGUI_API void    InsertChars(int pos, const char* text, const char* text_end = NULL);\r\n    bool    HasSelection() const { return SelectionStart != SelectionEnd; }\r\n};\r\n\r\n// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin().\r\n// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough.\r\nstruct ImGuiSizeConstraintCallbackData\r\n{\r\n    void*   UserData;       // Read-only.   What user passed to SetNextWindowSizeConstraints()\r\n    ImVec2  Pos;            // Read-only.    Window position, for reference.\r\n    ImVec2  CurrentSize;    // Read-only.    Current window size.\r\n    ImVec2  DesiredSize;    // Read-write.  Desired size, based on user's mouse position. Write to this field to restrain resizing.\r\n};\r\n\r\n// Helpers macros to generate 32-bits encoded colors\r\n#ifdef IMGUI_USE_BGRA_PACKED_COLOR\r\n#define IM_COL32_R_SHIFT    16\r\n#define IM_COL32_G_SHIFT    8\r\n#define IM_COL32_B_SHIFT    0\r\n#define IM_COL32_A_SHIFT    24\r\n#define IM_COL32_A_MASK     0xFF000000\r\n#else\r\n#define IM_COL32_R_SHIFT    0\r\n#define IM_COL32_G_SHIFT    8\r\n#define IM_COL32_B_SHIFT    16\r\n#define IM_COL32_A_SHIFT    24\r\n#define IM_COL32_A_MASK     0xFF000000\r\n#endif\r\n#define IM_COL32(R,G,B,A)    (((ImU32)(A)<<IM_COL32_A_SHIFT) | ((ImU32)(B)<<IM_COL32_B_SHIFT) | ((ImU32)(G)<<IM_COL32_G_SHIFT) | ((ImU32)(R)<<IM_COL32_R_SHIFT))\r\n#define IM_COL32_WHITE       IM_COL32(255,255,255,255)  // Opaque white = 0xFFFFFFFF\r\n#define IM_COL32_BLACK       IM_COL32(0,0,0,255)        // Opaque black\r\n#define IM_COL32_BLACK_TRANS IM_COL32(0,0,0,0)          // Transparent black = 0x00000000\r\n\r\n// ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)\r\n// Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API.\r\n// **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. MAY OBSOLETE.\r\n// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed.\r\nstruct ImColor\r\n{\r\n    ImVec4              Value;\r\n\r\n    ImColor()                                                       { Value.x = Value.y = Value.z = Value.w = 0.0f; }\r\n    ImColor(int r, int g, int b, int a = 255)                       { float sc = 1.0f/255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }\r\n    ImColor(ImU32 rgba)                                             { float sc = 1.0f/255.0f; Value.x = (float)((rgba>>IM_COL32_R_SHIFT)&0xFF) * sc; Value.y = (float)((rgba>>IM_COL32_G_SHIFT)&0xFF) * sc; Value.z = (float)((rgba>>IM_COL32_B_SHIFT)&0xFF) * sc; Value.w = (float)((rgba>>IM_COL32_A_SHIFT)&0xFF) * sc; }\r\n    ImColor(float r, float g, float b, float a = 1.0f)              { Value.x = r; Value.y = g; Value.z = b; Value.w = a; }\r\n    ImColor(const ImVec4& col)                                      { Value = col; }\r\n    inline operator ImU32() const                                   { return ImGui::ColorConvertFloat4ToU32(Value); }\r\n    inline operator ImVec4() const                                  { return Value; }\r\n\r\n    // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers.\r\n    inline void    SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; }\r\n    static ImColor HSV(float h, float s, float v, float a = 1.0f)   { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); }\r\n};\r\n\r\n// Helper: Manually clip large list of items.\r\n// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all.\r\n// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. \r\n// ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null.\r\n// Usage:\r\n//     ImGuiListClipper clipper(1000);  // we have 1000 elements, evenly spaced.\r\n//     while (clipper.Step())\r\n//         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)\r\n//             ImGui::Text(\"line number %d\", i);\r\n// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor).\r\n// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.\r\n// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.)\r\n// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.\r\nstruct ImGuiListClipper\r\n{\r\n    float   StartPosY;\r\n    float   ItemsHeight;\r\n    int     ItemsCount, StepNo, DisplayStart, DisplayEnd;\r\n\r\n    // items_count:  Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).\r\n    // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing().\r\n    // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step().\r\n    ImGuiListClipper(int items_count = -1, float items_height = -1.0f)  { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want).\r\n    ~ImGuiListClipper()                                                 { IM_ASSERT(ItemsCount == -1); }      // Assert if user forgot to call End() or Step() until false.\r\n\r\n    IMGUI_API bool Step();                                              // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.\r\n    IMGUI_API void Begin(int items_count, float items_height = -1.0f);  // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1.\r\n    IMGUI_API void End();                                               // Automatically called on the last call of Step() that returns false.\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Draw List\r\n// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList.\r\n//-----------------------------------------------------------------------------\r\n\r\n// Draw callbacks for advanced uses.\r\n// NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that)\r\n// Draw callback may be useful for example, A) Change your GPU render state, B) render a complex 3D scene inside a UI element (without an intermediate texture/render target), etc.\r\n// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()'\r\ntypedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);\r\n\r\n// Typically, 1 command = 1 gpu draw call (unless command is a callback)\r\nstruct ImDrawCmd\r\n{\r\n    unsigned int    ElemCount;              // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].\r\n    ImVec4          ClipRect;               // Clipping rectangle (x1, y1, x2, y2)\r\n    ImTextureID     TextureId;              // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.\r\n    ImDrawCallback  UserCallback;           // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.\r\n    void*           UserCallbackData;       // The draw callback code can access this.\r\n\r\n    ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; }\r\n};\r\n\r\n// Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h)\r\n#ifndef ImDrawIdx\r\ntypedef unsigned short ImDrawIdx;\r\n#endif\r\n\r\n// Vertex layout\r\n#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT\r\nstruct ImDrawVert\r\n{\r\n    ImVec2  pos;\r\n    ImVec2  uv;\r\n    ImU32   col;\r\n};\r\n#else\r\n// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h\r\n// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine.\r\n// The type has to be described within the macro (you can either declare the struct or use a typedef)\r\n// NOTE: IMGUI DOESN'T CLEAR THE STRUCTURE AND DOESN'T CALL A CONSTRUCTOR SO ANY CUSTOM FIELD WILL BE UNINITIALIZED. IF YOU ADD EXTRA FIELDS (SUCH AS A 'Z' COORDINATES) YOU WILL NEED TO CLEAR THEM DURING RENDER OR TO IGNORE THEM. \r\nIMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;\r\n#endif\r\n\r\n// Draw channels are used by the Columns API to \"split\" the render list into different channels while building, so items of each column can be batched together.\r\n// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered.\r\nstruct ImDrawChannel\r\n{\r\n    ImVector<ImDrawCmd>     CmdBuffer;\r\n    ImVector<ImDrawIdx>     IdxBuffer;\r\n};\r\n\r\n// Draw command list\r\n// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering.\r\n// At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged in the future.\r\n// If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives.\r\n// You can interleave normal ImGui:: calls and adding primitives to the current draw list.\r\n// All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), however you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well)\r\n// Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions).\r\nstruct ImDrawList\r\n{\r\n    // This is what you have to render\r\n    ImVector<ImDrawCmd>     CmdBuffer;          // Commands. Typically 1 command = 1 GPU draw call.\r\n    ImVector<ImDrawIdx>     IdxBuffer;          // Index buffer. Each command consume ImDrawCmd::ElemCount of those\r\n    ImVector<ImDrawVert>    VtxBuffer;          // Vertex buffer.\r\n\r\n    // [Internal, used while building lists]\r\n    const char*             _OwnerName;         // Pointer to owner window's name for debugging\r\n    unsigned int            _VtxCurrentIdx;     // [Internal] == VtxBuffer.Size\r\n    ImDrawVert*             _VtxWritePtr;       // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)\r\n    ImDrawIdx*              _IdxWritePtr;       // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)\r\n    ImVector<ImVec4>        _ClipRectStack;     // [Internal]\r\n    ImVector<ImTextureID>   _TextureIdStack;    // [Internal]\r\n    ImVector<ImVec2>        _Path;              // [Internal] current path building\r\n    int                     _ChannelsCurrent;   // [Internal] current channel number (0)\r\n    int                     _ChannelsCount;     // [Internal] number of active channels (1+)\r\n    ImVector<ImDrawChannel> _Channels;          // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size)\r\n\r\n    ImDrawList()  { _OwnerName = NULL; Clear(); }\r\n    ~ImDrawList() { ClearFreeMemory(); }\r\n    IMGUI_API void  PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false);  // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)\r\n    IMGUI_API void  PushClipRectFullScreen();\r\n    IMGUI_API void  PopClipRect();\r\n    IMGUI_API void  PushTextureID(const ImTextureID& texture_id);\r\n    IMGUI_API void  PopTextureID();\r\n    inline ImVec2   GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); }\r\n    inline ImVec2   GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); }\r\n\r\n    // Primitives\r\n    IMGUI_API void  AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f);\r\n    IMGUI_API void  AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0, float thickness = 1.0f);   // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding to which corner to round\r\n    IMGUI_API void  AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0);                     // a: upper-left, b: lower-right\r\n    IMGUI_API void  AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);\r\n    IMGUI_API void  AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f);\r\n    IMGUI_API void  AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col);\r\n    IMGUI_API void  AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness = 1.0f);\r\n    IMGUI_API void  AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col);\r\n    IMGUI_API void  AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f);\r\n    IMGUI_API void  AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12);\r\n    IMGUI_API void  AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);\r\n    IMGUI_API void  AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);\r\n    IMGUI_API void  AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = 0xFFFFFFFF);\r\n    IMGUI_API void  AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = 0xFFFFFFFF);\r\n    IMGUI_API void  AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased);\r\n    IMGUI_API void  AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased);\r\n    IMGUI_API void  AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0);\r\n\r\n    // Stateful path API, add points then finish with PathFill() or PathStroke()\r\n    inline    void  PathClear()                                                 { _Path.resize(0); }\r\n    inline    void  PathLineTo(const ImVec2& pos)                               { _Path.push_back(pos); }\r\n    inline    void  PathLineToMergeDuplicate(const ImVec2& pos)                 { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); }\r\n    inline    void  PathFillConvex(ImU32 col)                                   { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); }\r\n    inline    void  PathStroke(ImU32 col, bool closed, float thickness = 1.0f)  { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }\r\n    IMGUI_API void  PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);\r\n    IMGUI_API void  PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12);                                // Use precomputed angles for a 12 steps circle\r\n    IMGUI_API void  PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0);\r\n    IMGUI_API void  PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ~0);   // rounding_corners_flags: 4-bits corresponding to which corner to round\r\n\r\n    // Channels\r\n    // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives)\r\n    // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end)\r\n    IMGUI_API void  ChannelsSplit(int channels_count);\r\n    IMGUI_API void  ChannelsMerge();\r\n    IMGUI_API void  ChannelsSetCurrent(int channel_index);\r\n\r\n    // Advanced\r\n    IMGUI_API void  AddCallback(ImDrawCallback callback, void* callback_data);  // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.\r\n    IMGUI_API void  AddDrawCmd();                                               // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible\r\n\r\n    // Internal helpers\r\n    // NB: all primitives needs to be reserved via PrimReserve() beforehand!\r\n    IMGUI_API void  Clear();\r\n    IMGUI_API void  ClearFreeMemory();\r\n    IMGUI_API void  PrimReserve(int idx_count, int vtx_count);\r\n    IMGUI_API void  PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col);      // Axis aligned rectangle (composed of two triangles)\r\n    IMGUI_API void  PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col);\r\n    IMGUI_API void  PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col);\r\n    inline    void  PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col){ _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; }\r\n    inline    void  PrimWriteIdx(ImDrawIdx idx)                                 { *_IdxWritePtr = idx; _IdxWritePtr++; }\r\n    inline    void  PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col)     { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); }\r\n    IMGUI_API void  UpdateClipRect();\r\n    IMGUI_API void  UpdateTextureID();\r\n};\r\n\r\n// All draw data to render an ImGui frame\r\nstruct ImDrawData\r\n{\r\n    bool            Valid;                  // Only valid after Render() is called and before the next NewFrame() is called.\r\n    ImDrawList**    CmdLists;\r\n    int             CmdListsCount;\r\n    int             TotalVtxCount;          // For convenience, sum of all cmd_lists vtx_buffer.Size\r\n    int             TotalIdxCount;          // For convenience, sum of all cmd_lists idx_buffer.Size\r\n\r\n    // Functions\r\n    ImDrawData() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; }\r\n    IMGUI_API void DeIndexAllBuffers();               // For backward compatibility or convenience: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!\r\n    IMGUI_API void ScaleClipRects(const ImVec2& sc);  // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.\r\n};\r\n\r\nstruct ImFontConfig\r\n{\r\n    void*           FontData;                   //          // TTF/OTF data\r\n    int             FontDataSize;               //          // TTF/OTF data size\r\n    bool            FontDataOwnedByAtlas;       // true     // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).\r\n    int             FontNo;                     // 0        // Index of font within TTF/OTF file\r\n    float           SizePixels;                 //          // Size in pixels for rasterizer.\r\n    int             OversampleH, OversampleV;   // 3, 1     // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis.\r\n    bool            PixelSnapH;                 // false    // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.\r\n    ImVec2          GlyphExtraSpacing;          // 0, 0     // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.\r\n    ImVec2          GlyphOffset;                // 0, 0     // Offset all glyphs from this font input.\r\n    const ImWchar*  GlyphRanges;                // NULL     // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.\r\n    bool            MergeMode;                  // false    // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.\r\n    unsigned int    RasterizerFlags;            // 0x00     // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one.\r\n    float           RasterizerMultiply;         // 1.0f     // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.\r\n\r\n    // [Internal]\r\n    char            Name[32];                               // Name (strictly to ease debugging)\r\n    ImFont*         DstFont;\r\n\r\n    IMGUI_API ImFontConfig();\r\n};\r\n\r\n// Load and rasterize multiple TTF/OTF fonts into a same texture.\r\n// Sharing a texture for multiple fonts allows us to reduce the number of draw calls during rendering.\r\n// We also add custom graphic data into the texture that serves for ImGui.\r\n//  1. (Optional) Call AddFont*** functions. If you don't call any, the default font will be loaded for you.\r\n//  2. Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.\r\n//  3. Upload the pixels data into a texture within your graphics system.\r\n//  4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during rendering to identify the texture.\r\n// IMPORTANT: If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the ImFont is build (when calling GetTextData*** or Build()). We only copy the pointer, not the data.\r\nstruct ImFontAtlas\r\n{\r\n    IMGUI_API ImFontAtlas();\r\n    IMGUI_API ~ImFontAtlas();\r\n    IMGUI_API ImFont*           AddFont(const ImFontConfig* font_cfg);\r\n    IMGUI_API ImFont*           AddFontDefault(const ImFontConfig* font_cfg = NULL);\r\n    IMGUI_API ImFont*           AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL);\r\n    IMGUI_API ImFont*           AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL);                                       // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build()\r\n    IMGUI_API ImFont*           AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp\r\n    IMGUI_API ImFont*           AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL);              // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 paramaeter\r\n    IMGUI_API void              ClearTexData();             // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics memory.\r\n    IMGUI_API void              ClearInputData();           // Clear the input TTF data (inc sizes, glyph ranges)\r\n    IMGUI_API void              ClearFonts();               // Clear the ImGui-side font data (glyphs storage, UV coordinates)\r\n    IMGUI_API void              Clear();                    // Clear all\r\n\r\n    // Retrieve texture data\r\n    // User is in charge of copying the pixels into graphics memory, then call SetTextureUserID()\r\n    // After loading the texture into your graphic system, store your texture handle in 'TexID' (ignore if you aren't using multiple fonts nor images)\r\n    // RGBA32 format is provided for convenience and high compatibility, but note that all RGB pixels are white, so 75% of the memory is wasted.\r\n    // Pitch = Width * BytesPerPixels\r\n    IMGUI_API void              GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL);  // 1 byte per-pixel\r\n    IMGUI_API void              GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL);  // 4 bytes-per-pixel\r\n    void                        SetTexID(ImTextureID id)  { TexID = id; }\r\n\r\n    // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list)\r\n    // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8\"Hello world\" syntax. See FAQ for details.\r\n    IMGUI_API const ImWchar*    GetGlyphRangesDefault();    // Basic Latin, Extended Latin\r\n    IMGUI_API const ImWchar*    GetGlyphRangesKorean();     // Default + Korean characters\r\n    IMGUI_API const ImWchar*    GetGlyphRangesJapanese();   // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs\r\n    IMGUI_API const ImWchar*    GetGlyphRangesChinese();    // Japanese + full set of about 21000 CJK Unified Ideographs\r\n    IMGUI_API const ImWchar*    GetGlyphRangesCyrillic();   // Default + about 400 Cyrillic characters\r\n    IMGUI_API const ImWchar*    GetGlyphRangesThai();       // Default + Thai characters\r\n\r\n    // Helpers to build glyph ranges from text data. Feed all your application strings/characters to it then call BuildRanges().\r\n    struct GlyphRangesBuilder\r\n    {\r\n        ImVector<unsigned char> UsedChars;  // Store 1-bit per Unicode code point (0=unused, 1=used)\r\n        GlyphRangesBuilder()                { UsedChars.resize(0x10000 / 8); memset(UsedChars.Data, 0, 0x10000 / 8); }\r\n        bool           GetBit(int n)        { return (UsedChars[n >> 3] & (1 << (n & 7))) != 0; }\r\n        void           SetBit(int n)        { UsedChars[n >> 3] |= 1 << (n & 7); }  // Set bit 'c' in the array\r\n        void           AddChar(ImWchar c)   { SetBit(c); }                          // Add character\r\n        IMGUI_API void AddText(const char* text, const char* text_end = NULL);      // Add string (each character of the UTF-8 string are added)\r\n        IMGUI_API void AddRanges(const ImWchar* ranges);                            // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault) to force add all of ASCII/Latin+Ext\r\n        IMGUI_API void BuildRanges(ImVector<ImWchar>* out_ranges);                  // Output new ranges\r\n    };\r\n\r\n    // Members\r\n    // (Access texture data via GetTexData*() calls which will setup a default font for you.)\r\n    ImTextureID                 TexID;              // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.\r\n    unsigned char*              TexPixelsAlpha8;    // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight\r\n    unsigned int*               TexPixelsRGBA32;    // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4\r\n    int                         TexWidth;           // Texture width calculated during Build().\r\n    int                         TexHeight;          // Texture height calculated during Build().\r\n    int                         TexDesiredWidth;    // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.\r\n    int                         TexGlyphPadding;    // Padding between glyphs within texture in pixels. Defaults to 1.\r\n    ImVec2                      TexUvWhitePixel;    // Texture coordinates to a white pixel\r\n    ImVector<ImFont*>           Fonts;              // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font.\r\n\r\n    // [Private] User rectangle for packing custom texture data into the atlas.\r\n    struct CustomRect\r\n    {\r\n        unsigned int    ID;             // Input    // User ID. <0x10000 for font mapped data (WIP/UNSUPPORTED), >=0x10000 for other texture data\r\n        unsigned short  Width, Height;  // Input    // Desired rectangle dimension\r\n        unsigned short  X, Y;           // Output   // Packed position in Atlas\r\n        CustomRect()            { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; }\r\n        bool IsPacked() const   { return X != 0xFFFF; }\r\n    };\r\n\r\n    // [Private] Members\r\n    ImVector<CustomRect>        CustomRects;        // Rectangles for packing custom texture data into the atlas.\r\n    ImVector<ImFontConfig>      ConfigData;         // Internal data\r\n    IMGUI_API bool              Build();            // Build pixels data. This is automatically for you by the GetTexData*** functions.\r\n    IMGUI_API int               CustomRectRegister(unsigned int id, int width, int height);\r\n    IMGUI_API void              CustomRectCalcUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max);\r\n};\r\n\r\n// Font runtime data and rendering\r\n// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32().\r\nstruct ImFont\r\n{\r\n    struct Glyph\r\n    {\r\n        ImWchar                 Codepoint;\r\n        float                   XAdvance;\r\n        float                   X0, Y0, X1, Y1;\r\n        float                   U0, V0, U1, V1;     // Texture coordinates\r\n    };\r\n\r\n    // Members: Hot ~62/78 bytes\r\n    float                       FontSize;           // <user set>   // Height of characters, set during loading (don't change after loading)\r\n    float                       Scale;              // = 1.f        // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()\r\n    ImVec2                      DisplayOffset;      // = (0.f,1.f)  // Offset font rendering by xx pixels\r\n    ImVector<Glyph>             Glyphs;             //              // All glyphs.\r\n    ImVector<float>             IndexXAdvance;      //              // Sparse. Glyphs->XAdvance in a directly indexable way (more cache-friendly, for CalcTextSize functions which are often bottleneck in large UI).\r\n    ImVector<unsigned short>    IndexLookup;        //              // Sparse. Index glyphs by Unicode code-point.\r\n    const Glyph*                FallbackGlyph;      // == FindGlyph(FontFallbackChar)\r\n    float                       FallbackXAdvance;   // == FallbackGlyph->XAdvance\r\n    ImWchar                     FallbackChar;       // = '?'        // Replacement glyph if one isn't found. Only set via SetFallbackChar()\r\n\r\n    // Members: Cold ~18/26 bytes\r\n    short                       ConfigDataCount;    // ~ 1          // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.\r\n    ImFontConfig*               ConfigData;         //              // Pointer within ContainerAtlas->ConfigData\r\n    ImFontAtlas*                ContainerAtlas;     //              // What we has been loaded into\r\n    float                       Ascent, Descent;    //              // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]\r\n    int                         MetricsTotalSurface;//              // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)\r\n\r\n    // Methods\r\n    IMGUI_API ImFont();\r\n    IMGUI_API ~ImFont();\r\n    IMGUI_API void              Clear();\r\n    IMGUI_API void              BuildLookupTable();\r\n    IMGUI_API const Glyph*      FindGlyph(ImWchar c) const;\r\n    IMGUI_API void              SetFallbackChar(ImWchar c);\r\n    float                       GetCharAdvance(ImWchar c) const     { return ((int)c < IndexXAdvance.Size) ? IndexXAdvance[(int)c] : FallbackXAdvance; }\r\n    bool                        IsLoaded() const                    { return ContainerAtlas != NULL; }\r\n\r\n    // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.\r\n    // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable.\r\n    IMGUI_API ImVec2            CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8\r\n    IMGUI_API const char*       CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const;\r\n    IMGUI_API void              RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const;\r\n    IMGUI_API void              RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const;\r\n\r\n    // Private\r\n    IMGUI_API void              GrowIndex(int new_size);\r\n    IMGUI_API void              AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built.\r\n};\r\n\r\n#if defined(__clang__)\r\n#pragma clang diagnostic pop\r\n#endif\r\n\r\n// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h)\r\n#ifdef IMGUI_INCLUDE_IMGUI_USER_H\r\n#include \"imgui_user.h\"\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui_demo.cpp",
    "content": "// dear imgui, v1.52 WIP\r\n// (demo code)\r\n\r\n// Message to the person tempted to delete this file when integrating ImGui into their code base:\r\n// Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.\r\n// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow().\r\n// During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu!\r\n// Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library.\r\n// Note that you can #define IMGUI_DISABLE_TEST_WINDOWS in imconfig.h for the same effect.\r\n// If you want to link core ImGui in your public builds but not those test windows, #define IMGUI_DISABLE_TEST_WINDOWS in imconfig.h and those functions will be empty.\r\n// For any other case, if you have ImGui available you probably want this to be available for reference and execution.\r\n// Thank you,\r\n// -Your beloved friend, imgui_demo.cpp (that you won't delete)\r\n\r\n// Message to beginner C/C++ programmer about the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions. \r\n// We do this as a way to gather code and data in the same place, make the demo code faster to read, faster to write, and smaller. A static variable persist across calls, \r\n// so it is essentially like a global variable but declared inside the scope of the function.\r\n// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads.\r\n// This may be a pattern you want to use in your code (simple is beautiful!), but most of the real data you would be editing is likely to be stored outside your function.\r\n\r\n#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)\r\n#define _CRT_SECURE_NO_WARNINGS\r\n#endif\r\n\r\n#include \"imgui.h\"\r\n#include <ctype.h>          // toupper, isprint\r\n#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf\r\n#include <stdio.h>          // vsnprintf, sscanf, printf\r\n#include <stdlib.h>         // NULL, malloc, free, atoi\r\n#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier\r\n#include <stddef.h>         // intptr_t\r\n#else\r\n#include <stdint.h>         // intptr_t\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen\r\n#define snprintf _snprintf\r\n#endif\r\n#ifdef __clang__\r\n#pragma clang diagnostic ignored \"-Wold-style-cast\"             // warning : use of old-style cast                              // yes, they are more terse.\r\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"    // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)\r\n#pragma clang diagnostic ignored \"-Wint-to-void-pointer-cast\"   // warning : cast to 'void *' from smaller integer type 'int'\r\n#pragma clang diagnostic ignored \"-Wformat-security\"            // warning : warning: format string is not a string literal\r\n#pragma clang diagnostic ignored \"-Wexit-time-destructors\"      // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.\r\n#if __has_warning(\"-Wreserved-id-macro\")\r\n#pragma clang diagnostic ignored \"-Wreserved-id-macro\"          // warning : macro name is a reserved identifier                //\r\n#endif\r\n#elif defined(__GNUC__)\r\n#pragma GCC diagnostic ignored \"-Wint-to-pointer-cast\"          // warning: cast to pointer from integer of different size\r\n#pragma GCC diagnostic ignored \"-Wformat-security\"              // warning : format string is not a string literal (potentially insecure)\r\n#pragma GCC diagnostic ignored \"-Wdouble-promotion\"             // warning: implicit conversion from 'float' to 'double' when passing argument to function\r\n#pragma GCC diagnostic ignored \"-Wconversion\"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value\r\n#if (__GNUC__ >= 6)\r\n#pragma GCC diagnostic ignored \"-Wmisleading-indentation\"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on github.\r\n#endif\r\n#endif\r\n\r\n// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \\n.\r\n#ifdef _WIN32\r\n#define IM_NEWLINE \"\\r\\n\"\r\n#else\r\n#define IM_NEWLINE \"\\n\"\r\n#endif\r\n\r\n#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))\r\n#define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))\r\n\r\n//-----------------------------------------------------------------------------\r\n// DEMO CODE\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifndef IMGUI_DISABLE_TEST_WINDOWS\r\n\r\nstatic void ShowExampleAppConsole(bool* p_open);\r\nstatic void ShowExampleAppLog(bool* p_open);\r\nstatic void ShowExampleAppLayout(bool* p_open);\r\nstatic void ShowExampleAppPropertyEditor(bool* p_open);\r\nstatic void ShowExampleAppLongText(bool* p_open);\r\nstatic void ShowExampleAppAutoResize(bool* p_open);\r\nstatic void ShowExampleAppConstrainedResize(bool* p_open);\r\nstatic void ShowExampleAppFixedOverlay(bool* p_open);\r\nstatic void ShowExampleAppManipulatingWindowTitle(bool* p_open);\r\nstatic void ShowExampleAppCustomRendering(bool* p_open);\r\nstatic void ShowExampleAppMainMenuBar();\r\nstatic void ShowExampleMenuFile();\r\n\r\nstatic void ShowHelpMarker(const char* desc)\r\n{\r\n    ImGui::TextDisabled(\"(?)\");\r\n    if (ImGui::IsItemHovered())\r\n    {\r\n        ImGui::BeginTooltip();\r\n        ImGui::PushTextWrapPos(450.0f);\r\n        ImGui::TextUnformatted(desc);\r\n        ImGui::PopTextWrapPos();\r\n        ImGui::EndTooltip();\r\n    }\r\n}\r\n\r\nvoid ImGui::ShowUserGuide()\r\n{\r\n    ImGui::BulletText(\"Double-click on title bar to collapse window.\");\r\n    ImGui::BulletText(\"Click and drag on lower right corner to resize window.\");\r\n    ImGui::BulletText(\"Click and drag on any empty space to move window.\");\r\n    ImGui::BulletText(\"Mouse Wheel to scroll.\");\r\n    if (ImGui::GetIO().FontAllowUserScaling)\r\n        ImGui::BulletText(\"CTRL+Mouse Wheel to zoom window contents.\");\r\n    ImGui::BulletText(\"TAB/SHIFT+TAB to cycle through keyboard editable fields.\");\r\n    ImGui::BulletText(\"CTRL+Click on a slider or drag box to input text.\");\r\n    ImGui::BulletText(\r\n        \"While editing text:\\n\"\r\n        \"- Hold SHIFT or use mouse to select text\\n\"\r\n        \"- CTRL+Left/Right to word jump\\n\"\r\n        \"- CTRL+A or double-click to select all\\n\"\r\n        \"- CTRL+X,CTRL+C,CTRL+V clipboard\\n\"\r\n        \"- CTRL+Z,CTRL+Y undo/redo\\n\"\r\n        \"- ESCAPE to revert\\n\"\r\n        \"- You can apply arithmetic operators +,*,/ on numerical values.\\n\"\r\n        \"  Use +- to subtract.\\n\");\r\n}\r\n\r\n// Demonstrate most ImGui features (big function!)\r\nvoid ImGui::ShowTestWindow(bool* p_open)\r\n{\r\n    // Examples apps\r\n    static bool show_app_main_menu_bar = false;\r\n    static bool show_app_console = false;\r\n    static bool show_app_log = false;\r\n    static bool show_app_layout = false;\r\n    static bool show_app_property_editor = false;\r\n    static bool show_app_long_text = false;\r\n    static bool show_app_auto_resize = false;\r\n    static bool show_app_constrained_resize = false;\r\n    static bool show_app_fixed_overlay = false;\r\n    static bool show_app_manipulating_window_title = false;\r\n    static bool show_app_custom_rendering = false;\r\n    static bool show_app_style_editor = false;\r\n\r\n    static bool show_app_metrics = false;\r\n    static bool show_app_about = false;\r\n\r\n    if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();\r\n    if (show_app_console) ShowExampleAppConsole(&show_app_console);\r\n    if (show_app_log) ShowExampleAppLog(&show_app_log);\r\n    if (show_app_layout) ShowExampleAppLayout(&show_app_layout);\r\n    if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);\r\n    if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);\r\n    if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);\r\n    if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);\r\n    if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay);\r\n    if (show_app_manipulating_window_title) ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title);\r\n    if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);\r\n\r\n    if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics);\r\n    if (show_app_style_editor) { ImGui::Begin(\"Style Editor\", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }\r\n    if (show_app_about)\r\n    {\r\n        ImGui::Begin(\"About ImGui\", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);\r\n        ImGui::Text(\"dear imgui, %s\", ImGui::GetVersion());\r\n        ImGui::Separator();\r\n        ImGui::Text(\"By Omar Cornut and all github contributors.\");\r\n        ImGui::Text(\"ImGui is licensed under the MIT License, see LICENSE for more information.\");\r\n        ImGui::End();\r\n    }\r\n\r\n    static bool no_titlebar = false;\r\n    static bool no_border = true;\r\n    static bool no_resize = false;\r\n    static bool no_move = false;\r\n    static bool no_scrollbar = false;\r\n    static bool no_collapse = false;\r\n    static bool no_menu = false;\r\n\r\n    // Demonstrate the various window flags. Typically you would just use the default.\r\n    ImGuiWindowFlags window_flags = 0;\r\n    if (no_titlebar)  window_flags |= ImGuiWindowFlags_NoTitleBar;\r\n    if (!no_border)   window_flags |= ImGuiWindowFlags_ShowBorders;\r\n    if (no_resize)    window_flags |= ImGuiWindowFlags_NoResize;\r\n    if (no_move)      window_flags |= ImGuiWindowFlags_NoMove;\r\n    if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;\r\n    if (no_collapse)  window_flags |= ImGuiWindowFlags_NoCollapse;\r\n    if (!no_menu)     window_flags |= ImGuiWindowFlags_MenuBar;\r\n    ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiCond_FirstUseEver);\r\n    if (!ImGui::Begin(\"ImGui Demo\", p_open, window_flags))\r\n    {\r\n        // Early out if the window is collapsed, as an optimization.\r\n        ImGui::End();\r\n        return;\r\n    }\r\n\r\n    //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);    // 2/3 of the space for widget and 1/3 for labels\r\n    ImGui::PushItemWidth(-140);                                 // Right align, keep 140 pixels for labels\r\n\r\n    ImGui::Text(\"dear imgui says hello. (%s)\", IMGUI_VERSION);\r\n\r\n    // Menu\r\n    if (ImGui::BeginMenuBar())\r\n    {\r\n        if (ImGui::BeginMenu(\"Menu\"))\r\n        {\r\n            ShowExampleMenuFile();\r\n            ImGui::EndMenu();\r\n        }\r\n        if (ImGui::BeginMenu(\"Examples\"))\r\n        {\r\n            ImGui::MenuItem(\"Main menu bar\", NULL, &show_app_main_menu_bar);\r\n            ImGui::MenuItem(\"Console\", NULL, &show_app_console);\r\n            ImGui::MenuItem(\"Log\", NULL, &show_app_log);\r\n            ImGui::MenuItem(\"Simple layout\", NULL, &show_app_layout);\r\n            ImGui::MenuItem(\"Property editor\", NULL, &show_app_property_editor);\r\n            ImGui::MenuItem(\"Long text display\", NULL, &show_app_long_text);\r\n            ImGui::MenuItem(\"Auto-resizing window\", NULL, &show_app_auto_resize);\r\n            ImGui::MenuItem(\"Constrained-resizing window\", NULL, &show_app_constrained_resize);\r\n            ImGui::MenuItem(\"Simple overlay\", NULL, &show_app_fixed_overlay);\r\n            ImGui::MenuItem(\"Manipulating window title\", NULL, &show_app_manipulating_window_title);\r\n            ImGui::MenuItem(\"Custom rendering\", NULL, &show_app_custom_rendering);\r\n            ImGui::EndMenu();\r\n        }\r\n        if (ImGui::BeginMenu(\"Help\"))\r\n        {\r\n            ImGui::MenuItem(\"Metrics\", NULL, &show_app_metrics);\r\n            ImGui::MenuItem(\"Style Editor\", NULL, &show_app_style_editor);\r\n            ImGui::MenuItem(\"About ImGui\", NULL, &show_app_about);\r\n            ImGui::EndMenu();\r\n        }\r\n        ImGui::EndMenuBar();\r\n    }\r\n\r\n    ImGui::Spacing();\r\n    if (ImGui::CollapsingHeader(\"Help\"))\r\n    {\r\n        ImGui::TextWrapped(\"This window is being created by the ShowTestWindow() function. Please refer to the code for programming reference.\\n\\nUser Guide:\");\r\n        ImGui::ShowUserGuide();\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Window options\"))\r\n    {\r\n        ImGui::Checkbox(\"No titlebar\", &no_titlebar); ImGui::SameLine(150);\r\n        ImGui::Checkbox(\"No border\", &no_border); ImGui::SameLine(300);\r\n        ImGui::Checkbox(\"No resize\", &no_resize);\r\n        ImGui::Checkbox(\"No move\", &no_move); ImGui::SameLine(150);\r\n        ImGui::Checkbox(\"No scrollbar\", &no_scrollbar); ImGui::SameLine(300);\r\n        ImGui::Checkbox(\"No collapse\", &no_collapse);\r\n        ImGui::Checkbox(\"No menu\", &no_menu);\r\n\r\n        if (ImGui::TreeNode(\"Style\"))\r\n        {\r\n            ImGui::ShowStyleEditor();\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Logging\"))\r\n        {\r\n            ImGui::TextWrapped(\"The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output.\");\r\n            ImGui::LogButtons();\r\n            ImGui::TreePop();\r\n        }\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Widgets\"))\r\n    {\r\n\r\n        if (ImGui::TreeNode(\"Basic\"))\r\n        {\r\n            static int clicked = 0;\r\n            if (ImGui::Button(\"Button\")) \r\n                clicked++;\r\n            if (clicked & 1)\r\n            {\r\n                ImGui::SameLine();\r\n                ImGui::Text(\"Thanks for clicking me!\");\r\n            }\r\n\r\n            static bool check = true;\r\n            ImGui::Checkbox(\"checkbox\", &check);\r\n\r\n            static int e = 0;\r\n            ImGui::RadioButton(\"radio a\", &e, 0); ImGui::SameLine();\r\n            ImGui::RadioButton(\"radio b\", &e, 1); ImGui::SameLine();\r\n            ImGui::RadioButton(\"radio c\", &e, 2);\r\n\r\n            // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.\r\n            for (int i = 0; i < 7; i++)\r\n            {\r\n                if (i > 0) ImGui::SameLine();\r\n                ImGui::PushID(i);\r\n                ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));\r\n                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));\r\n                ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));\r\n                ImGui::Button(\"Click\");\r\n                ImGui::PopStyleColor(3);\r\n                ImGui::PopID();\r\n            }\r\n\r\n            ImGui::Text(\"Hover over me\");\r\n            if (ImGui::IsItemHovered())\r\n                ImGui::SetTooltip(\"I am a tooltip\");\r\n\r\n            ImGui::SameLine();\r\n            ImGui::Text(\"- or me\");\r\n            if (ImGui::IsItemHovered())\r\n            {\r\n                ImGui::BeginTooltip();\r\n                ImGui::Text(\"I am a fancy tooltip\");\r\n                static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };\r\n                ImGui::PlotLines(\"Curve\", arr, IM_ARRAYSIZE(arr));\r\n                ImGui::EndTooltip();\r\n            }\r\n\r\n            // Testing ImGuiOnceUponAFrame helper.\r\n            //static ImGuiOnceUponAFrame once;\r\n            //for (int i = 0; i < 5; i++)\r\n            //    if (once)\r\n            //        ImGui::Text(\"This will be displayed only once.\");\r\n\r\n            ImGui::Separator();\r\n\r\n            ImGui::LabelText(\"label\", \"Value\");\r\n\r\n            static int item = 1;\r\n            ImGui::Combo(\"combo\", &item, \"aaaa\\0bbbb\\0cccc\\0dddd\\0eeee\\0\\0\");   // Combo using values packed in a single constant string (for really quick combo)\r\n\r\n            const char* items[] = { \"AAAA\", \"BBBB\", \"CCCC\", \"DDDD\", \"EEEE\", \"FFFF\", \"GGGG\", \"HHHH\", \"IIII\", \"JJJJ\", \"KKKK\" };\r\n            static int item2 = -1;\r\n            ImGui::Combo(\"combo scroll\", &item2, items, IM_ARRAYSIZE(items));   // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that.\r\n\r\n            {\r\n                static char str0[128] = \"Hello, world!\";\r\n                static int i0=123;\r\n                static float f0=0.001f;\r\n                ImGui::InputText(\"input text\", str0, IM_ARRAYSIZE(str0));\r\n                ImGui::SameLine(); ShowHelpMarker(\"Hold SHIFT or use mouse to select text.\\n\" \"CTRL+Left/Right to word jump.\\n\" \"CTRL+A or double-click to select all.\\n\" \"CTRL+X,CTRL+C,CTRL+V clipboard.\\n\" \"CTRL+Z,CTRL+Y undo/redo.\\n\" \"ESCAPE to revert.\\n\");\r\n\r\n                ImGui::InputInt(\"input int\", &i0);\r\n                ImGui::SameLine(); ShowHelpMarker(\"You can apply arithmetic operators +,*,/ on numerical values.\\n  e.g. [ 100 ], input \\'*2\\', result becomes [ 200 ]\\nUse +- to subtract.\\n\");\r\n\r\n                ImGui::InputFloat(\"input float\", &f0, 0.01f, 1.0f);\r\n\r\n                static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };\r\n                ImGui::InputFloat3(\"input float3\", vec4a);\r\n            }\r\n\r\n            {\r\n                static int i1=50, i2=42;\r\n                ImGui::DragInt(\"drag int\", &i1, 1);\r\n                ImGui::SameLine(); ShowHelpMarker(\"Click and drag to edit value.\\nHold SHIFT/ALT for faster/slower edit.\\nDouble-click or CTRL+click to input value.\");\r\n\r\n                ImGui::DragInt(\"drag int 0..100\", &i2, 1, 0, 100, \"%.0f%%\");\r\n\r\n                static float f1=1.00f, f2=0.0067f;\r\n                ImGui::DragFloat(\"drag float\", &f1, 0.005f);\r\n                ImGui::DragFloat(\"drag small float\", &f2, 0.0001f, 0.0f, 0.0f, \"%.06f ns\");\r\n            }\r\n\r\n            {\r\n                static int i1=0;\r\n                ImGui::SliderInt(\"slider int\", &i1, -1, 3);\r\n                ImGui::SameLine(); ShowHelpMarker(\"CTRL+click to input value.\");\r\n\r\n                static float f1=0.123f, f2=0.0f;\r\n                ImGui::SliderFloat(\"slider float\", &f1, 0.0f, 1.0f, \"ratio = %.3f\");\r\n                ImGui::SliderFloat(\"slider log float\", &f2, -10.0f, 10.0f, \"%.4f\", 3.0f);\r\n                static float angle = 0.0f;\r\n                ImGui::SliderAngle(\"slider angle\", &angle);\r\n            }\r\n\r\n            static float col1[3] = { 1.0f,0.0f,0.2f };\r\n            static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };\r\n            ImGui::ColorEdit3(\"color 1\", col1);\r\n            ImGui::SameLine(); ShowHelpMarker(\"Click on the colored square to open a color picker.\\nRight-click on the colored square to show options.\\nCTRL+click on individual component to input value.\\n\");\r\n\r\n            ImGui::ColorEdit4(\"color 2\", col2);\r\n\r\n            const char* listbox_items[] = { \"Apple\", \"Banana\", \"Cherry\", \"Kiwi\", \"Mango\", \"Orange\", \"Pineapple\", \"Strawberry\", \"Watermelon\" };\r\n            static int listbox_item_current = 1;\r\n            ImGui::ListBox(\"listbox\\n(single select)\", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);\r\n\r\n            //static int listbox_item_current2 = 2;\r\n            //ImGui::PushItemWidth(-1);\r\n            //ImGui::ListBox(\"##listbox2\", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);\r\n            //ImGui::PopItemWidth();\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Trees\"))\r\n        {\r\n            if (ImGui::TreeNode(\"Basic trees\"))\r\n            {\r\n                for (int i = 0; i < 5; i++)\r\n                    if (ImGui::TreeNode((void*)(intptr_t)i, \"Child %d\", i))\r\n                    {\r\n                        ImGui::Text(\"blah blah\");\r\n                        ImGui::SameLine(); \r\n                        if (ImGui::SmallButton(\"print\")) printf(\"Child %d pressed\", i);\r\n                        ImGui::TreePop();\r\n                    }\r\n                ImGui::TreePop();\r\n            }\r\n\r\n            if (ImGui::TreeNode(\"Advanced, with Selectable nodes\"))\r\n            {\r\n                ShowHelpMarker(\"This is a more standard looking tree with selectable nodes.\\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.\");\r\n                static bool align_label_with_current_x_position = false;\r\n                ImGui::Checkbox(\"Align label with current X position)\", &align_label_with_current_x_position);\r\n                ImGui::Text(\"Hello!\");\r\n                if (align_label_with_current_x_position)\r\n                    ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());\r\n\r\n                static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.\r\n                int node_clicked = -1;                // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.\r\n                ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.\r\n                for (int i = 0; i < 6; i++)\r\n                {\r\n                    // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.\r\n                    ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);\r\n                    if (i < 3)\r\n                    {\r\n                        // Node\r\n                        bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, \"Selectable Node %d\", i);\r\n                        if (ImGui::IsItemClicked()) \r\n                            node_clicked = i;\r\n                        if (node_open)\r\n                        {\r\n                            ImGui::Text(\"Blah blah\\nBlah Blah\");\r\n                            ImGui::TreePop();\r\n                        }\r\n                    }\r\n                    else\r\n                    {\r\n                        // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().\r\n                        ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, \"Selectable Leaf %d\", i);\r\n                        if (ImGui::IsItemClicked()) \r\n                            node_clicked = i;\r\n                    }\r\n                }\r\n                if (node_clicked != -1)\r\n                {\r\n                    // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.\r\n                    if (ImGui::GetIO().KeyCtrl)\r\n                        selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle\r\n                    else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection\r\n                        selection_mask = (1 << node_clicked);           // Click to single-select\r\n                }\r\n                ImGui::PopStyleVar();\r\n                if (align_label_with_current_x_position)\r\n                    ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());\r\n                ImGui::TreePop();\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Collapsing Headers\"))\r\n        {\r\n            static bool closable_group = true;\r\n            if (ImGui::CollapsingHeader(\"Header\"))\r\n            {\r\n                ImGui::Checkbox(\"Enable extra group\", &closable_group);\r\n                for (int i = 0; i < 5; i++)\r\n                    ImGui::Text(\"Some content %d\", i);\r\n            }\r\n            if (ImGui::CollapsingHeader(\"Header with a close button\", &closable_group))\r\n            {\r\n                for (int i = 0; i < 5; i++)\r\n                    ImGui::Text(\"More content %d\", i);\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Bullets\"))\r\n        {\r\n            ImGui::BulletText(\"Bullet point 1\");\r\n            ImGui::BulletText(\"Bullet point 2\\nOn multiple lines\");\r\n            ImGui::Bullet(); ImGui::Text(\"Bullet point 3 (two calls)\");\r\n            ImGui::Bullet(); ImGui::SmallButton(\"Button\");\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Text\"))\r\n        {\r\n            if (ImGui::TreeNode(\"Colored Text\"))\r\n            {\r\n                // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.\r\n                ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), \"Pink\");\r\n                ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), \"Yellow\");\r\n                ImGui::TextDisabled(\"Disabled\");\r\n                ImGui::SameLine(); ShowHelpMarker(\"The TextDisabled color is stored in ImGuiStyle.\");\r\n                ImGui::TreePop();\r\n            }\r\n\r\n            if (ImGui::TreeNode(\"Word Wrapping\"))\r\n            {\r\n                // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.\r\n                ImGui::TextWrapped(\"This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.\");\r\n                ImGui::Spacing();\r\n\r\n                static float wrap_width = 200.0f;\r\n                ImGui::SliderFloat(\"Wrap width\", &wrap_width, -20, 600, \"%.0f\");\r\n\r\n                ImGui::Text(\"Test paragraph 1:\");\r\n                ImVec2 pos = ImGui::GetCursorScreenPos();\r\n                ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));\r\n                ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);\r\n                ImGui::Text(\"The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.\", wrap_width);\r\n                ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));\r\n                ImGui::PopTextWrapPos();\r\n\r\n                ImGui::Text(\"Test paragraph 2:\");\r\n                pos = ImGui::GetCursorScreenPos();\r\n                ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));\r\n                ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);\r\n                ImGui::Text(\"aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh\");\r\n                ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));\r\n                ImGui::PopTextWrapPos();\r\n\r\n                ImGui::TreePop();\r\n            }\r\n\r\n            if (ImGui::TreeNode(\"UTF-8 Text\"))\r\n            {\r\n                // UTF-8 test with Japanese characters\r\n                // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html)\r\n                // - From C++11 you can use the u8\"my text\" syntax to encode literal strings as UTF-8\r\n                // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature')\r\n                // - HOWEVER, FOR THIS DEMO FILE, BECAUSE WE WANT TO SUPPORT COMPILER, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.\r\n                //   Instead we are encoding a few string with hexadecimal constants. Don't do this in your application!\r\n                // Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.\r\n                ImGui::TextWrapped(\"CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.\");\r\n                ImGui::Text(\"Hiragana: \\xe3\\x81\\x8b\\xe3\\x81\\x8d\\xe3\\x81\\x8f\\xe3\\x81\\x91\\xe3\\x81\\x93 (kakikukeko)\");\r\n                ImGui::Text(\"Kanjis: \\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e (nihongo)\");\r\n                static char buf[32] = \"\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e\"; // \"nihongo\"\r\n                ImGui::InputText(\"UTF-8 input\", buf, IM_ARRAYSIZE(buf));\r\n                ImGui::TreePop();\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Images\"))\r\n        {\r\n            ImGui::TextWrapped(\"Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!\");\r\n            ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos();\r\n            float tex_w = (float)ImGui::GetIO().Fonts->TexWidth;\r\n            float tex_h = (float)ImGui::GetIO().Fonts->TexHeight;\r\n            ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;\r\n            ImGui::Text(\"%.0fx%.0f\", tex_w, tex_h);\r\n            ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));\r\n            if (ImGui::IsItemHovered())\r\n            {\r\n                ImGui::BeginTooltip();\r\n                float focus_sz = 32.0f;\r\n                float focus_x = ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > tex_w - focus_sz) focus_x = tex_w - focus_sz;\r\n                float focus_y = ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > tex_h - focus_sz) focus_y = tex_h - focus_sz;\r\n                ImGui::Text(\"Min: (%.2f, %.2f)\", focus_x, focus_y);\r\n                ImGui::Text(\"Max: (%.2f, %.2f)\", focus_x + focus_sz, focus_y + focus_sz);\r\n                ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h);\r\n                ImVec2 uv1 = ImVec2((focus_x + focus_sz) / tex_w, (focus_y + focus_sz) / tex_h);\r\n                ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));\r\n                ImGui::EndTooltip();\r\n            }\r\n            ImGui::TextWrapped(\"And now some textured buttons..\");\r\n            static int pressed_count = 0;\r\n            for (int i = 0; i < 8; i++)\r\n            {\r\n                ImGui::PushID(i);\r\n                int frame_padding = -1 + i;     // -1 = uses default padding\r\n                if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding, ImColor(0,0,0,255)))\r\n                    pressed_count += 1;\r\n                ImGui::PopID();\r\n                ImGui::SameLine();\r\n            }\r\n            ImGui::NewLine();\r\n            ImGui::Text(\"Pressed %d times.\", pressed_count);\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Selectables\"))\r\n        {\r\n            if (ImGui::TreeNode(\"Basic\"))\r\n            {\r\n                static bool selected[4] = { false, true, false, false };\r\n                ImGui::Selectable(\"1. I am selectable\", &selected[0]);\r\n                ImGui::Selectable(\"2. I am selectable\", &selected[1]);\r\n                ImGui::Text(\"3. I am not selectable\");\r\n                ImGui::Selectable(\"4. I am selectable\", &selected[2]);\r\n                if (ImGui::Selectable(\"5. I am double clickable\", selected[3], ImGuiSelectableFlags_AllowDoubleClick))\r\n                    if (ImGui::IsMouseDoubleClicked(0))\r\n                        selected[3] = !selected[3];\r\n                ImGui::TreePop();\r\n            }\r\n            if (ImGui::TreeNode(\"Rendering more text into the same block\"))\r\n            {\r\n                static bool selected[3] = { false, false, false };\r\n                ImGui::Selectable(\"main.c\", &selected[0]);    ImGui::SameLine(300); ImGui::Text(\" 2,345 bytes\");\r\n                ImGui::Selectable(\"Hello.cpp\", &selected[1]); ImGui::SameLine(300); ImGui::Text(\"12,345 bytes\");\r\n                ImGui::Selectable(\"Hello.h\", &selected[2]);   ImGui::SameLine(300); ImGui::Text(\" 2,345 bytes\");\r\n                ImGui::TreePop();\r\n            }\r\n            if (ImGui::TreeNode(\"In columns\"))\r\n            {\r\n                ImGui::Columns(3, NULL, false);\r\n                static bool selected[16] = { 0 };\r\n                for (int i = 0; i < 16; i++)\r\n                {\r\n                    char label[32]; sprintf(label, \"Item %d\", i);\r\n                    if (ImGui::Selectable(label, &selected[i])) {}\r\n                    ImGui::NextColumn();\r\n                }\r\n                ImGui::Columns(1);\r\n                ImGui::TreePop();\r\n            }\r\n            if (ImGui::TreeNode(\"Grid\"))\r\n            {\r\n                static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };\r\n                for (int i = 0; i < 16; i++)\r\n                {\r\n                    ImGui::PushID(i);\r\n                    if (ImGui::Selectable(\"Sailor\", &selected[i], 0, ImVec2(50,50)))\r\n                    {\r\n                        int x = i % 4, y = i / 4;\r\n                        if (x > 0) selected[i - 1] ^= 1;\r\n                        if (x < 3) selected[i + 1] ^= 1;\r\n                        if (y > 0) selected[i - 4] ^= 1;\r\n                        if (y < 3) selected[i + 4] ^= 1;\r\n                    }\r\n                    if ((i % 4) < 3) ImGui::SameLine();\r\n                    ImGui::PopID();\r\n                }\r\n                ImGui::TreePop();\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Filtered Text Input\"))\r\n        {\r\n            static char buf1[64] = \"\"; ImGui::InputText(\"default\", buf1, 64);\r\n            static char buf2[64] = \"\"; ImGui::InputText(\"decimal\", buf2, 64, ImGuiInputTextFlags_CharsDecimal);\r\n            static char buf3[64] = \"\"; ImGui::InputText(\"hexadecimal\", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);\r\n            static char buf4[64] = \"\"; ImGui::InputText(\"uppercase\", buf4, 64, ImGuiInputTextFlags_CharsUppercase);\r\n            static char buf5[64] = \"\"; ImGui::InputText(\"no blank\", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);\r\n            struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr(\"imgui\", (char)data->EventChar)) return 0; return 1; } };\r\n            static char buf6[64] = \"\"; ImGui::InputText(\"\\\"imgui\\\" letters\", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);\r\n\r\n            ImGui::Text(\"Password input\");\r\n            static char bufpass[64] = \"password123\";\r\n            ImGui::InputText(\"password\", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);\r\n            ImGui::SameLine(); ShowHelpMarker(\"Display all characters as '*'.\\nDisable clipboard cut and copy.\\nDisable logging.\\n\");\r\n            ImGui::InputText(\"password (clear)\", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Multi-line Text Input\"))\r\n        {\r\n            static bool read_only = false;\r\n            static char text[1024*16] =\r\n                \"/*\\n\"\r\n                \" The Pentium F00F bug, shorthand for F0 0F C7 C8,\\n\"\r\n                \" the hexadecimal encoding of one offending instruction,\\n\"\r\n                \" more formally, the invalid operand with locked CMPXCHG8B\\n\"\r\n                \" instruction bug, is a design flaw in the majority of\\n\"\r\n                \" Intel Pentium, Pentium MMX, and Pentium OverDrive\\n\"\r\n                \" processors (all in the P5 microarchitecture).\\n\"\r\n                \"*/\\n\\n\"\r\n                \"label:\\n\"\r\n                \"\\tlock cmpxchg8b eax\\n\";\r\n\r\n            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));\r\n            ImGui::Checkbox(\"Read-only\", &read_only);\r\n            ImGui::PopStyleVar();\r\n            ImGui::InputTextMultiline(\"##source\", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));\r\n            ImGui::TreePop();\r\n        }\r\n\r\n\r\n        if (ImGui::TreeNode(\"Plots widgets\"))\r\n        {\r\n            static bool animate = true;\r\n            ImGui::Checkbox(\"Animate\", &animate);\r\n\r\n            static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };\r\n            ImGui::PlotLines(\"Frame Times\", arr, IM_ARRAYSIZE(arr));\r\n\r\n            // Create a dummy array of contiguous float values to plot\r\n            // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.\r\n            static float values[90] = { 0 };\r\n            static int values_offset = 0;\r\n            static float refresh_time = 0.0f;\r\n            if (!animate || refresh_time == 0.0f)\r\n                refresh_time = ImGui::GetTime();\r\n            while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo\r\n            {\r\n                static float phase = 0.0f;\r\n                values[values_offset] = cosf(phase);\r\n                values_offset = (values_offset+1) % IM_ARRAYSIZE(values);\r\n                phase += 0.10f*values_offset;\r\n                refresh_time += 1.0f/60.0f;\r\n            }\r\n            ImGui::PlotLines(\"Lines\", values, IM_ARRAYSIZE(values), values_offset, \"avg 0.0\", -1.0f, 1.0f, ImVec2(0,80));\r\n            ImGui::PlotHistogram(\"Histogram\", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));\r\n\r\n            // Use functions to generate output\r\n            // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.\r\n            struct Funcs\r\n            {\r\n                static float Sin(void*, int i) { return sinf(i * 0.1f); }\r\n                static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }\r\n            };\r\n            static int func_type = 0, display_count = 70;\r\n            ImGui::Separator();\r\n            ImGui::PushItemWidth(100); ImGui::Combo(\"func\", &func_type, \"Sin\\0Saw\\0\"); ImGui::PopItemWidth();\r\n            ImGui::SameLine();\r\n            ImGui::SliderInt(\"Sample count\", &display_count, 1, 400);\r\n            float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;\r\n            ImGui::PlotLines(\"Lines\", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));\r\n            ImGui::PlotHistogram(\"Histogram\", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));\r\n            ImGui::Separator();\r\n\r\n            // Animate a simple progress bar\r\n            static float progress = 0.0f, progress_dir = 1.0f;\r\n            if (animate)\r\n            {\r\n                progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;\r\n                if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }\r\n                if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }\r\n            }\r\n\r\n            // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.\r\n            ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));\r\n            ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);\r\n            ImGui::Text(\"Progress Bar\");\r\n\r\n            float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;\r\n            char buf[32];\r\n            sprintf(buf, \"%d/%d\", (int)(progress_saturated*1753), 1753);\r\n            ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Color/Picker Widgets\"))\r\n        {\r\n            static ImVec4 color = ImColor(114, 144, 154, 200);\r\n\r\n            static bool hdr = false;\r\n            static bool alpha_preview = true;\r\n            static bool alpha_half_preview = false;\r\n            static bool options_menu = true;\r\n            ImGui::Checkbox(\"With HDR\", &hdr); ImGui::SameLine(); ShowHelpMarker(\"Currently all this does is to lift the 0..1 limits on dragging widgets.\");\r\n            ImGui::Checkbox(\"With Alpha Preview\", &alpha_preview);\r\n            ImGui::Checkbox(\"With Half Alpha Preview\", &alpha_half_preview);\r\n            ImGui::Checkbox(\"With Options Menu\", &options_menu); ImGui::SameLine(); ShowHelpMarker(\"Right-click on the individual color widget to show options.\");\r\n            int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);\r\n\r\n            ImGui::Text(\"Color widget:\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Click on the colored square to open a color picker.\\nCTRL+click on individual component to input value.\\n\");\r\n            ImGui::ColorEdit3(\"MyColor##1\", (float*)&color, misc_flags);\r\n\r\n            ImGui::Text(\"Color widget HSV with Alpha:\");\r\n            ImGui::ColorEdit4(\"MyColor##2\", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);\r\n\r\n            ImGui::Text(\"Color widget with Float Display:\");\r\n            ImGui::ColorEdit4(\"MyColor##2f\", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);\r\n\r\n            ImGui::Text(\"Color button with Picker:\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.\");\r\n            ImGui::ColorEdit4(\"MyColor##3\", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);\r\n\r\n            ImGui::Text(\"Color button with Custom Picker Popup:\");\r\n            static bool saved_palette_inited = false;\r\n            static ImVec4 saved_palette[32];\r\n            static ImVec4 backup_color;\r\n            if (!saved_palette_inited)\r\n                for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)\r\n                    ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);\r\n            bool open_popup = ImGui::ColorButton(\"MyColor##3b\", color, misc_flags);\r\n            ImGui::SameLine();\r\n            open_popup |= ImGui::Button(\"Palette\");\r\n            if (open_popup)\r\n            {\r\n                ImGui::OpenPopup(\"mypicker\");\r\n                backup_color = color;\r\n            }\r\n            if (ImGui::BeginPopup(\"mypicker\"))\r\n            {\r\n                // FIXME: Adding a drag and drop example here would be perfect!\r\n                ImGui::Text(\"MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!\");\r\n                ImGui::Separator();\r\n                ImGui::ColorPicker4(\"##picker\", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);\r\n                ImGui::SameLine();\r\n                ImGui::BeginGroup();\r\n                ImGui::Text(\"Current\");\r\n                ImGui::ColorButton(\"##current\", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));\r\n                ImGui::Text(\"Previous\");\r\n                if (ImGui::ColorButton(\"##previous\", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))\r\n                    color = backup_color;\r\n                ImGui::Separator();\r\n                ImGui::Text(\"Palette\");\r\n                for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)\r\n                {\r\n                    ImGui::PushID(n);\r\n                    if ((n % 8) != 0)\r\n                        ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);\r\n                    if (ImGui::ColorButton(\"##palette\", saved_palette[n], ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20)))\r\n                        color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!\r\n                    ImGui::PopID();\r\n                }\r\n                ImGui::EndGroup();\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            ImGui::Text(\"Color button only:\");\r\n            ImGui::ColorButton(\"MyColor##3b\", *(ImVec4*)&color, misc_flags, ImVec2(80,80));\r\n\r\n            ImGui::Text(\"Color picker:\");\r\n            static bool alpha = true;\r\n            static bool alpha_bar = true;\r\n            static bool side_preview = true;\r\n            static bool ref_color = false;\r\n            static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);\r\n            static int inputs_mode = 2;\r\n            static int picker_mode = 0;\r\n            ImGui::Checkbox(\"With Alpha\", &alpha);\r\n            ImGui::Checkbox(\"With Alpha Bar\", &alpha_bar);\r\n            ImGui::Checkbox(\"With Side Preview\", &side_preview);\r\n            if (side_preview)\r\n            {\r\n                ImGui::SameLine();\r\n                ImGui::Checkbox(\"With Ref Color\", &ref_color);\r\n                if (ref_color)\r\n                {\r\n                    ImGui::SameLine();\r\n                    ImGui::ColorEdit4(\"##RefColor\", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);\r\n                }\r\n            }\r\n            ImGui::Combo(\"Inputs Mode\", &inputs_mode, \"All Inputs\\0No Inputs\\0RGB Input\\0HSV Input\\0HEX Input\\0\");\r\n            ImGui::Combo(\"Picker Mode\", &picker_mode, \"Auto/Current\\0Hue bar + SV rect\\0Hue wheel + SV triangle\\0\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"User can right-click the picker to change mode.\");\r\n            ImGuiColorEditFlags flags = misc_flags;\r\n            if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()\r\n            if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;\r\n            if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;\r\n            if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;\r\n            if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;\r\n            if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;\r\n            if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;\r\n            if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;\r\n            if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;\r\n            ImGui::ColorPicker4(\"MyColor##4\", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);\r\n\r\n            ImGui::Text(\"Programmatically set defaults/options:\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"SetColorEditOptions() is designed to allow you to set boot-time default.\\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.\");\r\n            if (ImGui::Button(\"Uint8 + HSV\"))\r\n                ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV);\r\n            ImGui::SameLine();\r\n            if (ImGui::Button(\"Float + HDR\"))\r\n                ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_RGB);\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Range Widgets\"))\r\n        {\r\n            static float begin = 10, end = 90;\r\n            static int begin_i = 100, end_i = 1000;\r\n            ImGui::DragFloatRange2(\"range\", &begin, &end, 0.25f, 0.0f, 100.0f, \"Min: %.1f %%\", \"Max: %.1f %%\");\r\n            ImGui::DragIntRange2(\"range int (no bounds)\", &begin_i, &end_i, 5, 0, 0, \"Min: %.0f units\", \"Max: %.0f units\");\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Multi-component Widgets\"))\r\n        {\r\n            static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };\r\n            static int vec4i[4] = { 1, 5, 100, 255 };\r\n\r\n            ImGui::InputFloat2(\"input float2\", vec4f);\r\n            ImGui::DragFloat2(\"drag float2\", vec4f, 0.01f, 0.0f, 1.0f);\r\n            ImGui::SliderFloat2(\"slider float2\", vec4f, 0.0f, 1.0f);\r\n            ImGui::DragInt2(\"drag int2\", vec4i, 1, 0, 255);\r\n            ImGui::InputInt2(\"input int2\", vec4i);\r\n            ImGui::SliderInt2(\"slider int2\", vec4i, 0, 255);\r\n            ImGui::Spacing();\r\n\r\n            ImGui::InputFloat3(\"input float3\", vec4f);\r\n            ImGui::DragFloat3(\"drag float3\", vec4f, 0.01f, 0.0f, 1.0f);\r\n            ImGui::SliderFloat3(\"slider float3\", vec4f, 0.0f, 1.0f);\r\n            ImGui::DragInt3(\"drag int3\", vec4i, 1, 0, 255);\r\n            ImGui::InputInt3(\"input int3\", vec4i);\r\n            ImGui::SliderInt3(\"slider int3\", vec4i, 0, 255);\r\n            ImGui::Spacing();\r\n\r\n            ImGui::InputFloat4(\"input float4\", vec4f);\r\n            ImGui::DragFloat4(\"drag float4\", vec4f, 0.01f, 0.0f, 1.0f);\r\n            ImGui::SliderFloat4(\"slider float4\", vec4f, 0.0f, 1.0f);\r\n            ImGui::InputInt4(\"input int4\", vec4i);\r\n            ImGui::DragInt4(\"drag int4\", vec4i, 1, 0, 255);\r\n            ImGui::SliderInt4(\"slider int4\", vec4i, 0, 255);\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Vertical Sliders\"))\r\n        {\r\n            const float spacing = 4;\r\n            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));\r\n\r\n            static int int_value = 0;\r\n            ImGui::VSliderInt(\"##int\", ImVec2(18,160), &int_value, 0, 5);\r\n            ImGui::SameLine();\r\n\r\n            static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };\r\n            ImGui::PushID(\"set1\");\r\n            for (int i = 0; i < 7; i++)\r\n            {\r\n                if (i > 0) ImGui::SameLine();\r\n                ImGui::PushID(i);\r\n                ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));\r\n                ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));\r\n                ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));\r\n                ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));\r\n                ImGui::VSliderFloat(\"##v\", ImVec2(18,160), &values[i], 0.0f, 1.0f, \"\");\r\n                if (ImGui::IsItemActive() || ImGui::IsItemHovered())\r\n                    ImGui::SetTooltip(\"%.3f\", values[i]);\r\n                ImGui::PopStyleColor(4);\r\n                ImGui::PopID();\r\n            }\r\n            ImGui::PopID();\r\n\r\n            ImGui::SameLine();\r\n            ImGui::PushID(\"set2\");\r\n            static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };\r\n            const int rows = 3;\r\n            const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);\r\n            for (int nx = 0; nx < 4; nx++)\r\n            {\r\n                if (nx > 0) ImGui::SameLine();\r\n                ImGui::BeginGroup();\r\n                for (int ny = 0; ny < rows; ny++)\r\n                {\r\n                    ImGui::PushID(nx*rows+ny);\r\n                    ImGui::VSliderFloat(\"##v\", small_slider_size, &values2[nx], 0.0f, 1.0f, \"\");\r\n                    if (ImGui::IsItemActive() || ImGui::IsItemHovered())\r\n                        ImGui::SetTooltip(\"%.3f\", values2[nx]);\r\n                    ImGui::PopID();\r\n                }\r\n                ImGui::EndGroup();\r\n            }\r\n            ImGui::PopID();\r\n\r\n            ImGui::SameLine();\r\n            ImGui::PushID(\"set3\");\r\n            for (int i = 0; i < 4; i++)\r\n            {\r\n                if (i > 0) ImGui::SameLine();\r\n                ImGui::PushID(i);\r\n                ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);\r\n                ImGui::VSliderFloat(\"##v\", ImVec2(40,160), &values[i], 0.0f, 1.0f, \"%.2f\\nsec\");\r\n                ImGui::PopStyleVar();\r\n                ImGui::PopID();\r\n            }\r\n            ImGui::PopID();\r\n            ImGui::PopStyleVar();\r\n            ImGui::TreePop();\r\n        }\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Layout\"))\r\n    {\r\n        if (ImGui::TreeNode(\"Child regions\"))\r\n        {\r\n            ImGui::Text(\"Without border\");\r\n            static int line = 50;\r\n            bool goto_line = ImGui::Button(\"Goto\");\r\n            ImGui::SameLine();\r\n            ImGui::PushItemWidth(100);\r\n            goto_line |= ImGui::InputInt(\"##Line\", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);\r\n            ImGui::PopItemWidth();\r\n            ImGui::BeginChild(\"Sub1\", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar);\r\n            for (int i = 0; i < 100; i++)\r\n            {\r\n                ImGui::Text(\"%04d: scrollable region\", i);\r\n                if (goto_line && line == i)\r\n                    ImGui::SetScrollHere();\r\n            }\r\n            if (goto_line && line >= 100)\r\n                ImGui::SetScrollHere();\r\n            ImGui::EndChild();\r\n\r\n            ImGui::SameLine();\r\n\r\n            ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f);\r\n            ImGui::BeginChild(\"Sub2\", ImVec2(0,300), true);\r\n            ImGui::Text(\"With border\");\r\n            ImGui::Columns(2);\r\n            for (int i = 0; i < 100; i++)\r\n            {\r\n                if (i == 50)\r\n                    ImGui::NextColumn();\r\n                char buf[32];\r\n                sprintf(buf, \"%08x\", i*5731);\r\n                ImGui::Button(buf, ImVec2(-1.0f, 0.0f));\r\n            }\r\n            ImGui::EndChild();\r\n            ImGui::PopStyleVar();\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Widgets Width\"))\r\n        {\r\n            static float f = 0.0f;\r\n            ImGui::Text(\"PushItemWidth(100)\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Fixed width.\");\r\n            ImGui::PushItemWidth(100);\r\n            ImGui::DragFloat(\"float##1\", &f);\r\n            ImGui::PopItemWidth();\r\n\r\n            ImGui::Text(\"PushItemWidth(GetWindowWidth() * 0.5f)\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Half of window width.\");\r\n            ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);\r\n            ImGui::DragFloat(\"float##2\", &f);\r\n            ImGui::PopItemWidth();\r\n\r\n            ImGui::Text(\"PushItemWidth(GetContentRegionAvailWidth() * 0.5f)\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Half of available width.\\n(~ right-cursor_pos)\\n(works within a column set)\");\r\n            ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);\r\n            ImGui::DragFloat(\"float##3\", &f);\r\n            ImGui::PopItemWidth();\r\n\r\n            ImGui::Text(\"PushItemWidth(-100)\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Align to right edge minus 100\");\r\n            ImGui::PushItemWidth(-100);\r\n            ImGui::DragFloat(\"float##4\", &f);\r\n            ImGui::PopItemWidth();\r\n\r\n            ImGui::Text(\"PushItemWidth(-1)\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Align to right edge\");\r\n            ImGui::PushItemWidth(-1);\r\n            ImGui::DragFloat(\"float##5\", &f);\r\n            ImGui::PopItemWidth();\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Basic Horizontal Layout\"))\r\n        {\r\n            ImGui::TextWrapped(\"(Use ImGui::SameLine() to keep adding items to the right of the preceding item)\");\r\n\r\n            // Text\r\n            ImGui::Text(\"Two items: Hello\"); ImGui::SameLine();\r\n            ImGui::TextColored(ImVec4(1,1,0,1), \"Sailor\");\r\n\r\n            // Adjust spacing\r\n            ImGui::Text(\"More spacing: Hello\"); ImGui::SameLine(0, 20);\r\n            ImGui::TextColored(ImVec4(1,1,0,1), \"Sailor\");\r\n\r\n            // Button\r\n            ImGui::AlignFirstTextHeightToWidgets();\r\n            ImGui::Text(\"Normal buttons\"); ImGui::SameLine();\r\n            ImGui::Button(\"Banana\"); ImGui::SameLine();\r\n            ImGui::Button(\"Apple\"); ImGui::SameLine();\r\n            ImGui::Button(\"Corniflower\");\r\n\r\n            // Button\r\n            ImGui::Text(\"Small buttons\"); ImGui::SameLine();\r\n            ImGui::SmallButton(\"Like this one\"); ImGui::SameLine();\r\n            ImGui::Text(\"can fit within a text block.\");\r\n\r\n            // Aligned to arbitrary position. Easy/cheap column.\r\n            ImGui::Text(\"Aligned\");\r\n            ImGui::SameLine(150); ImGui::Text(\"x=150\");\r\n            ImGui::SameLine(300); ImGui::Text(\"x=300\");\r\n            ImGui::Text(\"Aligned\");\r\n            ImGui::SameLine(150); ImGui::SmallButton(\"x=150\");\r\n            ImGui::SameLine(300); ImGui::SmallButton(\"x=300\");\r\n\r\n            // Checkbox\r\n            static bool c1=false,c2=false,c3=false,c4=false;\r\n            ImGui::Checkbox(\"My\", &c1); ImGui::SameLine();\r\n            ImGui::Checkbox(\"Tailor\", &c2); ImGui::SameLine();\r\n            ImGui::Checkbox(\"Is\", &c3); ImGui::SameLine();\r\n            ImGui::Checkbox(\"Rich\", &c4);\r\n\r\n            // Various\r\n            static float f0=1.0f, f1=2.0f, f2=3.0f;\r\n            ImGui::PushItemWidth(80);\r\n            const char* items[] = { \"AAAA\", \"BBBB\", \"CCCC\", \"DDDD\" };\r\n            static int item = -1;\r\n            ImGui::Combo(\"Combo\", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();\r\n            ImGui::SliderFloat(\"X\", &f0, 0.0f,5.0f); ImGui::SameLine();\r\n            ImGui::SliderFloat(\"Y\", &f1, 0.0f,5.0f); ImGui::SameLine();\r\n            ImGui::SliderFloat(\"Z\", &f2, 0.0f,5.0f);\r\n            ImGui::PopItemWidth();\r\n\r\n            ImGui::PushItemWidth(80);\r\n            ImGui::Text(\"Lists:\");\r\n            static int selection[4] = { 0, 1, 2, 3 };\r\n            for (int i = 0; i < 4; i++)\r\n            {\r\n                if (i > 0) ImGui::SameLine();\r\n                ImGui::PushID(i);\r\n                ImGui::ListBox(\"\", &selection[i], items, IM_ARRAYSIZE(items));\r\n                ImGui::PopID();\r\n                //if (ImGui::IsItemHovered()) ImGui::SetTooltip(\"ListBox %d hovered\", i);\r\n            }\r\n            ImGui::PopItemWidth();\r\n\r\n            // Dummy\r\n            ImVec2 sz(30,30);\r\n            ImGui::Button(\"A\", sz); ImGui::SameLine();\r\n            ImGui::Dummy(sz); ImGui::SameLine();\r\n            ImGui::Button(\"B\", sz);\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Groups\"))\r\n        {\r\n            ImGui::TextWrapped(\"(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)\");\r\n            ImGui::BeginGroup();\r\n            {\r\n                ImGui::BeginGroup();\r\n                ImGui::Button(\"AAA\");\r\n                ImGui::SameLine();\r\n                ImGui::Button(\"BBB\");\r\n                ImGui::SameLine();\r\n                ImGui::BeginGroup();\r\n                ImGui::Button(\"CCC\");\r\n                ImGui::Button(\"DDD\");\r\n                ImGui::EndGroup();\r\n                if (ImGui::IsItemHovered())\r\n                    ImGui::SetTooltip(\"Group hovered\");\r\n                ImGui::SameLine();\r\n                ImGui::Button(\"EEE\");\r\n                ImGui::EndGroup();\r\n            }\r\n            // Capture the group size and create widgets using the same size\r\n            ImVec2 size = ImGui::GetItemRectSize();\r\n            const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };\r\n            ImGui::PlotHistogram(\"##values\", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);\r\n\r\n            ImGui::Button(\"ACTION\", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));\r\n            ImGui::SameLine();\r\n            ImGui::Button(\"REACTION\", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));\r\n            ImGui::EndGroup();\r\n            ImGui::SameLine();\r\n\r\n            ImGui::Button(\"LEVERAGE\\nBUZZWORD\", size);\r\n            ImGui::SameLine();\r\n\r\n            ImGui::ListBoxHeader(\"List\", size);\r\n            ImGui::Selectable(\"Selected\", true);\r\n            ImGui::Selectable(\"Not Selected\", false);\r\n            ImGui::ListBoxFooter();\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Text Baseline Alignment\"))\r\n        {\r\n            ImGui::TextWrapped(\"(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \\\"small\\\" widgets fit in less vertical spaces than lines with normal widgets)\");\r\n\r\n            ImGui::Text(\"One\\nTwo\\nThree\"); ImGui::SameLine();\r\n            ImGui::Text(\"Hello\\nWorld\"); ImGui::SameLine();\r\n            ImGui::Text(\"Banana\");\r\n\r\n            ImGui::Text(\"Banana\"); ImGui::SameLine();\r\n            ImGui::Text(\"Hello\\nWorld\"); ImGui::SameLine();\r\n            ImGui::Text(\"One\\nTwo\\nThree\");\r\n\r\n            ImGui::Button(\"HOP##1\"); ImGui::SameLine();\r\n            ImGui::Text(\"Banana\"); ImGui::SameLine();\r\n            ImGui::Text(\"Hello\\nWorld\"); ImGui::SameLine();\r\n            ImGui::Text(\"Banana\");\r\n\r\n            ImGui::Button(\"HOP##2\"); ImGui::SameLine();\r\n            ImGui::Text(\"Hello\\nWorld\"); ImGui::SameLine();\r\n            ImGui::Text(\"Banana\");\r\n\r\n            ImGui::Button(\"TEST##1\"); ImGui::SameLine();\r\n            ImGui::Text(\"TEST\"); ImGui::SameLine();\r\n            ImGui::SmallButton(\"TEST##2\");\r\n\r\n            ImGui::AlignFirstTextHeightToWidgets(); // If your line starts with text, call this to align it to upcoming widgets.\r\n            ImGui::Text(\"Text aligned to Widget\"); ImGui::SameLine();\r\n            ImGui::Button(\"Widget##1\"); ImGui::SameLine();\r\n            ImGui::Text(\"Widget\"); ImGui::SameLine();\r\n            ImGui::SmallButton(\"Widget##2\");\r\n\r\n            // Tree\r\n            const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;\r\n            ImGui::Button(\"Button##1\");\r\n            ImGui::SameLine(0.0f, spacing);\r\n            if (ImGui::TreeNode(\"Node##1\")) { for (int i = 0; i < 6; i++) ImGui::BulletText(\"Item %d..\", i); ImGui::TreePop(); }    // Dummy tree data\r\n\r\n            ImGui::AlignFirstTextHeightToWidgets();         // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).\r\n            bool node_open = ImGui::TreeNode(\"Node##2\");  // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.\r\n            ImGui::SameLine(0.0f, spacing); ImGui::Button(\"Button##2\");\r\n            if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText(\"Item %d..\", i); ImGui::TreePop(); }   // Dummy tree data\r\n\r\n            // Bullet\r\n            ImGui::Button(\"Button##3\");\r\n            ImGui::SameLine(0.0f, spacing);\r\n            ImGui::BulletText(\"Bullet text\");\r\n\r\n            ImGui::AlignFirstTextHeightToWidgets();\r\n            ImGui::BulletText(\"Node\");\r\n            ImGui::SameLine(0.0f, spacing); ImGui::Button(\"Button##4\");\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Scrolling\"))\r\n        {\r\n            ImGui::TextWrapped(\"(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)\");\r\n            static bool track = true;\r\n            static int track_line = 50, scroll_to_px = 200;\r\n            ImGui::Checkbox(\"Track\", &track);\r\n            ImGui::PushItemWidth(100);\r\n            ImGui::SameLine(130); track |= ImGui::DragInt(\"##line\", &track_line, 0.25f, 0, 99, \"Line = %.0f\");\r\n            bool scroll_to = ImGui::Button(\"Scroll To Pos\");\r\n            ImGui::SameLine(130); scroll_to |= ImGui::DragInt(\"##pos_y\", &scroll_to_px, 1.00f, 0, 9999, \"Y = %.0f px\");\r\n            ImGui::PopItemWidth();\r\n            if (scroll_to) track = false;\r\n\r\n            for (int i = 0; i < 5; i++)\r\n            {\r\n                if (i > 0) ImGui::SameLine();\r\n                ImGui::BeginGroup();\r\n                ImGui::Text(\"%s\", i == 0 ? \"Top\" : i == 1 ? \"25%\" : i == 2 ? \"Center\" : i == 3 ? \"75%\" : \"Bottom\");\r\n                ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);\r\n                if (scroll_to)\r\n                    ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);\r\n                for (int line = 0; line < 100; line++)\r\n                {\r\n                    if (track && line == track_line)\r\n                    {\r\n                        ImGui::TextColored(ImColor(255,255,0), \"Line %d\", line);\r\n                        ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom\r\n                    }\r\n                    else\r\n                    {\r\n                        ImGui::Text(\"Line %d\", line);\r\n                    }\r\n                }\r\n                float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();\r\n                ImGui::EndChild();\r\n                ImGui::Text(\"%.0f/%0.f\", scroll_y, scroll_max_y);\r\n                ImGui::EndGroup();\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Horizontal Scrolling\"))\r\n        {\r\n            ImGui::Bullet(); ImGui::TextWrapped(\"Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.\");\r\n            ImGui::Bullet(); ImGui::TextWrapped(\"You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().\");\r\n            static int lines = 7;\r\n            ImGui::SliderInt(\"Lines\", &lines, 1, 15);\r\n            ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);\r\n            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));\r\n            ImGui::BeginChild(\"scrolling\", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);\r\n            for (int line = 0; line < lines; line++)\r\n            {\r\n                // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off \r\n                // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API)\r\n                int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);\r\n                for (int n = 0; n < num_buttons; n++)\r\n                {\r\n                    if (n > 0) ImGui::SameLine();\r\n                    ImGui::PushID(n + line * 1000);\r\n                    char num_buf[16];\r\n                    const char* label = (!(n%15)) ? \"FizzBuzz\" : (!(n%3)) ? \"Fizz\" : (!(n%5)) ? \"Buzz\" : (sprintf(num_buf, \"%d\", n), num_buf);\r\n                    float hue = n*0.05f;\r\n                    ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));\r\n                    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));\r\n                    ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));\r\n                    ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));\r\n                    ImGui::PopStyleColor(3);\r\n                    ImGui::PopID();\r\n                }\r\n            }\r\n            float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();\r\n            ImGui::EndChild();\r\n            ImGui::PopStyleVar(2);\r\n            float scroll_x_delta = 0.0f;\r\n            ImGui::SmallButton(\"<<\"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine(); \r\n            ImGui::Text(\"Scroll from code\"); ImGui::SameLine();\r\n            ImGui::SmallButton(\">>\"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine(); \r\n            ImGui::Text(\"%.0f/%.0f\", scroll_x, scroll_max_x);\r\n            if (scroll_x_delta != 0.0f)\r\n            {\r\n                ImGui::BeginChild(\"scrolling\"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window)\r\n                ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);\r\n                ImGui::End();\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Clipping\"))\r\n        {\r\n            static ImVec2 size(100, 100), offset(50, 20);\r\n            ImGui::TextWrapped(\"On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.\");\r\n            ImGui::DragFloat2(\"size\", (float*)&size, 0.5f, 0.0f, 200.0f, \"%.0f\");\r\n            ImGui::TextWrapped(\"(Click and drag)\");\r\n            ImVec2 pos = ImGui::GetCursorScreenPos();\r\n            ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);\r\n            ImGui::InvisibleButton(\"##dummy\", size);\r\n            if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }\r\n            ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));\r\n            ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), \"Line 1 hello\\nLine 2 clip me!\", NULL, 0.0f, &clip_rect);\r\n            ImGui::TreePop();\r\n        }\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Popups & Modal windows\"))\r\n    {\r\n        if (ImGui::TreeNode(\"Popups\"))\r\n        {\r\n            ImGui::TextWrapped(\"When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.\");\r\n\r\n            static int selected_fish = -1;\r\n            const char* names[] = { \"Bream\", \"Haddock\", \"Mackerel\", \"Pollock\", \"Tilefish\" };\r\n            static bool toggles[] = { true, false, false, false, false };\r\n\r\n            // Simple selection popup\r\n            // (If you want to show the current selection inside the Button itself, you may want to build a string using the \"###\" operator to preserve a constant ID with a variable label)\r\n            if (ImGui::Button(\"Select..\"))\r\n                ImGui::OpenPopup(\"select\");\r\n            ImGui::SameLine();\r\n            ImGui::Text(selected_fish == -1 ? \"<None>\" : names[selected_fish]);\r\n            if (ImGui::BeginPopup(\"select\"))\r\n            {\r\n                ImGui::Text(\"Aquarium\");\r\n                ImGui::Separator();\r\n                for (int i = 0; i < IM_ARRAYSIZE(names); i++)\r\n                    if (ImGui::Selectable(names[i]))\r\n                        selected_fish = i;\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            // Showing a menu with toggles\r\n            if (ImGui::Button(\"Toggle..\"))\r\n                ImGui::OpenPopup(\"toggle\");\r\n            if (ImGui::BeginPopup(\"toggle\"))\r\n            {\r\n                for (int i = 0; i < IM_ARRAYSIZE(names); i++)\r\n                    ImGui::MenuItem(names[i], \"\", &toggles[i]);\r\n                if (ImGui::BeginMenu(\"Sub-menu\"))\r\n                {\r\n                    ImGui::MenuItem(\"Click me\");\r\n                    ImGui::EndMenu();\r\n                }\r\n\r\n                ImGui::Separator();\r\n                ImGui::Text(\"Tooltip here\");\r\n                if (ImGui::IsItemHovered())\r\n                    ImGui::SetTooltip(\"I am a tooltip over a popup\");\r\n\r\n                if (ImGui::Button(\"Stacked Popup\"))\r\n                    ImGui::OpenPopup(\"another popup\");\r\n                if (ImGui::BeginPopup(\"another popup\"))\r\n                {\r\n                    for (int i = 0; i < IM_ARRAYSIZE(names); i++)\r\n                        ImGui::MenuItem(names[i], \"\", &toggles[i]);\r\n                    if (ImGui::BeginMenu(\"Sub-menu\"))\r\n                    {\r\n                        ImGui::MenuItem(\"Click me\");\r\n                        ImGui::EndMenu();\r\n                    }\r\n                    ImGui::EndPopup();\r\n                }\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            if (ImGui::Button(\"Popup Menu..\"))\r\n                ImGui::OpenPopup(\"FilePopup\");\r\n            if (ImGui::BeginPopup(\"FilePopup\"))\r\n            {\r\n                ShowExampleMenuFile();\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            ImGui::Spacing();\r\n            ImGui::TextWrapped(\"Below we are testing adding menu items to a regular window. It's rather unusual but should work!\");\r\n            ImGui::Separator();\r\n            // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above.\r\n            // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here\r\n            // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus.\r\n            ImGui::PushID(\"foo\");\r\n            ImGui::MenuItem(\"Menu item\", \"CTRL+M\");\r\n            if (ImGui::BeginMenu(\"Menu inside a regular window\"))\r\n            {\r\n                ShowExampleMenuFile();\r\n                ImGui::EndMenu();\r\n            }\r\n            ImGui::PopID();\r\n            ImGui::Separator();\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Context menus\"))\r\n        {\r\n            static float value = 0.5f;\r\n            ImGui::Text(\"Value = %.3f (<-- right-click here)\", value);\r\n            if (ImGui::BeginPopupContextItem(\"item context menu\"))\r\n            {\r\n                if (ImGui::Selectable(\"Set to zero\")) value = 0.0f;\r\n                if (ImGui::Selectable(\"Set to PI\")) value = 3.1415f;\r\n                ImGui::DragFloat(\"Value\", &value, 0.1f, 0.0f, 0.0f);\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            static char name[32] = \"Label1\";\r\n            char buf[64]; sprintf(buf, \"Button: %s###Button\", name); // ### operator override ID ignoring the preceeding label\r\n            ImGui::Button(buf);\r\n            if (ImGui::BeginPopupContextItem(\"rename context menu\"))\r\n            {\r\n                ImGui::Text(\"Edit name:\");\r\n                ImGui::InputText(\"##edit\", name, IM_ARRAYSIZE(name));\r\n                if (ImGui::Button(\"Close\"))\r\n                    ImGui::CloseCurrentPopup();\r\n                ImGui::EndPopup();\r\n            }\r\n            ImGui::SameLine(); ImGui::Text(\"(<-- right-click here)\");\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Modals\"))\r\n        {\r\n            ImGui::TextWrapped(\"Modal windows are like popups but the user cannot close them by clicking outside the window.\");\r\n\r\n            if (ImGui::Button(\"Delete..\"))\r\n                ImGui::OpenPopup(\"Delete?\");\r\n            if (ImGui::BeginPopupModal(\"Delete?\", NULL, ImGuiWindowFlags_AlwaysAutoResize))\r\n            {\r\n                ImGui::Text(\"All those beautiful files will be deleted.\\nThis operation cannot be undone!\\n\\n\");\r\n                ImGui::Separator();\r\n\r\n                //static int dummy_i = 0;\r\n                //ImGui::Combo(\"Combo\", &dummy_i, \"Delete\\0Delete harder\\0\");\r\n\r\n                static bool dont_ask_me_next_time = false;\r\n                ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));\r\n                ImGui::Checkbox(\"Don't ask me next time\", &dont_ask_me_next_time);\r\n                ImGui::PopStyleVar();\r\n\r\n                if (ImGui::Button(\"OK\", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }\r\n                ImGui::SameLine();\r\n                if (ImGui::Button(\"Cancel\", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            if (ImGui::Button(\"Stacked modals..\"))\r\n                ImGui::OpenPopup(\"Stacked 1\");\r\n            if (ImGui::BeginPopupModal(\"Stacked 1\"))\r\n            {\r\n                ImGui::Text(\"Hello from Stacked The First\\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening.\");\r\n                static int item = 1;\r\n                ImGui::Combo(\"Combo\", &item, \"aaaa\\0bbbb\\0cccc\\0dddd\\0eeee\\0\\0\");\r\n\r\n                if (ImGui::Button(\"Add another modal..\"))\r\n                    ImGui::OpenPopup(\"Stacked 2\");\r\n                if (ImGui::BeginPopupModal(\"Stacked 2\"))\r\n                {\r\n                    ImGui::Text(\"Hello from Stacked The Second\");\r\n                    if (ImGui::Button(\"Close\"))\r\n                        ImGui::CloseCurrentPopup();\r\n                    ImGui::EndPopup();\r\n                }\r\n\r\n                if (ImGui::Button(\"Close\"))\r\n                    ImGui::CloseCurrentPopup();\r\n                ImGui::EndPopup();\r\n            }\r\n\r\n            ImGui::TreePop();\r\n        }\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Columns\"))\r\n    {\r\n        ImGui::PushID(\"Columns\");\r\n\r\n        // Basic columns\r\n        if (ImGui::TreeNode(\"Basic\"))\r\n        {\r\n            ImGui::Text(\"Without border:\");\r\n            ImGui::Columns(3, \"mycolumns3\", false);  // 3-ways, no border\r\n            ImGui::Separator();\r\n            for (int n = 0; n < 14; n++)\r\n            {\r\n                char label[32];\r\n                sprintf(label, \"Item %d\", n);\r\n                if (ImGui::Selectable(label)) {}\r\n                //if (ImGui::Button(label, ImVec2(-1,0))) {}\r\n                ImGui::NextColumn();\r\n            }\r\n            ImGui::Columns(1);\r\n            ImGui::Separator();\r\n\r\n            ImGui::Text(\"With border:\");\r\n            ImGui::Columns(4, \"mycolumns\"); // 4-ways, with border\r\n            ImGui::Separator();\r\n            ImGui::Text(\"ID\"); ImGui::NextColumn();\r\n            ImGui::Text(\"Name\"); ImGui::NextColumn();\r\n            ImGui::Text(\"Path\"); ImGui::NextColumn();\r\n            ImGui::Text(\"Flags\"); ImGui::NextColumn();\r\n            ImGui::Separator();\r\n            const char* names[3] = { \"One\", \"Two\", \"Three\" };\r\n            const char* paths[3] = { \"/path/one\", \"/path/two\", \"/path/three\" };\r\n            static int selected = -1;\r\n            for (int i = 0; i < 3; i++)\r\n            {\r\n                char label[32];\r\n                sprintf(label, \"%04d\", i);\r\n                if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))\r\n                    selected = i;\r\n                ImGui::NextColumn();\r\n                ImGui::Text(names[i]); ImGui::NextColumn();\r\n                ImGui::Text(paths[i]); ImGui::NextColumn();\r\n                ImGui::Text(\"....\"); ImGui::NextColumn();\r\n            }\r\n            ImGui::Columns(1);\r\n            ImGui::Separator();\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        // Create multiple items in a same cell before switching to next column\r\n        if (ImGui::TreeNode(\"Mixed items\"))\r\n        {\r\n            ImGui::Columns(3, \"mixed\");\r\n            ImGui::Separator();\r\n\r\n            ImGui::Text(\"Hello\");\r\n            ImGui::Button(\"Banana\");\r\n            ImGui::NextColumn();\r\n\r\n            ImGui::Text(\"ImGui\");\r\n            ImGui::Button(\"Apple\");\r\n            static float foo = 1.0f;\r\n            ImGui::InputFloat(\"red\", &foo, 0.05f, 0, 3);\r\n            ImGui::Text(\"An extra line here.\");\r\n            ImGui::NextColumn();\r\n\r\n                ImGui::Text(\"Sailor\");\r\n            ImGui::Button(\"Corniflower\");\r\n            static float bar = 1.0f;\r\n            ImGui::InputFloat(\"blue\", &bar, 0.05f, 0, 3);\r\n            ImGui::NextColumn();\r\n\r\n            if (ImGui::CollapsingHeader(\"Category A\")) { ImGui::Text(\"Blah blah blah\"); } ImGui::NextColumn();\r\n            if (ImGui::CollapsingHeader(\"Category B\")) { ImGui::Text(\"Blah blah blah\"); } ImGui::NextColumn();\r\n            if (ImGui::CollapsingHeader(\"Category C\")) { ImGui::Text(\"Blah blah blah\"); } ImGui::NextColumn();\r\n            ImGui::Columns(1);\r\n            ImGui::Separator();\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        // Word wrapping\r\n        if (ImGui::TreeNode(\"Word-wrapping\"))\r\n        {\r\n            ImGui::Columns(2, \"word-wrapping\");\r\n            ImGui::Separator();\r\n            ImGui::TextWrapped(\"The quick brown fox jumps over the lazy dog.\");\r\n            ImGui::TextWrapped(\"Hello Left\");\r\n            ImGui::NextColumn();\r\n            ImGui::TextWrapped(\"The quick brown fox jumps over the lazy dog.\");\r\n            ImGui::TextWrapped(\"Hello Right\");\r\n            ImGui::Columns(1);\r\n            ImGui::Separator();\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Borders\"))\r\n        {\r\n            // NB: Future columns API should allow automatic horizontal borders.\r\n            static bool h_borders = true;\r\n            static bool v_borders = true;\r\n            ImGui::Checkbox(\"horizontal\", &h_borders);\r\n            ImGui::SameLine();\r\n            ImGui::Checkbox(\"vertical\", &v_borders);\r\n            ImGui::Columns(4, NULL, v_borders);\r\n            for (int i = 0; i < 4*3; i++)\r\n            {\r\n                if (h_borders && ImGui::GetColumnIndex() == 0)\r\n                    ImGui::Separator();\r\n                ImGui::Text(\"%c%c%c\", 'a'+i, 'a'+i, 'a'+i);\r\n                ImGui::Text(\"Width %.2f\\nOffset %.2f\", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());\r\n                ImGui::NextColumn();\r\n            }\r\n            ImGui::Columns(1);\r\n            if (h_borders)\r\n                ImGui::Separator();\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        // Scrolling columns\r\n        /*\r\n        if (ImGui::TreeNode(\"Vertical Scrolling\"))\r\n        {\r\n            ImGui::BeginChild(\"##header\", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));\r\n            ImGui::Columns(3);\r\n            ImGui::Text(\"ID\"); ImGui::NextColumn();\r\n            ImGui::Text(\"Name\"); ImGui::NextColumn();\r\n            ImGui::Text(\"Path\"); ImGui::NextColumn();\r\n            ImGui::Columns(1);\r\n            ImGui::Separator();\r\n            ImGui::EndChild();\r\n            ImGui::BeginChild(\"##scrollingregion\", ImVec2(0, 60));\r\n            ImGui::Columns(3);\r\n            for (int i = 0; i < 10; i++)\r\n            {\r\n                ImGui::Text(\"%04d\", i); ImGui::NextColumn();\r\n                ImGui::Text(\"Foobar\"); ImGui::NextColumn();\r\n                ImGui::Text(\"/path/foobar/%04d/\", i); ImGui::NextColumn();\r\n            }\r\n            ImGui::Columns(1);\r\n            ImGui::EndChild();\r\n            ImGui::TreePop();\r\n        }\r\n        */\r\n\r\n        if (ImGui::TreeNode(\"Horizontal Scrolling\"))\r\n        {\r\n            ImGui::SetNextWindowContentWidth(1500);\r\n            ImGui::BeginChild(\"##scrollingregion\", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar);\r\n            ImGui::Columns(10);\r\n            for (int i = 0; i < 20; i++)\r\n                for (int j = 0; j < 10; j++)\r\n                {\r\n                    ImGui::Text(\"Line %d Column %d...\", i, j);\r\n                    ImGui::NextColumn();\r\n                }\r\n            ImGui::Columns(1);\r\n            ImGui::EndChild();\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        bool node_open = ImGui::TreeNode(\"Tree within single cell\");\r\n        ImGui::SameLine(); ShowHelpMarker(\"NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.\");\r\n        if (node_open)\r\n        {\r\n            ImGui::Columns(2, \"tree items\");\r\n            ImGui::Separator();\r\n            if (ImGui::TreeNode(\"Hello\")) { ImGui::BulletText(\"Sailor\"); ImGui::TreePop(); } ImGui::NextColumn();\r\n            if (ImGui::TreeNode(\"Bonjour\")) { ImGui::BulletText(\"Marin\"); ImGui::TreePop(); } ImGui::NextColumn();\r\n            ImGui::Columns(1);\r\n            ImGui::Separator();\r\n            ImGui::TreePop();\r\n        }\r\n        ImGui::PopID();\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Filtering\"))\r\n    {\r\n        static ImGuiTextFilter filter;\r\n        ImGui::Text(\"Filter usage:\\n\"\r\n                    \"  \\\"\\\"         display all lines\\n\"\r\n                    \"  \\\"xxx\\\"      display lines containing \\\"xxx\\\"\\n\"\r\n                    \"  \\\"xxx,yyy\\\"  display lines containing \\\"xxx\\\" or \\\"yyy\\\"\\n\"\r\n                    \"  \\\"-xxx\\\"     hide lines containing \\\"xxx\\\"\");\r\n        filter.Draw();\r\n        const char* lines[] = { \"aaa1.c\", \"bbb1.c\", \"ccc1.c\", \"aaa2.cpp\", \"bbb2.cpp\", \"ccc2.cpp\", \"abc.h\", \"hello, world\" };\r\n        for (int i = 0; i < IM_ARRAYSIZE(lines); i++)\r\n            if (filter.PassFilter(lines[i]))\r\n                ImGui::BulletText(\"%s\", lines[i]);\r\n    }\r\n\r\n    if (ImGui::CollapsingHeader(\"Inputs & Focus\"))\r\n    {\r\n        ImGuiIO& io = ImGui::GetIO();\r\n        ImGui::Checkbox(\"io.MouseDrawCursor\", &io.MouseDrawCursor);\r\n        ImGui::SameLine(); ShowHelpMarker(\"Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\");\r\n\r\n        ImGui::Text(\"WantCaptureMouse: %d\", io.WantCaptureMouse);\r\n        ImGui::Text(\"WantCaptureKeyboard: %d\", io.WantCaptureKeyboard);\r\n        ImGui::Text(\"WantTextInput: %d\", io.WantTextInput);\r\n\r\n        if (ImGui::TreeNode(\"Keyboard & Mouse State\"))\r\n        {\r\n            ImGui::Text(\"Mouse pos: (%g, %g)\", io.MousePos.x, io.MousePos.y);\r\n            ImGui::Text(\"Mouse down:\");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text(\"b%d (%.02f secs)\", i, io.MouseDownDuration[i]); }\r\n            ImGui::Text(\"Mouse clicked:\");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))          { ImGui::SameLine(); ImGui::Text(\"b%d\", i); }\r\n            ImGui::Text(\"Mouse dbl-clicked:\"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text(\"b%d\", i); }\r\n            ImGui::Text(\"Mouse released:\"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))         { ImGui::SameLine(); ImGui::Text(\"b%d\", i); }\r\n            ImGui::Text(\"Mouse wheel: %.1f\", io.MouseWheel);\r\n\r\n            ImGui::Text(\"Keys down:\");      for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f)     { ImGui::SameLine(); ImGui::Text(\"%d (%.02f secs)\", i, io.KeysDownDuration[i]); }\r\n            ImGui::Text(\"Keys pressed:\");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))             { ImGui::SameLine(); ImGui::Text(\"%d\", i); }\r\n            ImGui::Text(\"Keys release:\");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))            { ImGui::SameLine(); ImGui::Text(\"%d\", i); }\r\n            ImGui::Text(\"Keys mods: %s%s%s%s\", io.KeyCtrl ? \"CTRL \" : \"\", io.KeyShift ? \"SHIFT \" : \"\", io.KeyAlt ? \"ALT \" : \"\", io.KeySuper ? \"SUPER \" : \"\");\r\n\r\n\r\n            ImGui::Button(\"Hovering me sets the\\nkeyboard capture flag\");\r\n            if (ImGui::IsItemHovered())\r\n                ImGui::CaptureKeyboardFromApp(true);\r\n            ImGui::SameLine();\r\n            ImGui::Button(\"Holding me clears the\\nthe keyboard capture flag\");\r\n            if (ImGui::IsItemActive())\r\n                ImGui::CaptureKeyboardFromApp(false);\r\n\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Tabbing\"))\r\n        {\r\n            ImGui::Text(\"Use TAB/SHIFT+TAB to cycle through keyboard editable fields.\");\r\n            static char buf[32] = \"dummy\";\r\n            ImGui::InputText(\"1\", buf, IM_ARRAYSIZE(buf));\r\n            ImGui::InputText(\"2\", buf, IM_ARRAYSIZE(buf));\r\n            ImGui::InputText(\"3\", buf, IM_ARRAYSIZE(buf));\r\n            ImGui::PushAllowKeyboardFocus(false);\r\n            ImGui::InputText(\"4 (tab skip)\", buf, IM_ARRAYSIZE(buf));\r\n            //ImGui::SameLine(); ShowHelperMarker(\"Use ImGui::PushAllowKeyboardFocus(bool)\\nto disable tabbing through certain widgets.\");\r\n            ImGui::PopAllowKeyboardFocus();\r\n            ImGui::InputText(\"5\", buf, IM_ARRAYSIZE(buf));\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Focus from code\"))\r\n        {\r\n            bool focus_1 = ImGui::Button(\"Focus on 1\"); ImGui::SameLine();\r\n            bool focus_2 = ImGui::Button(\"Focus on 2\"); ImGui::SameLine();\r\n            bool focus_3 = ImGui::Button(\"Focus on 3\");\r\n            int has_focus = 0;\r\n            static char buf[128] = \"click on a button to set focus\";\r\n\r\n            if (focus_1) ImGui::SetKeyboardFocusHere();\r\n            ImGui::InputText(\"1\", buf, IM_ARRAYSIZE(buf));\r\n            if (ImGui::IsItemActive()) has_focus = 1;\r\n\r\n            if (focus_2) ImGui::SetKeyboardFocusHere();\r\n            ImGui::InputText(\"2\", buf, IM_ARRAYSIZE(buf));\r\n            if (ImGui::IsItemActive()) has_focus = 2;\r\n\r\n            ImGui::PushAllowKeyboardFocus(false);\r\n            if (focus_3) ImGui::SetKeyboardFocusHere();\r\n            ImGui::InputText(\"3 (tab skip)\", buf, IM_ARRAYSIZE(buf));\r\n            if (ImGui::IsItemActive()) has_focus = 3;\r\n            ImGui::PopAllowKeyboardFocus();\r\n            if (has_focus)\r\n                ImGui::Text(\"Item with focus: %d\", has_focus);\r\n            else\r\n                ImGui::Text(\"Item with focus: <none>\");\r\n            ImGui::TextWrapped(\"Cursor & selection are preserved when refocusing last used item in code.\");\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Dragging\"))\r\n        {\r\n            ImGui::TextWrapped(\"You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.\");\r\n            ImGui::Button(\"Drag Me\");\r\n            if (ImGui::IsItemActive())\r\n            {\r\n                // Draw a line between the button and the mouse cursor\r\n                ImDrawList* draw_list = ImGui::GetWindowDrawList();\r\n                draw_list->PushClipRectFullScreen();\r\n                draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f);\r\n                draw_list->PopClipRect();\r\n                ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);\r\n                ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);\r\n                ImVec2 mouse_delta = io.MouseDelta;\r\n                ImGui::SameLine(); ImGui::Text(\"Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)\", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n\r\n        if (ImGui::TreeNode(\"Mouse cursors\"))\r\n        {\r\n            ImGui::Text(\"Hover to see mouse cursors:\");\r\n            ImGui::SameLine(); ShowHelpMarker(\"Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.\");\r\n            for (int i = 0; i < ImGuiMouseCursor_Count_; i++)\r\n            {\r\n                char label[32];\r\n                sprintf(label, \"Mouse cursor %d\", i);\r\n                ImGui::Bullet(); ImGui::Selectable(label, false);\r\n                if (ImGui::IsItemHovered())\r\n                    ImGui::SetMouseCursor(i);\r\n            }\r\n            ImGui::TreePop();\r\n        }\r\n    }\r\n\r\n    ImGui::End();\r\n}\r\n\r\nvoid ImGui::ShowStyleEditor(ImGuiStyle* ref)\r\n{\r\n    ImGuiStyle& style = ImGui::GetStyle();\r\n\r\n    // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to the default style)\r\n    const ImGuiStyle default_style; // Default style\r\n    if (ImGui::Button(\"Revert Style\"))\r\n        style = ref ? *ref : default_style;\r\n\r\n    if (ref)\r\n    {\r\n        ImGui::SameLine();\r\n        if (ImGui::Button(\"Save Style\"))\r\n            *ref = style;\r\n    }\r\n\r\n    ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.55f);\r\n\r\n    if (ImGui::TreeNode(\"Rendering\"))\r\n    {\r\n        ImGui::Checkbox(\"Anti-aliased lines\", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker(\"When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.\");\r\n        ImGui::Checkbox(\"Anti-aliased shapes\", &style.AntiAliasedShapes);\r\n        ImGui::PushItemWidth(100);\r\n        ImGui::DragFloat(\"Curve Tessellation Tolerance\", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);\r\n        if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;\r\n        ImGui::DragFloat(\"Global Alpha\", &style.Alpha, 0.005f, 0.20f, 1.0f, \"%.2f\"); // Not exposing zero here so user doesn't \"lose\" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.\r\n        ImGui::PopItemWidth();\r\n        ImGui::TreePop();\r\n    }\r\n\r\n    if (ImGui::TreeNode(\"Settings\"))\r\n    {\r\n        ImGui::SliderFloat2(\"WindowPadding\", (float*)&style.WindowPadding, 0.0f, 20.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"WindowRounding\", &style.WindowRounding, 0.0f, 16.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"ChildWindowRounding\", &style.ChildWindowRounding, 0.0f, 16.0f, \"%.0f\");\r\n        ImGui::SliderFloat2(\"FramePadding\", (float*)&style.FramePadding, 0.0f, 20.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"FrameRounding\", &style.FrameRounding, 0.0f, 16.0f, \"%.0f\");\r\n        ImGui::SliderFloat2(\"ItemSpacing\", (float*)&style.ItemSpacing, 0.0f, 20.0f, \"%.0f\");\r\n        ImGui::SliderFloat2(\"ItemInnerSpacing\", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, \"%.0f\");\r\n        ImGui::SliderFloat2(\"TouchExtraPadding\", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"IndentSpacing\", &style.IndentSpacing, 0.0f, 30.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"ScrollbarSize\", &style.ScrollbarSize, 1.0f, 20.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"ScrollbarRounding\", &style.ScrollbarRounding, 0.0f, 16.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"GrabMinSize\", &style.GrabMinSize, 1.0f, 20.0f, \"%.0f\");\r\n        ImGui::SliderFloat(\"GrabRounding\", &style.GrabRounding, 0.0f, 16.0f, \"%.0f\");\r\n        ImGui::Text(\"Alignment\");\r\n        ImGui::SliderFloat2(\"WindowTitleAlign\", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, \"%.2f\");\r\n        ImGui::SliderFloat2(\"ButtonTextAlign\", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, \"%.2f\"); ImGui::SameLine(); ShowHelpMarker(\"Alignment applies when a button is larger than its text content.\");\r\n        ImGui::TreePop();\r\n    }\r\n\r\n    if (ImGui::TreeNode(\"Colors\"))\r\n    {\r\n        static int output_dest = 0;\r\n        static bool output_only_modified = false;\r\n        if (ImGui::Button(\"Copy Colors\"))\r\n        {\r\n            if (output_dest == 0)\r\n                ImGui::LogToClipboard();\r\n            else\r\n                ImGui::LogToTTY();\r\n            ImGui::LogText(\"ImGuiStyle& style = ImGui::GetStyle();\" IM_NEWLINE);\r\n            for (int i = 0; i < ImGuiCol_COUNT; i++)\r\n            {\r\n                const ImVec4& col = style.Colors[i];\r\n                const char* name = ImGui::GetStyleColorName(i);\r\n                if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0)\r\n                    ImGui::LogText(\"style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);\" IM_NEWLINE, name, 22 - (int)strlen(name), \"\", col.x, col.y, col.z, col.w);\r\n            }\r\n            ImGui::LogFinish();\r\n        }\r\n        ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo(\"##output_type\", &output_dest, \"To Clipboard\\0To TTY\\0\"); ImGui::PopItemWidth();\r\n        ImGui::SameLine(); ImGui::Checkbox(\"Only Modified Fields\", &output_only_modified);\r\n\r\n        ImGui::Text(\"Tip: Left-click on colored square to open color picker,\\nRight-click to open edit options menu.\");\r\n\r\n        static ImGuiTextFilter filter;\r\n        filter.Draw(\"Filter colors\", 200);\r\n\r\n        static ImGuiColorEditFlags alpha_flags = 0;\r\n        ImGui::RadioButton(\"Opaque\", &alpha_flags, 0); ImGui::SameLine(); \r\n        ImGui::RadioButton(\"Alpha\", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine(); \r\n        ImGui::RadioButton(\"Both\", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);\r\n\r\n        ImGui::BeginChild(\"#colors\", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);\r\n        ImGui::PushItemWidth(-160);\r\n        for (int i = 0; i < ImGuiCol_COUNT; i++)\r\n        {\r\n            const char* name = ImGui::GetStyleColorName(i);\r\n            if (!filter.PassFilter(name))\r\n                continue;\r\n            ImGui::PushID(i);\r\n            ImGui::ColorEdit4(name, (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);\r\n            if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0)\r\n            {\r\n                ImGui::SameLine(); if (ImGui::Button(\"Revert\")) style.Colors[i] = ref ? ref->Colors[i] : default_style.Colors[i];\r\n                if (ref) { ImGui::SameLine(); if (ImGui::Button(\"Save\")) ref->Colors[i] = style.Colors[i]; }\r\n            }\r\n            ImGui::PopID();\r\n        }\r\n        ImGui::PopItemWidth();\r\n        ImGui::EndChild();\r\n\r\n        ImGui::TreePop();\r\n    }\r\n\r\n    bool fonts_opened = ImGui::TreeNode(\"Fonts\", \"Fonts (%d)\", ImGui::GetIO().Fonts->Fonts.Size);\r\n    ImGui::SameLine(); ShowHelpMarker(\"Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\\nbefore calling io.Fonts->GetTex* functions.\");\r\n    if (fonts_opened)\r\n    {\r\n        ImFontAtlas* atlas = ImGui::GetIO().Fonts;\r\n        if (ImGui::TreeNode(\"Atlas texture\", \"Atlas texture (%dx%d pixels)\", atlas->TexWidth, atlas->TexHeight))\r\n        {\r\n            ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));\r\n            ImGui::TreePop();\r\n        }\r\n        ImGui::PushItemWidth(100);\r\n        for (int i = 0; i < atlas->Fonts.Size; i++)\r\n        {\r\n            ImFont* font = atlas->Fonts[i];\r\n            bool font_details_opened = ImGui::TreeNode(font, \"Font %d: \\'%s\\', %.2f px, %d glyphs\", i, font->ConfigData ? font->ConfigData[0].Name : \"\", font->FontSize, font->Glyphs.Size);\r\n            ImGui::SameLine(); if (ImGui::SmallButton(\"Set as default\")) ImGui::GetIO().FontDefault = font;\r\n            if (font_details_opened)\r\n            {\r\n                ImGui::PushFont(font);\r\n                ImGui::Text(\"The quick brown fox jumps over the lazy dog\");\r\n                ImGui::PopFont();\r\n                ImGui::DragFloat(\"Font scale\", &font->Scale, 0.005f, 0.3f, 2.0f, \"%.1f\");   // Scale only this font\r\n                ImGui::SameLine(); ShowHelpMarker(\"Note than the default embedded font is NOT meant to be scaled.\\n\\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\\n\\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)\");\r\n                ImGui::Text(\"Ascent: %f, Descent: %f, Height: %f\", font->Ascent, font->Descent, font->Ascent - font->Descent);\r\n                ImGui::Text(\"Fallback character: '%c' (%d)\", font->FallbackChar, font->FallbackChar);\r\n                ImGui::Text(\"Texture surface: %d pixels (approx) ~ %dx%d\", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));\r\n                for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)\r\n                {\r\n                    ImFontConfig* cfg = &font->ConfigData[config_i];\r\n                    ImGui::BulletText(\"Input %d: \\'%s\\', Oversample: (%d,%d), PixelSnapH: %d\", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);\r\n                }\r\n                if (ImGui::TreeNode(\"Glyphs\", \"Glyphs (%d)\", font->Glyphs.Size))\r\n                {\r\n                    // Display all glyphs of the fonts in separate pages of 256 characters\r\n                    const ImFont::Glyph* glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior.\r\n                    font->FallbackGlyph = NULL;\r\n                    for (int base = 0; base < 0x10000; base += 256)\r\n                    {\r\n                        int count = 0;\r\n                        for (int n = 0; n < 256; n++)\r\n                            count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0;\r\n                        if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, \"U+%04X..U+%04X (%d %s)\", base, base+255, count, count > 1 ? \"glyphs\" : \"glyph\"))\r\n                        {\r\n                            float cell_spacing = style.ItemSpacing.y;\r\n                            ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1);\r\n                            ImVec2 base_pos = ImGui::GetCursorScreenPos();\r\n                            ImDrawList* draw_list = ImGui::GetWindowDrawList();\r\n                            for (int n = 0; n < 256; n++)\r\n                            {\r\n                                ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing));\r\n                                ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y);\r\n                                const ImFont::Glyph* glyph = font->FindGlyph((ImWchar)(base+n));;\r\n                                draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));\r\n                                font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.\r\n                                if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))\r\n                                {\r\n                                    ImGui::BeginTooltip();\r\n                                    ImGui::Text(\"Codepoint: U+%04X\", base+n);\r\n                                    ImGui::Separator();\r\n                                    ImGui::Text(\"XAdvance+1: %.1f\", glyph->XAdvance);\r\n                                    ImGui::Text(\"Pos: (%.2f,%.2f)->(%.2f,%.2f)\", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);\r\n                                    ImGui::Text(\"UV: (%.3f,%.3f)->(%.3f,%.3f)\", glyph->U0, glyph->V0, glyph->U1, glyph->V1);\r\n                                    ImGui::EndTooltip();\r\n                                }\r\n                            }\r\n                            ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16));\r\n                            ImGui::TreePop();\r\n                        }\r\n                    }\r\n                    font->FallbackGlyph = glyph_fallback;\r\n                    ImGui::TreePop();\r\n                }\r\n                ImGui::TreePop();\r\n            }\r\n        }\r\n        static float window_scale = 1.0f;\r\n        ImGui::DragFloat(\"this window scale\", &window_scale, 0.005f, 0.3f, 2.0f, \"%.1f\");              // scale only this window\r\n        ImGui::DragFloat(\"global scale\", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, \"%.1f\"); // scale everything\r\n        ImGui::PopItemWidth();\r\n        ImGui::SetWindowFontScale(window_scale);\r\n        ImGui::TreePop();\r\n    }\r\n\r\n    ImGui::PopItemWidth();\r\n}\r\n\r\n// Demonstrate creating a fullscreen menu bar and populating it.\r\nstatic void ShowExampleAppMainMenuBar()\r\n{\r\n    if (ImGui::BeginMainMenuBar())\r\n    {\r\n        if (ImGui::BeginMenu(\"File\"))\r\n        {\r\n            ShowExampleMenuFile();\r\n            ImGui::EndMenu();\r\n        }\r\n        if (ImGui::BeginMenu(\"Edit\"))\r\n        {\r\n            if (ImGui::MenuItem(\"Undo\", \"CTRL+Z\")) {}\r\n            if (ImGui::MenuItem(\"Redo\", \"CTRL+Y\", false, false)) {}  // Disabled item\r\n            ImGui::Separator();\r\n            if (ImGui::MenuItem(\"Cut\", \"CTRL+X\")) {}\r\n            if (ImGui::MenuItem(\"Copy\", \"CTRL+C\")) {}\r\n            if (ImGui::MenuItem(\"Paste\", \"CTRL+V\")) {}\r\n            ImGui::EndMenu();\r\n        }\r\n        ImGui::EndMainMenuBar();\r\n    }\r\n}\r\n\r\nstatic void ShowExampleMenuFile()\r\n{\r\n    ImGui::MenuItem(\"(dummy menu)\", NULL, false, false);\r\n    if (ImGui::MenuItem(\"New\")) {}\r\n    if (ImGui::MenuItem(\"Open\", \"Ctrl+O\")) {}\r\n    if (ImGui::BeginMenu(\"Open Recent\"))\r\n    {\r\n        ImGui::MenuItem(\"fish_hat.c\");\r\n        ImGui::MenuItem(\"fish_hat.inl\");\r\n        ImGui::MenuItem(\"fish_hat.h\");\r\n        if (ImGui::BeginMenu(\"More..\"))\r\n        {\r\n            ImGui::MenuItem(\"Hello\");\r\n            ImGui::MenuItem(\"Sailor\");\r\n            if (ImGui::BeginMenu(\"Recurse..\"))\r\n            {\r\n                ShowExampleMenuFile();\r\n                ImGui::EndMenu();\r\n            }\r\n            ImGui::EndMenu();\r\n        }\r\n        ImGui::EndMenu();\r\n    }\r\n    if (ImGui::MenuItem(\"Save\", \"Ctrl+S\")) {}\r\n    if (ImGui::MenuItem(\"Save As..\")) {}\r\n    ImGui::Separator();\r\n    if (ImGui::BeginMenu(\"Options\"))\r\n    {\r\n        static bool enabled = true;\r\n        ImGui::MenuItem(\"Enabled\", \"\", &enabled);\r\n        ImGui::BeginChild(\"child\", ImVec2(0, 60), true);\r\n        for (int i = 0; i < 10; i++)\r\n            ImGui::Text(\"Scrolling Text %d\", i);\r\n        ImGui::EndChild();\r\n        static float f = 0.5f;\r\n        static int n = 0;\r\n        static bool b = true;\r\n        ImGui::SliderFloat(\"Value\", &f, 0.0f, 1.0f);\r\n        ImGui::InputFloat(\"Input\", &f, 0.1f);\r\n        ImGui::Combo(\"Combo\", &n, \"Yes\\0No\\0Maybe\\0\\0\");\r\n        ImGui::Checkbox(\"Check\", &b);\r\n        ImGui::EndMenu();\r\n    }\r\n    if (ImGui::BeginMenu(\"Colors\"))\r\n    {\r\n        for (int i = 0; i < ImGuiCol_COUNT; i++)\r\n            ImGui::MenuItem(ImGui::GetStyleColorName((ImGuiCol)i));\r\n        ImGui::EndMenu();\r\n    }\r\n    if (ImGui::BeginMenu(\"Disabled\", false)) // Disabled\r\n    {\r\n        IM_ASSERT(0);\r\n    }\r\n    if (ImGui::MenuItem(\"Checked\", NULL, true)) {}\r\n    if (ImGui::MenuItem(\"Quit\", \"Alt+F4\")) {}\r\n}\r\n\r\n// Demonstrate creating a window which gets auto-resized according to its content.\r\nstatic void ShowExampleAppAutoResize(bool* p_open)\r\n{\r\n    if (!ImGui::Begin(\"Example: Auto-resizing window\", p_open, ImGuiWindowFlags_AlwaysAutoResize))\r\n    {\r\n        ImGui::End();\r\n        return;\r\n    }\r\n\r\n    static int lines = 10;\r\n    ImGui::Text(\"Window will resize every-frame to the size of its content.\\nNote that you probably don't want to query the window size to\\noutput your content because that would create a feedback loop.\");\r\n    ImGui::SliderInt(\"Number of lines\", &lines, 1, 20);\r\n    for (int i = 0; i < lines; i++)\r\n        ImGui::Text(\"%*sThis is line %d\", i*4, \"\", i); // Pad with space to extend size horizontally\r\n    ImGui::End();\r\n}\r\n\r\n// Demonstrate creating a window with custom resize constraints.\r\nstatic void ShowExampleAppConstrainedResize(bool* p_open)\r\n{\r\n    struct CustomConstraints // Helper functions to demonstrate programmatic constraints\r\n    {\r\n        static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }\r\n        static void Step(ImGuiSizeConstraintCallbackData* data)   { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }\r\n    };\r\n\r\n    static int type = 0;\r\n    if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only\r\n    if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only\r\n    if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100\r\n    if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0),   ImVec2(400, FLT_MAX));     // Width 300-400\r\n    if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);          // Always Square\r\n    if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step\r\n\r\n    if (ImGui::Begin(\"Example: Constrained Resize\", p_open))\r\n    {\r\n        const char* desc[] = \r\n        {\r\n            \"Resize vertical only\",\r\n            \"Resize horizontal only\",\r\n            \"Width > 100, Height > 100\",\r\n            \"Width 300-400\",\r\n            \"Custom: Always Square\",\r\n            \"Custom: Fixed Steps (100)\",\r\n        };\r\n        ImGui::Combo(\"Constraint\", &type, desc, IM_ARRAYSIZE(desc)); \r\n        if (ImGui::Button(\"200x200\")) { ImGui::SetWindowSize(ImVec2(200,200)); } ImGui::SameLine();\r\n        if (ImGui::Button(\"500x500\")) { ImGui::SetWindowSize(ImVec2(500,500)); } ImGui::SameLine();\r\n        if (ImGui::Button(\"800x200\")) { ImGui::SetWindowSize(ImVec2(800,200)); }\r\n        for (int i = 0; i < 10; i++) \r\n            ImGui::Text(\"Hello, sailor! Making this line long enough for the example.\");\r\n    }\r\n    ImGui::End();\r\n}\r\n\r\n// Demonstrate creating a simple static window with no decoration.\r\nstatic void ShowExampleAppFixedOverlay(bool* p_open)\r\n{\r\n    ImGui::SetNextWindowPos(ImVec2(10,10));\r\n    ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));\r\n    if (!ImGui::Begin(\"Example: Fixed Overlay\", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings))\r\n    {\r\n        ImGui::End();\r\n        return;\r\n    }\r\n    ImGui::Text(\"Simple overlay\\non the top-left side of the screen.\");\r\n    ImGui::Separator();\r\n    ImGui::Text(\"Mouse Position: (%.1f,%.1f)\", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);\r\n    ImGui::End();\r\n    ImGui::PopStyleColor();\r\n}\r\n\r\n// Demonstrate using \"##\" and \"###\" in identifiers to manipulate ID generation.\r\n// Read section \"How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs.\" about ID.\r\nstatic void ShowExampleAppManipulatingWindowTitle(bool*)\r\n{\r\n    // By default, Windows are uniquely identified by their title.\r\n    // You can use the \"##\" and \"###\" markers to manipulate the display/ID.\r\n\r\n    // Using \"##\" to display same title but have unique identifier.\r\n    ImGui::SetNextWindowPos(ImVec2(100,100), ImGuiCond_FirstUseEver);\r\n    ImGui::Begin(\"Same title as another window##1\");\r\n    ImGui::Text(\"This is window 1.\\nMy title is the same as window 2, but my identifier is unique.\");\r\n    ImGui::End();\r\n\r\n    ImGui::SetNextWindowPos(ImVec2(100,200), ImGuiCond_FirstUseEver);\r\n    ImGui::Begin(\"Same title as another window##2\");\r\n    ImGui::Text(\"This is window 2.\\nMy title is the same as window 1, but my identifier is unique.\");\r\n    ImGui::End();\r\n\r\n    // Using \"###\" to display a changing title but keep a static identifier \"AnimatedTitle\"\r\n    char buf[128];\r\n    sprintf(buf, \"Animated title %c %d###AnimatedTitle\", \"|/-\\\\\"[(int)(ImGui::GetTime()/0.25f)&3], rand());\r\n    ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiCond_FirstUseEver);\r\n    ImGui::Begin(buf);\r\n    ImGui::Text(\"This window has a changing title.\");\r\n    ImGui::End();\r\n}\r\n\r\n// Demonstrate using the low-level ImDrawList to draw custom shapes. \r\nstatic void ShowExampleAppCustomRendering(bool* p_open)\r\n{\r\n    ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiCond_FirstUseEver);\r\n    if (!ImGui::Begin(\"Example: Custom rendering\", p_open))\r\n    {\r\n        ImGui::End();\r\n        return;\r\n    }\r\n\r\n    // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.\r\n    // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.\r\n    // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)\r\n    // In this example we are not using the maths operators!\r\n    ImDrawList* draw_list = ImGui::GetWindowDrawList();\r\n\r\n    // Primitives\r\n    ImGui::Text(\"Primitives\");\r\n    static float sz = 36.0f;\r\n    static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f);\r\n    ImGui::DragFloat(\"Size\", &sz, 0.2f, 2.0f, 72.0f, \"%.0f\");\r\n    ImGui::ColorEdit3(\"Color\", &col.x);\r\n    {\r\n        const ImVec2 p = ImGui::GetCursorScreenPos();\r\n        const ImU32 col32 = ImColor(col);\r\n        float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;\r\n        for (int n = 0; n < 2; n++)\r\n        {\r\n            float thickness = (n == 0) ? 1.0f : 4.0f;\r\n            draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, thickness); x += sz+spacing;\r\n            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ~0, thickness); x += sz+spacing;\r\n            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ~0, thickness); x += sz+spacing;\r\n            draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, thickness); x += sz+spacing;\r\n            draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y   ), col32, thickness); x += sz+spacing;\r\n            draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, thickness); x += sz+spacing;\r\n            draw_list->AddLine(ImVec2(x, y), ImVec2(x,    y+sz), col32, thickness); x += spacing;\r\n            draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, thickness);\r\n            x = p.x + 4;\r\n            y += sz+spacing;\r\n        }\r\n        draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;\r\n        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;\r\n        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;\r\n        draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;\r\n        draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0));\r\n        ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));\r\n    }\r\n    ImGui::Separator();\r\n    {\r\n        static ImVector<ImVec2> points;\r\n        static bool adding_line = false;\r\n        ImGui::Text(\"Canvas example\");\r\n        if (ImGui::Button(\"Clear\")) points.clear();\r\n        if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button(\"Undo\")) { points.pop_back(); points.pop_back(); } }\r\n        ImGui::Text(\"Left-click and drag to add lines,\\nRight-click to undo\");\r\n\r\n        // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()\r\n        // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().\r\n        // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).\r\n        ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!\r\n        ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available\r\n        if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;\r\n        if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;\r\n        draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(50,50,50), ImColor(50,50,60), ImColor(60,60,70), ImColor(50,50,60));\r\n        draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255));\r\n\r\n        bool adding_preview = false;\r\n        ImGui::InvisibleButton(\"canvas\", canvas_size);\r\n        ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);\r\n        if (adding_line)\r\n        {\r\n            adding_preview = true;\r\n            points.push_back(mouse_pos_in_canvas);\r\n            if (!ImGui::GetIO().MouseDown[0])\r\n                adding_line = adding_preview = false;\r\n        }\r\n        if (ImGui::IsItemHovered())\r\n        {\r\n            if (!adding_line && ImGui::IsMouseClicked(0))\r\n            {\r\n                points.push_back(mouse_pos_in_canvas);\r\n                adding_line = true;\r\n            }\r\n            if (ImGui::IsMouseClicked(1) && !points.empty())\r\n            {\r\n                adding_line = adding_preview = false;\r\n                points.pop_back();\r\n                points.pop_back();\r\n            }\r\n        }\r\n        draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y));      // clip lines within the canvas (if we resize it, etc.)\r\n        for (int i = 0; i < points.Size - 1; i += 2)\r\n            draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), IM_COL32(255,255,0,255), 2.0f);\r\n        draw_list->PopClipRect();\r\n        if (adding_preview)\r\n            points.pop_back();\r\n    }\r\n    ImGui::End();\r\n}\r\n\r\n// Demonstrating creating a simple console window, with scrolling, filtering, completion and history.\r\n// For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.\r\nstruct ExampleAppConsole\r\n{\r\n    char                  InputBuf[256];\r\n    ImVector<char*>       Items;\r\n    bool                  ScrollToBottom;\r\n    ImVector<char*>       History;\r\n    int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.\r\n    ImVector<const char*> Commands;\r\n\r\n    ExampleAppConsole()\r\n    {\r\n        ClearLog();\r\n        memset(InputBuf, 0, sizeof(InputBuf));\r\n        HistoryPos = -1;\r\n        Commands.push_back(\"HELP\");\r\n        Commands.push_back(\"HISTORY\");\r\n        Commands.push_back(\"CLEAR\");\r\n        Commands.push_back(\"CLASSIFY\");  // \"classify\" is here to provide an example of \"C\"+[tab] completing to \"CL\" and displaying matches.\r\n        AddLog(\"Welcome to ImGui!\");\r\n    }\r\n    ~ExampleAppConsole()\r\n    {\r\n        ClearLog();\r\n        for (int i = 0; i < History.Size; i++)\r\n            free(History[i]);\r\n    }\r\n\r\n    // Portable helpers\r\n    static int   Stricmp(const char* str1, const char* str2)         { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }\r\n    static int   Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }\r\n    static char* Strdup(const char *str)                             { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }\r\n\r\n    void    ClearLog()\r\n    {\r\n        for (int i = 0; i < Items.Size; i++)\r\n            free(Items[i]);\r\n        Items.clear();\r\n        ScrollToBottom = true;\r\n    }\r\n\r\n    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)\r\n    {\r\n        char buf[1024];\r\n        va_list args;\r\n        va_start(args, fmt);\r\n        vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);\r\n        buf[IM_ARRAYSIZE(buf)-1] = 0;\r\n        va_end(args);\r\n        Items.push_back(Strdup(buf));\r\n        ScrollToBottom = true;\r\n    }\r\n\r\n    void    Draw(const char* title, bool* p_open)\r\n    {\r\n        ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);\r\n        if (!ImGui::Begin(title, p_open))\r\n        {\r\n            ImGui::End();\r\n            return;\r\n        }\r\n\r\n        ImGui::TextWrapped(\"This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.\");\r\n        ImGui::TextWrapped(\"Enter 'HELP' for help, press TAB to use text completion.\");\r\n\r\n        // TODO: display items starting from the bottom\r\n\r\n        if (ImGui::SmallButton(\"Add Dummy Text\")) { AddLog(\"%d some text\", Items.Size); AddLog(\"some more text\"); AddLog(\"display very important message here!\"); } ImGui::SameLine();\r\n        if (ImGui::SmallButton(\"Add Dummy Error\")) { AddLog(\"[error] something went wrong\"); } ImGui::SameLine();\r\n        if (ImGui::SmallButton(\"Clear\")) { ClearLog(); } ImGui::SameLine();\r\n        bool copy_to_clipboard = ImGui::SmallButton(\"Copy\"); ImGui::SameLine();\r\n        if (ImGui::SmallButton(\"Scroll to bottom\")) ScrollToBottom = true;\r\n        //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog(\"Spam %f\", t); }\r\n\r\n        ImGui::Separator();\r\n\r\n        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));\r\n        static ImGuiTextFilter filter;\r\n        filter.Draw(\"Filter (\\\"incl,-excl\\\") (\\\"error\\\")\", 180);\r\n        ImGui::PopStyleVar();\r\n        ImGui::Separator();\r\n\r\n        ImGui::BeginChild(\"ScrollingRegion\", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);\r\n        if (ImGui::BeginPopupContextWindow())\r\n        {\r\n            if (ImGui::Selectable(\"Clear\")) ClearLog();\r\n            ImGui::EndPopup();\r\n        }\r\n\r\n        // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());\r\n        // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.\r\n        // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.\r\n        // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:\r\n        //     ImGuiListClipper clipper(Items.Size);\r\n        //     while (clipper.Step())\r\n        //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)\r\n        // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.\r\n        // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,\r\n        // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!\r\n        // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.\r\n        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing\r\n        if (copy_to_clipboard)\r\n            ImGui::LogToClipboard();\r\n        for (int i = 0; i < Items.Size; i++)\r\n        {\r\n            const char* item = Items[i];\r\n            if (!filter.PassFilter(item))\r\n                continue;\r\n            ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text.\r\n            if (strstr(item, \"[error]\")) col = ImColor(1.0f,0.4f,0.4f,1.0f);\r\n            else if (strncmp(item, \"# \", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);\r\n            ImGui::PushStyleColor(ImGuiCol_Text, col);\r\n            ImGui::TextUnformatted(item);\r\n            ImGui::PopStyleColor();\r\n        }\r\n        if (copy_to_clipboard)\r\n            ImGui::LogFinish();\r\n        if (ScrollToBottom)\r\n            ImGui::SetScrollHere();\r\n        ScrollToBottom = false;\r\n        ImGui::PopStyleVar();\r\n        ImGui::EndChild();\r\n        ImGui::Separator();\r\n\r\n        // Command-line\r\n        if (ImGui::InputText(\"Input\", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))\r\n        {\r\n            char* input_end = InputBuf+strlen(InputBuf);\r\n            while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0;\r\n            if (InputBuf[0])\r\n                ExecCommand(InputBuf);\r\n            strcpy(InputBuf, \"\");\r\n        }\r\n\r\n        // Demonstrate keeping auto focus on the input box\r\n        if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)))\r\n            ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget\r\n\r\n        ImGui::End();\r\n    }\r\n\r\n    void    ExecCommand(const char* command_line)\r\n    {\r\n        AddLog(\"# %s\\n\", command_line);\r\n\r\n        // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.\r\n        HistoryPos = -1;\r\n        for (int i = History.Size-1; i >= 0; i--)\r\n            if (Stricmp(History[i], command_line) == 0)\r\n            {\r\n                free(History[i]);\r\n                History.erase(History.begin() + i);\r\n                break;\r\n            }\r\n        History.push_back(Strdup(command_line));\r\n\r\n        // Process command\r\n        if (Stricmp(command_line, \"CLEAR\") == 0)\r\n        {\r\n            ClearLog();\r\n        }\r\n        else if (Stricmp(command_line, \"HELP\") == 0)\r\n        {\r\n            AddLog(\"Commands:\");\r\n            for (int i = 0; i < Commands.Size; i++)\r\n                AddLog(\"- %s\", Commands[i]);\r\n        }\r\n        else if (Stricmp(command_line, \"HISTORY\") == 0)\r\n        {\r\n            int first = History.Size - 10;\r\n            for (int i = first > 0 ? first : 0; i < History.Size; i++)\r\n                AddLog(\"%3d: %s\\n\", i, History[i]);\r\n        }\r\n        else\r\n        {\r\n            AddLog(\"Unknown command: '%s'\\n\", command_line);\r\n        }\r\n    }\r\n\r\n    static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks\r\n    {\r\n        ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;\r\n        return console->TextEditCallback(data);\r\n    }\r\n\r\n    int     TextEditCallback(ImGuiTextEditCallbackData* data)\r\n    {\r\n        //AddLog(\"cursor: %d, selection: %d-%d\", data->CursorPos, data->SelectionStart, data->SelectionEnd);\r\n        switch (data->EventFlag)\r\n        {\r\n        case ImGuiInputTextFlags_CallbackCompletion:\r\n            {\r\n                // Example of TEXT COMPLETION\r\n\r\n                // Locate beginning of current word\r\n                const char* word_end = data->Buf + data->CursorPos;\r\n                const char* word_start = word_end;\r\n                while (word_start > data->Buf)\r\n                {\r\n                    const char c = word_start[-1];\r\n                    if (c == ' ' || c == '\\t' || c == ',' || c == ';')\r\n                        break;\r\n                    word_start--;\r\n                }\r\n\r\n                // Build a list of candidates\r\n                ImVector<const char*> candidates;\r\n                for (int i = 0; i < Commands.Size; i++)\r\n                    if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)\r\n                        candidates.push_back(Commands[i]);\r\n\r\n                if (candidates.Size == 0)\r\n                {\r\n                    // No match\r\n                    AddLog(\"No match for \\\"%.*s\\\"!\\n\", (int)(word_end-word_start), word_start);\r\n                }\r\n                else if (candidates.Size == 1)\r\n                {\r\n                    // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing\r\n                    data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));\r\n                    data->InsertChars(data->CursorPos, candidates[0]);\r\n                    data->InsertChars(data->CursorPos, \" \");\r\n                }\r\n                else\r\n                {\r\n                    // Multiple matches. Complete as much as we can, so inputing \"C\" will complete to \"CL\" and display \"CLEAR\" and \"CLASSIFY\"\r\n                    int match_len = (int)(word_end - word_start);\r\n                    for (;;)\r\n                    {\r\n                        int c = 0;\r\n                        bool all_candidates_matches = true;\r\n                        for (int i = 0; i < candidates.Size && all_candidates_matches; i++)\r\n                            if (i == 0)\r\n                                c = toupper(candidates[i][match_len]);\r\n                            else if (c == 0 || c != toupper(candidates[i][match_len]))\r\n                                all_candidates_matches = false;\r\n                        if (!all_candidates_matches)\r\n                            break;\r\n                        match_len++;\r\n                    }\r\n\r\n                    if (match_len > 0)\r\n                    {\r\n                        data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));\r\n                        data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);\r\n                    }\r\n\r\n                    // List matches\r\n                    AddLog(\"Possible matches:\\n\");\r\n                    for (int i = 0; i < candidates.Size; i++)\r\n                        AddLog(\"- %s\\n\", candidates[i]);\r\n                }\r\n\r\n                break;\r\n            }\r\n        case ImGuiInputTextFlags_CallbackHistory:\r\n            {\r\n                // Example of HISTORY\r\n                const int prev_history_pos = HistoryPos;\r\n                if (data->EventKey == ImGuiKey_UpArrow)\r\n                {\r\n                    if (HistoryPos == -1)\r\n                        HistoryPos = History.Size - 1;\r\n                    else if (HistoryPos > 0)\r\n                        HistoryPos--;\r\n                }\r\n                else if (data->EventKey == ImGuiKey_DownArrow)\r\n                {\r\n                    if (HistoryPos != -1)\r\n                        if (++HistoryPos >= History.Size)\r\n                            HistoryPos = -1;\r\n                }\r\n\r\n                // A better implementation would preserve the data on the current input line along with cursor position.\r\n                if (prev_history_pos != HistoryPos)\r\n                {\r\n                    data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, \"%s\", (HistoryPos >= 0) ? History[HistoryPos] : \"\");\r\n                    data->BufDirty = true;\r\n                }\r\n            }\r\n        }\r\n        return 0;\r\n    }\r\n};\r\n\r\nstatic void ShowExampleAppConsole(bool* p_open)\r\n{\r\n    static ExampleAppConsole console;\r\n    console.Draw(\"Example: Console\", p_open);\r\n}\r\n\r\n// Usage:\r\n//  static ExampleAppLog my_log;\r\n//  my_log.AddLog(\"Hello %d world\\n\", 123);\r\n//  my_log.Draw(\"title\");\r\nstruct ExampleAppLog\r\n{\r\n    ImGuiTextBuffer     Buf;\r\n    ImGuiTextFilter     Filter;\r\n    ImVector<int>       LineOffsets;        // Index to lines offset\r\n    bool                ScrollToBottom;\r\n\r\n    void    Clear()     { Buf.clear(); LineOffsets.clear(); }\r\n\r\n    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)\r\n    {\r\n        int old_size = Buf.size();\r\n        va_list args;\r\n        va_start(args, fmt);\r\n        Buf.appendv(fmt, args);\r\n        va_end(args);\r\n        for (int new_size = Buf.size(); old_size < new_size; old_size++)\r\n            if (Buf[old_size] == '\\n')\r\n                LineOffsets.push_back(old_size);\r\n        ScrollToBottom = true;\r\n    }\r\n\r\n    void    Draw(const char* title, bool* p_open = NULL)\r\n    {\r\n        ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver);\r\n        ImGui::Begin(title, p_open);\r\n        if (ImGui::Button(\"Clear\")) Clear();\r\n        ImGui::SameLine();\r\n        bool copy = ImGui::Button(\"Copy\");\r\n        ImGui::SameLine();\r\n        Filter.Draw(\"Filter\", -100.0f);\r\n        ImGui::Separator();\r\n        ImGui::BeginChild(\"scrolling\", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);\r\n        if (copy) ImGui::LogToClipboard();\r\n\r\n        if (Filter.IsActive())\r\n        {\r\n            const char* buf_begin = Buf.begin();\r\n            const char* line = buf_begin;\r\n            for (int line_no = 0; line != NULL; line_no++)\r\n            {\r\n                const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;\r\n                if (Filter.PassFilter(line, line_end))\r\n                    ImGui::TextUnformatted(line, line_end);\r\n                line = line_end && line_end[1] ? line_end + 1 : NULL;\r\n            }\r\n        }\r\n        else\r\n        {\r\n            ImGui::TextUnformatted(Buf.begin());\r\n        }\r\n\r\n        if (ScrollToBottom)\r\n            ImGui::SetScrollHere(1.0f);\r\n        ScrollToBottom = false;\r\n        ImGui::EndChild();\r\n        ImGui::End();\r\n    }\r\n};\r\n\r\n// Demonstrate creating a simple log window with basic filtering.\r\nstatic void ShowExampleAppLog(bool* p_open)\r\n{\r\n    static ExampleAppLog log;\r\n\r\n    // Demo: add random items (unless Ctrl is held)\r\n    static float last_time = -1.0f;\r\n    float time = ImGui::GetTime();\r\n    if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)\r\n    {\r\n        const char* random_words[] = { \"system\", \"info\", \"warning\", \"error\", \"fatal\", \"notice\", \"log\" };\r\n        log.AddLog(\"[%s] Hello, time is %.1f, rand() %d\\n\", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand());\r\n        last_time = time;\r\n    }\r\n\r\n    log.Draw(\"Example: Log\", p_open);\r\n}\r\n\r\n// Demonstrate create a window with multiple child windows.\r\nstatic void ShowExampleAppLayout(bool* p_open)\r\n{\r\n    ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);\r\n    if (ImGui::Begin(\"Example: Layout\", p_open, ImGuiWindowFlags_MenuBar))\r\n    {\r\n        if (ImGui::BeginMenuBar())\r\n        {\r\n            if (ImGui::BeginMenu(\"File\"))\r\n            {\r\n                if (ImGui::MenuItem(\"Close\")) *p_open = false;\r\n                ImGui::EndMenu();\r\n            }\r\n            ImGui::EndMenuBar();\r\n        }\r\n\r\n        // left\r\n        static int selected = 0;\r\n        ImGui::BeginChild(\"left pane\", ImVec2(150, 0), true);\r\n        for (int i = 0; i < 100; i++)\r\n        {\r\n            char label[128];\r\n            sprintf(label, \"MyObject %d\", i);\r\n            if (ImGui::Selectable(label, selected == i))\r\n                selected = i;\r\n        }\r\n        ImGui::EndChild();\r\n        ImGui::SameLine();\r\n\r\n        // right\r\n        ImGui::BeginGroup();\r\n            ImGui::BeginChild(\"item view\", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us\r\n                ImGui::Text(\"MyObject: %d\", selected);\r\n                ImGui::Separator();\r\n                ImGui::TextWrapped(\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \");\r\n            ImGui::EndChild();\r\n            ImGui::BeginChild(\"buttons\");\r\n                if (ImGui::Button(\"Revert\")) {}\r\n                ImGui::SameLine();\r\n                if (ImGui::Button(\"Save\")) {}\r\n            ImGui::EndChild();\r\n        ImGui::EndGroup();\r\n    }\r\n    ImGui::End();\r\n}\r\n\r\n// Demonstrate create a simple property editor.\r\nstatic void ShowExampleAppPropertyEditor(bool* p_open)\r\n{\r\n    ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);\r\n    if (!ImGui::Begin(\"Example: Property editor\", p_open))\r\n    {\r\n        ImGui::End();\r\n        return;\r\n    }\r\n\r\n    ShowHelpMarker(\"This example shows how you may implement a property editor using two columns.\\nAll objects/fields data are dummies here.\\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\\nyour cursor horizontally instead of using the Columns() API.\");\r\n\r\n    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));\r\n    ImGui::Columns(2);\r\n    ImGui::Separator();\r\n\r\n    struct funcs\r\n    {\r\n        static void ShowDummyObject(const char* prefix, int uid)\r\n        {\r\n            ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.\r\n            ImGui::AlignFirstTextHeightToWidgets();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.\r\n            bool node_open = ImGui::TreeNode(\"Object\", \"%s_%u\", prefix, uid);\r\n            ImGui::NextColumn();\r\n            ImGui::AlignFirstTextHeightToWidgets();\r\n            ImGui::Text(\"my sailor is rich\");\r\n            ImGui::NextColumn();\r\n            if (node_open)\r\n            {\r\n                static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };\r\n                for (int i = 0; i < 8; i++)\r\n                {\r\n                    ImGui::PushID(i); // Use field index as identifier.\r\n                    if (i < 2)\r\n                    {\r\n                        ShowDummyObject(\"Child\", 424242);\r\n                    }\r\n                    else\r\n                    {\r\n                        ImGui::AlignFirstTextHeightToWidgets();\r\n                        // Here we use a Selectable (instead of Text) to highlight on hover\r\n                        //ImGui::Text(\"Field_%d\", i);\r\n                        char label[32];\r\n                        sprintf(label, \"Field_%d\", i);\r\n                        ImGui::Bullet();\r\n                        ImGui::Selectable(label);\r\n                        ImGui::NextColumn();\r\n                        ImGui::PushItemWidth(-1);\r\n                        if (i >= 5)\r\n                            ImGui::InputFloat(\"##value\", &dummy_members[i], 1.0f);\r\n                        else\r\n                            ImGui::DragFloat(\"##value\", &dummy_members[i], 0.01f);\r\n                        ImGui::PopItemWidth();\r\n                        ImGui::NextColumn();\r\n                    }\r\n                    ImGui::PopID();\r\n                }\r\n                ImGui::TreePop();\r\n            }\r\n            ImGui::PopID();\r\n        }\r\n    };\r\n\r\n    // Iterate dummy objects with dummy members (all the same data)\r\n    for (int obj_i = 0; obj_i < 3; obj_i++)\r\n        funcs::ShowDummyObject(\"Object\", obj_i);\r\n\r\n    ImGui::Columns(1);\r\n    ImGui::Separator();\r\n    ImGui::PopStyleVar();\r\n    ImGui::End();\r\n}\r\n\r\n// Demonstrate/test rendering huge amount of text, and the incidence of clipping.\r\nstatic void ShowExampleAppLongText(bool* p_open)\r\n{\r\n    ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);\r\n    if (!ImGui::Begin(\"Example: Long text display\", p_open))\r\n    {\r\n        ImGui::End();\r\n        return;\r\n    }\r\n\r\n    static int test_type = 0;\r\n    static ImGuiTextBuffer log;\r\n    static int lines = 0;\r\n    ImGui::Text(\"Printing unusually long amount of text.\");\r\n    ImGui::Combo(\"Test type\", &test_type, \"Single call to TextUnformatted()\\0Multiple calls to Text(), clipped manually\\0Multiple calls to Text(), not clipped\\0\");\r\n    ImGui::Text(\"Buffer contents: %d lines, %d bytes\", lines, log.size());\r\n    if (ImGui::Button(\"Clear\")) { log.clear(); lines = 0; }\r\n    ImGui::SameLine();\r\n    if (ImGui::Button(\"Add 1000 lines\"))\r\n    {\r\n        for (int i = 0; i < 1000; i++)\r\n            log.append(\"%i The quick brown fox jumps over the lazy dog\\n\", lines+i);\r\n        lines += 1000;\r\n    }\r\n    ImGui::BeginChild(\"Log\");\r\n    switch (test_type)\r\n    {\r\n    case 0:\r\n        // Single call to TextUnformatted() with a big buffer\r\n        ImGui::TextUnformatted(log.begin(), log.end());\r\n        break;\r\n    case 1:\r\n        {\r\n            // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.\r\n            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));\r\n            ImGuiListClipper clipper(lines);\r\n            while (clipper.Step())\r\n                for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)\r\n                    ImGui::Text(\"%i The quick brown fox jumps over the lazy dog\", i);\r\n            ImGui::PopStyleVar();\r\n            break;\r\n        }\r\n    case 2:\r\n        // Multiple calls to Text(), not clipped (slow)\r\n        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));\r\n        for (int i = 0; i < lines; i++)\r\n            ImGui::Text(\"%i The quick brown fox jumps over the lazy dog\", i);\r\n        ImGui::PopStyleVar();\r\n        break;\r\n    }\r\n    ImGui::EndChild();\r\n    ImGui::End();\r\n}\r\n\r\n// End of Demo code\r\n#else\r\n\r\nvoid ImGui::ShowTestWindow(bool*) {}\r\nvoid ImGui::ShowUserGuide() {}\r\nvoid ImGui::ShowStyleEditor(ImGuiStyle*) {}\r\n\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui_draw.cpp",
    "content": "// dear imgui, v1.52 WIP\r\n// (drawing and font code)\r\n\r\n// Contains implementation for\r\n// - ImDrawList\r\n// - ImDrawData\r\n// - ImFontAtlas\r\n// - ImFont\r\n// - Default font data\r\n\r\n#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)\r\n#define _CRT_SECURE_NO_WARNINGS\r\n#endif\r\n\r\n#include \"imgui.h\"\r\n#define IMGUI_DEFINE_MATH_OPERATORS\r\n#define IMGUI_DEFINE_PLACEMENT_NEW\r\n#include \"imgui_internal.h\"\r\n\r\n#include <stdio.h>      // vsnprintf, sscanf, printf\r\n#if !defined(alloca)\r\n#ifdef _WIN32\r\n#include <malloc.h>     // alloca\r\n#elif (defined(__FreeBSD__) || defined(FreeBSD_kernel) || defined(__DragonFly__)) && !defined(__GLIBC__)\r\n#include <stdlib.h>     // alloca. FreeBSD uses stdlib.h unless GLIBC\r\n#else\r\n#include <alloca.h>     // alloca\r\n#endif\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)\r\n#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen\r\n#define snprintf _snprintf\r\n#endif\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic ignored \"-Wold-style-cast\"         // warning : use of old-style cast                              // yes, they are more terse.\r\n#pragma clang diagnostic ignored \"-Wfloat-equal\"            // warning : comparing floating point with == or != is unsafe   // storing and comparing against same constants ok.\r\n#pragma clang diagnostic ignored \"-Wglobal-constructors\"    // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.\r\n#pragma clang diagnostic ignored \"-Wsign-conversion\"        // warning : implicit conversion changes signedness             //\r\n#if __has_warning(\"-Wreserved-id-macro\")\r\n#pragma clang diagnostic ignored \"-Wreserved-id-macro\"      // warning : macro name is a reserved identifier                //\r\n#endif\r\n#elif defined(__GNUC__)\r\n#pragma GCC diagnostic ignored \"-Wunused-function\"          // warning: 'xxxx' defined but not used\r\n#pragma GCC diagnostic ignored \"-Wdouble-promotion\"         // warning: implicit conversion from 'float' to 'double' when passing argument to function\r\n#pragma GCC diagnostic ignored \"-Wconversion\"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value\r\n#pragma GCC diagnostic ignored \"-Wcast-qual\"                // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers\r\n#endif\r\n\r\n//-------------------------------------------------------------------------\r\n// STB libraries implementation\r\n//-------------------------------------------------------------------------\r\n\r\n//#define IMGUI_STB_NAMESPACE     ImGuiStb\r\n//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION\r\n//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION\r\n\r\n#ifdef IMGUI_STB_NAMESPACE\r\nnamespace IMGUI_STB_NAMESPACE\r\n{\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (push)\r\n#pragma warning (disable: 4456)                             // declaration of 'xx' hides previous local declaration\r\n#endif\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic push\r\n#pragma clang diagnostic ignored \"-Wold-style-cast\"         // warning : use of old-style cast                              // yes, they are more terse.\r\n#pragma clang diagnostic ignored \"-Wunused-function\"\r\n#pragma clang diagnostic ignored \"-Wmissing-prototypes\"\r\n#endif\r\n\r\n#ifdef __GNUC__\r\n#pragma GCC diagnostic push\r\n#pragma GCC diagnostic ignored \"-Wtype-limits\"              // warning: comparison is always true due to limited range of data type [-Wtype-limits]\r\n#endif\r\n\r\n#define STBRP_ASSERT(x)    IM_ASSERT(x)\r\n#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION\r\n#define STBRP_STATIC\r\n#define STB_RECT_PACK_IMPLEMENTATION\r\n#endif\r\n#include \"stb_rect_pack.h\"\r\n\r\n#define STBTT_malloc(x,u)  ((void)(u), ImGui::MemAlloc(x))\r\n#define STBTT_free(x,u)    ((void)(u), ImGui::MemFree(x))\r\n#define STBTT_assert(x)    IM_ASSERT(x)\r\n#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION\r\n#define STBTT_STATIC\r\n#define STB_TRUETYPE_IMPLEMENTATION\r\n#else\r\n#define STBTT_DEF extern\r\n#endif\r\n#include \"stb_truetype.h\"\r\n\r\n#ifdef __GNUC__\r\n#pragma GCC diagnostic pop\r\n#endif\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic pop\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (pop)\r\n#endif\r\n\r\n#ifdef IMGUI_STB_NAMESPACE\r\n} // namespace ImGuiStb\r\nusing namespace IMGUI_STB_NAMESPACE;\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImDrawList\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift\r\n\r\nvoid ImDrawList::Clear()\r\n{\r\n    CmdBuffer.resize(0);\r\n    IdxBuffer.resize(0);\r\n    VtxBuffer.resize(0);\r\n    _VtxCurrentIdx = 0;\r\n    _VtxWritePtr = NULL;\r\n    _IdxWritePtr = NULL;\r\n    _ClipRectStack.resize(0);\r\n    _TextureIdStack.resize(0);\r\n    _Path.resize(0);\r\n    _ChannelsCurrent = 0;\r\n    _ChannelsCount = 1;\r\n    // NB: Do not clear channels so our allocations are re-used after the first frame.\r\n}\r\n\r\nvoid ImDrawList::ClearFreeMemory()\r\n{\r\n    CmdBuffer.clear();\r\n    IdxBuffer.clear();\r\n    VtxBuffer.clear();\r\n    _VtxCurrentIdx = 0;\r\n    _VtxWritePtr = NULL;\r\n    _IdxWritePtr = NULL;\r\n    _ClipRectStack.clear();\r\n    _TextureIdStack.clear();\r\n    _Path.clear();\r\n    _ChannelsCurrent = 0;\r\n    _ChannelsCount = 1;\r\n    for (int i = 0; i < _Channels.Size; i++)\r\n    {\r\n        if (i == 0) memset(&_Channels[0], 0, sizeof(_Channels[0]));  // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again\r\n        _Channels[i].CmdBuffer.clear();\r\n        _Channels[i].IdxBuffer.clear();\r\n    }\r\n    _Channels.clear();\r\n}\r\n\r\n// Use macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug mode\r\n#define GetCurrentClipRect()    (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1]  : GNullClipRect)\r\n#define GetCurrentTextureId()   (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL)\r\n\r\nvoid ImDrawList::AddDrawCmd()\r\n{\r\n    ImDrawCmd draw_cmd;\r\n    draw_cmd.ClipRect = GetCurrentClipRect();\r\n    draw_cmd.TextureId = GetCurrentTextureId();\r\n\r\n    IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);\r\n    CmdBuffer.push_back(draw_cmd);\r\n}\r\n\r\nvoid ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)\r\n{\r\n    ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;\r\n    if (!current_cmd || current_cmd->ElemCount != 0 || current_cmd->UserCallback != NULL)\r\n    {\r\n        AddDrawCmd();\r\n        current_cmd = &CmdBuffer.back();\r\n    }\r\n    current_cmd->UserCallback = callback;\r\n    current_cmd->UserCallbackData = callback_data;\r\n\r\n    AddDrawCmd(); // Force a new command after us (see comment below)\r\n}\r\n\r\n// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.\r\n// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.\r\nvoid ImDrawList::UpdateClipRect()\r\n{\r\n    // If current command is used with different settings we need to add a new command\r\n    const ImVec4 curr_clip_rect = GetCurrentClipRect();\r\n    ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size-1] : NULL;\r\n    if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL)\r\n    {\r\n        AddDrawCmd();\r\n        return;\r\n    }\r\n\r\n    // Try to merge with previous command if it matches, else use current command\r\n    ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;\r\n    if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL)\r\n        CmdBuffer.pop_back();\r\n    else\r\n        curr_cmd->ClipRect = curr_clip_rect;\r\n}\r\n\r\nvoid ImDrawList::UpdateTextureID()\r\n{\r\n    // If current command is used with different settings we need to add a new command\r\n    const ImTextureID curr_texture_id = GetCurrentTextureId();\r\n    ImDrawCmd* curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;\r\n    if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL)\r\n    {\r\n        AddDrawCmd();\r\n        return;\r\n    }\r\n\r\n    // Try to merge with previous command if it matches, else use current command\r\n    ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;\r\n    if (prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL)\r\n        CmdBuffer.pop_back();\r\n    else\r\n        curr_cmd->TextureId = curr_texture_id;\r\n}\r\n\r\n#undef GetCurrentClipRect\r\n#undef GetCurrentTextureId\r\n\r\n// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)\r\nvoid ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect)\r\n{\r\n    ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);\r\n    if (intersect_with_current_clip_rect && _ClipRectStack.Size)\r\n    {\r\n        ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size-1];\r\n        if (cr.x < current.x) cr.x = current.x;\r\n        if (cr.y < current.y) cr.y = current.y;\r\n        if (cr.z > current.z) cr.z = current.z;\r\n        if (cr.w > current.w) cr.w = current.w;\r\n    }\r\n    cr.z = ImMax(cr.x, cr.z);\r\n    cr.w = ImMax(cr.y, cr.w);\r\n\r\n    _ClipRectStack.push_back(cr);\r\n    UpdateClipRect();\r\n}\r\n\r\nvoid ImDrawList::PushClipRectFullScreen()\r\n{\r\n    PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w));\r\n    //PushClipRect(GetVisibleRect());   // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here?\r\n}\r\n\r\nvoid ImDrawList::PopClipRect()\r\n{\r\n    IM_ASSERT(_ClipRectStack.Size > 0);\r\n    _ClipRectStack.pop_back();\r\n    UpdateClipRect();\r\n}\r\n\r\nvoid ImDrawList::PushTextureID(const ImTextureID& texture_id)\r\n{\r\n    _TextureIdStack.push_back(texture_id);\r\n    UpdateTextureID();\r\n}\r\n\r\nvoid ImDrawList::PopTextureID()\r\n{\r\n    IM_ASSERT(_TextureIdStack.Size > 0);\r\n    _TextureIdStack.pop_back();\r\n    UpdateTextureID();\r\n}\r\n\r\nvoid ImDrawList::ChannelsSplit(int channels_count)\r\n{\r\n    IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1);\r\n    int old_channels_count = _Channels.Size;\r\n    if (old_channels_count < channels_count)\r\n        _Channels.resize(channels_count);\r\n    _ChannelsCount = channels_count;\r\n\r\n    // _Channels[] (24 bytes each) hold storage that we'll swap with this->_CmdBuffer/_IdxBuffer\r\n    // The content of _Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to.\r\n    // When we switch to the next channel, we'll copy _CmdBuffer/_IdxBuffer into _Channels[0] and then _Channels[1] into _CmdBuffer/_IdxBuffer\r\n    memset(&_Channels[0], 0, sizeof(ImDrawChannel));\r\n    for (int i = 1; i < channels_count; i++)\r\n    {\r\n        if (i >= old_channels_count)\r\n        {\r\n            IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel();\r\n        }\r\n        else\r\n        {\r\n            _Channels[i].CmdBuffer.resize(0);\r\n            _Channels[i].IdxBuffer.resize(0);\r\n        }\r\n        if (_Channels[i].CmdBuffer.Size == 0)\r\n        {\r\n            ImDrawCmd draw_cmd;\r\n            draw_cmd.ClipRect = _ClipRectStack.back();\r\n            draw_cmd.TextureId = _TextureIdStack.back();\r\n            _Channels[i].CmdBuffer.push_back(draw_cmd);\r\n        }\r\n    }\r\n}\r\n\r\nvoid ImDrawList::ChannelsMerge()\r\n{\r\n    // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.\r\n    if (_ChannelsCount <= 1)\r\n        return;\r\n\r\n    ChannelsSetCurrent(0);\r\n    if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0)\r\n        CmdBuffer.pop_back();\r\n\r\n    int new_cmd_buffer_count = 0, new_idx_buffer_count = 0;\r\n    for (int i = 1; i < _ChannelsCount; i++)\r\n    {\r\n        ImDrawChannel& ch = _Channels[i];\r\n        if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0)\r\n            ch.CmdBuffer.pop_back();\r\n        new_cmd_buffer_count += ch.CmdBuffer.Size;\r\n        new_idx_buffer_count += ch.IdxBuffer.Size;\r\n    }\r\n    CmdBuffer.resize(CmdBuffer.Size + new_cmd_buffer_count);\r\n    IdxBuffer.resize(IdxBuffer.Size + new_idx_buffer_count);\r\n\r\n    ImDrawCmd* cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count;\r\n    _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count;\r\n    for (int i = 1; i < _ChannelsCount; i++)\r\n    {\r\n        ImDrawChannel& ch = _Channels[i];\r\n        if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; }\r\n        if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; }\r\n    }\r\n    AddDrawCmd();\r\n    _ChannelsCount = 1;\r\n}\r\n\r\nvoid ImDrawList::ChannelsSetCurrent(int idx)\r\n{\r\n    IM_ASSERT(idx < _ChannelsCount);\r\n    if (_ChannelsCurrent == idx) return;\r\n    memcpy(&_Channels.Data[_ChannelsCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer)); // copy 12 bytes, four times\r\n    memcpy(&_Channels.Data[_ChannelsCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer));\r\n    _ChannelsCurrent = idx;\r\n    memcpy(&CmdBuffer, &_Channels.Data[_ChannelsCurrent].CmdBuffer, sizeof(CmdBuffer));\r\n    memcpy(&IdxBuffer, &_Channels.Data[_ChannelsCurrent].IdxBuffer, sizeof(IdxBuffer));\r\n    _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size;\r\n}\r\n\r\n// NB: this can be called with negative count for removing primitives (as long as the result does not underflow)\r\nvoid ImDrawList::PrimReserve(int idx_count, int vtx_count)\r\n{\r\n    ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1];\r\n    draw_cmd.ElemCount += idx_count;\r\n\r\n    int vtx_buffer_old_size = VtxBuffer.Size;\r\n    VtxBuffer.resize(vtx_buffer_old_size + vtx_count);\r\n    _VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size;\r\n\r\n    int idx_buffer_old_size = IdxBuffer.Size;\r\n    IdxBuffer.resize(idx_buffer_old_size + idx_count);\r\n    _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size;\r\n}\r\n\r\n// Fully unrolled with inline call to keep our debug builds decently fast.\r\nvoid ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col)\r\n{\r\n    ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel);\r\n    ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;\r\n    _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);\r\n    _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);\r\n    _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;\r\n    _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;\r\n    _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;\r\n    _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col;\r\n    _VtxWritePtr += 4;\r\n    _VtxCurrentIdx += 4;\r\n    _IdxWritePtr += 6;\r\n}\r\n\r\nvoid ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col)\r\n{\r\n    ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y);\r\n    ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;\r\n    _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);\r\n    _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);\r\n    _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col;\r\n    _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col;\r\n    _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col;\r\n    _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col;\r\n    _VtxWritePtr += 4;\r\n    _VtxCurrentIdx += 4;\r\n    _IdxWritePtr += 6;\r\n}\r\n\r\nvoid ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)\r\n{\r\n    ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;\r\n    _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);\r\n    _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);\r\n    _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col;\r\n    _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col;\r\n    _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col;\r\n    _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col;\r\n    _VtxWritePtr += 4;\r\n    _VtxCurrentIdx += 4;\r\n    _IdxWritePtr += 6;\r\n}\r\n\r\n// TODO: Thickness anti-aliased lines cap are missing their AA fringe.\r\nvoid ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness, bool anti_aliased)\r\n{\r\n    if (points_count < 2)\r\n        return;\r\n\r\n    const ImVec2 uv = GImGui->FontTexUvWhitePixel;\r\n    anti_aliased &= GImGui->Style.AntiAliasedLines;\r\n    //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug\r\n\r\n    int count = points_count;\r\n    if (!closed)\r\n        count = points_count-1;\r\n\r\n    const bool thick_line = thickness > 1.0f;\r\n    if (anti_aliased)\r\n    {\r\n        // Anti-aliased stroke\r\n        const float AA_SIZE = 1.0f;\r\n        const ImU32 col_trans = col & ~IM_COL32_A_MASK;\r\n\r\n        const int idx_count = thick_line ? count*18 : count*12;\r\n        const int vtx_count = thick_line ? points_count*4 : points_count*3;\r\n        PrimReserve(idx_count, vtx_count);\r\n\r\n        // Temporary buffer\r\n        ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2));\r\n        ImVec2* temp_points = temp_normals + points_count;\r\n\r\n        for (int i1 = 0; i1 < count; i1++)\r\n        {\r\n            const int i2 = (i1+1) == points_count ? 0 : i1+1;\r\n            ImVec2 diff = points[i2] - points[i1];\r\n            diff *= ImInvLength(diff, 1.0f);\r\n            temp_normals[i1].x = diff.y;\r\n            temp_normals[i1].y = -diff.x;\r\n        }\r\n        if (!closed)\r\n            temp_normals[points_count-1] = temp_normals[points_count-2];\r\n\r\n        if (!thick_line)\r\n        {\r\n            if (!closed)\r\n            {\r\n                temp_points[0] = points[0] + temp_normals[0] * AA_SIZE;\r\n                temp_points[1] = points[0] - temp_normals[0] * AA_SIZE;\r\n                temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * AA_SIZE;\r\n                temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE;\r\n            }\r\n\r\n            // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.\r\n            unsigned int idx1 = _VtxCurrentIdx;\r\n            for (int i1 = 0; i1 < count; i1++)\r\n            {\r\n                const int i2 = (i1+1) == points_count ? 0 : i1+1;\r\n                unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+3;\r\n\r\n                // Average normals\r\n                ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;\r\n                float dmr2 = dm.x*dm.x + dm.y*dm.y;\r\n                if (dmr2 > 0.000001f)\r\n                {\r\n                    float scale = 1.0f / dmr2;\r\n                    if (scale > 100.0f) scale = 100.0f;\r\n                    dm *= scale;\r\n                }\r\n                dm *= AA_SIZE;\r\n                temp_points[i2*2+0] = points[i2] + dm;\r\n                temp_points[i2*2+1] = points[i2] - dm;\r\n\r\n                // Add indexes\r\n                _IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2);\r\n                _IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0);\r\n                _IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0);\r\n                _IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10]= (ImDrawIdx)(idx2+0); _IdxWritePtr[11]= (ImDrawIdx)(idx2+1);\r\n                _IdxWritePtr += 12;\r\n\r\n                idx1 = idx2;\r\n            }\r\n\r\n            // Add vertexes\r\n            for (int i = 0; i < points_count; i++)\r\n            {\r\n                _VtxWritePtr[0].pos = points[i];          _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;\r\n                _VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans;\r\n                _VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col_trans;\r\n                _VtxWritePtr += 3;\r\n            }\r\n        }\r\n        else\r\n        {\r\n            const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;\r\n            if (!closed)\r\n            {\r\n                temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE);\r\n                temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness);\r\n                temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness);\r\n                temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE);\r\n                temp_points[(points_count-1)*4+0] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE);\r\n                temp_points[(points_count-1)*4+1] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness);\r\n                temp_points[(points_count-1)*4+2] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness);\r\n                temp_points[(points_count-1)*4+3] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE);\r\n            }\r\n\r\n            // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.\r\n            unsigned int idx1 = _VtxCurrentIdx;\r\n            for (int i1 = 0; i1 < count; i1++)\r\n            {\r\n                const int i2 = (i1+1) == points_count ? 0 : i1+1;\r\n                unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+4;\r\n\r\n                // Average normals\r\n                ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;\r\n                float dmr2 = dm.x*dm.x + dm.y*dm.y;\r\n                if (dmr2 > 0.000001f)\r\n                {\r\n                    float scale = 1.0f / dmr2;\r\n                    if (scale > 100.0f) scale = 100.0f;\r\n                    dm *= scale;\r\n                }\r\n                ImVec2 dm_out = dm * (half_inner_thickness + AA_SIZE);\r\n                ImVec2 dm_in = dm * half_inner_thickness;\r\n                temp_points[i2*4+0] = points[i2] + dm_out;\r\n                temp_points[i2*4+1] = points[i2] + dm_in;\r\n                temp_points[i2*4+2] = points[i2] - dm_in;\r\n                temp_points[i2*4+3] = points[i2] - dm_out;\r\n\r\n                // Add indexes\r\n                _IdxWritePtr[0]  = (ImDrawIdx)(idx2+1); _IdxWritePtr[1]  = (ImDrawIdx)(idx1+1); _IdxWritePtr[2]  = (ImDrawIdx)(idx1+2);\r\n                _IdxWritePtr[3]  = (ImDrawIdx)(idx1+2); _IdxWritePtr[4]  = (ImDrawIdx)(idx2+2); _IdxWritePtr[5]  = (ImDrawIdx)(idx2+1);\r\n                _IdxWritePtr[6]  = (ImDrawIdx)(idx2+1); _IdxWritePtr[7]  = (ImDrawIdx)(idx1+1); _IdxWritePtr[8]  = (ImDrawIdx)(idx1+0);\r\n                _IdxWritePtr[9]  = (ImDrawIdx)(idx1+0); _IdxWritePtr[10] = (ImDrawIdx)(idx2+0); _IdxWritePtr[11] = (ImDrawIdx)(idx2+1);\r\n                _IdxWritePtr[12] = (ImDrawIdx)(idx2+2); _IdxWritePtr[13] = (ImDrawIdx)(idx1+2); _IdxWritePtr[14] = (ImDrawIdx)(idx1+3);\r\n                _IdxWritePtr[15] = (ImDrawIdx)(idx1+3); _IdxWritePtr[16] = (ImDrawIdx)(idx2+3); _IdxWritePtr[17] = (ImDrawIdx)(idx2+2);\r\n                _IdxWritePtr += 18;\r\n\r\n                idx1 = idx2;\r\n            }\r\n\r\n            // Add vertexes\r\n            for (int i = 0; i < points_count; i++)\r\n            {\r\n                _VtxWritePtr[0].pos = temp_points[i*4+0]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col_trans;\r\n                _VtxWritePtr[1].pos = temp_points[i*4+1]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;\r\n                _VtxWritePtr[2].pos = temp_points[i*4+2]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;\r\n                _VtxWritePtr[3].pos = temp_points[i*4+3]; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col_trans;\r\n                _VtxWritePtr += 4;\r\n            }\r\n        }\r\n        _VtxCurrentIdx += (ImDrawIdx)vtx_count;\r\n    }\r\n    else\r\n    {\r\n        // Non Anti-aliased Stroke\r\n        const int idx_count = count*6;\r\n        const int vtx_count = count*4;      // FIXME-OPT: Not sharing edges\r\n        PrimReserve(idx_count, vtx_count);\r\n\r\n        for (int i1 = 0; i1 < count; i1++)\r\n        {\r\n            const int i2 = (i1+1) == points_count ? 0 : i1+1;\r\n            const ImVec2& p1 = points[i1];\r\n            const ImVec2& p2 = points[i2];\r\n            ImVec2 diff = p2 - p1;\r\n            diff *= ImInvLength(diff, 1.0f);\r\n\r\n            const float dx = diff.x * (thickness * 0.5f);\r\n            const float dy = diff.y * (thickness * 0.5f);\r\n            _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;\r\n            _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;\r\n            _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;\r\n            _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col;\r\n            _VtxWritePtr += 4;\r\n\r\n            _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2);\r\n            _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3);\r\n            _IdxWritePtr += 6;\r\n            _VtxCurrentIdx += 4;\r\n        }\r\n    }\r\n}\r\n\r\nvoid ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased)\r\n{\r\n    const ImVec2 uv = GImGui->FontTexUvWhitePixel;\r\n    anti_aliased &= GImGui->Style.AntiAliasedShapes;\r\n    //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug\r\n\r\n    if (anti_aliased)\r\n    {\r\n        // Anti-aliased Fill\r\n        const float AA_SIZE = 1.0f;\r\n        const ImU32 col_trans = col & ~IM_COL32_A_MASK;\r\n        const int idx_count = (points_count-2)*3 + points_count*6;\r\n        const int vtx_count = (points_count*2);\r\n        PrimReserve(idx_count, vtx_count);\r\n\r\n        // Add indexes for fill\r\n        unsigned int vtx_inner_idx = _VtxCurrentIdx;\r\n        unsigned int vtx_outer_idx = _VtxCurrentIdx+1;\r\n        for (int i = 2; i < points_count; i++)\r\n        {\r\n            _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+((i-1)<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx+(i<<1));\r\n            _IdxWritePtr += 3;\r\n        }\r\n\r\n        // Compute normals\r\n        ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2));\r\n        for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)\r\n        {\r\n            const ImVec2& p0 = points[i0];\r\n            const ImVec2& p1 = points[i1];\r\n            ImVec2 diff = p1 - p0;\r\n            diff *= ImInvLength(diff, 1.0f);\r\n            temp_normals[i0].x = diff.y;\r\n            temp_normals[i0].y = -diff.x;\r\n        }\r\n\r\n        for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)\r\n        {\r\n            // Average normals\r\n            const ImVec2& n0 = temp_normals[i0];\r\n            const ImVec2& n1 = temp_normals[i1];\r\n            ImVec2 dm = (n0 + n1) * 0.5f;\r\n            float dmr2 = dm.x*dm.x + dm.y*dm.y;\r\n            if (dmr2 > 0.000001f)\r\n            {\r\n                float scale = 1.0f / dmr2;\r\n                if (scale > 100.0f) scale = 100.0f;\r\n                dm *= scale;\r\n            }\r\n            dm *= AA_SIZE * 0.5f;\r\n\r\n            // Add vertices\r\n            _VtxWritePtr[0].pos = (points[i1] - dm); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;        // Inner\r\n            _VtxWritePtr[1].pos = (points[i1] + dm); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans;  // Outer\r\n            _VtxWritePtr += 2;\r\n\r\n            // Add indexes for fringes\r\n            _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+(i0<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx+(i0<<1));\r\n            _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx+(i1<<1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx+(i1<<1));\r\n            _IdxWritePtr += 6;\r\n        }\r\n        _VtxCurrentIdx += (ImDrawIdx)vtx_count;\r\n    }\r\n    else\r\n    {\r\n        // Non Anti-aliased Fill\r\n        const int idx_count = (points_count-2)*3;\r\n        const int vtx_count = points_count;\r\n        PrimReserve(idx_count, vtx_count);\r\n        for (int i = 0; i < vtx_count; i++)\r\n        {\r\n            _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;\r\n            _VtxWritePtr++;\r\n        }\r\n        for (int i = 2; i < points_count; i++)\r\n        {\r\n            _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i);\r\n            _IdxWritePtr += 3;\r\n        }\r\n        _VtxCurrentIdx += (ImDrawIdx)vtx_count;\r\n    }\r\n}\r\n\r\nvoid ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12)\r\n{\r\n    static ImVec2 circle_vtx[12];\r\n    static bool circle_vtx_builds = false;\r\n    const int circle_vtx_count = IM_ARRAYSIZE(circle_vtx);\r\n    if (!circle_vtx_builds)\r\n    {\r\n        for (int i = 0; i < circle_vtx_count; i++)\r\n        {\r\n            const float a = ((float)i / (float)circle_vtx_count) * 2*IM_PI;\r\n            circle_vtx[i].x = cosf(a);\r\n            circle_vtx[i].y = sinf(a);\r\n        }\r\n        circle_vtx_builds = true;\r\n    }\r\n\r\n    if (radius == 0.0f || a_min_of_12 > a_max_of_12)\r\n    {\r\n        _Path.push_back(centre);\r\n        return;\r\n    }\r\n    _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1));\r\n    for (int a = a_min_of_12; a <= a_max_of_12; a++)\r\n    {\r\n        const ImVec2& c = circle_vtx[a % circle_vtx_count];\r\n        _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius));\r\n    }\r\n}\r\n\r\nvoid ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments)\r\n{\r\n    if (radius == 0.0f)\r\n    {\r\n        _Path.push_back(centre);\r\n        return;\r\n    }\r\n    _Path.reserve(_Path.Size + (num_segments + 1));\r\n    for (int i = 0; i <= num_segments; i++)\r\n    {\r\n        const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);\r\n        _Path.push_back(ImVec2(centre.x + cosf(a) * radius, centre.y + sinf(a) * radius));\r\n    }\r\n}\r\n\r\nstatic void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)\r\n{\r\n    float dx = x4 - x1;\r\n    float dy = y4 - y1;\r\n    float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);\r\n    float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);\r\n    d2 = (d2 >= 0) ? d2 : -d2;\r\n    d3 = (d3 >= 0) ? d3 : -d3;\r\n    if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy))\r\n    {\r\n        path->push_back(ImVec2(x4, y4));\r\n    }\r\n    else if (level < 10)\r\n    {\r\n        float x12 = (x1+x2)*0.5f,       y12 = (y1+y2)*0.5f;\r\n        float x23 = (x2+x3)*0.5f,       y23 = (y2+y3)*0.5f;\r\n        float x34 = (x3+x4)*0.5f,       y34 = (y3+y4)*0.5f;\r\n        float x123 = (x12+x23)*0.5f,    y123 = (y12+y23)*0.5f;\r\n        float x234 = (x23+x34)*0.5f,    y234 = (y23+y34)*0.5f;\r\n        float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f;\r\n\r\n        PathBezierToCasteljau(path, x1,y1,        x12,y12,    x123,y123,  x1234,y1234, tess_tol, level+1);\r\n        PathBezierToCasteljau(path, x1234,y1234,  x234,y234,  x34,y34,    x4,y4,       tess_tol, level+1);\r\n    }\r\n}\r\n\r\nvoid ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments)\r\n{\r\n    ImVec2 p1 = _Path.back();\r\n    if (num_segments == 0)\r\n    {\r\n        // Auto-tessellated\r\n        PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, GImGui->Style.CurveTessellationTol, 0);\r\n    }\r\n    else\r\n    {\r\n        float t_step = 1.0f / (float)num_segments;\r\n        for (int i_step = 1; i_step <= num_segments; i_step++)\r\n        {\r\n            float t = t_step * i_step;\r\n            float u = 1.0f - t;\r\n            float w1 = u*u*u;\r\n            float w2 = 3*u*u*t;\r\n            float w3 = 3*u*t*t;\r\n            float w4 = t*t*t;\r\n            _Path.push_back(ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y));\r\n        }\r\n    }\r\n}\r\n\r\nvoid ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners)\r\n{\r\n    const int corners_top = ImGuiCorner_TopLeft | ImGuiCorner_TopRight;\r\n    const int corners_bottom = ImGuiCorner_BotLeft | ImGuiCorner_BotRight;\r\n    const int corners_left = ImGuiCorner_TopLeft | ImGuiCorner_BotLeft;\r\n    const int corners_right = ImGuiCorner_TopRight | ImGuiCorner_BotRight;\r\n\r\n    rounding = ImMin(rounding, fabsf(b.x - a.x) * ( ((rounding_corners & corners_top)  == corners_top)  || ((rounding_corners & corners_bottom) == corners_bottom) ? 0.5f : 1.0f ) - 1.0f);\r\n    rounding = ImMin(rounding, fabsf(b.y - a.y) * ( ((rounding_corners & corners_left) == corners_left) || ((rounding_corners & corners_right)  == corners_right)  ? 0.5f : 1.0f ) - 1.0f);\r\n\r\n    if (rounding <= 0.0f || rounding_corners == 0)\r\n    {\r\n        PathLineTo(a);\r\n        PathLineTo(ImVec2(b.x, a.y));\r\n        PathLineTo(b);\r\n        PathLineTo(ImVec2(a.x, b.y));\r\n    }\r\n    else\r\n    {\r\n        const float rounding_tl = (rounding_corners & ImGuiCorner_TopLeft) ? rounding : 0.0f;\r\n        const float rounding_tr = (rounding_corners & ImGuiCorner_TopRight) ? rounding : 0.0f;\r\n        const float rounding_br = (rounding_corners & ImGuiCorner_BotRight) ? rounding : 0.0f;\r\n        const float rounding_bl = (rounding_corners & ImGuiCorner_BotLeft) ? rounding : 0.0f;\r\n        PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);\r\n        PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);\r\n        PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);\r\n        PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6);\r\n    }\r\n}\r\n\r\nvoid ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n    PathLineTo(a + ImVec2(0.5f,0.5f));\r\n    PathLineTo(b + ImVec2(0.5f,0.5f));\r\n    PathStroke(col, false, thickness);\r\n}\r\n\r\n// a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly.\r\nvoid ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n    PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners_flags);\r\n    PathStroke(col, true, thickness);\r\n}\r\n\r\nvoid ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n    if (rounding > 0.0f)\r\n    {\r\n        PathRect(a, b, rounding, rounding_corners_flags);\r\n        PathFillConvex(col);\r\n    }\r\n    else\r\n    {\r\n        PrimReserve(6, 4);\r\n        PrimRect(a, b, col);\r\n    }\r\n}\r\n\r\nvoid ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)\r\n{\r\n    if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    const ImVec2 uv = GImGui->FontTexUvWhitePixel;\r\n    PrimReserve(6, 4);\r\n    PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2));\r\n    PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3));\r\n    PrimWriteVtx(a, uv, col_upr_left);\r\n    PrimWriteVtx(ImVec2(c.x, a.y), uv, col_upr_right);\r\n    PrimWriteVtx(c, uv, col_bot_right);\r\n    PrimWriteVtx(ImVec2(a.x, c.y), uv, col_bot_left);\r\n}\r\n\r\nvoid ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    PathLineTo(a);\r\n    PathLineTo(b);\r\n    PathLineTo(c);\r\n    PathLineTo(d);\r\n    PathStroke(col, true, thickness);\r\n}\r\n\r\nvoid ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    PathLineTo(a);\r\n    PathLineTo(b);\r\n    PathLineTo(c);\r\n    PathLineTo(d);\r\n    PathFillConvex(col);\r\n}\r\n\r\nvoid ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    PathLineTo(a);\r\n    PathLineTo(b);\r\n    PathLineTo(c);\r\n    PathStroke(col, true, thickness);\r\n}\r\n\r\nvoid ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    PathLineTo(a);\r\n    PathLineTo(b);\r\n    PathLineTo(c);\r\n    PathFillConvex(col);\r\n}\r\n\r\nvoid ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;\r\n    PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments);\r\n    PathStroke(col, true, thickness);\r\n}\r\n\r\nvoid ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;\r\n    PathArcTo(centre, radius, 0.0f, a_max, num_segments);\r\n    PathFillConvex(col);\r\n}\r\n\r\nvoid ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    PathLineTo(pos0);\r\n    PathBezierCurveTo(cp0, cp1, pos1, num_segments);\r\n    PathStroke(col, false, thickness);\r\n}\r\n\r\nvoid ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    if (text_end == NULL)\r\n        text_end = text_begin + strlen(text_begin);\r\n    if (text_begin == text_end)\r\n        return;\r\n\r\n    // IMPORTANT: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it is just SO useful.\r\n    // Might just move Font/FontSize to ImDrawList?\r\n    if (font == NULL)\r\n        font = GImGui->Font;\r\n    if (font_size == 0.0f)\r\n        font_size = GImGui->FontSize;\r\n\r\n    IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back());  // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.\r\n\r\n    ImVec4 clip_rect = _ClipRectStack.back();\r\n    if (cpu_fine_clip_rect)\r\n    {\r\n        clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x);\r\n        clip_rect.y = ImMax(clip_rect.y, cpu_fine_clip_rect->y);\r\n        clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z);\r\n        clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);\r\n    }\r\n    font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);\r\n}\r\n\r\nvoid ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)\r\n{\r\n    AddText(NULL, 0.0f, pos, col, text_begin, text_end);\r\n}\r\n\r\nvoid ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    // FIXME-OPT: This is wasting draw calls.\r\n    const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();\r\n    if (push_texture_id)\r\n        PushTextureID(user_texture_id);\r\n\r\n    PrimReserve(6, 4);\r\n    PrimRectUV(a, b, uv_a, uv_b, col);\r\n\r\n    if (push_texture_id)\r\n        PopTextureID();\r\n}\r\n\r\nvoid ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)\r\n{\r\n    if ((col & IM_COL32_A_MASK) == 0)\r\n        return;\r\n\r\n    const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();\r\n    if (push_texture_id)\r\n        PushTextureID(user_texture_id);\r\n\r\n    PrimReserve(6, 4);\r\n    PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col);\r\n\r\n    if (push_texture_id)\r\n        PopTextureID();\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImDrawData\r\n//-----------------------------------------------------------------------------\r\n\r\n// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!\r\nvoid ImDrawData::DeIndexAllBuffers()\r\n{\r\n    ImVector<ImDrawVert> new_vtx_buffer;\r\n    TotalVtxCount = TotalIdxCount = 0;\r\n    for (int i = 0; i < CmdListsCount; i++)\r\n    {\r\n        ImDrawList* cmd_list = CmdLists[i];\r\n        if (cmd_list->IdxBuffer.empty())\r\n            continue;\r\n        new_vtx_buffer.resize(cmd_list->IdxBuffer.Size);\r\n        for (int j = 0; j < cmd_list->IdxBuffer.Size; j++)\r\n            new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]];\r\n        cmd_list->VtxBuffer.swap(new_vtx_buffer);\r\n        cmd_list->IdxBuffer.resize(0);\r\n        TotalVtxCount += cmd_list->VtxBuffer.Size;\r\n    }\r\n}\r\n\r\n// Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.\r\nvoid ImDrawData::ScaleClipRects(const ImVec2& scale)\r\n{\r\n    for (int i = 0; i < CmdListsCount; i++)\r\n    {\r\n        ImDrawList* cmd_list = CmdLists[i];\r\n        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)\r\n        {\r\n            ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i];\r\n            cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, cmd->ClipRect.w * scale.y);\r\n        }\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImFontConfig\r\n//-----------------------------------------------------------------------------\r\n\r\nImFontConfig::ImFontConfig()\r\n{\r\n    FontData = NULL;\r\n    FontDataSize = 0;\r\n    FontDataOwnedByAtlas = true;\r\n    FontNo = 0;\r\n    SizePixels = 0.0f;\r\n    OversampleH = 3;\r\n    OversampleV = 1;\r\n    PixelSnapH = false;\r\n    GlyphExtraSpacing = ImVec2(0.0f, 0.0f);\r\n    GlyphOffset = ImVec2(0.0f, 0.0f);\r\n    GlyphRanges = NULL;\r\n    MergeMode = false;\r\n    RasterizerFlags = 0x00;\r\n    RasterizerMultiply = 1.0f;\r\n    memset(Name, 0, sizeof(Name));\r\n    DstFont = NULL;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImFontAtlas\r\n//-----------------------------------------------------------------------------\r\n\r\n// A work of art lies ahead! (. = white layer, X = black layer, others are blank)\r\n// The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes.\r\nconst int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 90;\r\nconst int FONT_ATLAS_DEFAULT_TEX_DATA_H      = 27;\r\nconst int FONT_ATLAS_DEFAULT_TEX_DATA_ID     = 0xF0000;\r\nconst char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] =\r\n{\r\n    \"..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX\"\r\n    \"..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X\"\r\n    \"---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X\"\r\n    \"X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X\"\r\n    \"XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X\"\r\n    \"X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X\"\r\n    \"X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX\"\r\n    \"X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      \"\r\n    \"X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       \"\r\n    \"X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        \"\r\n    \"X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         \"\r\n    \"X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          \"\r\n    \"X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           \"\r\n    \"X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            \"\r\n    \"X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           \"\r\n    \"X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          \"\r\n    \"X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          \"\r\n    \"X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------\"\r\n    \"X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           \"\r\n    \"XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           \"\r\n    \"      X..X          -  X...X  -         X...X         -  X..X           X..X  -           \"\r\n    \"       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           \"\r\n    \"------------        -    X    -           X           -X.....................X-           \"\r\n    \"                    ----------------------------------- X...XXXXXXXXXXXXX...X -           \"\r\n    \"                                                      -  X..X           X..X  -           \"\r\n    \"                                                      -   X.X           X.X   -           \"\r\n    \"                                                      -    XX           XX    -           \"\r\n};\r\n\r\nImFontAtlas::ImFontAtlas()\r\n{\r\n    TexID = NULL;\r\n    TexPixelsAlpha8 = NULL;\r\n    TexPixelsRGBA32 = NULL;\r\n    TexWidth = TexHeight = TexDesiredWidth = 0;\r\n    TexGlyphPadding = 1;\r\n    TexUvWhitePixel = ImVec2(0, 0);\r\n}\r\n\r\nImFontAtlas::~ImFontAtlas()\r\n{\r\n    Clear();\r\n}\r\n\r\nvoid    ImFontAtlas::ClearInputData()\r\n{\r\n    for (int i = 0; i < ConfigData.Size; i++)\r\n        if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas)\r\n        {\r\n            ImGui::MemFree(ConfigData[i].FontData);\r\n            ConfigData[i].FontData = NULL;\r\n        }\r\n\r\n    // When clearing this we lose access to the font name and other information used to build the font.\r\n    for (int i = 0; i < Fonts.Size; i++)\r\n        if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size)\r\n        {\r\n            Fonts[i]->ConfigData = NULL;\r\n            Fonts[i]->ConfigDataCount = 0;\r\n        }\r\n    ConfigData.clear();\r\n    CustomRects.clear();\r\n}\r\n\r\nvoid    ImFontAtlas::ClearTexData()\r\n{\r\n    if (TexPixelsAlpha8)\r\n        ImGui::MemFree(TexPixelsAlpha8);\r\n    if (TexPixelsRGBA32)\r\n        ImGui::MemFree(TexPixelsRGBA32);\r\n    TexPixelsAlpha8 = NULL;\r\n    TexPixelsRGBA32 = NULL;\r\n}\r\n\r\nvoid    ImFontAtlas::ClearFonts()\r\n{\r\n    for (int i = 0; i < Fonts.Size; i++)\r\n    {\r\n        Fonts[i]->~ImFont();\r\n        ImGui::MemFree(Fonts[i]);\r\n    }\r\n    Fonts.clear();\r\n}\r\n\r\nvoid    ImFontAtlas::Clear()\r\n{\r\n    ClearInputData();\r\n    ClearTexData();\r\n    ClearFonts();\r\n}\r\n\r\nvoid    ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)\r\n{\r\n    // Build atlas on demand\r\n    if (TexPixelsAlpha8 == NULL)\r\n    {\r\n        if (ConfigData.empty())\r\n            AddFontDefault();\r\n        Build();\r\n    }\r\n\r\n    *out_pixels = TexPixelsAlpha8;\r\n    if (out_width) *out_width = TexWidth;\r\n    if (out_height) *out_height = TexHeight;\r\n    if (out_bytes_per_pixel) *out_bytes_per_pixel = 1;\r\n}\r\n\r\nvoid    ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)\r\n{\r\n    // Convert to RGBA32 format on demand\r\n    // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp\r\n    if (!TexPixelsRGBA32)\r\n    {\r\n        unsigned char* pixels;\r\n        GetTexDataAsAlpha8(&pixels, NULL, NULL);\r\n        TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4));\r\n        const unsigned char* src = pixels;\r\n        unsigned int* dst = TexPixelsRGBA32;\r\n        for (int n = TexWidth * TexHeight; n > 0; n--)\r\n            *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));\r\n    }\r\n\r\n    *out_pixels = (unsigned char*)TexPixelsRGBA32;\r\n    if (out_width) *out_width = TexWidth;\r\n    if (out_height) *out_height = TexHeight;\r\n    if (out_bytes_per_pixel) *out_bytes_per_pixel = 4;\r\n}\r\n\r\nImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)\r\n{\r\n    IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);\r\n    IM_ASSERT(font_cfg->SizePixels > 0.0f);\r\n\r\n    // Create new font\r\n    if (!font_cfg->MergeMode)\r\n    {\r\n        ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont));\r\n        IM_PLACEMENT_NEW(font) ImFont();\r\n        Fonts.push_back(font);\r\n    }\r\n    else\r\n    {\r\n        IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.\r\n    }\r\n\r\n    ConfigData.push_back(*font_cfg);\r\n    ImFontConfig& new_font_cfg = ConfigData.back();\r\n    if (!new_font_cfg.DstFont)\r\n        new_font_cfg.DstFont = Fonts.back();\r\n    if (!new_font_cfg.FontDataOwnedByAtlas)\r\n    {\r\n        new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize);\r\n        new_font_cfg.FontDataOwnedByAtlas = true;\r\n        memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);\r\n    }\r\n\r\n    // Invalidate texture\r\n    ClearTexData();\r\n    return new_font_cfg.DstFont;\r\n}\r\n\r\n// Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder)\r\nstatic unsigned int stb_decompress_length(unsigned char *input);\r\nstatic unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length);\r\nstatic const char*  GetDefaultCompressedFontDataTTFBase85();\r\nstatic unsigned int Decode85Byte(char c)                                    { return c >= '\\\\' ? c-36 : c-35; }\r\nstatic void         Decode85(const unsigned char* src, unsigned char* dst)\r\n{\r\n    while (*src)\r\n    {\r\n        unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));\r\n        dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF);   // We can't assume little-endianness.\r\n        src += 5;\r\n        dst += 4;\r\n    }\r\n}\r\n\r\n// Load embedded ProggyClean.ttf at size 13, disable oversampling\r\nImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)\r\n{\r\n    ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();\r\n    if (!font_cfg_template)\r\n    {\r\n        font_cfg.OversampleH = font_cfg.OversampleV = 1;\r\n        font_cfg.PixelSnapH = true;\r\n    }\r\n    if (font_cfg.Name[0] == '\\0') strcpy(font_cfg.Name, \"ProggyClean.ttf, 13px\");\r\n    if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f;\r\n\r\n    const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();\r\n    ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, GetGlyphRangesDefault());\r\n    return font;\r\n}\r\n\r\nImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)\r\n{\r\n    int data_size = 0;\r\n    void* data = ImFileLoadToMemory(filename, \"rb\", &data_size, 0);\r\n    if (!data)\r\n    {\r\n        IM_ASSERT(0); // Could not load file.\r\n        return NULL;\r\n    }\r\n    ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();\r\n    if (font_cfg.Name[0] == '\\0')\r\n    {\r\n        // Store a short copy of filename into into the font name for convenience\r\n        const char* p;\r\n        for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\\\'; p--) {}\r\n        snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), \"%s, %.0fpx\", p, size_pixels);\r\n    }\r\n    return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges);\r\n}\r\n\r\n// NBM Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().\r\nImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)\r\n{\r\n    ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();\r\n    IM_ASSERT(font_cfg.FontData == NULL);\r\n    font_cfg.FontData = ttf_data;\r\n    font_cfg.FontDataSize = ttf_size;\r\n    font_cfg.SizePixels = size_pixels;\r\n    if (glyph_ranges)\r\n        font_cfg.GlyphRanges = glyph_ranges;\r\n    return AddFont(&font_cfg);\r\n}\r\n\r\nImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)\r\n{\r\n    const unsigned int buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data);\r\n    unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size);\r\n    stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);\r\n\r\n    ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();\r\n    IM_ASSERT(font_cfg.FontData == NULL);\r\n    font_cfg.FontDataOwnedByAtlas = true;\r\n    return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges);\r\n}\r\n\r\nImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)\r\n{\r\n    int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;\r\n    void* compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size);\r\n    Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);\r\n    ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);\r\n    ImGui::MemFree(compressed_ttf);\r\n    return font;\r\n}\r\n\r\nint ImFontAtlas::CustomRectRegister(unsigned int id, int width, int height)\r\n{\r\n    IM_ASSERT(width > 0 && width <= 0xFFFF);\r\n    IM_ASSERT(height > 0 && height <= 0xFFFF);\r\n    CustomRect r;\r\n    r.ID = id;\r\n    r.Width = (unsigned short)width;\r\n    r.Height = (unsigned short)height;\r\n    CustomRects.push_back(r);\r\n    return CustomRects.Size - 1; // Return index\r\n}\r\n\r\nvoid ImFontAtlas::CustomRectCalcUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max)\r\n{\r\n    IM_ASSERT(TexWidth > 0 && TexHeight > 0);   // Font atlas needs to be built before we can calculate UV coordinates\r\n    IM_ASSERT(rect->IsPacked());                // Make sure the rectangle has been packed\r\n    *out_uv_min = ImVec2((float)rect->X / TexWidth, (float)rect->Y / TexHeight);\r\n    *out_uv_max = ImVec2((float)(rect->X + rect->Width) / TexWidth, (float)(rect->Y + rect->Height) / TexHeight);\r\n}\r\n\r\nbool    ImFontAtlas::Build()\r\n{\r\n    return ImFontAtlasBuildWithStbTruetype(this);\r\n}\r\n\r\nvoid    ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor)\r\n{\r\n    for (unsigned int i = 0; i < 256; i++)\r\n    {\r\n        unsigned int value = (unsigned int)(i * in_brighten_factor);\r\n        out_table[i] = value > 255 ? 255 : (value & 0xFF);\r\n    }\r\n}\r\n\r\nvoid    ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride)\r\n{\r\n    unsigned char* data = pixels + x + y * stride;\r\n    for (int j = h; j > 0; j--, data += stride)\r\n        for (int i = 0; i < w; i++)\r\n            data[i] = table[data[i]];\r\n}\r\n\r\nbool    ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)\r\n{\r\n    IM_ASSERT(atlas->ConfigData.Size > 0);\r\n\r\n    ImFontAtlasBuildRegisterDefaultCustomRects(atlas);\r\n\r\n    atlas->TexID = NULL;\r\n    atlas->TexWidth = atlas->TexHeight = 0;\r\n    atlas->TexUvWhitePixel = ImVec2(0, 0);\r\n    atlas->ClearTexData();\r\n\r\n    // Count glyphs/ranges\r\n    int total_glyphs_count = 0;\r\n    int total_ranges_count = 0;\r\n    for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)\r\n    {\r\n        ImFontConfig& cfg = atlas->ConfigData[input_i];\r\n        if (!cfg.GlyphRanges)\r\n            cfg.GlyphRanges = atlas->GetGlyphRangesDefault();\r\n        for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, total_ranges_count++)\r\n            total_glyphs_count += (in_range[1] - in_range[0]) + 1;\r\n    }\r\n\r\n    // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish.\r\n    // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.\r\n    atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512;\r\n    atlas->TexHeight = 0;\r\n\r\n    // Start packing\r\n    const int max_tex_height = 1024*32;\r\n    stbtt_pack_context spc;\r\n    stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL);\r\n    stbtt_PackSetOversampling(&spc, 1, 1);\r\n\r\n    // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).\r\n    ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info);\r\n\r\n    // Initialize font information (so we can error without any cleanup)\r\n    struct ImFontTempBuildData\r\n    {\r\n        stbtt_fontinfo      FontInfo;\r\n        stbrp_rect*         Rects;\r\n        int                 RectsCount;\r\n        stbtt_pack_range*   Ranges;\r\n        int                 RangesCount;\r\n    };\r\n    ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)atlas->ConfigData.Size * sizeof(ImFontTempBuildData));\r\n    for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)\r\n    {\r\n        ImFontConfig& cfg = atlas->ConfigData[input_i];\r\n        ImFontTempBuildData& tmp = tmp_array[input_i];\r\n        IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));\r\n\r\n        const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo);\r\n        IM_ASSERT(font_offset >= 0);\r\n        if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset))\r\n            return false;\r\n    }\r\n\r\n    // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)\r\n    int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0;\r\n    stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbtt_packedchar));\r\n    stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbrp_rect));\r\n    stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_ranges_count * sizeof(stbtt_pack_range));\r\n    memset(buf_packedchars, 0, total_glyphs_count * sizeof(stbtt_packedchar));\r\n    memset(buf_rects, 0, total_glyphs_count * sizeof(stbrp_rect));              // Unnecessary but let's clear this for the sake of sanity.\r\n    memset(buf_ranges, 0, total_ranges_count * sizeof(stbtt_pack_range));\r\n\r\n    // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point)\r\n    for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)\r\n    {\r\n        ImFontConfig& cfg = atlas->ConfigData[input_i];\r\n        ImFontTempBuildData& tmp = tmp_array[input_i];\r\n\r\n        // Setup ranges\r\n        int font_glyphs_count = 0;\r\n        int font_ranges_count = 0;\r\n        for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, font_ranges_count++)\r\n            font_glyphs_count += (in_range[1] - in_range[0]) + 1;\r\n        tmp.Ranges = buf_ranges + buf_ranges_n;\r\n        tmp.RangesCount = font_ranges_count;\r\n        buf_ranges_n += font_ranges_count;\r\n        for (int i = 0; i < font_ranges_count; i++)\r\n        {\r\n            const ImWchar* in_range = &cfg.GlyphRanges[i * 2];\r\n            stbtt_pack_range& range = tmp.Ranges[i];\r\n            range.font_size = cfg.SizePixels;\r\n            range.first_unicode_codepoint_in_range = in_range[0];\r\n            range.num_chars = (in_range[1] - in_range[0]) + 1;\r\n            range.chardata_for_range = buf_packedchars + buf_packedchars_n;\r\n            buf_packedchars_n += range.num_chars;\r\n        }\r\n\r\n        // Pack\r\n        tmp.Rects = buf_rects + buf_rects_n;\r\n        tmp.RectsCount = font_glyphs_count;\r\n        buf_rects_n += font_glyphs_count;\r\n        stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV);\r\n        int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects);\r\n        IM_ASSERT(n == font_glyphs_count);\r\n        stbrp_pack_rects((stbrp_context*)spc.pack_info, tmp.Rects, n);\r\n\r\n        // Extend texture height\r\n        for (int i = 0; i < n; i++)\r\n            if (tmp.Rects[i].was_packed)\r\n                atlas->TexHeight = ImMax(atlas->TexHeight, tmp.Rects[i].y + tmp.Rects[i].h);\r\n    }\r\n    IM_ASSERT(buf_rects_n == total_glyphs_count);\r\n    IM_ASSERT(buf_packedchars_n == total_glyphs_count);\r\n    IM_ASSERT(buf_ranges_n == total_ranges_count);\r\n\r\n    // Create texture\r\n    atlas->TexHeight = ImUpperPowerOfTwo(atlas->TexHeight);\r\n    atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight);\r\n    memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);\r\n    spc.pixels = atlas->TexPixelsAlpha8;\r\n    spc.height = atlas->TexHeight;\r\n\r\n    // Second pass: render font characters\r\n    for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)\r\n    {\r\n        ImFontConfig& cfg = atlas->ConfigData[input_i];\r\n        ImFontTempBuildData& tmp = tmp_array[input_i];\r\n        stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV);\r\n        stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects);\r\n        if (cfg.RasterizerMultiply != 1.0f)\r\n        {\r\n            unsigned char multiply_table[256];\r\n            ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply);\r\n            for (const stbrp_rect* r = tmp.Rects; r != tmp.Rects + tmp.RectsCount; r++)\r\n                if (r->was_packed)\r\n                    ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, spc.pixels, r->x, r->y, r->w, r->h, spc.stride_in_bytes);\r\n        }\r\n        tmp.Rects = NULL;\r\n    }\r\n\r\n    // End packing\r\n    stbtt_PackEnd(&spc);\r\n    ImGui::MemFree(buf_rects);\r\n    buf_rects = NULL;\r\n\r\n    // Third pass: setup ImFont and glyphs for runtime\r\n    for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)\r\n    {\r\n        ImFontConfig& cfg = atlas->ConfigData[input_i];\r\n        ImFontTempBuildData& tmp = tmp_array[input_i];\r\n        ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true)\r\n\r\n        const float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels);\r\n        int unscaled_ascent, unscaled_descent, unscaled_line_gap;\r\n        stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap);\r\n\r\n        const float ascent = unscaled_ascent * font_scale;\r\n        const float descent = unscaled_descent * font_scale;\r\n        ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);\r\n        const float off_x = cfg.GlyphOffset.x;\r\n        const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f);\r\n\r\n        dst_font->FallbackGlyph = NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable()\r\n        for (int i = 0; i < tmp.RangesCount; i++)\r\n        {\r\n            stbtt_pack_range& range = tmp.Ranges[i];\r\n            for (int char_idx = 0; char_idx < range.num_chars; char_idx += 1)\r\n            {\r\n                const stbtt_packedchar& pc = range.chardata_for_range[char_idx];\r\n                if (!pc.x0 && !pc.x1 && !pc.y0 && !pc.y1)\r\n                    continue;\r\n\r\n                const int codepoint = range.first_unicode_codepoint_in_range + char_idx;\r\n                if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint))\r\n                    continue;\r\n\r\n                stbtt_aligned_quad q;\r\n                float dummy_x = 0.0f, dummy_y = 0.0f;\r\n                stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0);\r\n\r\n                dst_font->Glyphs.resize(dst_font->Glyphs.Size + 1);\r\n                ImFont::Glyph& glyph = dst_font->Glyphs.back();\r\n                glyph.Codepoint = (ImWchar)codepoint;\r\n                glyph.X0 = q.x0 + off_x; \r\n                glyph.Y0 = q.y0 + off_y; \r\n                glyph.X1 = q.x1 + off_x; \r\n                glyph.Y1 = q.y1 + off_y;\r\n                glyph.U0 = q.s0; \r\n                glyph.V0 = q.t0; \r\n                glyph.U1 = q.s1; \r\n                glyph.V1 = q.t1;\r\n                glyph.XAdvance = (pc.xadvance + cfg.GlyphExtraSpacing.x);  // Bake spacing into XAdvance\r\n\r\n                if (cfg.PixelSnapH)\r\n                    glyph.XAdvance = (float)(int)(glyph.XAdvance + 0.5f);\r\n                dst_font->MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * atlas->TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * atlas->TexHeight + 1.99f); // +1 to account for average padding, +0.99 to round\r\n            }\r\n        }\r\n        cfg.DstFont->BuildLookupTable();\r\n    }\r\n\r\n    // Cleanup temporaries\r\n    ImGui::MemFree(buf_packedchars);\r\n    ImGui::MemFree(buf_ranges);\r\n    ImGui::MemFree(tmp_array);\r\n\r\n    // Render into our custom data block\r\n    ImFontAtlasBuildRenderDefaultTexData(atlas);\r\n\r\n    return true;\r\n}\r\n\r\nvoid ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas)\r\n{\r\n    // FIXME-WIP: We should register in the constructor (but cannot because our static instances may not have allocator ready by the time they initialize). This needs to be fixed because we can expose CustomRects.\r\n    if (atlas->CustomRects.empty())\r\n        atlas->CustomRectRegister(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H);\r\n}\r\n\r\nvoid ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent)\r\n{\r\n    if (!font_config->MergeMode)\r\n    {\r\n        font->ContainerAtlas = atlas;\r\n        font->ConfigData = font_config;\r\n        font->ConfigDataCount = 0;\r\n        font->FontSize = font_config->SizePixels;\r\n        font->Ascent = ascent;\r\n        font->Descent = descent;\r\n        font->Glyphs.resize(0);\r\n        font->MetricsTotalSurface = 0;\r\n    }\r\n    font->ConfigDataCount++;\r\n}\r\n\r\nvoid ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaque)\r\n{\r\n    stbrp_context* pack_context = (stbrp_context*)pack_context_opaque;\r\n\r\n    ImVector<ImFontAtlas::CustomRect>& user_rects = atlas->CustomRects;\r\n    ImVector<stbrp_rect> pack_rects;\r\n    pack_rects.resize(user_rects.Size);\r\n    memset(pack_rects.Data, 0, sizeof(stbrp_rect) * user_rects.Size);\r\n    for (int i = 0; i < user_rects.Size; i++)\r\n    {\r\n        pack_rects[i].w = user_rects[i].Width;\r\n        pack_rects[i].h = user_rects[i].Height;\r\n    }\r\n    stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size);\r\n    for (int i = 0; i < pack_rects.Size; i++)\r\n        if (pack_rects[i].was_packed)\r\n        {\r\n            user_rects[i].X = pack_rects[i].x;\r\n            user_rects[i].Y = pack_rects[i].y;\r\n            IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);\r\n            atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);\r\n        }\r\n}\r\n\r\nvoid ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)\r\n{\r\n    ImFontAtlas::CustomRect& r = atlas->CustomRects[0];\r\n    IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID);\r\n    IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1);\r\n    IM_ASSERT(r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);\r\n    IM_ASSERT(r.IsPacked());\r\n    IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);\r\n\r\n    // Render/copy pixels\r\n    for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++)\r\n        for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++)\r\n        {\r\n            const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * atlas->TexWidth;\r\n            const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;\r\n            atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00;\r\n            atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00;\r\n        }\r\n    const ImVec2 tex_uv_scale(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);\r\n    atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * tex_uv_scale.x, (r.Y + 0.5f) * tex_uv_scale.y);\r\n\r\n    // Setup mouse cursors\r\n    const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] =\r\n    {\r\n        // Pos ........ Size ......... Offset ......\r\n        { ImVec2(0,3),  ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow\r\n        { ImVec2(13,0), ImVec2(7,16),  ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput\r\n        { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move\r\n        { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS\r\n        { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW\r\n        { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW\r\n        { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE\r\n    };\r\n\r\n    for (int type = 0; type < ImGuiMouseCursor_Count_; type++)\r\n    {\r\n        ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type];\r\n        ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.X, (float)r.Y);\r\n        const ImVec2 size = cursor_datas[type][1];\r\n        cursor_data.Type = type;\r\n        cursor_data.Size = size;\r\n        cursor_data.HotOffset = cursor_datas[type][2];\r\n        cursor_data.TexUvMin[0] = (pos) * tex_uv_scale;\r\n        cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale;\r\n        pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;\r\n        cursor_data.TexUvMin[1] = (pos) * tex_uv_scale;\r\n        cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale;\r\n    }\r\n}\r\n\r\n// Retrieve list of range (2 int per range, values are inclusive)\r\nconst ImWchar*   ImFontAtlas::GetGlyphRangesDefault()\r\n{\r\n    static const ImWchar ranges[] =\r\n    {\r\n        0x0020, 0x00FF, // Basic Latin + Latin Supplement\r\n        0,\r\n    };\r\n    return &ranges[0];\r\n}\r\n\r\nconst ImWchar*  ImFontAtlas::GetGlyphRangesKorean()\r\n{\r\n    static const ImWchar ranges[] =\r\n    {\r\n        0x0020, 0x00FF, // Basic Latin + Latin Supplement\r\n        0x3131, 0x3163, // Korean alphabets\r\n        0xAC00, 0xD79D, // Korean characters\r\n        0,\r\n    };\r\n    return &ranges[0];\r\n}\r\n\r\nconst ImWchar*  ImFontAtlas::GetGlyphRangesChinese()\r\n{\r\n    static const ImWchar ranges[] =\r\n    {\r\n        0x0020, 0x00FF, // Basic Latin + Latin Supplement\r\n        0x3000, 0x30FF, // Punctuations, Hiragana, Katakana\r\n        0x31F0, 0x31FF, // Katakana Phonetic Extensions\r\n        0xFF00, 0xFFEF, // Half-width characters\r\n        0x4e00, 0x9FAF, // CJK Ideograms\r\n        0,\r\n    };\r\n    return &ranges[0];\r\n}\r\n\r\nconst ImWchar*  ImFontAtlas::GetGlyphRangesJapanese()\r\n{\r\n    // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1.\r\n    // This encoding helps us reduce the source code size.\r\n    static const short offsets_from_0x4E00[] =\r\n    {\r\n        -1,0,1,3,0,0,0,0,1,0,5,1,1,0,7,4,6,10,0,1,9,9,7,1,3,19,1,10,7,1,0,1,0,5,1,0,6,4,2,6,0,0,12,6,8,0,3,5,0,1,0,9,0,0,8,1,1,3,4,5,13,0,0,8,2,17,\r\n        4,3,1,1,9,6,0,0,0,2,1,3,2,22,1,9,11,1,13,1,3,12,0,5,9,2,0,6,12,5,3,12,4,1,2,16,1,1,4,6,5,3,0,6,13,15,5,12,8,14,0,0,6,15,3,6,0,18,8,1,6,14,1,\r\n        5,4,12,24,3,13,12,10,24,0,0,0,1,0,1,1,2,9,10,2,2,0,0,3,3,1,0,3,8,0,3,2,4,4,1,6,11,10,14,6,15,3,4,15,1,0,0,5,2,2,0,0,1,6,5,5,6,0,3,6,5,0,0,1,0,\r\n        11,2,2,8,4,7,0,10,0,1,2,17,19,3,0,2,5,0,6,2,4,4,6,1,1,11,2,0,3,1,2,1,2,10,7,6,3,16,0,8,24,0,0,3,1,1,3,0,1,6,0,0,0,2,0,1,5,15,0,1,0,0,2,11,19,\r\n        1,4,19,7,6,5,1,0,0,0,0,5,1,0,1,9,0,0,5,0,2,0,1,0,3,0,11,3,0,2,0,0,0,0,0,9,3,6,4,12,0,14,0,0,29,10,8,0,14,37,13,0,31,16,19,0,8,30,1,20,8,3,48,\r\n        21,1,0,12,0,10,44,34,42,54,11,18,82,0,2,1,2,12,1,0,6,2,17,2,12,7,0,7,17,4,2,6,24,23,8,23,39,2,16,23,1,0,5,1,2,15,14,5,6,2,11,0,8,6,2,2,2,14,\r\n        20,4,15,3,4,11,10,10,2,5,2,1,30,2,1,0,0,22,5,5,0,3,1,5,4,1,0,0,2,2,21,1,5,1,2,16,2,1,3,4,0,8,4,0,0,5,14,11,2,16,1,13,1,7,0,22,15,3,1,22,7,14,\r\n        22,19,11,24,18,46,10,20,64,45,3,2,0,4,5,0,1,4,25,1,0,0,2,10,0,0,0,1,0,1,2,0,0,9,1,2,0,0,0,2,5,2,1,1,5,5,8,1,1,1,5,1,4,9,1,3,0,1,0,1,1,2,0,0,\r\n        2,0,1,8,22,8,1,0,0,0,0,4,2,1,0,9,8,5,0,9,1,30,24,2,6,4,39,0,14,5,16,6,26,179,0,2,1,1,0,0,0,5,2,9,6,0,2,5,16,7,5,1,1,0,2,4,4,7,15,13,14,0,0,\r\n        3,0,1,0,0,0,2,1,6,4,5,1,4,9,0,3,1,8,0,0,10,5,0,43,0,2,6,8,4,0,2,0,0,9,6,0,9,3,1,6,20,14,6,1,4,0,7,2,3,0,2,0,5,0,3,1,0,3,9,7,0,3,4,0,4,9,1,6,0,\r\n        9,0,0,2,3,10,9,28,3,6,2,4,1,2,32,4,1,18,2,0,3,1,5,30,10,0,2,2,2,0,7,9,8,11,10,11,7,2,13,7,5,10,0,3,40,2,0,1,6,12,0,4,5,1,5,11,11,21,4,8,3,7,\r\n        8,8,33,5,23,0,0,19,8,8,2,3,0,6,1,1,1,5,1,27,4,2,5,0,3,5,6,3,1,0,3,1,12,5,3,3,2,0,7,7,2,1,0,4,0,1,1,2,0,10,10,6,2,5,9,7,5,15,15,21,6,11,5,20,\r\n        4,3,5,5,2,5,0,2,1,0,1,7,28,0,9,0,5,12,5,5,18,30,0,12,3,3,21,16,25,32,9,3,14,11,24,5,66,9,1,2,0,5,9,1,5,1,8,0,8,3,3,0,1,15,1,4,8,1,2,7,0,7,2,\r\n        8,3,7,5,3,7,10,2,1,0,0,2,25,0,6,4,0,10,0,4,2,4,1,12,5,38,4,0,4,1,10,5,9,4,0,14,4,2,5,18,20,21,1,3,0,5,0,7,0,3,7,1,3,1,1,8,1,0,0,0,3,2,5,2,11,\r\n        6,0,13,1,3,9,1,12,0,16,6,2,1,0,2,1,12,6,13,11,2,0,28,1,7,8,14,13,8,13,0,2,0,5,4,8,10,2,37,42,19,6,6,7,4,14,11,18,14,80,7,6,0,4,72,12,36,27,\r\n        7,7,0,14,17,19,164,27,0,5,10,7,3,13,6,14,0,2,2,5,3,0,6,13,0,0,10,29,0,4,0,3,13,0,3,1,6,51,1,5,28,2,0,8,0,20,2,4,0,25,2,10,13,10,0,16,4,0,1,0,\r\n        2,1,7,0,1,8,11,0,0,1,2,7,2,23,11,6,6,4,16,2,2,2,0,22,9,3,3,5,2,0,15,16,21,2,9,20,15,15,5,3,9,1,0,0,1,7,7,5,4,2,2,2,38,24,14,0,0,15,5,6,24,14,\r\n        5,5,11,0,21,12,0,3,8,4,11,1,8,0,11,27,7,2,4,9,21,59,0,1,39,3,60,62,3,0,12,11,0,3,30,11,0,13,88,4,15,5,28,13,1,4,48,17,17,4,28,32,46,0,16,0,\r\n        18,11,1,8,6,38,11,2,6,11,38,2,0,45,3,11,2,7,8,4,30,14,17,2,1,1,65,18,12,16,4,2,45,123,12,56,33,1,4,3,4,7,0,0,0,3,2,0,16,4,2,4,2,0,7,4,5,2,26,\r\n        2,25,6,11,6,1,16,2,6,17,77,15,3,35,0,1,0,5,1,0,38,16,6,3,12,3,3,3,0,9,3,1,3,5,2,9,0,18,0,25,1,3,32,1,72,46,6,2,7,1,3,14,17,0,28,1,40,13,0,20,\r\n        15,40,6,38,24,12,43,1,1,9,0,12,6,0,6,2,4,19,3,7,1,48,0,9,5,0,5,6,9,6,10,15,2,11,19,3,9,2,0,1,10,1,27,8,1,3,6,1,14,0,26,0,27,16,3,4,9,6,2,23,\r\n        9,10,5,25,2,1,6,1,1,48,15,9,15,14,3,4,26,60,29,13,37,21,1,6,4,0,2,11,22,23,16,16,2,2,1,3,0,5,1,6,4,0,0,4,0,0,8,3,0,2,5,0,7,1,7,3,13,2,4,10,\r\n        3,0,2,31,0,18,3,0,12,10,4,1,0,7,5,7,0,5,4,12,2,22,10,4,2,15,2,8,9,0,23,2,197,51,3,1,1,4,13,4,3,21,4,19,3,10,5,40,0,4,1,1,10,4,1,27,34,7,21,\r\n        2,17,2,9,6,4,2,3,0,4,2,7,8,2,5,1,15,21,3,4,4,2,2,17,22,1,5,22,4,26,7,0,32,1,11,42,15,4,1,2,5,0,19,3,1,8,6,0,10,1,9,2,13,30,8,2,24,17,19,1,4,\r\n        4,25,13,0,10,16,11,39,18,8,5,30,82,1,6,8,18,77,11,13,20,75,11,112,78,33,3,0,0,60,17,84,9,1,1,12,30,10,49,5,32,158,178,5,5,6,3,3,1,3,1,4,7,6,\r\n        19,31,21,0,2,9,5,6,27,4,9,8,1,76,18,12,1,4,0,3,3,6,3,12,2,8,30,16,2,25,1,5,5,4,3,0,6,10,2,3,1,0,5,1,19,3,0,8,1,5,2,6,0,0,0,19,1,2,0,5,1,2,5,\r\n        1,3,7,0,4,12,7,3,10,22,0,9,5,1,0,2,20,1,1,3,23,30,3,9,9,1,4,191,14,3,15,6,8,50,0,1,0,0,4,0,0,1,0,2,4,2,0,2,3,0,2,0,2,2,8,7,0,1,1,1,3,3,17,11,\r\n        91,1,9,3,2,13,4,24,15,41,3,13,3,1,20,4,125,29,30,1,0,4,12,2,21,4,5,5,19,11,0,13,11,86,2,18,0,7,1,8,8,2,2,22,1,2,6,5,2,0,1,2,8,0,2,0,5,2,1,0,\r\n        2,10,2,0,5,9,2,1,2,0,1,0,4,0,0,10,2,5,3,0,6,1,0,1,4,4,33,3,13,17,3,18,6,4,7,1,5,78,0,4,1,13,7,1,8,1,0,35,27,15,3,0,0,0,1,11,5,41,38,15,22,6,\r\n        14,14,2,1,11,6,20,63,5,8,27,7,11,2,2,40,58,23,50,54,56,293,8,8,1,5,1,14,0,1,12,37,89,8,8,8,2,10,6,0,0,0,4,5,2,1,0,1,1,2,7,0,3,3,0,4,6,0,3,2,\r\n        19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20,\r\n        109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,\r\n    };\r\n    static ImWchar base_ranges[] =\r\n    {\r\n        0x0020, 0x00FF, // Basic Latin + Latin Supplement\r\n        0x3000, 0x30FF, // Punctuations, Hiragana, Katakana\r\n        0x31F0, 0x31FF, // Katakana Phonetic Extensions\r\n        0xFF00, 0xFFEF, // Half-width characters\r\n    };\r\n    static bool full_ranges_unpacked = false;\r\n    static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1];\r\n    if (!full_ranges_unpacked)\r\n    {\r\n        // Unpack\r\n        int codepoint = 0x4e00;\r\n        memcpy(full_ranges, base_ranges, sizeof(base_ranges));\r\n        ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);;\r\n        for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)\r\n            dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));\r\n        dst[0] = 0;\r\n        full_ranges_unpacked = true;\r\n    }\r\n    return &full_ranges[0];\r\n}\r\n\r\nconst ImWchar*  ImFontAtlas::GetGlyphRangesCyrillic()\r\n{\r\n    static const ImWchar ranges[] =\r\n    {\r\n        0x0020, 0x00FF, // Basic Latin + Latin Supplement\r\n        0x0400, 0x052F, // Cyrillic + Cyrillic Supplement\r\n        0x2DE0, 0x2DFF, // Cyrillic Extended-A\r\n        0xA640, 0xA69F, // Cyrillic Extended-B\r\n        0,\r\n    };\r\n    return &ranges[0];\r\n}\r\n\r\nconst ImWchar*  ImFontAtlas::GetGlyphRangesThai()\r\n{\r\n    static const ImWchar ranges[] =\r\n    {\r\n        0x0020, 0x00FF, // Basic Latin\r\n        0x0E00, 0x0E7F, // Thai\r\n        0,\r\n    };\r\n    return &ranges[0];\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImFontAtlas::GlyphRangesBuilder\r\n//-----------------------------------------------------------------------------\r\n\r\nvoid ImFontAtlas::GlyphRangesBuilder::AddText(const char* text, const char* text_end)\r\n{\r\n    while (text_end ? (text < text_end) : *text)\r\n    {\r\n        unsigned int c = 0;\r\n        int c_len = ImTextCharFromUtf8(&c, text, text_end);\r\n        text += c_len;\r\n        if (c_len == 0)\r\n            break;\r\n        if (c < 0x10000)\r\n            AddChar((ImWchar)c);\r\n    }\r\n}\r\n\r\nvoid ImFontAtlas::GlyphRangesBuilder::AddRanges(const ImWchar* ranges)\r\n{\r\n    for (; ranges[0]; ranges += 2)\r\n        for (ImWchar c = ranges[0]; c <= ranges[1]; c++)\r\n            AddChar(c);\r\n}\r\n\r\nvoid ImFontAtlas::GlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)\r\n{\r\n    for (int n = 0; n < 0x10000; n++)\r\n        if (GetBit(n))\r\n        {\r\n            out_ranges->push_back((ImWchar)n);\r\n            while (n < 0x10000 && GetBit(n + 1))\r\n                n++;\r\n            out_ranges->push_back((ImWchar)n);\r\n        }\r\n    out_ranges->push_back(0);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ImFont\r\n//-----------------------------------------------------------------------------\r\n\r\nImFont::ImFont()\r\n{\r\n    Scale = 1.0f;\r\n    FallbackChar = (ImWchar)'?';\r\n    Clear();\r\n}\r\n\r\nImFont::~ImFont()\r\n{\r\n    // Invalidate active font so that the user gets a clear crash instead of a dangling pointer.\r\n    // If you want to delete fonts you need to do it between Render() and NewFrame().\r\n    // FIXME-CLEANUP\r\n    /*\r\n    ImGuiContext& g = *GImGui;\r\n    if (g.Font == this)\r\n        g.Font = NULL;\r\n    */\r\n    Clear();\r\n}\r\n\r\nvoid    ImFont::Clear()\r\n{\r\n    FontSize = 0.0f;\r\n    DisplayOffset = ImVec2(0.0f, 1.0f);\r\n    Glyphs.clear();\r\n    IndexXAdvance.clear();\r\n    IndexLookup.clear();\r\n    FallbackGlyph = NULL;\r\n    FallbackXAdvance = 0.0f;\r\n    ConfigDataCount = 0;\r\n    ConfigData = NULL;\r\n    ContainerAtlas = NULL;\r\n    Ascent = Descent = 0.0f;\r\n    MetricsTotalSurface = 0;\r\n}\r\n\r\nvoid ImFont::BuildLookupTable()\r\n{\r\n    int max_codepoint = 0;\r\n    for (int i = 0; i != Glyphs.Size; i++)\r\n        max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint);\r\n\r\n    IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved\r\n    IndexXAdvance.clear();\r\n    IndexLookup.clear();\r\n    GrowIndex(max_codepoint + 1);\r\n    for (int i = 0; i < Glyphs.Size; i++)\r\n    {\r\n        int codepoint = (int)Glyphs[i].Codepoint;\r\n        IndexXAdvance[codepoint] = Glyphs[i].XAdvance;\r\n        IndexLookup[codepoint] = (unsigned short)i;\r\n    }\r\n\r\n    // Create a glyph to handle TAB\r\n    // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at \"column 0\" ?)\r\n    if (FindGlyph((unsigned short)' '))\r\n    {\r\n        if (Glyphs.back().Codepoint != '\\t')   // So we can call this function multiple times\r\n            Glyphs.resize(Glyphs.Size + 1);\r\n        ImFont::Glyph& tab_glyph = Glyphs.back();\r\n        tab_glyph = *FindGlyph((unsigned short)' ');\r\n        tab_glyph.Codepoint = '\\t';\r\n        tab_glyph.XAdvance *= 4;\r\n        IndexXAdvance[(int)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance;\r\n        IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size-1);\r\n    }\r\n\r\n    FallbackGlyph = NULL;\r\n    FallbackGlyph = FindGlyph(FallbackChar);\r\n    FallbackXAdvance = FallbackGlyph ? FallbackGlyph->XAdvance : 0.0f;\r\n    for (int i = 0; i < max_codepoint + 1; i++)\r\n        if (IndexXAdvance[i] < 0.0f)\r\n            IndexXAdvance[i] = FallbackXAdvance;\r\n}\r\n\r\nvoid ImFont::SetFallbackChar(ImWchar c)\r\n{\r\n    FallbackChar = c;\r\n    BuildLookupTable();\r\n}\r\n\r\nvoid ImFont::GrowIndex(int new_size)\r\n{\r\n    IM_ASSERT(IndexXAdvance.Size == IndexLookup.Size);\r\n    int old_size = IndexLookup.Size;\r\n    if (new_size <= old_size)\r\n        return;\r\n    IndexXAdvance.resize(new_size);\r\n    IndexLookup.resize(new_size);\r\n    for (int i = old_size; i < new_size; i++)\r\n    {\r\n        IndexXAdvance[i] = -1.0f;\r\n        IndexLookup[i] = (unsigned short)-1;\r\n    }\r\n}\r\n\r\nvoid ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)\r\n{\r\n    IM_ASSERT(IndexLookup.Size > 0);    // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function.\r\n    int index_size = IndexLookup.Size;\r\n\r\n    if (dst < index_size && IndexLookup.Data[dst] == (unsigned short)-1 && !overwrite_dst) // 'dst' already exists\r\n        return;\r\n    if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op\r\n        return;\r\n\r\n    GrowIndex(dst + 1);\r\n    IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (unsigned short)-1;\r\n    IndexXAdvance[dst] = (src < index_size) ? IndexXAdvance.Data[src] : 1.0f;\r\n}\r\n\r\nconst ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const\r\n{\r\n    if (c < IndexLookup.Size)\r\n    {\r\n        const unsigned short i = IndexLookup[c];\r\n        if (i != (unsigned short)-1)\r\n            return &Glyphs.Data[i];\r\n    }\r\n    return FallbackGlyph;\r\n}\r\n\r\nconst char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const\r\n{\r\n    // Simple word-wrapping for English, not full-featured. Please submit failing cases!\r\n    // FIXME: Much possible improvements (don't cut things like \"word !\", \"word!!!\" but cut within \"word,,,,\", more sensible support for punctuations, support for Unicode punctuations, etc.)\r\n\r\n    // For references, possible wrap point marked with ^\r\n    //  \"aaa bbb, ccc,ddd. eee   fff. ggg!\"\r\n    //      ^    ^    ^   ^   ^__    ^    ^\r\n\r\n    // List of hardcoded separators: .,;!?'\"\r\n\r\n    // Skip extra blanks after a line returns (that includes not counting them in width computation)\r\n    // e.g. \"Hello    world\" --> \"Hello\" \"World\"\r\n\r\n    // Cut words that cannot possibly fit within one line.\r\n    // e.g.: \"The tropical fish\" with ~5 characters worth of width --> \"The tr\" \"opical\" \"fish\"\r\n\r\n    float line_width = 0.0f;\r\n    float word_width = 0.0f;\r\n    float blank_width = 0.0f;\r\n    wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters\r\n\r\n    const char* word_end = text;\r\n    const char* prev_word_end = NULL;\r\n    bool inside_word = true;\r\n\r\n    const char* s = text;\r\n    while (s < text_end)\r\n    {\r\n        unsigned int c = (unsigned int)*s;\r\n        const char* next_s;\r\n        if (c < 0x80)\r\n            next_s = s + 1;\r\n        else\r\n            next_s = s + ImTextCharFromUtf8(&c, s, text_end);\r\n        if (c == 0)\r\n            break;\r\n\r\n        if (c < 32)\r\n        {\r\n            if (c == '\\n')\r\n            {\r\n                line_width = word_width = blank_width = 0.0f;\r\n                inside_word = true;\r\n                s = next_s;\r\n                continue;\r\n            }\r\n            if (c == '\\r')\r\n            {\r\n                s = next_s;\r\n                continue;\r\n            }\r\n        }\r\n\r\n        const float char_width = ((int)c < IndexXAdvance.Size ? IndexXAdvance[(int)c] : FallbackXAdvance);\r\n        if (ImCharIsSpace(c))\r\n        {\r\n            if (inside_word)\r\n            {\r\n                line_width += blank_width;\r\n                blank_width = 0.0f;\r\n                word_end = s;\r\n            }\r\n            blank_width += char_width;\r\n            inside_word = false;\r\n        }\r\n        else\r\n        {\r\n            word_width += char_width;\r\n            if (inside_word)\r\n            {\r\n                word_end = next_s;\r\n            }\r\n            else\r\n            {\r\n                prev_word_end = word_end;\r\n                line_width += word_width + blank_width;\r\n                word_width = blank_width = 0.0f;\r\n            }\r\n\r\n            // Allow wrapping after punctuation.\r\n            inside_word = !(c == '.' || c == ',' || c == ';' || c == '!' || c == '?' || c == '\\\"');\r\n        }\r\n\r\n        // We ignore blank width at the end of the line (they can be skipped)\r\n        if (line_width + word_width >= wrap_width)\r\n        {\r\n            // Words that cannot possibly fit within an entire line will be cut anywhere.\r\n            if (word_width < wrap_width)\r\n                s = prev_word_end ? prev_word_end : word_end;\r\n            break;\r\n        }\r\n\r\n        s = next_s;\r\n    }\r\n\r\n    return s;\r\n}\r\n\r\nImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const\r\n{\r\n    if (!text_end)\r\n        text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this.\r\n\r\n    const float line_height = size;\r\n    const float scale = size / FontSize;\r\n\r\n    ImVec2 text_size = ImVec2(0,0);\r\n    float line_width = 0.0f;\r\n\r\n    const bool word_wrap_enabled = (wrap_width > 0.0f);\r\n    const char* word_wrap_eol = NULL;\r\n\r\n    const char* s = text_begin;\r\n    while (s < text_end)\r\n    {\r\n        if (word_wrap_enabled)\r\n        {\r\n            // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.\r\n            if (!word_wrap_eol)\r\n            {\r\n                word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width);\r\n                if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.\r\n                    word_wrap_eol++;    // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below\r\n            }\r\n\r\n            if (s >= word_wrap_eol)\r\n            {\r\n                if (text_size.x < line_width)\r\n                    text_size.x = line_width;\r\n                text_size.y += line_height;\r\n                line_width = 0.0f;\r\n                word_wrap_eol = NULL;\r\n\r\n                // Wrapping skips upcoming blanks\r\n                while (s < text_end)\r\n                {\r\n                    const char c = *s;\r\n                    if (ImCharIsSpace(c)) { s++; } else if (c == '\\n') { s++; break; } else { break; }\r\n                }\r\n                continue;\r\n            }\r\n        }\r\n\r\n        // Decode and advance source\r\n        const char* prev_s = s;\r\n        unsigned int c = (unsigned int)*s;\r\n        if (c < 0x80)\r\n        {\r\n            s += 1;\r\n        }\r\n        else\r\n        {\r\n            s += ImTextCharFromUtf8(&c, s, text_end);\r\n            if (c == 0) // Malformed UTF-8?\r\n                break;\r\n        }\r\n\r\n        if (c < 32)\r\n        {\r\n            if (c == '\\n')\r\n            {\r\n                text_size.x = ImMax(text_size.x, line_width);\r\n                text_size.y += line_height;\r\n                line_width = 0.0f;\r\n                continue;\r\n            }\r\n            if (c == '\\r')\r\n                continue;\r\n        }\r\n\r\n        const float char_width = ((int)c < IndexXAdvance.Size ? IndexXAdvance[(int)c] : FallbackXAdvance) * scale;\r\n        if (line_width + char_width >= max_width)\r\n        {\r\n            s = prev_s;\r\n            break;\r\n        }\r\n\r\n        line_width += char_width;\r\n    }\r\n\r\n    if (text_size.x < line_width)\r\n        text_size.x = line_width;\r\n\r\n    if (line_width > 0 || text_size.y == 0.0f)\r\n        text_size.y += line_height;\r\n\r\n    if (remaining)\r\n        *remaining = s;\r\n\r\n    return text_size;\r\n}\r\n\r\nvoid ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const\r\n{\r\n    if (c == ' ' || c == '\\t' || c == '\\n' || c == '\\r') // Match behavior of RenderText(), those 4 codepoints are hard-coded.\r\n        return;\r\n    if (const Glyph* glyph = FindGlyph(c))\r\n    {\r\n        float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;\r\n        pos.x = (float)(int)pos.x + DisplayOffset.x;\r\n        pos.y = (float)(int)pos.y + DisplayOffset.y;\r\n        draw_list->PrimReserve(6, 4);\r\n        draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);\r\n    }\r\n}\r\n\r\nvoid ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const\r\n{\r\n    if (!text_end)\r\n        text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls.\r\n\r\n    // Align to be pixel perfect\r\n    pos.x = (float)(int)pos.x + DisplayOffset.x;\r\n    pos.y = (float)(int)pos.y + DisplayOffset.y;\r\n    float x = pos.x;\r\n    float y = pos.y;\r\n    if (y > clip_rect.w)\r\n        return;\r\n\r\n    const float scale = size / FontSize;\r\n    const float line_height = FontSize * scale;\r\n    const bool word_wrap_enabled = (wrap_width > 0.0f);\r\n    const char* word_wrap_eol = NULL;\r\n\r\n    // Skip non-visible lines\r\n    const char* s = text_begin;\r\n    if (!word_wrap_enabled && y + line_height < clip_rect.y)\r\n        while (s < text_end && *s != '\\n')  // Fast-forward to next line\r\n            s++;\r\n\r\n    // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)\r\n    const int vtx_count_max = (int)(text_end - s) * 4;\r\n    const int idx_count_max = (int)(text_end - s) * 6;\r\n    const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;\r\n    draw_list->PrimReserve(idx_count_max, vtx_count_max);\r\n\r\n    ImDrawVert* vtx_write = draw_list->_VtxWritePtr;\r\n    ImDrawIdx* idx_write = draw_list->_IdxWritePtr;\r\n    unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;\r\n\r\n    while (s < text_end)\r\n    {\r\n        if (word_wrap_enabled)\r\n        {\r\n            // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.\r\n            if (!word_wrap_eol)\r\n            {\r\n                word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x));\r\n                if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.\r\n                    word_wrap_eol++;    // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below\r\n            }\r\n\r\n            if (s >= word_wrap_eol)\r\n            {\r\n                x = pos.x;\r\n                y += line_height;\r\n                word_wrap_eol = NULL;\r\n\r\n                // Wrapping skips upcoming blanks\r\n                while (s < text_end)\r\n                {\r\n                    const char c = *s;\r\n                    if (ImCharIsSpace(c)) { s++; } else if (c == '\\n') { s++; break; } else { break; }\r\n                }\r\n                continue;\r\n            }\r\n        }\r\n\r\n        // Decode and advance source\r\n        unsigned int c = (unsigned int)*s;\r\n        if (c < 0x80)\r\n        {\r\n            s += 1;\r\n        }\r\n        else\r\n        {\r\n            s += ImTextCharFromUtf8(&c, s, text_end);\r\n            if (c == 0) // Malformed UTF-8?\r\n                break;\r\n        }\r\n\r\n        if (c < 32)\r\n        {\r\n            if (c == '\\n')\r\n            {\r\n                x = pos.x;\r\n                y += line_height;\r\n\r\n                if (y > clip_rect.w)\r\n                    break;\r\n                if (!word_wrap_enabled && y + line_height < clip_rect.y)\r\n                    while (s < text_end && *s != '\\n')  // Fast-forward to next line\r\n                        s++;\r\n                continue;\r\n            }\r\n            if (c == '\\r')\r\n                continue;\r\n        }\r\n\r\n        float char_width = 0.0f;\r\n        if (const Glyph* glyph = FindGlyph((unsigned short)c))\r\n        {\r\n            char_width = glyph->XAdvance * scale;\r\n\r\n            // Arbitrarily assume that both space and tabs are empty glyphs as an optimization\r\n            if (c != ' ' && c != '\\t')\r\n            {\r\n                // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w\r\n                float x1 = x + glyph->X0 * scale;\r\n                float x2 = x + glyph->X1 * scale;\r\n                float y1 = y + glyph->Y0 * scale;\r\n                float y2 = y + glyph->Y1 * scale;\r\n                if (x1 <= clip_rect.z && x2 >= clip_rect.x)\r\n                {\r\n                    // Render a character\r\n                    float u1 = glyph->U0;\r\n                    float v1 = glyph->V0;\r\n                    float u2 = glyph->U1;\r\n                    float v2 = glyph->V1;\r\n\r\n                    // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.\r\n                    if (cpu_fine_clip)\r\n                    {\r\n                        if (x1 < clip_rect.x)\r\n                        {\r\n                            u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1);\r\n                            x1 = clip_rect.x;\r\n                        }\r\n                        if (y1 < clip_rect.y)\r\n                        {\r\n                            v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1);\r\n                            y1 = clip_rect.y;\r\n                        }\r\n                        if (x2 > clip_rect.z)\r\n                        {\r\n                            u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1);\r\n                            x2 = clip_rect.z;\r\n                        }\r\n                        if (y2 > clip_rect.w)\r\n                        {\r\n                            v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1);\r\n                            y2 = clip_rect.w;\r\n                        }\r\n                        if (y1 >= y2)\r\n                        {\r\n                            x += char_width;\r\n                            continue;\r\n                        }\r\n                    }\r\n\r\n                    // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:\r\n                    {\r\n                        idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2);\r\n                        idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3);\r\n                        vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1;\r\n                        vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1;\r\n                        vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2;\r\n                        vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2;\r\n                        vtx_write += 4;\r\n                        vtx_current_idx += 4;\r\n                        idx_write += 6;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        x += char_width;\r\n    }\r\n\r\n    // Give back unused vertices\r\n    draw_list->VtxBuffer.resize((int)(vtx_write - draw_list->VtxBuffer.Data));\r\n    draw_list->IdxBuffer.resize((int)(idx_write - draw_list->IdxBuffer.Data));\r\n    draw_list->CmdBuffer[draw_list->CmdBuffer.Size-1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);\r\n    draw_list->_VtxWritePtr = vtx_write;\r\n    draw_list->_IdxWritePtr = idx_write;\r\n    draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size;\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// Internals Drawing Helpers\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic inline float ImAcos01(float x)\r\n{\r\n    if (x <= 0.0f) return IM_PI * 0.5f;\r\n    if (x >= 1.0f) return 0.0f;\r\n    return acosf(x);\r\n    //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do.\r\n}\r\n\r\n// FIXME: Cleanup and move code to ImDrawList.\r\nvoid ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding)\r\n{\r\n    if (x_end_norm == x_start_norm)\r\n        return;\r\n    if (x_start_norm > x_end_norm)\r\n        ImSwap(x_start_norm, x_end_norm);\r\n\r\n    ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y);\r\n    ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y);\r\n    if (rounding == 0.0f)\r\n    {\r\n        draw_list->AddRectFilled(p0, p1, col, 0.0f);\r\n        return;\r\n    }\r\n\r\n    rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding);\r\n    const float inv_rounding = 1.0f / rounding;\r\n    const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding);\r\n    const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding);\r\n    const float x0 = ImMax(p0.x, rect.Min.x + rounding);\r\n    if (arc0_b == arc0_e)\r\n    {\r\n        draw_list->PathLineTo(ImVec2(x0, p1.y));\r\n        draw_list->PathLineTo(ImVec2(x0, p0.y));\r\n    }\r\n    else if (arc0_b == 0.0f && arc0_e == IM_PI*0.5f)\r\n    {\r\n        draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL\r\n        draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR\r\n    }\r\n    else\r\n    {\r\n        draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL\r\n        draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR\r\n    }\r\n    if (p1.x > rect.Min.x + rounding)\r\n    {\r\n        const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding);\r\n        const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding);\r\n        const float x1 = ImMin(p1.x, rect.Max.x - rounding);\r\n        if (arc1_b == arc1_e)\r\n        {\r\n            draw_list->PathLineTo(ImVec2(x1, p0.y));\r\n            draw_list->PathLineTo(ImVec2(x1, p1.y));\r\n        }\r\n        else if (arc1_b == 0.0f && arc1_e == IM_PI*0.5f)\r\n        {\r\n            draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR\r\n            draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3);  // BR\r\n        }\r\n        else\r\n        {\r\n            draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR\r\n            draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR\r\n        }\r\n    }\r\n    draw_list->PathFillConvex(col);\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// DEFAULT FONT DATA\r\n//-----------------------------------------------------------------------------\r\n// Compressed with stb_compress() then converted to a C array.\r\n// Use the program in extra_fonts/binary_to_compressed_c.cpp to create the array from a TTF file.\r\n// Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h\r\n//-----------------------------------------------------------------------------\r\n\r\nstatic unsigned int stb_decompress_length(unsigned char *input)\r\n{\r\n    return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];\r\n}\r\n\r\nstatic unsigned char *stb__barrier, *stb__barrier2, *stb__barrier3, *stb__barrier4;\r\nstatic unsigned char *stb__dout;\r\nstatic void stb__match(unsigned char *data, unsigned int length)\r\n{\r\n    // INVERSE of memmove... write each byte before copying the next...\r\n    IM_ASSERT (stb__dout + length <= stb__barrier);\r\n    if (stb__dout + length > stb__barrier) { stb__dout += length; return; }\r\n    if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; }\r\n    while (length--) *stb__dout++ = *data++;\r\n}\r\n\r\nstatic void stb__lit(unsigned char *data, unsigned int length)\r\n{\r\n    IM_ASSERT (stb__dout + length <= stb__barrier);\r\n    if (stb__dout + length > stb__barrier) { stb__dout += length; return; }\r\n    if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }\r\n    memcpy(stb__dout, data, length);\r\n    stb__dout += length;\r\n}\r\n\r\n#define stb__in2(x)   ((i[x] << 8) + i[(x)+1])\r\n#define stb__in3(x)   ((i[x] << 16) + stb__in2((x)+1))\r\n#define stb__in4(x)   ((i[x] << 24) + stb__in3((x)+1))\r\n\r\nstatic unsigned char *stb_decompress_token(unsigned char *i)\r\n{\r\n    if (*i >= 0x20) { // use fewer if's for cases that expand small\r\n        if (*i >= 0x80)       stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;\r\n        else if (*i >= 0x40)  stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;\r\n        else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);\r\n    } else { // more ifs for cases that expand large, since overhead is amortized\r\n        if (*i >= 0x18)       stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;\r\n        else if (*i >= 0x10)  stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;\r\n        else if (*i >= 0x08)  stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);\r\n        else if (*i == 0x07)  stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);\r\n        else if (*i == 0x06)  stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;\r\n        else if (*i == 0x04)  stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;\r\n    }\r\n    return i;\r\n}\r\n\r\nstatic unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)\r\n{\r\n    const unsigned long ADLER_MOD = 65521;\r\n    unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;\r\n    unsigned long blocklen, i;\r\n\r\n    blocklen = buflen % 5552;\r\n    while (buflen) {\r\n        for (i=0; i + 7 < blocklen; i += 8) {\r\n            s1 += buffer[0], s2 += s1;\r\n            s1 += buffer[1], s2 += s1;\r\n            s1 += buffer[2], s2 += s1;\r\n            s1 += buffer[3], s2 += s1;\r\n            s1 += buffer[4], s2 += s1;\r\n            s1 += buffer[5], s2 += s1;\r\n            s1 += buffer[6], s2 += s1;\r\n            s1 += buffer[7], s2 += s1;\r\n\r\n            buffer += 8;\r\n        }\r\n\r\n        for (; i < blocklen; ++i)\r\n            s1 += *buffer++, s2 += s1;\r\n\r\n        s1 %= ADLER_MOD, s2 %= ADLER_MOD;\r\n        buflen -= blocklen;\r\n        blocklen = 5552;\r\n    }\r\n    return (unsigned int)(s2 << 16) + (unsigned int)s1;\r\n}\r\n\r\nstatic unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length)\r\n{\r\n    unsigned int olen;\r\n    if (stb__in4(0) != 0x57bC0000) return 0;\r\n    if (stb__in4(4) != 0)          return 0; // error! stream is > 4GB\r\n    olen = stb_decompress_length(i);\r\n    stb__barrier2 = i;\r\n    stb__barrier3 = i+length;\r\n    stb__barrier = output + olen;\r\n    stb__barrier4 = output;\r\n    i += 16;\r\n\r\n    stb__dout = output;\r\n    for (;;) {\r\n        unsigned char *old_i = i;\r\n        i = stb_decompress_token(i);\r\n        if (i == old_i) {\r\n            if (*i == 0x05 && i[1] == 0xfa) {\r\n                IM_ASSERT(stb__dout == output + olen);\r\n                if (stb__dout != output + olen) return 0;\r\n                if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2))\r\n                    return 0;\r\n                return olen;\r\n            } else {\r\n                IM_ASSERT(0); /* NOTREACHED */\r\n                return 0;\r\n            }\r\n        }\r\n        IM_ASSERT(stb__dout <= output + olen);\r\n        if (stb__dout > output + olen)\r\n            return 0;\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------\r\n// ProggyClean.ttf\r\n// Copyright (c) 2004, 2005 Tristan Grimmer\r\n// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)\r\n// Download and more information at http://upperbounds.net\r\n//-----------------------------------------------------------------------------\r\n// File: 'ProggyClean.ttf' (41208 bytes)\r\n// Exported using binary_to_compressed_c.cpp\r\n//-----------------------------------------------------------------------------\r\nstatic const char proggy_clean_ttf_compressed_data_base85[11980+1] =\r\n    \"7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/\"\r\n    \"2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#\"\r\n    \"`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL\"\r\n    \"i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N\"\r\n    \"kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N\"\r\n    \"*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)\"\r\n    \"tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX\"\r\n    \"ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc.\"\r\n    \"x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G\"\r\n    \"CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)\"\r\n    \"U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#\"\r\n    \"'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM\"\r\n    \"_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu\"\r\n    \"Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/\"\r\n    \"/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L\"\r\n    \"%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#\"\r\n    \"OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)(\"\r\n    \"h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h\"\r\n    \"o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO\"\r\n    \"j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-\"\r\n    \"sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-\"\r\n    \"eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO\"\r\n    \"M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%\"\r\n    \"LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]\"\r\n    \"%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et\"\r\n    \"Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:\"\r\n    \"a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL(\"\r\n    \"$/V,;(kXZejWO`<[5?\\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<\"\r\n    \"nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?\"\r\n    \"7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;\"\r\n    \")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M\"\r\n    \"D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(\"\r\n    \"P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs\"\r\n    \"bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q\"\r\n    \"h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-\"\r\n    \"V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i\"\r\n    \"sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7\"\r\n    \".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@\"\r\n    \"$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*\"\r\n    \"hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u\"\r\n    \"@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#\"\r\n    \"w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#\"\r\n    \"u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0\"\r\n    \"d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8\"\r\n    \"6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#\"\r\n    \"b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD\"\r\n    \":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+\"\r\n    \"tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*\"\r\n    \"$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7\"\r\n    \":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A\"\r\n    \"7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7\"\r\n    \"u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT\"\r\n    \"LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M\"\r\n    \":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>\"\r\n    \"_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%\"\r\n    \"hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;\"\r\n    \"^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:\"\r\n    \"+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%\"\r\n    \"9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-\"\r\n    \"CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*\"\r\n    \"hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY\"\r\n    \"8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-\"\r\n    \"S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`\"\r\n    \"0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/\"\r\n    \"+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj\"\r\n    \"M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V\"\r\n    \"?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK\"\r\n    \"Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa\"\r\n    \">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>\"\r\n    \"[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I\"\r\n    \"wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#\"\r\n    \"Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$\"\r\n    \"MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)\"\r\n    \"i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo\"\r\n    \"1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P\"\r\n    \"iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO\"\r\n    \"URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#\"\r\n    \";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>\"\r\n    \"w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#\"\r\n    \"d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4\"\r\n    \"A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#\"\r\n    \"/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#\"\r\n    \"m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#\"\r\n    \"TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP\"\r\n    \"GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp\"\r\n    \"O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#\";\r\n\r\nstatic const char* GetDefaultCompressedFontDataTTFBase85()\r\n{\r\n    return proggy_clean_ttf_compressed_data_base85;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui_impl_dx11.cpp",
    "content": "// ImGui Win32 + DirectX11 binding\r\n// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.\r\n\r\n// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.\r\n// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().\r\n// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.\r\n// https://github.com/ocornut/imgui\r\n\r\n#include \"pch.h\"\r\n#include \"imgui.h\"\r\n#include \"imgui_impl_dx11.h\"\r\n\r\n// DirectX\r\n#include <d3d11.h>\r\n#include <d3dcompiler.h>\r\n#define DIRECTINPUT_VERSION 0x0800\r\n#include <dinput.h>\r\n\r\n// Data\r\nstatic INT64                    g_Time = 0;\r\nstatic INT64                    g_TicksPerSecond = 0;\r\n\r\nstatic HWND                     g_hWnd = 0;\r\nstatic ID3D11Device*            g_pd3dDevice = NULL;\r\nstatic ID3D11DeviceContext*     g_pd3dDeviceContext = NULL;\r\nstatic ID3D11Buffer*            g_pVB = NULL;\r\nstatic ID3D11Buffer*            g_pIB = NULL;\r\nstatic ID3D10Blob *             g_pVertexShaderBlob = NULL;\r\nstatic ID3D11VertexShader*      g_pVertexShader = NULL;\r\nstatic ID3D11InputLayout*       g_pInputLayout = NULL;\r\nstatic ID3D11Buffer*            g_pVertexConstantBuffer = NULL;\r\nstatic ID3D10Blob *             g_pPixelShaderBlob = NULL;\r\nstatic ID3D11PixelShader*       g_pPixelShader = NULL;\r\nstatic ID3D11SamplerState*      g_pFontSampler = NULL;\r\nstatic ID3D11ShaderResourceView*g_pFontTextureView = NULL;\r\nstatic ID3D11RasterizerState*   g_pRasterizerState = NULL;\r\nstatic ID3D11BlendState*        g_pBlendState = NULL;\r\nstatic ID3D11DepthStencilState* g_pDepthStencilState = NULL;\r\nstatic int                      g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;\r\n\r\nstruct VERTEX_CONSTANT_BUFFER\r\n{\r\n    float        mvp[4][4];\r\n};\r\n\r\n// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)\r\n// If text or lines are blurry when integrating ImGui in your engine:\r\n// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)\r\nvoid ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)\r\n{\r\n    ID3D11DeviceContext* ctx = g_pd3dDeviceContext;\r\n\r\n    // Create and grow vertex/index buffers if needed\r\n    if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)\r\n    {\r\n        if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }\r\n        g_VertexBufferSize = draw_data->TotalVtxCount + 5000;\r\n        D3D11_BUFFER_DESC desc;\r\n        memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));\r\n        desc.Usage = D3D11_USAGE_DYNAMIC;\r\n        desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);\r\n        desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;\r\n        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;\r\n        desc.MiscFlags = 0;\r\n        if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)\r\n            return;\r\n    }\r\n    if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)\r\n    {\r\n        if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }\r\n        g_IndexBufferSize = draw_data->TotalIdxCount + 10000;\r\n        D3D11_BUFFER_DESC desc;\r\n        memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));\r\n        desc.Usage = D3D11_USAGE_DYNAMIC;\r\n        desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);\r\n        desc.BindFlags = D3D11_BIND_INDEX_BUFFER;\r\n        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;\r\n        if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)\r\n            return;\r\n    }\r\n\r\n    // Copy and convert all vertices into a single contiguous buffer\r\n    D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;\r\n    if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)\r\n        return;\r\n    if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)\r\n        return;\r\n    ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;\r\n    ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;\r\n    for (int n = 0; n < draw_data->CmdListsCount; n++)\r\n    {\r\n        const ImDrawList* cmd_list = draw_data->CmdLists[n];\r\n        memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));\r\n        memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));\r\n        vtx_dst += cmd_list->VtxBuffer.Size;\r\n        idx_dst += cmd_list->IdxBuffer.Size;\r\n    }\r\n    ctx->Unmap(g_pVB, 0);\r\n    ctx->Unmap(g_pIB, 0);\r\n\r\n    // Setup orthographic projection matrix into our constant buffer\r\n    {\r\n        D3D11_MAPPED_SUBRESOURCE mapped_resource;\r\n        if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)\r\n            return;\r\n        VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;\r\n        float L = 0.0f;\r\n        float R = ImGui::GetIO().DisplaySize.x;\r\n        float B = ImGui::GetIO().DisplaySize.y;\r\n        float T = 0.0f;\r\n        float mvp[4][4] =\r\n        {\r\n            { 2.0f/(R-L),   0.0f,           0.0f,       0.0f },\r\n            { 0.0f,         2.0f/(T-B),     0.0f,       0.0f },\r\n            { 0.0f,         0.0f,           0.5f,       0.0f },\r\n            { (R+L)/(L-R),  (T+B)/(B-T),    0.5f,       1.0f },\r\n        };\r\n        memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));\r\n        ctx->Unmap(g_pVertexConstantBuffer, 0);\r\n    }\r\n\r\n    // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)\r\n    struct BACKUP_DX11_STATE\r\n    {\r\n        UINT                        ScissorRectsCount, ViewportsCount;\r\n        D3D11_RECT                  ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];\r\n        D3D11_VIEWPORT              Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];\r\n        ID3D11RasterizerState*      RS;\r\n        ID3D11BlendState*           BlendState;\r\n        FLOAT                       BlendFactor[4];\r\n        UINT                        SampleMask;\r\n        UINT                        StencilRef;\r\n        ID3D11DepthStencilState*    DepthStencilState;\r\n        ID3D11ShaderResourceView*   PSShaderResource;\r\n        ID3D11SamplerState*         PSSampler;\r\n        ID3D11PixelShader*          PS;\r\n        ID3D11VertexShader*         VS;\r\n        UINT                        PSInstancesCount, VSInstancesCount;\r\n        ID3D11ClassInstance*        PSInstances[256], *VSInstances[256];   // 256 is max according to PSSetShader documentation\r\n        D3D11_PRIMITIVE_TOPOLOGY    PrimitiveTopology;\r\n        ID3D11Buffer*               IndexBuffer, *VertexBuffer, *VSConstantBuffer;\r\n        UINT                        IndexBufferOffset, VertexBufferStride, VertexBufferOffset;\r\n        DXGI_FORMAT                 IndexBufferFormat;\r\n        ID3D11InputLayout*          InputLayout;\r\n    };\r\n    BACKUP_DX11_STATE old;\r\n    old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;\r\n    ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);\r\n    ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);\r\n    ctx->RSGetState(&old.RS);\r\n    ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);\r\n    ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);\r\n    ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);\r\n    ctx->PSGetSamplers(0, 1, &old.PSSampler);\r\n    old.PSInstancesCount = old.VSInstancesCount = 256;\r\n    ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);\r\n    ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);\r\n    ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);\r\n    ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);\r\n    ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);\r\n    ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);\r\n    ctx->IAGetInputLayout(&old.InputLayout);\r\n\r\n    // Setup viewport\r\n    D3D11_VIEWPORT vp;\r\n    memset(&vp, 0, sizeof(D3D11_VIEWPORT));\r\n    vp.Width = ImGui::GetIO().DisplaySize.x;\r\n    vp.Height = ImGui::GetIO().DisplaySize.y;\r\n    vp.MinDepth = 0.0f;\r\n    vp.MaxDepth = 1.0f;\r\n    vp.TopLeftX = vp.TopLeftY = 0.0f;\r\n    ctx->RSSetViewports(1, &vp);\r\n\r\n    // Bind shader and vertex buffers\r\n    unsigned int stride = sizeof(ImDrawVert);\r\n    unsigned int offset = 0;\r\n    ctx->IASetInputLayout(g_pInputLayout);\r\n    ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);\r\n    ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);\r\n    ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\r\n    ctx->VSSetShader(g_pVertexShader, NULL, 0);\r\n    ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);\r\n    ctx->PSSetShader(g_pPixelShader, NULL, 0);\r\n    ctx->PSSetSamplers(0, 1, &g_pFontSampler);\r\n\r\n    // Setup render state\r\n    const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };\r\n    ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);\r\n    ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);\r\n    ctx->RSSetState(g_pRasterizerState);\r\n\r\n    // Render command lists\r\n    int vtx_offset = 0;\r\n    int idx_offset = 0;\r\n    for (int n = 0; n < draw_data->CmdListsCount; n++)\r\n    {\r\n        const ImDrawList* cmd_list = draw_data->CmdLists[n];\r\n        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)\r\n        {\r\n            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];\r\n            if (pcmd->UserCallback)\r\n            {\r\n                pcmd->UserCallback(cmd_list, pcmd);\r\n            }\r\n            else\r\n            {\r\n                const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };\r\n                ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);\r\n                ctx->RSSetScissorRects(1, &r);\r\n                ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);\r\n            }\r\n            idx_offset += pcmd->ElemCount;\r\n        }\r\n        vtx_offset += cmd_list->VtxBuffer.Size;\r\n    }\r\n\r\n    // Restore modified DX state\r\n    ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);\r\n    ctx->RSSetViewports(old.ViewportsCount, old.Viewports);\r\n    ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();\r\n    ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();\r\n    ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();\r\n    ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();\r\n    ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();\r\n    ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();\r\n    for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();\r\n    ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();\r\n    ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();\r\n    for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();\r\n    ctx->IASetPrimitiveTopology(old.PrimitiveTopology);\r\n    ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();\r\n    ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();\r\n    ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();\r\n}\r\n\r\nIMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)\r\n{\r\n    ImGuiIO& io = ImGui::GetIO();\r\n    switch (msg)\r\n    {\r\n    case WM_LBUTTONDOWN:\r\n        io.MouseDown[0] = true;\r\n        return true;\r\n    case WM_LBUTTONUP:\r\n        io.MouseDown[0] = false;\r\n        return true;\r\n    case WM_RBUTTONDOWN:\r\n        io.MouseDown[1] = true;\r\n        return true;\r\n    case WM_RBUTTONUP:\r\n        io.MouseDown[1] = false;\r\n        return true;\r\n    case WM_MBUTTONDOWN:\r\n        io.MouseDown[2] = true;\r\n        return true;\r\n    case WM_MBUTTONUP:\r\n        io.MouseDown[2] = false;\r\n        return true;\r\n    case WM_MOUSEWHEEL:\r\n        io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;\r\n        return true;\r\n    case WM_MOUSEMOVE:\r\n        io.MousePos.x = (signed short)(lParam);\r\n        io.MousePos.y = (signed short)(lParam >> 16);\r\n        return true;\r\n    case WM_KEYDOWN:\r\n        if (wParam < 256)\r\n            io.KeysDown[wParam] = 1;\r\n        return true;\r\n    case WM_KEYUP:\r\n        if (wParam < 256)\r\n            io.KeysDown[wParam] = 0;\r\n        return true;\r\n    case WM_CHAR:\r\n        // You can also use ToAscii()+GetKeyboardState() to retrieve characters.\r\n        if (wParam > 0 && wParam < 0x10000)\r\n            io.AddInputCharacter((unsigned short)wParam);\r\n        return true;\r\n    }\r\n    return 0;\r\n}\r\n\r\nstatic void ImGui_ImplDX11_CreateFontsTexture()\r\n{\r\n    // Build texture atlas\r\n    ImGuiIO& io = ImGui::GetIO();\r\n    unsigned char* pixels;\r\n    int width, height;\r\n    io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);\r\n\r\n    // Upload texture to graphics system\r\n    {\r\n        D3D11_TEXTURE2D_DESC desc;\r\n        ZeroMemory(&desc, sizeof(desc));\r\n        desc.Width = width;\r\n        desc.Height = height;\r\n        desc.MipLevels = 1;\r\n        desc.ArraySize = 1;\r\n        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;\r\n        desc.SampleDesc.Count = 1;\r\n        desc.Usage = D3D11_USAGE_DEFAULT;\r\n        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;\r\n        desc.CPUAccessFlags = 0;\r\n\r\n        ID3D11Texture2D *pTexture = NULL;\r\n        D3D11_SUBRESOURCE_DATA subResource;\r\n        subResource.pSysMem = pixels;\r\n        subResource.SysMemPitch = desc.Width * 4;\r\n        subResource.SysMemSlicePitch = 0;\r\n        g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);\r\n\r\n        // Create texture view\r\n        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;\r\n        ZeroMemory(&srvDesc, sizeof(srvDesc));\r\n        srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;\r\n        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;\r\n        srvDesc.Texture2D.MipLevels = desc.MipLevels;\r\n        srvDesc.Texture2D.MostDetailedMip = 0;\r\n        g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);\r\n        pTexture->Release();\r\n    }\r\n\r\n    // Store our identifier\r\n    io.Fonts->TexID = (void *)g_pFontTextureView;\r\n\r\n    // Create texture sampler\r\n    {\r\n        D3D11_SAMPLER_DESC desc;\r\n        ZeroMemory(&desc, sizeof(desc));\r\n        desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;\r\n        desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;\r\n        desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;\r\n        desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;\r\n        desc.MipLODBias = 0.f;\r\n        desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;\r\n        desc.MinLOD = 0.f;\r\n        desc.MaxLOD = 0.f;\r\n        g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);\r\n    }\r\n}\r\n\r\nbool    ImGui_ImplDX11_CreateDeviceObjects()\r\n{\r\n    if (!g_pd3dDevice)\r\n        return false;\r\n    if (g_pFontSampler)\r\n        ImGui_ImplDX11_InvalidateDeviceObjects();\r\n\r\n    // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)\r\n    // If you would like to use this DX11 sample code but remove this dependency you can: \r\n    //  1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]\r\n    //  2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. \r\n    // See https://github.com/ocornut/imgui/pull/638 for sources and details.\r\n\r\n    // Create the vertex shader\r\n    {\r\n        static const char* vertexShader =\r\n            \"cbuffer vertexBuffer : register(b0) \\\r\n            {\\\r\n            float4x4 ProjectionMatrix; \\\r\n            };\\\r\n            struct VS_INPUT\\\r\n            {\\\r\n            float2 pos : POSITION;\\\r\n            float4 col : COLOR0;\\\r\n            float2 uv  : TEXCOORD0;\\\r\n            };\\\r\n            \\\r\n            struct PS_INPUT\\\r\n            {\\\r\n            float4 pos : SV_POSITION;\\\r\n            float4 col : COLOR0;\\\r\n            float2 uv  : TEXCOORD0;\\\r\n            };\\\r\n            \\\r\n            PS_INPUT main(VS_INPUT input)\\\r\n            {\\\r\n            PS_INPUT output;\\\r\n            output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\\\r\n            output.col = input.col;\\\r\n            output.uv  = input.uv;\\\r\n            return output;\\\r\n            }\";\r\n\r\n        D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, \"main\", \"vs_4_0\", 0, 0, &g_pVertexShaderBlob, NULL);\r\n        if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!\r\n            return false;\r\n        if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)\r\n            return false;\r\n\r\n        // Create the input layout\r\n        D3D11_INPUT_ELEMENT_DESC local_layout[] = {\r\n            { \"POSITION\", 0, DXGI_FORMAT_R32G32_FLOAT,   0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },\r\n            { \"TEXCOORD\", 0, DXGI_FORMAT_R32G32_FLOAT,   0, (size_t)(&((ImDrawVert*)0)->uv),  D3D11_INPUT_PER_VERTEX_DATA, 0 },\r\n            { \"COLOR\",    0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },\r\n        };\r\n        if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)\r\n            return false;\r\n\r\n        // Create the constant buffer\r\n        {\r\n            D3D11_BUFFER_DESC desc;\r\n            desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);\r\n            desc.Usage = D3D11_USAGE_DYNAMIC;\r\n            desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;\r\n            desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;\r\n            desc.MiscFlags = 0;\r\n            g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);\r\n        }\r\n    }\r\n\r\n    // Create the pixel shader\r\n    {\r\n        static const char* pixelShader =\r\n            \"struct PS_INPUT\\\r\n            {\\\r\n            float4 pos : SV_POSITION;\\\r\n            float4 col : COLOR0;\\\r\n            float2 uv  : TEXCOORD0;\\\r\n            };\\\r\n            sampler sampler0;\\\r\n            Texture2D texture0;\\\r\n            \\\r\n            float4 main(PS_INPUT input) : SV_Target\\\r\n            {\\\r\n            float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \\\r\n            return out_col; \\\r\n            }\";\r\n\r\n        D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, \"main\", \"ps_4_0\", 0, 0, &g_pPixelShaderBlob, NULL);\r\n        if (g_pPixelShaderBlob == NULL)  // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!\r\n            return false;\r\n        if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)\r\n            return false;\r\n    }\r\n\r\n    // Create the blending setup\r\n    {\r\n        D3D11_BLEND_DESC desc;\r\n        ZeroMemory(&desc, sizeof(desc));\r\n        desc.AlphaToCoverageEnable = false;\r\n        desc.RenderTarget[0].BlendEnable = true;\r\n        desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;\r\n        desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;\r\n        desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;\r\n        desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;\r\n        desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;\r\n        desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;\r\n        desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;\r\n        g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);\r\n    }\r\n\r\n    // Create the rasterizer state\r\n    {\r\n        D3D11_RASTERIZER_DESC desc;\r\n        ZeroMemory(&desc, sizeof(desc));\r\n        desc.FillMode = D3D11_FILL_SOLID;\r\n        desc.CullMode = D3D11_CULL_NONE;\r\n        desc.ScissorEnable = true;\r\n        desc.DepthClipEnable = true;\r\n        g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);\r\n    }\r\n\r\n    // Create depth-stencil State\r\n    {\r\n        D3D11_DEPTH_STENCIL_DESC desc;\r\n        ZeroMemory(&desc, sizeof(desc));\r\n        desc.DepthEnable = false;\r\n        desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;\r\n        desc.DepthFunc = D3D11_COMPARISON_ALWAYS;\r\n        desc.StencilEnable = false;\r\n        desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;\r\n        desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;\r\n        desc.BackFace = desc.FrontFace;\r\n        g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);\r\n    }\r\n\r\n    ImGui_ImplDX11_CreateFontsTexture();\r\n\r\n    return true;\r\n}\r\n\r\nvoid    ImGui_ImplDX11_InvalidateDeviceObjects()\r\n{\r\n    if (!g_pd3dDevice)\r\n        return;\r\n\r\n    if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }\r\n    if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.\r\n    if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }\r\n    if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }\r\n\r\n    if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }\r\n    if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }\r\n    if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }\r\n    if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }\r\n    if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }\r\n    if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }\r\n    if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }\r\n    if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }\r\n    if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }\r\n}\r\n\r\nbool    ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context)\r\n{\r\n    g_hWnd = (HWND)hwnd;\r\n    g_pd3dDevice = device;\r\n    g_pd3dDeviceContext = device_context;\r\n\r\n    if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))\r\n        return false;\r\n    if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))\r\n        return false;\r\n\r\n    ImGuiIO& io = ImGui::GetIO();\r\n    io.KeyMap[ImGuiKey_Tab] = VK_TAB;                       // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.\r\n    io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;\r\n    io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;\r\n    io.KeyMap[ImGuiKey_UpArrow] = VK_UP;\r\n    io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;\r\n    io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;\r\n    io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;\r\n    io.KeyMap[ImGuiKey_Home] = VK_HOME;\r\n    io.KeyMap[ImGuiKey_End] = VK_END;\r\n    io.KeyMap[ImGuiKey_Delete] = VK_DELETE;\r\n    io.KeyMap[ImGuiKey_Backspace] = VK_BACK;\r\n    io.KeyMap[ImGuiKey_Enter] = VK_RETURN;\r\n    io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;\r\n    io.KeyMap[ImGuiKey_A] = 'A';\r\n    io.KeyMap[ImGuiKey_C] = 'C';\r\n    io.KeyMap[ImGuiKey_V] = 'V';\r\n    io.KeyMap[ImGuiKey_X] = 'X';\r\n    io.KeyMap[ImGuiKey_Y] = 'Y';\r\n    io.KeyMap[ImGuiKey_Z] = 'Z';\r\n\r\n    io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists;  // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.\r\n    io.ImeWindowHandle = g_hWnd;\r\n\r\n    return true;\r\n}\r\n\r\nvoid ImGui_ImplDX11_Shutdown()\r\n{\r\n    ImGui_ImplDX11_InvalidateDeviceObjects();\r\n    ImGui::Shutdown();\r\n    g_pd3dDevice = NULL;\r\n    g_pd3dDeviceContext = NULL;\r\n    g_hWnd = (HWND)0;\r\n}\r\n\r\nvoid ImGui_ImplDX11_NewFrame()\r\n{\r\n    if (!g_pFontSampler)\r\n        ImGui_ImplDX11_CreateDeviceObjects();\r\n\r\n    ImGuiIO& io = ImGui::GetIO();\r\n\r\n    // Setup display size (every frame to accommodate for window resizing)\r\n    RECT rect;\r\n    GetClientRect(g_hWnd, &rect);\r\n    io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));\r\n\r\n    // Setup time step\r\n    INT64 current_time;\r\n    QueryPerformanceCounter((LARGE_INTEGER *)&current_time);\r\n    io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;\r\n    g_Time = current_time;\r\n\r\n    // Read keyboard modifiers inputs\r\n    io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;\r\n    io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;\r\n    io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;\r\n    io.KeySuper = false;\r\n\tio.MouseDrawCursor = true;\r\n    // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events\r\n    // io.MousePos : filled by WM_MOUSEMOVE events\r\n    // io.MouseDown : filled by WM_*BUTTON* events\r\n    // io.MouseWheel : filled by WM_MOUSEWHEEL events\r\n\r\n    // Hide OS mouse cursor if ImGui is drawing it\r\n    if (io.MouseDrawCursor)\r\n        SetCursor(NULL);\r\n\r\n    // Start the frame\r\n    ImGui::NewFrame();\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui_impl_dx11.h",
    "content": "// ImGui Win32 + DirectX11 binding\r\n// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.\r\n\r\n// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.\r\n// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().\r\n// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.\r\n// https://github.com/ocornut/imgui\r\n\r\nstruct ID3D11Device;\r\nstruct ID3D11DeviceContext;\r\n\r\nIMGUI_API bool        ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context);\r\nIMGUI_API void        ImGui_ImplDX11_Shutdown();\r\nIMGUI_API void        ImGui_ImplDX11_NewFrame();\r\n\r\n// Use if you want to reset your rendering device without losing ImGui state.\r\nIMGUI_API void        ImGui_ImplDX11_InvalidateDeviceObjects();\r\nIMGUI_API bool        ImGui_ImplDX11_CreateDeviceObjects();\r\n\r\n// Handler for Win32 messages, update mouse/keyboard data.\r\n// You may or not need this for your implementation, but it can serve as reference for handling inputs.\r\n// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.\r\nIMGUI_API LRESULT   ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/imgui_internal.h",
    "content": "// dear imgui, v1.52 WIP\r\n// (internals)\r\n\r\n// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!\r\n// Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)\r\n//   #define IMGUI_DEFINE_MATH_OPERATORS\r\n// Define IM_PLACEMENT_NEW() macro helper.\r\n//   #define IMGUI_DEFINE_PLACEMENT_NEW\r\n\r\n#pragma once\r\n\r\n#ifndef IMGUI_VERSION\r\n#error Must include imgui.h before imgui_internal.h\r\n#endif\r\n\r\n#include <stdio.h>      // FILE*\r\n#include <math.h>       // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (push)\r\n#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)\r\n#endif\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic push\r\n#pragma clang diagnostic ignored \"-Wunused-function\"        // for stb_textedit.h\r\n#pragma clang diagnostic ignored \"-Wmissing-prototypes\"     // for stb_textedit.h\r\n#pragma clang diagnostic ignored \"-Wold-style-cast\"\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Forward Declarations\r\n//-----------------------------------------------------------------------------\r\n\r\nstruct ImRect;\r\nstruct ImGuiColMod;\r\nstruct ImGuiStyleMod;\r\nstruct ImGuiGroupData;\r\nstruct ImGuiSimpleColumns;\r\nstruct ImGuiDrawContext;\r\nstruct ImGuiTextEditState;\r\nstruct ImGuiIniData;\r\nstruct ImGuiMouseCursorData;\r\nstruct ImGuiPopupRef;\r\nstruct ImGuiWindow;\r\n\r\ntypedef int ImGuiLayoutType;      // enum ImGuiLayoutType_\r\ntypedef int ImGuiButtonFlags;     // enum ImGuiButtonFlags_\r\ntypedef int ImGuiTreeNodeFlags;   // enum ImGuiTreeNodeFlags_\r\ntypedef int ImGuiSliderFlags;     // enum ImGuiSliderFlags_\r\ntypedef int ImGuiItemFlags;       // enum ImGuiItemFlags_\r\n\r\n//-------------------------------------------------------------------------\r\n// STB libraries\r\n//-------------------------------------------------------------------------\r\n\r\nnamespace ImGuiStb\r\n{\r\n\r\n#undef STB_TEXTEDIT_STRING\r\n#undef STB_TEXTEDIT_CHARTYPE\r\n#define STB_TEXTEDIT_STRING             ImGuiTextEditState\r\n#define STB_TEXTEDIT_CHARTYPE           ImWchar\r\n#define STB_TEXTEDIT_GETWIDTH_NEWLINE   -1.0f\r\n#include \"stb_textedit.h\"\r\n\r\n} // namespace ImGuiStb\r\n\r\n//-----------------------------------------------------------------------------\r\n// Context\r\n//-----------------------------------------------------------------------------\r\n\r\n#ifndef GImGui\r\nextern IMGUI_API ImGuiContext* GImGui;  // Current implicit ImGui context pointer\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Helpers\r\n//-----------------------------------------------------------------------------\r\n\r\n#define IM_ARRAYSIZE(_ARR)      ((int)(sizeof(_ARR)/sizeof(*_ARR)))\r\n#define IM_PI                   3.14159265358979323846f\r\n#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM))\r\n\r\n// Helpers: UTF-8 <> wchar\r\nIMGUI_API int           ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end);      // return output UTF-8 bytes count\r\nIMGUI_API int           ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end);          // return input UTF-8 bytes count\r\nIMGUI_API int           ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL);   // return input UTF-8 bytes count\r\nIMGUI_API int           ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end);                            // return number of UTF-8 code-points (NOT bytes count)\r\nIMGUI_API int           ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end);                   // return number of bytes to express string as UTF-8 code-points\r\n\r\n// Helpers: Misc\r\nIMGUI_API ImU32         ImHash(const void* data, int data_size, ImU32 seed = 0);    // Pass data_size==0 for zero-terminated strings\r\nIMGUI_API void*         ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0);\r\nIMGUI_API FILE*         ImFileOpen(const char* filename, const char* file_open_mode);\r\nstatic inline bool      ImCharIsSpace(int c)            { return c == ' ' || c == '\\t' || c == 0x3000; }\r\nstatic inline bool      ImIsPowerOfTwo(int v)           { return v != 0 && (v & (v - 1)) == 0; }\r\nstatic inline int       ImUpperPowerOfTwo(int v)        { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }\r\n\r\n// Helpers: Geometry\r\nIMGUI_API ImVec2        ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);\r\nIMGUI_API bool          ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);\r\nIMGUI_API ImVec2        ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);\r\nIMGUI_API void          ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);\r\n\r\n// Helpers: String\r\nIMGUI_API int           ImStricmp(const char* str1, const char* str2);\r\nIMGUI_API int           ImStrnicmp(const char* str1, const char* str2, int count);\r\nIMGUI_API char*         ImStrdup(const char* str);\r\nIMGUI_API int           ImStrlenW(const ImWchar* str);\r\nIMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line\r\nIMGUI_API const char*   ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);\r\nIMGUI_API int           ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_FMTARGS(3);\r\nIMGUI_API int           ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) IM_FMTLIST(3);\r\n\r\n// Helpers: Math\r\n// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined)\r\n#ifdef IMGUI_DEFINE_MATH_OPERATORS\r\nstatic inline ImVec2 operator*(const ImVec2& lhs, const float rhs)              { return ImVec2(lhs.x*rhs, lhs.y*rhs); }\r\nstatic inline ImVec2 operator/(const ImVec2& lhs, const float rhs)              { return ImVec2(lhs.x/rhs, lhs.y/rhs); }\r\nstatic inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs)            { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }\r\nstatic inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs)            { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }\r\nstatic inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs)            { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }\r\nstatic inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs)            { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }\r\nstatic inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs)                { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }\r\nstatic inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs)                { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }\r\nstatic inline ImVec2& operator*=(ImVec2& lhs, const float rhs)                  { lhs.x *= rhs; lhs.y *= rhs; return lhs; }\r\nstatic inline ImVec2& operator/=(ImVec2& lhs, const float rhs)                  { lhs.x /= rhs; lhs.y /= rhs; return lhs; }\r\nstatic inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs)            { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); }\r\n#endif\r\n\r\nstatic inline int    ImMin(int lhs, int rhs)                                    { return lhs < rhs ? lhs : rhs; }\r\nstatic inline int    ImMax(int lhs, int rhs)                                    { return lhs >= rhs ? lhs : rhs; }\r\nstatic inline float  ImMin(float lhs, float rhs)                                { return lhs < rhs ? lhs : rhs; }\r\nstatic inline float  ImMax(float lhs, float rhs)                                { return lhs >= rhs ? lhs : rhs; }\r\nstatic inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs)                { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); }\r\nstatic inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs)                { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); }\r\nstatic inline int    ImClamp(int v, int mn, int mx)                             { return (v < mn) ? mn : (v > mx) ? mx : v; }\r\nstatic inline float  ImClamp(float v, float mn, float mx)                       { return (v < mn) ? mn : (v > mx) ? mx : v; }\r\nstatic inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx)      { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); }\r\nstatic inline float  ImSaturate(float f)                                        { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }\r\nstatic inline void   ImSwap(float& a, float& b)                                 { float tmp = a; a = b; b = tmp; }\r\nstatic inline int    ImLerp(int a, int b, float t)                              { return (int)(a + (b - a) * t); }\r\nstatic inline float  ImLerp(float a, float b, float t)                          { return a + (b - a) * t; }\r\nstatic inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t)          { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); }\r\nstatic inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t)  { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }\r\nstatic inline float  ImLengthSqr(const ImVec2& lhs)                             { return lhs.x*lhs.x + lhs.y*lhs.y; }\r\nstatic inline float  ImLengthSqr(const ImVec4& lhs)                             { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }\r\nstatic inline float  ImInvLength(const ImVec2& lhs, float fail_value)           { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }\r\nstatic inline float  ImFloor(float f)                                           { return (float)(int)f; }\r\nstatic inline ImVec2 ImFloor(const ImVec2& v)                                   { return ImVec2((float)(int)v.x, (float)(int)v.y); }\r\nstatic inline float  ImDot(const ImVec2& a, const ImVec2& b)                    { return a.x * b.x + a.y * b.y; }\r\nstatic inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a)        { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }\r\n\r\n// We call C++ constructor on own allocated memory via the placement \"new(ptr) Type()\" syntax.\r\n// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.\r\n#ifdef IMGUI_DEFINE_PLACEMENT_NEW\r\nstruct ImPlacementNewDummy {};\r\ninline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; }\r\ninline void operator delete(void*, ImPlacementNewDummy, void*) {}\r\n#define IM_PLACEMENT_NEW(_PTR)  new(ImPlacementNewDummy(), _PTR)\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------\r\n// Types\r\n//-----------------------------------------------------------------------------\r\n\r\nenum ImGuiButtonFlags_\r\n{\r\n    ImGuiButtonFlags_Repeat                 = 1 << 0,   // hold to repeat\r\n    ImGuiButtonFlags_PressedOnClickRelease  = 1 << 1,   // (default) return pressed on click+release on same item (default if no PressedOn** flag is set)\r\n    ImGuiButtonFlags_PressedOnClick         = 1 << 2,   // return pressed on click (default requires click+release)\r\n    ImGuiButtonFlags_PressedOnRelease       = 1 << 3,   // return pressed on release (default requires click+release)\r\n    ImGuiButtonFlags_PressedOnDoubleClick   = 1 << 4,   // return pressed on double-click (default requires click+release)\r\n    ImGuiButtonFlags_FlattenChilds          = 1 << 5,   // allow interaction even if a child window is overlapping\r\n    ImGuiButtonFlags_DontClosePopups        = 1 << 6,   // disable automatically closing parent popup on press\r\n    ImGuiButtonFlags_Disabled               = 1 << 7,   // disable interaction\r\n    ImGuiButtonFlags_AlignTextBaseLine      = 1 << 8,   // vertically align button to match text baseline - ButtonEx() only\r\n    ImGuiButtonFlags_NoKeyModifiers         = 1 << 9,   // disable interaction if a key modifier is held\r\n    ImGuiButtonFlags_AllowOverlapMode       = 1 << 10   // require previous frame HoveredId to either match id or be null before being usable\r\n};\r\n\r\nenum ImGuiSliderFlags_\r\n{\r\n    ImGuiSliderFlags_Vertical               = 1 << 0\r\n};\r\n\r\nenum ImGuiColumnsFlags_\r\n{\r\n    // Default: 0\r\n    ImGuiColumnsFlags_NoBorder              = 1 << 0,   // Disable column dividers\r\n    ImGuiColumnsFlags_NoResize              = 1 << 1,   // Disable resizing columns when clicking on the dividers\r\n    ImGuiColumnsFlags_NoPreserveWidths      = 1 << 2,   // Disable column width preservation when adjusting columns\r\n    ImGuiColumnsFlags_NoForceWithinWindow   = 1 << 3    // Disable forcing columns to fit within window\r\n};\r\n\r\nenum ImGuiSelectableFlagsPrivate_\r\n{\r\n    // NB: need to be in sync with last value of ImGuiSelectableFlags_\r\n    ImGuiSelectableFlags_Menu               = 1 << 3,\r\n    ImGuiSelectableFlags_MenuItem           = 1 << 4,\r\n    ImGuiSelectableFlags_Disabled           = 1 << 5,\r\n    ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6\r\n};\r\n\r\n// FIXME: this is in development, not exposed/functional as a generic feature yet.\r\nenum ImGuiLayoutType_\r\n{\r\n    ImGuiLayoutType_Vertical,\r\n    ImGuiLayoutType_Horizontal\r\n};\r\n\r\nenum ImGuiPlotType\r\n{\r\n    ImGuiPlotType_Lines,\r\n    ImGuiPlotType_Histogram\r\n};\r\n\r\nenum ImGuiDataType\r\n{\r\n    ImGuiDataType_Int,\r\n    ImGuiDataType_Float,\r\n    ImGuiDataType_Float2,\r\n};\r\n\r\nenum ImGuiDir\r\n{\r\n    ImGuiDir_None    = -1,\r\n    ImGuiDir_Left    = 0,\r\n    ImGuiDir_Right   = 1,\r\n    ImGuiDir_Up      = 2,\r\n    ImGuiDir_Down    = 3,\r\n};\r\n\r\nenum ImGuiCorner\r\n{\r\n    ImGuiCorner_TopLeft     = 1 << 0, // 1\r\n    ImGuiCorner_TopRight    = 1 << 1, // 2\r\n    ImGuiCorner_BotRight    = 1 << 2, // 4\r\n    ImGuiCorner_BotLeft     = 1 << 3, // 8\r\n    ImGuiCorner_All         = 0x0F\r\n};\r\n\r\n// 2D axis aligned bounding-box\r\n// NB: we can't rely on ImVec2 math operators being available here\r\nstruct IMGUI_API ImRect\r\n{\r\n    ImVec2      Min;    // Upper-left\r\n    ImVec2      Max;    // Lower-right\r\n\r\n    ImRect()                                        : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX)  {}\r\n    ImRect(const ImVec2& min, const ImVec2& max)    : Min(min), Max(max)                            {}\r\n    ImRect(const ImVec4& v)                         : Min(v.x, v.y), Max(v.z, v.w)                  {}\r\n    ImRect(float x1, float y1, float x2, float y2)  : Min(x1, y1), Max(x2, y2)                      {}\r\n\r\n    ImVec2      GetCenter() const               { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }\r\n    ImVec2      GetSize() const                 { return ImVec2(Max.x-Min.x, Max.y-Min.y); }\r\n    float       GetWidth() const                { return Max.x-Min.x; }\r\n    float       GetHeight() const               { return Max.y-Min.y; }\r\n    ImVec2      GetTL() const                   { return Min; }                   // Top-left\r\n    ImVec2      GetTR() const                   { return ImVec2(Max.x, Min.y); }  // Top-right\r\n    ImVec2      GetBL() const                   { return ImVec2(Min.x, Max.y); }  // Bottom-left\r\n    ImVec2      GetBR() const                   { return Max; }                   // Bottom-right\r\n    bool        Contains(const ImVec2& p) const { return p.x >= Min.x     && p.y >= Min.y     && p.x < Max.x     && p.y < Max.y; }\r\n    bool        Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }\r\n    bool        Overlaps(const ImRect& r) const { return r.Min.y < Max.y  && r.Max.y > Min.y  && r.Min.x < Max.x && r.Max.x > Min.x; }\r\n    void        Add(const ImVec2& rhs)          { if (Min.x > rhs.x)     Min.x = rhs.x;     if (Min.y > rhs.y) Min.y = rhs.y;         if (Max.x < rhs.x) Max.x = rhs.x;         if (Max.y < rhs.y) Max.y = rhs.y; }\r\n    void        Add(const ImRect& rhs)          { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }\r\n    void        Expand(const float amount)      { Min.x -= amount;   Min.y -= amount;   Max.x += amount;   Max.y += amount; }\r\n    void        Expand(const ImVec2& amount)    { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }\r\n    void        Translate(const ImVec2& v)      { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; }\r\n    void        ClipWith(const ImRect& clip)    { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }\r\n    void        Floor()                         { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }\r\n    ImVec2      GetClosestPoint(ImVec2 p, bool on_edge) const\r\n    {\r\n        if (!on_edge && Contains(p))\r\n            return p;\r\n        if (p.x > Max.x) p.x = Max.x;\r\n        else if (p.x < Min.x) p.x = Min.x;\r\n        if (p.y > Max.y) p.y = Max.y;\r\n        else if (p.y < Min.y) p.y = Min.y;\r\n        return p;\r\n    }\r\n};\r\n\r\n// Stacked color modifier, backup of modified data so we can restore it\r\nstruct ImGuiColMod\r\n{\r\n    ImGuiCol    Col;\r\n    ImVec4      BackupValue;\r\n};\r\n\r\n// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.\r\nstruct ImGuiStyleMod\r\n{\r\n    ImGuiStyleVar   VarIdx;\r\n    union           { int BackupInt[2]; float BackupFloat[2]; };\r\n    ImGuiStyleMod(ImGuiStyleVar idx, int v)     { VarIdx = idx; BackupInt[0] = v; }\r\n    ImGuiStyleMod(ImGuiStyleVar idx, float v)   { VarIdx = idx; BackupFloat[0] = v; }\r\n    ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v)  { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }\r\n};\r\n\r\n// Stacked data for BeginGroup()/EndGroup()\r\nstruct ImGuiGroupData\r\n{\r\n    ImVec2      BackupCursorPos;\r\n    ImVec2      BackupCursorMaxPos;\r\n    float       BackupIndentX;\r\n    float       BackupGroupOffsetX;\r\n    float       BackupCurrentLineHeight;\r\n    float       BackupCurrentLineTextBaseOffset;\r\n    float       BackupLogLinePosY;\r\n    bool        BackupActiveIdIsAlive;\r\n    bool        AdvanceCursor;\r\n};\r\n\r\n// Per column data for Columns()\r\nstruct ImGuiColumnData\r\n{\r\n    float       OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)\r\n    ImRect      ClipRect;\r\n    //float     IndentX;\r\n};\r\n\r\n// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper.\r\nstruct IMGUI_API ImGuiSimpleColumns\r\n{\r\n    int         Count;\r\n    float       Spacing;\r\n    float       Width, NextWidth;\r\n    float       Pos[8], NextWidths[8];\r\n\r\n    ImGuiSimpleColumns();\r\n    void        Update(int count, float spacing, bool clear);\r\n    float       DeclColumns(float w0, float w1, float w2);\r\n    float       CalcExtraSpace(float avail_w);\r\n};\r\n\r\n// Internal state of the currently focused/edited text input box\r\nstruct IMGUI_API ImGuiTextEditState\r\n{\r\n    ImGuiID             Id;                         // widget id owning the text state\r\n    ImVector<ImWchar>   Text;                       // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.\r\n    ImVector<char>      InitialText;                // backup of end-user buffer at the time of focus (in UTF-8, unaltered)\r\n    ImVector<char>      TempTextBuffer;\r\n    int                 CurLenA, CurLenW;           // we need to maintain our buffer length in both UTF-8 and wchar format.\r\n    int                 BufSizeA;                   // end-user buffer size\r\n    float               ScrollX;\r\n    ImGuiStb::STB_TexteditState   StbState;\r\n    float               CursorAnim;\r\n    bool                CursorFollow;\r\n    bool                SelectedAllMouseLock;\r\n\r\n    ImGuiTextEditState()                            { memset(this, 0, sizeof(*this)); }\r\n    void                CursorAnimReset()           { CursorAnim = -0.30f; }                                   // After a user-input the cursor stays on for a while without blinking\r\n    void                CursorClamp()               { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); }\r\n    bool                HasSelection() const        { return StbState.select_start != StbState.select_end; }\r\n    void                ClearSelection()            { StbState.select_start = StbState.select_end = StbState.cursor; }\r\n    void                SelectAll()                 { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }\r\n    void                OnKeyPressed(int key);\r\n};\r\n\r\n// Data saved in imgui.ini file\r\nstruct ImGuiIniData\r\n{\r\n    char*       Name;\r\n    ImGuiID     Id;\r\n    ImVec2      Pos;\r\n    ImVec2      Size;\r\n    bool        Collapsed;\r\n};\r\n\r\n// Mouse cursor data (used when io.MouseDrawCursor is set)\r\nstruct ImGuiMouseCursorData\r\n{\r\n    ImGuiMouseCursor    Type;\r\n    ImVec2              HotOffset;\r\n    ImVec2              Size;\r\n    ImVec2              TexUvMin[2];\r\n    ImVec2              TexUvMax[2];\r\n};\r\n\r\n// Storage for current popup stack\r\nstruct ImGuiPopupRef\r\n{\r\n    ImGuiID         PopupId;        // Set on OpenPopup()\r\n    ImGuiWindow*    Window;         // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()\r\n    ImGuiWindow*    ParentWindow;   // Set on OpenPopup()\r\n    ImGuiID         ParentMenuSet;  // Set on OpenPopup()\r\n    ImVec2          MousePosOnOpen; // Copy of mouse position at the time of opening popup\r\n\r\n    ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }\r\n};\r\n\r\n// Main state for ImGui\r\nstruct ImGuiContext\r\n{\r\n    bool                    Initialized;\r\n    ImGuiIO                 IO;\r\n    ImGuiStyle              Style;\r\n    ImFont*                 Font;                               // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()\r\n    float                   FontSize;                           // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.\r\n    float                   FontBaseSize;                       // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.\r\n    ImVec2                  FontTexUvWhitePixel;                // (Shortcut) == Font->TexUvWhitePixel\r\n\r\n    float                   Time;\r\n    int                     FrameCount;\r\n    int                     FrameCountEnded;\r\n    int                     FrameCountRendered;\r\n    ImVector<ImGuiWindow*>  Windows;\r\n    ImVector<ImGuiWindow*>  WindowsSortBuffer;\r\n    ImVector<ImGuiWindow*>  CurrentWindowStack;\r\n    ImGuiWindow*            CurrentWindow;                      // Being drawn into\r\n    ImGuiWindow*            NavWindow;                          // Nav/focused window for navigation\r\n    ImGuiWindow*            HoveredWindow;                      // Will catch mouse inputs\r\n    ImGuiWindow*            HoveredRootWindow;                  // Will catch mouse inputs (for focus/move only)\r\n    ImGuiID                 HoveredId;                          // Hovered widget\r\n    bool                    HoveredIdAllowOverlap;\r\n    ImGuiID                 HoveredIdPreviousFrame;\r\n    ImGuiID                 ActiveId;                           // Active widget\r\n    ImGuiID                 ActiveIdPreviousFrame;\r\n    bool                    ActiveIdIsAlive;                    // Active widget has been seen this frame\r\n    bool                    ActiveIdIsJustActivated;            // Set at the time of activation for one frame\r\n    bool                    ActiveIdAllowOverlap;               // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)\r\n\r\n    ImVec2                  ActiveIdClickOffset;                // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)\r\n    ImGuiWindow*            ActiveIdWindow;\r\n    ImGuiWindow*            MovedWindow;                        // Track the child window we clicked on to move a window.\r\n    ImGuiID                 MovedWindowMoveId;                  // == MovedWindow->RootWindow->MoveId\r\n    ImVector<ImGuiIniData>  Settings;                           // .ini Settings\r\n    float                   SettingsDirtyTimer;                 // Save .ini Settings on disk when time reaches zero\r\n    ImVector<ImGuiColMod>   ColorModifiers;                     // Stack for PushStyleColor()/PopStyleColor()\r\n    ImVector<ImGuiStyleMod> StyleModifiers;                     // Stack for PushStyleVar()/PopStyleVar()\r\n    ImVector<ImFont*>       FontStack;                          // Stack for PushFont()/PopFont()\r\n    ImVector<ImGuiPopupRef> OpenPopupStack;                     // Which popups are open (persistent)\r\n    ImVector<ImGuiPopupRef> CurrentPopupStack;                  // Which level of BeginPopup() we are in (reset every frame)\r\n\r\n    // Storage for SetNexWindow** and SetNextTreeNode*** functions\r\n    ImVec2                  SetNextWindowPosVal;\r\n    ImVec2                  SetNextWindowSizeVal;\r\n    ImVec2                  SetNextWindowContentSizeVal;\r\n    bool                    SetNextWindowCollapsedVal;\r\n    ImGuiCond               SetNextWindowPosCond;\r\n    ImGuiCond               SetNextWindowSizeCond;\r\n    ImGuiCond               SetNextWindowContentSizeCond;\r\n    ImGuiCond               SetNextWindowCollapsedCond;\r\n    ImRect                  SetNextWindowSizeConstraintRect;           // Valid if 'SetNextWindowSizeConstraint' is true\r\n    ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback;\r\n    void*                   SetNextWindowSizeConstraintCallbackUserData;\r\n    bool                    SetNextWindowSizeConstraint;\r\n    bool                    SetNextWindowFocus;\r\n    bool                    SetNextTreeNodeOpenVal;\r\n    ImGuiCond               SetNextTreeNodeOpenCond;\r\n\r\n    // Render\r\n    ImDrawData              RenderDrawData;                     // Main ImDrawData instance to pass render information to the user\r\n    ImVector<ImDrawList*>   RenderDrawLists[3];\r\n    float                   ModalWindowDarkeningRatio;\r\n    ImDrawList              OverlayDrawList;                    // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays\r\n    ImGuiMouseCursor        MouseCursor;\r\n    ImGuiMouseCursorData    MouseCursorData[ImGuiMouseCursor_Count_];\r\n\r\n    // Widget state\r\n    ImGuiTextEditState      InputTextState;\r\n    ImFont                  InputTextPasswordFont;\r\n    ImGuiID                 ScalarAsInputTextId;                // Temporary text input when CTRL+clicking on a slider, etc.\r\n    ImGuiColorEditFlags     ColorEditOptions;                   // Store user options for color edit widgets\r\n    ImVec4                  ColorPickerRef;\r\n    float                   DragCurrentValue;                   // Currently dragged value, always float, not rounded by end-user precision settings\r\n    ImVec2                  DragLastMouseDelta;\r\n    float                   DragSpeedDefaultRatio;              // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio\r\n    float                   DragSpeedScaleSlow;\r\n    float                   DragSpeedScaleFast;\r\n    ImVec2                  ScrollbarClickDeltaToGrabCenter;    // Distance between mouse and center of grab box, normalized in parent space. Use storage?\r\n    int                     TooltipOverrideCount;\r\n    ImVector<char>          PrivateClipboard;                   // If no custom clipboard handler is defined\r\n    ImVec2                  OsImePosRequest, OsImePosSet;       // Cursor position request & last passed to the OS Input Method Editor\r\n\r\n    // Logging\r\n    bool                    LogEnabled;\r\n    FILE*                   LogFile;                            // If != NULL log to stdout/ file\r\n    ImGuiTextBuffer*        LogClipboard;                       // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.\r\n    int                     LogStartDepth;\r\n    int                     LogAutoExpandMaxDepth;\r\n\r\n    // Misc\r\n    float                   FramerateSecPerFrame[120];          // calculate estimate of framerate for user\r\n    int                     FramerateSecPerFrameIdx;\r\n    float                   FramerateSecPerFrameAccum;\r\n    int                     WantCaptureMouseNextFrame;          // explicit capture via CaptureInputs() sets those flags\r\n    int                     WantCaptureKeyboardNextFrame;\r\n    int                     WantTextInputNextFrame;\r\n    char                    TempBuffer[1024*3+1];               // temporary text buffer\r\n\r\n    ImGuiContext()\r\n    {\r\n        Initialized = false;\r\n        Font = NULL;\r\n        FontSize = FontBaseSize = 0.0f;\r\n        FontTexUvWhitePixel = ImVec2(0.0f, 0.0f);\r\n\r\n        Time = 0.0f;\r\n        FrameCount = 0;\r\n        FrameCountEnded = FrameCountRendered = -1;\r\n        CurrentWindow = NULL;\r\n        NavWindow = NULL;\r\n        HoveredWindow = NULL;\r\n        HoveredRootWindow = NULL;\r\n        HoveredId = 0;\r\n        HoveredIdAllowOverlap = false;\r\n        HoveredIdPreviousFrame = 0;\r\n        ActiveId = 0;\r\n        ActiveIdPreviousFrame = 0;\r\n        ActiveIdIsAlive = false;\r\n        ActiveIdIsJustActivated = false;\r\n        ActiveIdAllowOverlap = false;\r\n        ActiveIdClickOffset = ImVec2(-1,-1);\r\n        ActiveIdWindow = NULL;\r\n        MovedWindow = NULL;\r\n        MovedWindowMoveId = 0;\r\n        SettingsDirtyTimer = 0.0f;\r\n\r\n        SetNextWindowPosVal = ImVec2(0.0f, 0.0f);\r\n        SetNextWindowSizeVal = ImVec2(0.0f, 0.0f);\r\n        SetNextWindowCollapsedVal = false;\r\n        SetNextWindowPosCond = 0;\r\n        SetNextWindowSizeCond = 0;\r\n        SetNextWindowContentSizeCond = 0;\r\n        SetNextWindowCollapsedCond = 0;\r\n        SetNextWindowSizeConstraintRect = ImRect();\r\n        SetNextWindowSizeConstraintCallback = NULL;\r\n        SetNextWindowSizeConstraintCallbackUserData = NULL;\r\n        SetNextWindowSizeConstraint = false;\r\n        SetNextWindowFocus = false;\r\n        SetNextTreeNodeOpenVal = false;\r\n        SetNextTreeNodeOpenCond = 0;\r\n\r\n        ScalarAsInputTextId = 0;\r\n        ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;\r\n        DragCurrentValue = 0.0f;\r\n        DragLastMouseDelta = ImVec2(0.0f, 0.0f);\r\n        DragSpeedDefaultRatio = 1.0f / 100.0f;\r\n        DragSpeedScaleSlow = 1.0f / 100.0f;\r\n        DragSpeedScaleFast = 10.0f;\r\n        ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);\r\n        TooltipOverrideCount = 0;\r\n        OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);\r\n\r\n        ModalWindowDarkeningRatio = 0.0f;\r\n        OverlayDrawList._OwnerName = \"##Overlay\"; // Give it a name for debugging\r\n        MouseCursor = ImGuiMouseCursor_Arrow;\r\n        memset(MouseCursorData, 0, sizeof(MouseCursorData));\r\n\r\n        LogEnabled = false;\r\n        LogFile = NULL;\r\n        LogClipboard = NULL;\r\n        LogStartDepth = 0;\r\n        LogAutoExpandMaxDepth = 2;\r\n\r\n        memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));\r\n        FramerateSecPerFrameIdx = 0;\r\n        FramerateSecPerFrameAccum = 0.0f;\r\n        WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;\r\n        memset(TempBuffer, 0, sizeof(TempBuffer));\r\n    }\r\n};\r\n\r\n// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().\r\nenum ImGuiItemFlags_\r\n{\r\n    ImGuiItemFlags_AllowKeyboardFocus           = 1 << 0,  // true\r\n    ImGuiItemFlags_ButtonRepeat                 = 1 << 1,  // false    // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.\r\n    //ImGuiItemFlags_Disabled                   = 1 << 2,  // false    // All widgets appears are disabled\r\n    //ImGuiItemFlags_AllowNavDefaultFocus       = 1 << 3,  // true\r\n    //ImGuiItemFlags_SelectableDontClosePopup   = 1 << 4,  // false    // MenuItem/Selectable() automatically closes current Popup window\r\n    ImGuiItemFlags_Default_                 = ImGuiItemFlags_AllowKeyboardFocus\r\n};\r\n\r\n// Transient per-window data, reset at the beginning of the frame\r\n// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered.\r\nstruct IMGUI_API ImGuiDrawContext\r\n{\r\n    ImVec2                  CursorPos;\r\n    ImVec2                  CursorPosPrevLine;\r\n    ImVec2                  CursorStartPos;\r\n    ImVec2                  CursorMaxPos;           // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame\r\n    float                   CurrentLineHeight;\r\n    float                   CurrentLineTextBaseOffset;\r\n    float                   PrevLineHeight;\r\n    float                   PrevLineTextBaseOffset;\r\n    float                   LogLinePosY;\r\n    int                     TreeDepth;\r\n    ImGuiID                 LastItemId;\r\n    ImRect                  LastItemRect;\r\n    bool                    LastItemHoveredAndUsable;  // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window)\r\n    bool                    LastItemHoveredRect;       // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window)\r\n    bool                    MenuBarAppending;\r\n    float                   MenuBarOffsetX;\r\n    ImVector<ImGuiWindow*>  ChildWindows;\r\n    ImGuiStorage*           StateStorage;\r\n    ImGuiLayoutType         LayoutType;\r\n\r\n    // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.\r\n    ImGuiItemFlags          ItemFlags;              // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]\r\n    float                   ItemWidth;              // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window\r\n    float                   TextWrapPos;            // == TextWrapPosStack.back() [empty == -1.0f]\r\n    ImVector<ImGuiItemFlags>ItemFlagsStack;\r\n    ImVector<float>         ItemWidthStack;\r\n    ImVector<float>         TextWrapPosStack;\r\n    ImVector<ImGuiGroupData>GroupStack;\r\n    int                     StackSizesBackup[6];    // Store size of various stacks for asserting\r\n\r\n    float                   IndentX;                // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)\r\n    float                   GroupOffsetX;\r\n    float                   ColumnsOffsetX;         // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.\r\n    int                     ColumnsCurrent;\r\n    int                     ColumnsCount;\r\n    float                   ColumnsMinX;\r\n    float                   ColumnsMaxX;\r\n    float                   ColumnsStartPosY;\r\n    float                   ColumnsStartMaxPosX;   // Backup of CursorMaxPos\r\n    float                   ColumnsCellMinY;\r\n    float                   ColumnsCellMaxY;\r\n    ImGuiColumnsFlags       ColumnsFlags;\r\n    ImGuiID                 ColumnsSetId;\r\n    ImVector<ImGuiColumnData> ColumnsData;\r\n\r\n    ImGuiDrawContext()\r\n    {\r\n        CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);\r\n        CurrentLineHeight = PrevLineHeight = 0.0f;\r\n        CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;\r\n        LogLinePosY = -1.0f;\r\n        TreeDepth = 0;\r\n        LastItemId = 0;\r\n        LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f);\r\n        LastItemHoveredAndUsable = LastItemHoveredRect = false;\r\n        MenuBarAppending = false;\r\n        MenuBarOffsetX = 0.0f;\r\n        StateStorage = NULL;\r\n        LayoutType = ImGuiLayoutType_Vertical;\r\n        ItemWidth = 0.0f;\r\n        ItemFlags = ImGuiItemFlags_Default_;\r\n        TextWrapPos = -1.0f;\r\n        memset(StackSizesBackup, 0, sizeof(StackSizesBackup));\r\n\r\n        IndentX = 0.0f;\r\n        GroupOffsetX = 0.0f;\r\n        ColumnsOffsetX = 0.0f;\r\n        ColumnsCurrent = 0;\r\n        ColumnsCount = 1;\r\n        ColumnsMinX = ColumnsMaxX = 0.0f;\r\n        ColumnsStartPosY = 0.0f;\r\n        ColumnsStartMaxPosX = 0.0f;\r\n        ColumnsCellMinY = ColumnsCellMaxY = 0.0f;\r\n        ColumnsFlags = 0;\r\n        ColumnsSetId = 0;\r\n    }\r\n};\r\n\r\n// Windows data\r\nstruct IMGUI_API ImGuiWindow\r\n{\r\n    char*                   Name;\r\n    ImGuiID                 ID;                                 // == ImHash(Name)\r\n    ImGuiWindowFlags        Flags;                              // See enum ImGuiWindowFlags_\r\n    int                     OrderWithinParent;                  // Order within immediate parent window, if we are a child window. Otherwise 0.\r\n    ImVec2                  PosFloat;\r\n    ImVec2                  Pos;                                // Position rounded-up to nearest pixel\r\n    ImVec2                  Size;                               // Current size (==SizeFull or collapsed title bar size)\r\n    ImVec2                  SizeFull;                           // Size when non collapsed\r\n    ImVec2                  SizeContents;                       // Size of contents (== extents reach of the drawing cursor) from previous frame\r\n    ImVec2                  SizeContentsExplicit;               // Size of contents explicitly set by the user via SetNextWindowContentSize()\r\n    ImRect                  ContentsRegionRect;                 // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis\r\n    ImVec2                  WindowPadding;                      // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect\r\n    ImGuiID                 MoveId;                             // == window->GetID(\"#MOVE\")\r\n    ImVec2                  Scroll;\r\n    ImVec2                  ScrollTarget;                       // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)\r\n    ImVec2                  ScrollTargetCenterRatio;            // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered\r\n    bool                    ScrollbarX, ScrollbarY;\r\n    ImVec2                  ScrollbarSizes;\r\n    float                   BorderSize;\r\n    bool                    Active;                             // Set to true on Begin()\r\n    bool                    WasActive;\r\n    bool                    Accessed;                           // Set to true when any widget access the current window\r\n    bool                    Collapsed;                          // Set when collapsing window to become only title-bar\r\n    bool                    SkipItems;                          // Set when items can safely be all clipped (e.g. window not visible or collapsed)\r\n    bool                    Appearing;                          // Set during the frame where the window is appearing (or re-appearing)\r\n    int                     BeginCount;                         // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)\r\n    ImGuiID                 PopupId;                            // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)\r\n    int                     AutoFitFramesX, AutoFitFramesY;\r\n    bool                    AutoFitOnlyGrows;\r\n    int                     AutoFitChildAxises;\r\n    int                     AutoPosLastDirection;\r\n    int                     HiddenFrames;\r\n    ImGuiCond               SetWindowPosAllowFlags;             // store condition flags for next SetWindowPos() call.\r\n    ImGuiCond               SetWindowSizeAllowFlags;            // store condition flags for next SetWindowSize() call.\r\n    ImGuiCond               SetWindowCollapsedAllowFlags;       // store condition flags for next SetWindowCollapsed() call.\r\n    bool                    SetWindowPosCenterWanted;\r\n\r\n    ImGuiDrawContext        DC;                                 // Temporary per-window data, reset at the beginning of the frame\r\n    ImVector<ImGuiID>       IDStack;                            // ID stack. ID are hashes seeded with the value at the top of the stack\r\n    ImRect                  ClipRect;                           // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.\r\n    ImRect                  WindowRectClipped;                  // = WindowRect just after setup in Begin(). == window->Rect() for root window.\r\n    int                     LastFrameActive;\r\n    float                   ItemWidthDefault;\r\n    ImGuiSimpleColumns      MenuColumns;                        // Simplified columns storage for menu items\r\n    ImGuiStorage            StateStorage;\r\n    float                   FontWindowScale;                    // Scale multiplier per-window\r\n    ImDrawList*             DrawList;\r\n    ImGuiWindow*            ParentWindow;                       // Immediate parent in the window stack *regardless* of whether this window is a child window or not)\r\n    ImGuiWindow*            RootWindow;                         // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window.\r\n    ImGuiWindow*            RootNonPopupWindow;                 // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing\r\n\r\n    // Navigation / Focus\r\n    int                     FocusIdxAllCounter;                 // Start at -1 and increase as assigned via FocusItemRegister()\r\n    int                     FocusIdxTabCounter;                 // (same, but only count widgets which you can Tab through)\r\n    int                     FocusIdxAllRequestCurrent;          // Item being requested for focus\r\n    int                     FocusIdxTabRequestCurrent;          // Tab-able item being requested for focus\r\n    int                     FocusIdxAllRequestNext;             // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)\r\n    int                     FocusIdxTabRequestNext;             // \"\r\n\r\npublic:\r\n    ImGuiWindow(const char* name);\r\n    ~ImGuiWindow();\r\n\r\n    ImGuiID     GetID(const char* str, const char* str_end = NULL);\r\n    ImGuiID     GetID(const void* ptr);\r\n    ImGuiID     GetIDNoKeepAlive(const char* str, const char* str_end = NULL);\r\n\r\n    ImRect      Rect() const                            { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }\r\n    float       CalcFontSize() const                    { return GImGui->FontBaseSize * FontWindowScale; }\r\n    float       TitleBarHeight() const                  { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; }\r\n    ImRect      TitleBarRect() const                    { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }\r\n    float       MenuBarHeight() const                   { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }\r\n    ImRect      MenuBarRect() const                     { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }\r\n};\r\n\r\n//-----------------------------------------------------------------------------\r\n// Internal API\r\n// No guarantee of forward compatibility here.\r\n//-----------------------------------------------------------------------------\r\n\r\nnamespace ImGui\r\n{\r\n    // We should always have a CurrentWindow in the stack (there is an implicit \"Debug\" window)\r\n    // If this ever crash because g.CurrentWindow is NULL it means that either\r\n    // - ImGui::NewFrame() has never been called, which is illegal.\r\n    // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.\r\n    inline    ImGuiWindow*  GetCurrentWindowRead()      { ImGuiContext& g = *GImGui; return g.CurrentWindow; }\r\n    inline    ImGuiWindow*  GetCurrentWindow()          { ImGuiContext& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }\r\n    IMGUI_API ImGuiWindow*  GetParentWindow();\r\n    IMGUI_API ImGuiWindow*  FindWindowByName(const char* name);\r\n    IMGUI_API void          FocusWindow(ImGuiWindow* window);\r\n\r\n    IMGUI_API void          Initialize();\r\n    IMGUI_API void          EndFrame();                 // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead!\r\n\r\n    IMGUI_API void          SetActiveID(ImGuiID id, ImGuiWindow* window);\r\n    IMGUI_API void          ClearActiveID();\r\n    IMGUI_API void          SetHoveredID(ImGuiID id);\r\n    IMGUI_API void          KeepAliveID(ImGuiID id);\r\n\r\n    IMGUI_API void          ItemSize(const ImVec2& size, float text_offset_y = 0.0f);\r\n    IMGUI_API void          ItemSize(const ImRect& bb, float text_offset_y = 0.0f);\r\n    IMGUI_API bool          ItemAdd(const ImRect& bb, const ImGuiID* id);\r\n    IMGUI_API bool          IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged);\r\n    IMGUI_API bool          IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false);\r\n    IMGUI_API bool          FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true);      // Return true if focus is requested\r\n    IMGUI_API void          FocusableItemUnregister(ImGuiWindow* window);\r\n    IMGUI_API ImVec2        CalcItemSize(ImVec2 size, float default_x, float default_y);\r\n    IMGUI_API float         CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);\r\n    IMGUI_API void          PushItemFlag(ImGuiItemFlags option, bool enabled);\r\n    IMGUI_API void          PopItemFlag();\r\n\r\n    IMGUI_API void          OpenPopupEx(ImGuiID id, bool reopen_existing);\r\n    IMGUI_API bool          IsPopupOpen(ImGuiID id);\r\n\r\n    IMGUI_API int           CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate);\r\n\r\n    // FIXME-WIP: New Columns API\r\n    IMGUI_API void          BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().\r\n    IMGUI_API void          EndColumns();                                                         // close columns\r\n    IMGUI_API void          PushColumnClipRect(int column_index = -1);\r\n\r\n    // FIXME-WIP: New Combo API\r\n    IMGUI_API bool          BeginCombo(const char* label, const char* preview_value, float popup_opened_height);\r\n    IMGUI_API void          EndCombo();\r\n\r\n    // NB: All position are in absolute pixels coordinates (never using window coordinates internally)\r\n    // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.\r\n    IMGUI_API void          RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);\r\n    IMGUI_API void          RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);\r\n    IMGUI_API void          RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);\r\n    IMGUI_API void          RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);\r\n    IMGUI_API void          RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);\r\n    IMGUI_API void          RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0);\r\n    IMGUI_API void          RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f);\r\n    IMGUI_API void          RenderBullet(ImVec2 pos);\r\n    IMGUI_API void          RenderCheckMark(ImVec2 pos, ImU32 col);\r\n    IMGUI_API void          RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);\r\n    IMGUI_API const char*   FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.\r\n\r\n    IMGUI_API bool          ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);\r\n    IMGUI_API bool          ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);\r\n    IMGUI_API bool          CloseButton(ImGuiID id, const ImVec2& pos, float radius);\r\n\r\n    IMGUI_API bool          SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0);\r\n    IMGUI_API bool          SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power);\r\n    IMGUI_API bool          SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format);\r\n\r\n    IMGUI_API bool          DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power);\r\n    IMGUI_API bool          DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power);\r\n    IMGUI_API bool          DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format);\r\n\r\n    IMGUI_API bool          InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);\r\n    IMGUI_API bool          InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags);\r\n    IMGUI_API bool          InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags);\r\n    IMGUI_API bool          InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);\r\n    IMGUI_API bool          InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);\r\n\r\n    IMGUI_API void          ColorTooltip(const char* text, const float col[4], ImGuiColorEditFlags flags);\r\n\r\n    IMGUI_API bool          TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);\r\n    IMGUI_API bool          TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0);                     // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging\r\n    IMGUI_API void          TreePushRawID(ImGuiID id);\r\n\r\n    IMGUI_API void          PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);\r\n\r\n    IMGUI_API int           ParseFormatPrecision(const char* fmt, int default_value);\r\n    IMGUI_API float         RoundScalar(float value, int decimal_precision);\r\n\r\n} // namespace ImGui\r\n\r\n// ImFontAtlas internals\r\nIMGUI_API bool              ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas);\r\nIMGUI_API void              ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas);\r\nIMGUI_API void              ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); \r\nIMGUI_API void              ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc);\r\nIMGUI_API void              ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas);\r\nIMGUI_API void              ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);\r\nIMGUI_API void              ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic pop\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#pragma warning (pop)\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/stb_rect_pack.h",
    "content": "// stb_rect_pack.h - v0.10 - public domain - rectangle packing\r\n// Sean Barrett 2014\r\n//\r\n// Useful for e.g. packing rectangular textures into an atlas.\r\n// Does not do rotation.\r\n//\r\n// Not necessarily the awesomest packing method, but better than\r\n// the totally naive one in stb_truetype (which is primarily what\r\n// this is meant to replace).\r\n//\r\n// Has only had a few tests run, may have issues.\r\n//\r\n// More docs to come.\r\n//\r\n// No memory allocations; uses qsort() and assert() from stdlib.\r\n// Can override those by defining STBRP_SORT and STBRP_ASSERT.\r\n//\r\n// This library currently uses the Skyline Bottom-Left algorithm.\r\n//\r\n// Please note: better rectangle packers are welcome! Please\r\n// implement them to the same API, but with a different init\r\n// function.\r\n//\r\n// Credits\r\n//\r\n//  Library\r\n//    Sean Barrett\r\n//  Minor features\r\n//    Martins Mozeiko\r\n//  Bugfixes / warning fixes\r\n//    Jeremy Jaussaud\r\n//\r\n// Version history:\r\n//\r\n//     0.10  (2016-10-25)  remove cast-away-const to avoid warnings\r\n//     0.09  (2016-08-27)  fix compiler warnings\r\n//     0.08  (2015-09-13)  really fix bug with empty rects (w=0 or h=0)\r\n//     0.07  (2015-09-13)  fix bug with empty rects (w=0 or h=0)\r\n//     0.06  (2015-04-15)  added STBRP_SORT to allow replacing qsort\r\n//     0.05:  added STBRP_ASSERT to allow replacing assert\r\n//     0.04:  fixed minor bug in STBRP_LARGE_RECTS support\r\n//     0.01:  initial release\r\n//\r\n// LICENSE\r\n//\r\n//   This software is dual-licensed to the public domain and under the following\r\n//   license: you are granted a perpetual, irrevocable license to copy, modify,\r\n//   publish, and distribute this file as you see fit.\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n//       INCLUDE SECTION\r\n//\r\n\r\n#ifndef STB_INCLUDE_STB_RECT_PACK_H\r\n#define STB_INCLUDE_STB_RECT_PACK_H\r\n\r\n#define STB_RECT_PACK_VERSION  1\r\n\r\n#ifdef STBRP_STATIC\r\n#define STBRP_DEF static\r\n#else\r\n#define STBRP_DEF extern\r\n#endif\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\ntypedef struct stbrp_context stbrp_context;\r\ntypedef struct stbrp_node    stbrp_node;\r\ntypedef struct stbrp_rect    stbrp_rect;\r\n\r\n#ifdef STBRP_LARGE_RECTS\r\ntypedef int            stbrp_coord;\r\n#else\r\ntypedef unsigned short stbrp_coord;\r\n#endif\r\n\r\nSTBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);\r\n// Assign packed locations to rectangles. The rectangles are of type\r\n// 'stbrp_rect' defined below, stored in the array 'rects', and there\r\n// are 'num_rects' many of them.\r\n//\r\n// Rectangles which are successfully packed have the 'was_packed' flag\r\n// set to a non-zero value and 'x' and 'y' store the minimum location\r\n// on each axis (i.e. bottom-left in cartesian coordinates, top-left\r\n// if you imagine y increasing downwards). Rectangles which do not fit\r\n// have the 'was_packed' flag set to 0.\r\n//\r\n// You should not try to access the 'rects' array from another thread\r\n// while this function is running, as the function temporarily reorders\r\n// the array while it executes.\r\n//\r\n// To pack into another rectangle, you need to call stbrp_init_target\r\n// again. To continue packing into the same rectangle, you can call\r\n// this function again. Calling this multiple times with multiple rect\r\n// arrays will probably produce worse packing results than calling it\r\n// a single time with the full rectangle array, but the option is\r\n// available.\r\n\r\nstruct stbrp_rect\r\n{\r\n   // reserved for your use:\r\n   int            id;\r\n\r\n   // input:\r\n   stbrp_coord    w, h;\r\n\r\n   // output:\r\n   stbrp_coord    x, y;\r\n   int            was_packed;  // non-zero if valid packing\r\n\r\n}; // 16 bytes, nominally\r\n\r\n\r\nSTBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);\r\n// Initialize a rectangle packer to:\r\n//    pack a rectangle that is 'width' by 'height' in dimensions\r\n//    using temporary storage provided by the array 'nodes', which is 'num_nodes' long\r\n//\r\n// You must call this function every time you start packing into a new target.\r\n//\r\n// There is no \"shutdown\" function. The 'nodes' memory must stay valid for\r\n// the following stbrp_pack_rects() call (or calls), but can be freed after\r\n// the call (or calls) finish.\r\n//\r\n// Note: to guarantee best results, either:\r\n//       1. make sure 'num_nodes' >= 'width'\r\n//   or  2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'\r\n//\r\n// If you don't do either of the above things, widths will be quantized to multiples\r\n// of small integers to guarantee the algorithm doesn't run out of temporary storage.\r\n//\r\n// If you do #2, then the non-quantized algorithm will be used, but the algorithm\r\n// may run out of temporary storage and be unable to pack some rectangles.\r\n\r\nSTBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);\r\n// Optionally call this function after init but before doing any packing to\r\n// change the handling of the out-of-temp-memory scenario, described above.\r\n// If you call init again, this will be reset to the default (false).\r\n\r\n\r\nSTBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);\r\n// Optionally select which packing heuristic the library should use. Different\r\n// heuristics will produce better/worse results for different data sets.\r\n// If you call init again, this will be reset to the default.\r\n\r\nenum\r\n{\r\n   STBRP_HEURISTIC_Skyline_default=0,\r\n   STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,\r\n   STBRP_HEURISTIC_Skyline_BF_sortHeight\r\n};\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// the details of the following structures don't matter to you, but they must\r\n// be visible so you can handle the memory allocations for them\r\n\r\nstruct stbrp_node\r\n{\r\n   stbrp_coord  x,y;\r\n   stbrp_node  *next;\r\n};\r\n\r\nstruct stbrp_context\r\n{\r\n   int width;\r\n   int height;\r\n   int align;\r\n   int init_mode;\r\n   int heuristic;\r\n   int num_nodes;\r\n   stbrp_node *active_head;\r\n   stbrp_node *free_head;\r\n   stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'\r\n};\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n//     IMPLEMENTATION SECTION\r\n//\r\n\r\n#ifdef STB_RECT_PACK_IMPLEMENTATION\r\n#ifndef STBRP_SORT\r\n#include <stdlib.h>\r\n#define STBRP_SORT qsort\r\n#endif\r\n\r\n#ifndef STBRP_ASSERT\r\n#include <assert.h>\r\n#define STBRP_ASSERT assert\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#define STBRP__NOTUSED(v)  (void)(v)\r\n#else\r\n#define STBRP__NOTUSED(v)  (void)sizeof(v)\r\n#endif\r\n\r\nenum\r\n{\r\n   STBRP__INIT_skyline = 1\r\n};\r\n\r\nSTBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)\r\n{\r\n   switch (context->init_mode) {\r\n      case STBRP__INIT_skyline:\r\n         STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);\r\n         context->heuristic = heuristic;\r\n         break;\r\n      default:\r\n         STBRP_ASSERT(0);\r\n   }\r\n}\r\n\r\nSTBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)\r\n{\r\n   if (allow_out_of_mem)\r\n      // if it's ok to run out of memory, then don't bother aligning them;\r\n      // this gives better packing, but may fail due to OOM (even though\r\n      // the rectangles easily fit). @TODO a smarter approach would be to only\r\n      // quantize once we've hit OOM, then we could get rid of this parameter.\r\n      context->align = 1;\r\n   else {\r\n      // if it's not ok to run out of memory, then quantize the widths\r\n      // so that num_nodes is always enough nodes.\r\n      //\r\n      // I.e. num_nodes * align >= width\r\n      //                  align >= width / num_nodes\r\n      //                  align = ceil(width/num_nodes)\r\n\r\n      context->align = (context->width + context->num_nodes-1) / context->num_nodes;\r\n   }\r\n}\r\n\r\nSTBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)\r\n{\r\n   int i;\r\n#ifndef STBRP_LARGE_RECTS\r\n   STBRP_ASSERT(width <= 0xffff && height <= 0xffff);\r\n#endif\r\n\r\n   for (i=0; i < num_nodes-1; ++i)\r\n      nodes[i].next = &nodes[i+1];\r\n   nodes[i].next = NULL;\r\n   context->init_mode = STBRP__INIT_skyline;\r\n   context->heuristic = STBRP_HEURISTIC_Skyline_default;\r\n   context->free_head = &nodes[0];\r\n   context->active_head = &context->extra[0];\r\n   context->width = width;\r\n   context->height = height;\r\n   context->num_nodes = num_nodes;\r\n   stbrp_setup_allow_out_of_mem(context, 0);\r\n\r\n   // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)\r\n   context->extra[0].x = 0;\r\n   context->extra[0].y = 0;\r\n   context->extra[0].next = &context->extra[1];\r\n   context->extra[1].x = (stbrp_coord) width;\r\n#ifdef STBRP_LARGE_RECTS\r\n   context->extra[1].y = (1<<30);\r\n#else\r\n   context->extra[1].y = 65535;\r\n#endif\r\n   context->extra[1].next = NULL;\r\n}\r\n\r\n// find minimum y position if it starts at x1\r\nstatic int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)\r\n{\r\n   stbrp_node *node = first;\r\n   int x1 = x0 + width;\r\n   int min_y, visited_width, waste_area;\r\n\r\n   STBRP__NOTUSED(c);\r\n\r\n   STBRP_ASSERT(first->x <= x0);\r\n\r\n   #if 0\r\n   // skip in case we're past the node\r\n   while (node->next->x <= x0)\r\n      ++node;\r\n   #else\r\n   STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency\r\n   #endif\r\n\r\n   STBRP_ASSERT(node->x <= x0);\r\n\r\n   min_y = 0;\r\n   waste_area = 0;\r\n   visited_width = 0;\r\n   while (node->x < x1) {\r\n      if (node->y > min_y) {\r\n         // raise min_y higher.\r\n         // we've accounted for all waste up to min_y,\r\n         // but we'll now add more waste for everything we've visted\r\n         waste_area += visited_width * (node->y - min_y);\r\n         min_y = node->y;\r\n         // the first time through, visited_width might be reduced\r\n         if (node->x < x0)\r\n            visited_width += node->next->x - x0;\r\n         else\r\n            visited_width += node->next->x - node->x;\r\n      } else {\r\n         // add waste area\r\n         int under_width = node->next->x - node->x;\r\n         if (under_width + visited_width > width)\r\n            under_width = width - visited_width;\r\n         waste_area += under_width * (min_y - node->y);\r\n         visited_width += under_width;\r\n      }\r\n      node = node->next;\r\n   }\r\n\r\n   *pwaste = waste_area;\r\n   return min_y;\r\n}\r\n\r\ntypedef struct\r\n{\r\n   int x,y;\r\n   stbrp_node **prev_link;\r\n} stbrp__findresult;\r\n\r\nstatic stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)\r\n{\r\n   int best_waste = (1<<30), best_x, best_y = (1 << 30);\r\n   stbrp__findresult fr;\r\n   stbrp_node **prev, *node, *tail, **best = NULL;\r\n\r\n   // align to multiple of c->align\r\n   width = (width + c->align - 1);\r\n   width -= width % c->align;\r\n   STBRP_ASSERT(width % c->align == 0);\r\n\r\n   node = c->active_head;\r\n   prev = &c->active_head;\r\n   while (node->x + width <= c->width) {\r\n      int y,waste;\r\n      y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);\r\n      if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL\r\n         // bottom left\r\n         if (y < best_y) {\r\n            best_y = y;\r\n            best = prev;\r\n         }\r\n      } else {\r\n         // best-fit\r\n         if (y + height <= c->height) {\r\n            // can only use it if it first vertically\r\n            if (y < best_y || (y == best_y && waste < best_waste)) {\r\n               best_y = y;\r\n               best_waste = waste;\r\n               best = prev;\r\n            }\r\n         }\r\n      }\r\n      prev = &node->next;\r\n      node = node->next;\r\n   }\r\n\r\n   best_x = (best == NULL) ? 0 : (*best)->x;\r\n\r\n   // if doing best-fit (BF), we also have to try aligning right edge to each node position\r\n   //\r\n   // e.g, if fitting\r\n   //\r\n   //     ____________________\r\n   //    |____________________|\r\n   //\r\n   //            into\r\n   //\r\n   //   |                         |\r\n   //   |             ____________|\r\n   //   |____________|\r\n   //\r\n   // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned\r\n   //\r\n   // This makes BF take about 2x the time\r\n\r\n   if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {\r\n      tail = c->active_head;\r\n      node = c->active_head;\r\n      prev = &c->active_head;\r\n      // find first node that's admissible\r\n      while (tail->x < width)\r\n         tail = tail->next;\r\n      while (tail) {\r\n         int xpos = tail->x - width;\r\n         int y,waste;\r\n         STBRP_ASSERT(xpos >= 0);\r\n         // find the left position that matches this\r\n         while (node->next->x <= xpos) {\r\n            prev = &node->next;\r\n            node = node->next;\r\n         }\r\n         STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);\r\n         y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);\r\n         if (y + height < c->height) {\r\n            if (y <= best_y) {\r\n               if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {\r\n                  best_x = xpos;\r\n                  STBRP_ASSERT(y <= best_y);\r\n                  best_y = y;\r\n                  best_waste = waste;\r\n                  best = prev;\r\n               }\r\n            }\r\n         }\r\n         tail = tail->next;\r\n      }         \r\n   }\r\n\r\n   fr.prev_link = best;\r\n   fr.x = best_x;\r\n   fr.y = best_y;\r\n   return fr;\r\n}\r\n\r\nstatic stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)\r\n{\r\n   // find best position according to heuristic\r\n   stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);\r\n   stbrp_node *node, *cur;\r\n\r\n   // bail if:\r\n   //    1. it failed\r\n   //    2. the best node doesn't fit (we don't always check this)\r\n   //    3. we're out of memory\r\n   if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {\r\n      res.prev_link = NULL;\r\n      return res;\r\n   }\r\n\r\n   // on success, create new node\r\n   node = context->free_head;\r\n   node->x = (stbrp_coord) res.x;\r\n   node->y = (stbrp_coord) (res.y + height);\r\n\r\n   context->free_head = node->next;\r\n\r\n   // insert the new node into the right starting point, and\r\n   // let 'cur' point to the remaining nodes needing to be\r\n   // stiched back in\r\n\r\n   cur = *res.prev_link;\r\n   if (cur->x < res.x) {\r\n      // preserve the existing one, so start testing with the next one\r\n      stbrp_node *next = cur->next;\r\n      cur->next = node;\r\n      cur = next;\r\n   } else {\r\n      *res.prev_link = node;\r\n   }\r\n\r\n   // from here, traverse cur and free the nodes, until we get to one\r\n   // that shouldn't be freed\r\n   while (cur->next && cur->next->x <= res.x + width) {\r\n      stbrp_node *next = cur->next;\r\n      // move the current node to the free list\r\n      cur->next = context->free_head;\r\n      context->free_head = cur;\r\n      cur = next;\r\n   }\r\n\r\n   // stitch the list back in\r\n   node->next = cur;\r\n\r\n   if (cur->x < res.x + width)\r\n      cur->x = (stbrp_coord) (res.x + width);\r\n\r\n#ifdef _DEBUG\r\n   cur = context->active_head;\r\n   while (cur->x < context->width) {\r\n      STBRP_ASSERT(cur->x < cur->next->x);\r\n      cur = cur->next;\r\n   }\r\n   STBRP_ASSERT(cur->next == NULL);\r\n\r\n   {\r\n      stbrp_node *L1 = NULL, *L2 = NULL;\r\n      int count=0;\r\n      cur = context->active_head;\r\n      while (cur) {\r\n         L1 = cur;\r\n         cur = cur->next;\r\n         ++count;\r\n      }\r\n      cur = context->free_head;\r\n      while (cur) {\r\n         L2 = cur;\r\n         cur = cur->next;\r\n         ++count;\r\n      }\r\n      STBRP_ASSERT(count == context->num_nodes+2);\r\n   }\r\n#endif\r\n\r\n   return res;\r\n}\r\n\r\nstatic int rect_height_compare(const void *a, const void *b)\r\n{\r\n   const stbrp_rect *p = (const stbrp_rect *) a;\r\n   const stbrp_rect *q = (const stbrp_rect *) b;\r\n   if (p->h > q->h)\r\n      return -1;\r\n   if (p->h < q->h)\r\n      return  1;\r\n   return (p->w > q->w) ? -1 : (p->w < q->w);\r\n}\r\n\r\nstatic int rect_width_compare(const void *a, const void *b)\r\n{\r\n   const stbrp_rect *p = (const stbrp_rect *) a;\r\n   const stbrp_rect *q = (const stbrp_rect *) b;\r\n   if (p->w > q->w)\r\n      return -1;\r\n   if (p->w < q->w)\r\n      return  1;\r\n   return (p->h > q->h) ? -1 : (p->h < q->h);\r\n}\r\n\r\nstatic int rect_original_order(const void *a, const void *b)\r\n{\r\n   const stbrp_rect *p = (const stbrp_rect *) a;\r\n   const stbrp_rect *q = (const stbrp_rect *) b;\r\n   return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);\r\n}\r\n\r\n#ifdef STBRP_LARGE_RECTS\r\n#define STBRP__MAXVAL  0xffffffff\r\n#else\r\n#define STBRP__MAXVAL  0xffff\r\n#endif\r\n\r\nSTBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)\r\n{\r\n   int i;\r\n\r\n   // we use the 'was_packed' field internally to allow sorting/unsorting\r\n   for (i=0; i < num_rects; ++i) {\r\n      rects[i].was_packed = i;\r\n      #ifndef STBRP_LARGE_RECTS\r\n      STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);\r\n      #endif\r\n   }\r\n\r\n   // sort according to heuristic\r\n   STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);\r\n\r\n   for (i=0; i < num_rects; ++i) {\r\n      if (rects[i].w == 0 || rects[i].h == 0) {\r\n         rects[i].x = rects[i].y = 0;  // empty rect needs no space\r\n      } else {\r\n         stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);\r\n         if (fr.prev_link) {\r\n            rects[i].x = (stbrp_coord) fr.x;\r\n            rects[i].y = (stbrp_coord) fr.y;\r\n         } else {\r\n            rects[i].x = rects[i].y = STBRP__MAXVAL;\r\n         }\r\n      }\r\n   }\r\n\r\n   // unsort\r\n   STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);\r\n\r\n   // set was_packed flags\r\n   for (i=0; i < num_rects; ++i)\r\n      rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);\r\n}\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/stb_textedit.h",
    "content": "// [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothings/sb\r\n// [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815)\r\n// [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715)\r\n// [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681)\r\n// [ImGui] - fixed some minor warnings\r\n\r\n// stb_textedit.h - v1.9  - public domain - Sean Barrett\r\n// Development of this library was sponsored by RAD Game Tools\r\n//\r\n// This C header file implements the guts of a multi-line text-editing\r\n// widget; you implement display, word-wrapping, and low-level string\r\n// insertion/deletion, and stb_textedit will map user inputs into\r\n// insertions & deletions, plus updates to the cursor position,\r\n// selection state, and undo state.\r\n//\r\n// It is intended for use in games and other systems that need to build\r\n// their own custom widgets and which do not have heavy text-editing\r\n// requirements (this library is not recommended for use for editing large\r\n// texts, as its performance does not scale and it has limited undo).\r\n//\r\n// Non-trivial behaviors are modelled after Windows text controls.\r\n// \r\n//\r\n// LICENSE\r\n//\r\n//   This software is dual-licensed to the public domain and under the following\r\n//   license: you are granted a perpetual, irrevocable license to copy, modify,\r\n//   publish, and distribute this file as you see fit.\r\n//\r\n//\r\n// DEPENDENCIES\r\n//\r\n// Uses the C runtime function 'memmove', which you can override\r\n// by defining STB_TEXTEDIT_memmove before the implementation.\r\n// Uses no other functions. Performs no runtime allocations.\r\n//\r\n//\r\n// VERSION HISTORY\r\n//\r\n//   1.9  (2016-08-27) customizable move-by-word\r\n//   1.8  (2016-04-02) better keyboard handling when mouse button is down\r\n//   1.7  (2015-09-13) change y range handling in case baseline is non-0\r\n//   1.6  (2015-04-15) allow STB_TEXTEDIT_memmove\r\n//   1.5  (2014-09-10) add support for secondary keys for OS X\r\n//   1.4  (2014-08-17) fix signed/unsigned warnings\r\n//   1.3  (2014-06-19) fix mouse clicking to round to nearest char boundary\r\n//   1.2  (2014-05-27) fix some RAD types that had crept into the new code\r\n//   1.1  (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE )\r\n//   1.0  (2012-07-26) improve documentation, initial public release\r\n//   0.3  (2012-02-24) bugfixes, single-line mode; insert mode\r\n//   0.2  (2011-11-28) fixes to undo/redo\r\n//   0.1  (2010-07-08) initial version\r\n//\r\n// ADDITIONAL CONTRIBUTORS\r\n//\r\n//   Ulf Winklemann: move-by-word in 1.1\r\n//   Fabian Giesen: secondary key inputs in 1.5\r\n//   Martins Mozeiko: STB_TEXTEDIT_memmove\r\n//\r\n//   Bugfixes:\r\n//      Scott Graham\r\n//      Daniel Keller\r\n//      Omar Cornut\r\n//\r\n// USAGE\r\n//\r\n// This file behaves differently depending on what symbols you define\r\n// before including it.\r\n//\r\n//\r\n// Header-file mode:\r\n//\r\n//   If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this,\r\n//   it will operate in \"header file\" mode. In this mode, it declares a\r\n//   single public symbol, STB_TexteditState, which encapsulates the current\r\n//   state of a text widget (except for the string, which you will store\r\n//   separately).\r\n//\r\n//   To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a\r\n//   primitive type that defines a single character (e.g. char, wchar_t, etc).\r\n//\r\n//   To save space or increase undo-ability, you can optionally define the\r\n//   following things that are used by the undo system:\r\n//\r\n//      STB_TEXTEDIT_POSITIONTYPE         small int type encoding a valid cursor position\r\n//      STB_TEXTEDIT_UNDOSTATECOUNT       the number of undo states to allow\r\n//      STB_TEXTEDIT_UNDOCHARCOUNT        the number of characters to store in the undo buffer\r\n//\r\n//   If you don't define these, they are set to permissive types and\r\n//   moderate sizes. The undo system does no memory allocations, so\r\n//   it grows STB_TexteditState by the worst-case storage which is (in bytes):\r\n//\r\n//        [4 + sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT\r\n//      +      sizeof(STB_TEXTEDIT_CHARTYPE)      * STB_TEXTEDIT_UNDOCHAR_COUNT\r\n//\r\n//\r\n// Implementation mode:\r\n//\r\n//   If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it\r\n//   will compile the implementation of the text edit widget, depending\r\n//   on a large number of symbols which must be defined before the include.\r\n//\r\n//   The implementation is defined only as static functions. You will then\r\n//   need to provide your own APIs in the same file which will access the\r\n//   static functions.\r\n//\r\n//   The basic concept is that you provide a \"string\" object which\r\n//   behaves like an array of characters. stb_textedit uses indices to\r\n//   refer to positions in the string, implicitly representing positions\r\n//   in the displayed textedit. This is true for both plain text and\r\n//   rich text; even with rich text stb_truetype interacts with your\r\n//   code as if there was an array of all the displayed characters.\r\n//\r\n// Symbols that must be the same in header-file and implementation mode:\r\n//\r\n//     STB_TEXTEDIT_CHARTYPE             the character type\r\n//     STB_TEXTEDIT_POSITIONTYPE         small type that a valid cursor position\r\n//     STB_TEXTEDIT_UNDOSTATECOUNT       the number of undo states to allow\r\n//     STB_TEXTEDIT_UNDOCHARCOUNT        the number of characters to store in the undo buffer\r\n//\r\n// Symbols you must define for implementation mode:\r\n//\r\n//    STB_TEXTEDIT_STRING               the type of object representing a string being edited,\r\n//                                      typically this is a wrapper object with other data you need\r\n//\r\n//    STB_TEXTEDIT_STRINGLEN(obj)       the length of the string (ideally O(1))\r\n//    STB_TEXTEDIT_LAYOUTROW(&r,obj,n)  returns the results of laying out a line of characters\r\n//                                        starting from character #n (see discussion below)\r\n//    STB_TEXTEDIT_GETWIDTH(obj,n,i)    returns the pixel delta from the xpos of the i'th character\r\n//                                        to the xpos of the i+1'th char for a line of characters\r\n//                                        starting at character #n (i.e. accounts for kerning\r\n//                                        with previous char)\r\n//    STB_TEXTEDIT_KEYTOTEXT(k)         maps a keyboard input to an insertable character\r\n//                                        (return type is int, -1 means not valid to insert)\r\n//    STB_TEXTEDIT_GETCHAR(obj,i)       returns the i'th character of obj, 0-based\r\n//    STB_TEXTEDIT_NEWLINE              the character returned by _GETCHAR() we recognize\r\n//                                        as manually wordwrapping for end-of-line positioning\r\n//\r\n//    STB_TEXTEDIT_DELETECHARS(obj,i,n)      delete n characters starting at i\r\n//    STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n)   insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)\r\n//\r\n//    STB_TEXTEDIT_K_SHIFT       a power of two that is or'd in to a keyboard input to represent the shift key\r\n//\r\n//    STB_TEXTEDIT_K_LEFT        keyboard input to move cursor left\r\n//    STB_TEXTEDIT_K_RIGHT       keyboard input to move cursor right\r\n//    STB_TEXTEDIT_K_UP          keyboard input to move cursor up\r\n//    STB_TEXTEDIT_K_DOWN        keyboard input to move cursor down\r\n//    STB_TEXTEDIT_K_LINESTART   keyboard input to move cursor to start of line  // e.g. HOME\r\n//    STB_TEXTEDIT_K_LINEEND     keyboard input to move cursor to end of line    // e.g. END\r\n//    STB_TEXTEDIT_K_TEXTSTART   keyboard input to move cursor to start of text  // e.g. ctrl-HOME\r\n//    STB_TEXTEDIT_K_TEXTEND     keyboard input to move cursor to end of text    // e.g. ctrl-END\r\n//    STB_TEXTEDIT_K_DELETE      keyboard input to delete selection or character under cursor\r\n//    STB_TEXTEDIT_K_BACKSPACE   keyboard input to delete selection or character left of cursor\r\n//    STB_TEXTEDIT_K_UNDO        keyboard input to perform undo\r\n//    STB_TEXTEDIT_K_REDO        keyboard input to perform redo\r\n//\r\n// Optional:\r\n//    STB_TEXTEDIT_K_INSERT              keyboard input to toggle insert mode\r\n//    STB_TEXTEDIT_IS_SPACE(ch)          true if character is whitespace (e.g. 'isspace'),\r\n//                                          required for default WORDLEFT/WORDRIGHT handlers\r\n//    STB_TEXTEDIT_MOVEWORDLEFT(obj,i)   custom handler for WORDLEFT, returns index to move cursor to\r\n//    STB_TEXTEDIT_MOVEWORDRIGHT(obj,i)  custom handler for WORDRIGHT, returns index to move cursor to\r\n//    STB_TEXTEDIT_K_WORDLEFT            keyboard input to move cursor left one word // e.g. ctrl-LEFT\r\n//    STB_TEXTEDIT_K_WORDRIGHT           keyboard input to move cursor right one word // e.g. ctrl-RIGHT\r\n//    STB_TEXTEDIT_K_LINESTART2          secondary keyboard input to move cursor to start of line\r\n//    STB_TEXTEDIT_K_LINEEND2            secondary keyboard input to move cursor to end of line\r\n//    STB_TEXTEDIT_K_TEXTSTART2          secondary keyboard input to move cursor to start of text\r\n//    STB_TEXTEDIT_K_TEXTEND2            secondary keyboard input to move cursor to end of text\r\n//\r\n// Todo:\r\n//    STB_TEXTEDIT_K_PGUP        keyboard input to move cursor up a page\r\n//    STB_TEXTEDIT_K_PGDOWN      keyboard input to move cursor down a page\r\n//\r\n// Keyboard input must be encoded as a single integer value; e.g. a character code\r\n// and some bitflags that represent shift states. to simplify the interface, SHIFT must\r\n// be a bitflag, so we can test the shifted state of cursor movements to allow selection,\r\n// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.\r\n//\r\n// You can encode other things, such as CONTROL or ALT, in additional bits, and\r\n// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,\r\n// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN\r\n// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit,\r\n// and I pass both WM_KEYDOWN and WM_CHAR events to the \"key\" function in the\r\n// API below. The control keys will only match WM_KEYDOWN events because of the\r\n// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN\r\n// bit so it only decodes WM_CHAR events.\r\n//\r\n// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed\r\n// row of characters assuming they start on the i'th character--the width and\r\n// the height and the number of characters consumed. This allows this library\r\n// to traverse the entire layout incrementally. You need to compute word-wrapping\r\n// here.\r\n//\r\n// Each textfield keeps its own insert mode state, which is not how normal\r\n// applications work. To keep an app-wide insert mode, update/copy the\r\n// \"insert_mode\" field of STB_TexteditState before/after calling API functions.\r\n//\r\n// API\r\n//\r\n//    void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)\r\n//\r\n//    void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)\r\n//    void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)\r\n//    int  stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n//    int  stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)\r\n//    void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key)\r\n//\r\n//    Each of these functions potentially updates the string and updates the\r\n//    state.\r\n//\r\n//      initialize_state:\r\n//          set the textedit state to a known good default state when initially\r\n//          constructing the textedit.\r\n//\r\n//      click:\r\n//          call this with the mouse x,y on a mouse down; it will update the cursor\r\n//          and reset the selection start/end to the cursor point. the x,y must\r\n//          be relative to the text widget, with (0,0) being the top left.\r\n//     \r\n//      drag:\r\n//          call this with the mouse x,y on a mouse drag/up; it will update the\r\n//          cursor and the selection end point\r\n//     \r\n//      cut:\r\n//          call this to delete the current selection; returns true if there was\r\n//          one. you should FIRST copy the current selection to the system paste buffer.\r\n//          (To copy, just copy the current selection out of the string yourself.)\r\n//     \r\n//      paste:\r\n//          call this to paste text at the current cursor point or over the current\r\n//          selection if there is one.\r\n//     \r\n//      key:\r\n//          call this for keyboard inputs sent to the textfield. you can use it\r\n//          for \"key down\" events or for \"translated\" key events. if you need to\r\n//          do both (as in Win32), or distinguish Unicode characters from control\r\n//          inputs, set a high bit to distinguish the two; then you can define the\r\n//          various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit\r\n//          set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is\r\n//          clear.\r\n//     \r\n//   When rendering, you can read the cursor position and selection state from\r\n//   the STB_TexteditState.\r\n//\r\n//\r\n// Notes:\r\n//\r\n// This is designed to be usable in IMGUI, so it allows for the possibility of\r\n// running in an IMGUI that has NOT cached the multi-line layout. For this\r\n// reason, it provides an interface that is compatible with computing the\r\n// layout incrementally--we try to make sure we make as few passes through\r\n// as possible. (For example, to locate the mouse pointer in the text, we\r\n// could define functions that return the X and Y positions of characters\r\n// and binary search Y and then X, but if we're doing dynamic layout this\r\n// will run the layout algorithm many times, so instead we manually search\r\n// forward in one pass. Similar logic applies to e.g. up-arrow and\r\n// down-arrow movement.)\r\n//\r\n// If it's run in a widget that *has* cached the layout, then this is less\r\n// efficient, but it's not horrible on modern computers. But you wouldn't\r\n// want to edit million-line files with it.\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////\r\n////\r\n////   Header-file mode\r\n////\r\n////\r\n\r\n#ifndef INCLUDE_STB_TEXTEDIT_H\r\n#define INCLUDE_STB_TEXTEDIT_H\r\n\r\n////////////////////////////////////////////////////////////////////////\r\n//\r\n//     STB_TexteditState\r\n//\r\n// Definition of STB_TexteditState which you should store\r\n// per-textfield; it includes cursor position, selection state,\r\n// and undo state.\r\n//\r\n\r\n#ifndef STB_TEXTEDIT_UNDOSTATECOUNT\r\n#define STB_TEXTEDIT_UNDOSTATECOUNT   99\r\n#endif\r\n#ifndef STB_TEXTEDIT_UNDOCHARCOUNT\r\n#define STB_TEXTEDIT_UNDOCHARCOUNT   999\r\n#endif\r\n#ifndef STB_TEXTEDIT_CHARTYPE\r\n#define STB_TEXTEDIT_CHARTYPE        int\r\n#endif\r\n#ifndef STB_TEXTEDIT_POSITIONTYPE\r\n#define STB_TEXTEDIT_POSITIONTYPE    int\r\n#endif\r\n\r\ntypedef struct\r\n{\r\n   // private data\r\n   STB_TEXTEDIT_POSITIONTYPE  where;\r\n   short           insert_length;\r\n   short           delete_length;\r\n   short           char_storage;\r\n} StbUndoRecord;\r\n\r\ntypedef struct\r\n{\r\n   // private data\r\n   StbUndoRecord          undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];\r\n   STB_TEXTEDIT_CHARTYPE  undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];\r\n   short undo_point, redo_point;\r\n   short undo_char_point, redo_char_point;\r\n} StbUndoState;\r\n\r\ntypedef struct\r\n{\r\n   /////////////////////\r\n   //\r\n   // public data\r\n   //\r\n\r\n   int cursor;\r\n   // position of the text cursor within the string\r\n\r\n   int select_start;          // selection start point\r\n   int select_end;\r\n   // selection start and end point in characters; if equal, no selection.\r\n   // note that start may be less than or greater than end (e.g. when\r\n   // dragging the mouse, start is where the initial click was, and you\r\n   // can drag in either direction)\r\n\r\n   unsigned char insert_mode;\r\n   // each textfield keeps its own insert mode state. to keep an app-wide\r\n   // insert mode, copy this value in/out of the app state\r\n\r\n   /////////////////////\r\n   //\r\n   // private data\r\n   //\r\n   unsigned char cursor_at_end_of_line; // not implemented yet\r\n   unsigned char initialized;\r\n   unsigned char has_preferred_x;\r\n   unsigned char single_line;\r\n   unsigned char padding1, padding2, padding3;\r\n   float preferred_x; // this determines where the cursor up/down tries to seek to along x\r\n   StbUndoState undostate;\r\n} STB_TexteditState;\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////\r\n//\r\n//     StbTexteditRow\r\n//\r\n// Result of layout query, used by stb_textedit to determine where\r\n// the text in each row is.\r\n\r\n// result of layout query\r\ntypedef struct\r\n{\r\n   float x0,x1;             // starting x location, end x location (allows for align=right, etc)\r\n   float baseline_y_delta;  // position of baseline relative to previous row's baseline\r\n   float ymin,ymax;         // height of row above and below baseline\r\n   int num_chars;\r\n} StbTexteditRow;\r\n#endif //INCLUDE_STB_TEXTEDIT_H\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////\r\n////\r\n////   Implementation mode\r\n////\r\n////\r\n\r\n\r\n// implementation isn't include-guarded, since it might have indirectly\r\n// included just the \"header\" portion\r\n#ifdef STB_TEXTEDIT_IMPLEMENTATION\r\n\r\n#ifndef STB_TEXTEDIT_memmove\r\n#include <string.h>\r\n#define STB_TEXTEDIT_memmove memmove\r\n#endif\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n//      Mouse input handling\r\n//\r\n\r\n// traverse the layout to locate the nearest character to a display position\r\nstatic int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)\r\n{\r\n   StbTexteditRow r;\r\n   int n = STB_TEXTEDIT_STRINGLEN(str);\r\n   float base_y = 0, prev_x;\r\n   int i=0, k;\r\n\r\n   r.x0 = r.x1 = 0;\r\n   r.ymin = r.ymax = 0;\r\n   r.num_chars = 0;\r\n\r\n   // search rows to find one that straddles 'y'\r\n   while (i < n) {\r\n      STB_TEXTEDIT_LAYOUTROW(&r, str, i);\r\n      if (r.num_chars <= 0)\r\n         return n;\r\n\r\n      if (i==0 && y < base_y + r.ymin)\r\n         return 0;\r\n\r\n      if (y < base_y + r.ymax)\r\n         break;\r\n\r\n      i += r.num_chars;\r\n      base_y += r.baseline_y_delta;\r\n   }\r\n\r\n   // below all text, return 'after' last character\r\n   if (i >= n)\r\n      return n;\r\n\r\n   // check if it's before the beginning of the line\r\n   if (x < r.x0)\r\n      return i;\r\n\r\n   // check if it's before the end of the line\r\n   if (x < r.x1) {\r\n      // search characters in row for one that straddles 'x'\r\n      prev_x = r.x0;\r\n      for (k=0; k < r.num_chars; ++k) {\r\n         float w = STB_TEXTEDIT_GETWIDTH(str, i, k);\r\n         if (x < prev_x+w) {\r\n            if (x < prev_x+w/2)\r\n               return k+i;\r\n            else\r\n               return k+i+1;\r\n         }\r\n         prev_x += w;\r\n      }\r\n      // shouldn't happen, but if it does, fall through to end-of-line case\r\n   }\r\n\r\n   // if the last character is a newline, return that. otherwise return 'after' the last character\r\n   if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE)\r\n      return i+r.num_chars-1;\r\n   else\r\n      return i+r.num_chars;\r\n}\r\n\r\n// API click: on mouse down, move the cursor to the clicked location, and reset the selection\r\nstatic void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)\r\n{\r\n   state->cursor = stb_text_locate_coord(str, x, y);\r\n   state->select_start = state->cursor;\r\n   state->select_end = state->cursor;\r\n   state->has_preferred_x = 0;\r\n}\r\n\r\n// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location\r\nstatic void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)\r\n{\r\n   int p = stb_text_locate_coord(str, x, y);\r\n   if (state->select_start == state->select_end)\r\n      state->select_start = state->cursor;\r\n   state->cursor = state->select_end = p;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n//      Keyboard input handling\r\n//\r\n\r\n// forward declarations\r\nstatic void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);\r\nstatic void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);\r\nstatic void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);\r\nstatic void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);\r\nstatic void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);\r\n\r\ntypedef struct\r\n{\r\n   float x,y;    // position of n'th character\r\n   float height; // height of line\r\n   int first_char, length; // first char of row, and length\r\n   int prev_first;  // first char of previous row\r\n} StbFindState;\r\n\r\n// find the x/y location of a character, and remember info about the previous row in\r\n// case we get a move-up event (for page up, we'll have to rescan)\r\nstatic void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)\r\n{\r\n   StbTexteditRow r;\r\n   int prev_start = 0;\r\n   int z = STB_TEXTEDIT_STRINGLEN(str);\r\n   int i=0, first;\r\n\r\n   if (n == z) {\r\n      // if it's at the end, then find the last line -- simpler than trying to\r\n      // explicitly handle this case in the regular code\r\n      if (single_line) {\r\n         STB_TEXTEDIT_LAYOUTROW(&r, str, 0);\r\n         find->y = 0;\r\n         find->first_char = 0;\r\n         find->length = z;\r\n         find->height = r.ymax - r.ymin;\r\n         find->x = r.x1;\r\n      } else {\r\n         find->y = 0;\r\n         find->x = 0;\r\n         find->height = 1;\r\n         while (i < z) {\r\n            STB_TEXTEDIT_LAYOUTROW(&r, str, i);\r\n            prev_start = i;\r\n            i += r.num_chars;\r\n         }\r\n         find->first_char = i;\r\n         find->length = 0;\r\n         find->prev_first = prev_start;\r\n      }\r\n      return;\r\n   }\r\n\r\n   // search rows to find the one that straddles character n\r\n   find->y = 0;\r\n\r\n   for(;;) {\r\n      STB_TEXTEDIT_LAYOUTROW(&r, str, i);\r\n      if (n < i + r.num_chars)\r\n         break;\r\n      prev_start = i;\r\n      i += r.num_chars;\r\n      find->y += r.baseline_y_delta;\r\n   }\r\n\r\n   find->first_char = first = i;\r\n   find->length = r.num_chars;\r\n   find->height = r.ymax - r.ymin;\r\n   find->prev_first = prev_start;\r\n\r\n   // now scan to find xpos\r\n   find->x = r.x0;\r\n   i = 0;\r\n   for (i=0; first+i < n; ++i)\r\n      find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);\r\n}\r\n\r\n#define STB_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end)\r\n\r\n// make the selection/cursor state valid if client altered the string\r\nstatic void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n{\r\n   int n = STB_TEXTEDIT_STRINGLEN(str);\r\n   if (STB_TEXT_HAS_SELECTION(state)) {\r\n      if (state->select_start > n) state->select_start = n;\r\n      if (state->select_end   > n) state->select_end = n;\r\n      // if clamping forced them to be equal, move the cursor to match\r\n      if (state->select_start == state->select_end)\r\n         state->cursor = state->select_start;\r\n   }\r\n   if (state->cursor > n) state->cursor = n;\r\n}\r\n\r\n// delete characters while updating undo\r\nstatic void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)\r\n{\r\n   stb_text_makeundo_delete(str, state, where, len);\r\n   STB_TEXTEDIT_DELETECHARS(str, where, len);\r\n   state->has_preferred_x = 0;\r\n}\r\n\r\n// delete the section\r\nstatic void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n{\r\n   stb_textedit_clamp(str, state);\r\n   if (STB_TEXT_HAS_SELECTION(state)) {\r\n      if (state->select_start < state->select_end) {\r\n         stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start);\r\n         state->select_end = state->cursor = state->select_start;\r\n      } else {\r\n         stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end);\r\n         state->select_start = state->cursor = state->select_end;\r\n      }\r\n      state->has_preferred_x = 0;\r\n   }\r\n}\r\n\r\n// canoncialize the selection so start <= end\r\nstatic void stb_textedit_sortselection(STB_TexteditState *state)\r\n{\r\n   if (state->select_end < state->select_start) {\r\n      int temp = state->select_end;\r\n      state->select_end = state->select_start;\r\n      state->select_start = temp;\r\n   }\r\n}\r\n\r\n// move cursor to first character of selection\r\nstatic void stb_textedit_move_to_first(STB_TexteditState *state)\r\n{\r\n   if (STB_TEXT_HAS_SELECTION(state)) {\r\n      stb_textedit_sortselection(state);\r\n      state->cursor = state->select_start;\r\n      state->select_end = state->select_start;\r\n      state->has_preferred_x = 0;\r\n   }\r\n}\r\n\r\n// move cursor to last character of selection\r\nstatic void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n{\r\n   if (STB_TEXT_HAS_SELECTION(state)) {\r\n      stb_textedit_sortselection(state);\r\n      stb_textedit_clamp(str, state);\r\n      state->cursor = state->select_end;\r\n      state->select_start = state->select_end;\r\n      state->has_preferred_x = 0;\r\n   }\r\n}\r\n\r\n#ifdef STB_TEXTEDIT_IS_SPACE\r\nstatic int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )\r\n{\r\n   return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;\r\n}\r\n\r\n#ifndef STB_TEXTEDIT_MOVEWORDLEFT\r\nstatic int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )\r\n{\r\n   --c; // always move at least one character\r\n   while( c >= 0 && !is_word_boundary( str, c ) )\r\n      --c;\r\n\r\n   if( c < 0 )\r\n      c = 0;\r\n\r\n   return c;\r\n}\r\n#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous\r\n#endif\r\n\r\n#ifndef STB_TEXTEDIT_MOVEWORDRIGHT\r\nstatic int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )\r\n{\r\n   const int len = STB_TEXTEDIT_STRINGLEN(str);\r\n   ++c; // always move at least one character\r\n   while( c < len && !is_word_boundary( str, c ) )\r\n      ++c;\r\n\r\n   if( c > len )\r\n      c = len;\r\n\r\n   return c;\r\n}\r\n#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next\r\n#endif\r\n\r\n#endif\r\n\r\n// update selection and cursor to match each other\r\nstatic void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)\r\n{\r\n   if (!STB_TEXT_HAS_SELECTION(state))\r\n      state->select_start = state->select_end = state->cursor;\r\n   else\r\n      state->cursor = state->select_end;\r\n}\r\n\r\n// API cut: delete selection\r\nstatic int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n{\r\n   if (STB_TEXT_HAS_SELECTION(state)) {\r\n      stb_textedit_delete_selection(str,state); // implicity clamps\r\n      state->has_preferred_x = 0;\r\n      return 1;\r\n   }\r\n   return 0;\r\n}\r\n\r\n// API paste: replace existing selection with passed-in text\r\nstatic int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)\r\n{\r\n   STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *) ctext;\r\n   // if there's a selection, the paste should delete it\r\n   stb_textedit_clamp(str, state);\r\n   stb_textedit_delete_selection(str,state);\r\n   // try to insert the characters\r\n   if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {\r\n      stb_text_makeundo_insert(state, state->cursor, len);\r\n      state->cursor += len;\r\n      state->has_preferred_x = 0;\r\n      return 1;\r\n   }\r\n   // remove the undo since we didn't actually insert the characters\r\n   if (state->undostate.undo_point)\r\n      --state->undostate.undo_point;\r\n   return 0;\r\n}\r\n\r\n// API key: process a keyboard input\r\nstatic void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key)\r\n{\r\nretry:\r\n   switch (key) {\r\n      default: {\r\n         int c = STB_TEXTEDIT_KEYTOTEXT(key);\r\n         if (c > 0) {\r\n            STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;\r\n\r\n            // can't add newline in single-line mode\r\n            if (c == '\\n' && state->single_line)\r\n               break;\r\n\r\n            if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {\r\n               stb_text_makeundo_replace(str, state, state->cursor, 1, 1);\r\n               STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);\r\n               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {\r\n                  ++state->cursor;\r\n                  state->has_preferred_x = 0;\r\n               }\r\n            } else {\r\n               stb_textedit_delete_selection(str,state); // implicity clamps\r\n               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {\r\n                  stb_text_makeundo_insert(state, state->cursor, 1);\r\n                  ++state->cursor;\r\n                  state->has_preferred_x = 0;\r\n               }\r\n            }\r\n         }\r\n         break;\r\n      }\r\n\r\n#ifdef STB_TEXTEDIT_K_INSERT\r\n      case STB_TEXTEDIT_K_INSERT:\r\n         state->insert_mode = !state->insert_mode;\r\n         break;\r\n#endif\r\n         \r\n      case STB_TEXTEDIT_K_UNDO:\r\n         stb_text_undo(str, state);\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_REDO:\r\n         stb_text_redo(str, state);\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_LEFT:\r\n         // if currently there's a selection, move cursor to start of selection\r\n         if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_move_to_first(state);\r\n         else \r\n            if (state->cursor > 0)\r\n               --state->cursor;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_RIGHT:\r\n         // if currently there's a selection, move cursor to end of selection\r\n         if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_move_to_last(str, state);\r\n         else\r\n            ++state->cursor;\r\n         stb_textedit_clamp(str, state);\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT:\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_prep_selection_at_cursor(state);\r\n         // move selection left\r\n         if (state->select_end > 0)\r\n            --state->select_end;\r\n         state->cursor = state->select_end;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n#ifdef STB_TEXTEDIT_MOVEWORDLEFT\r\n      case STB_TEXTEDIT_K_WORDLEFT:\r\n         if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_move_to_first(state);\r\n         else {\r\n            state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);\r\n            stb_textedit_clamp( str, state );\r\n         }\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT:\r\n         if( !STB_TEXT_HAS_SELECTION( state ) )\r\n            stb_textedit_prep_selection_at_cursor(state);\r\n\r\n         state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);\r\n         state->select_end = state->cursor;\r\n\r\n         stb_textedit_clamp( str, state );\r\n         break;\r\n#endif\r\n\r\n#ifdef STB_TEXTEDIT_MOVEWORDRIGHT\r\n      case STB_TEXTEDIT_K_WORDRIGHT:\r\n         if (STB_TEXT_HAS_SELECTION(state)) \r\n            stb_textedit_move_to_last(str, state);\r\n         else {\r\n            state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);\r\n            stb_textedit_clamp( str, state );\r\n         }\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT:\r\n         if( !STB_TEXT_HAS_SELECTION( state ) )\r\n            stb_textedit_prep_selection_at_cursor(state);\r\n\r\n         state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);\r\n         state->select_end = state->cursor;\r\n\r\n         stb_textedit_clamp( str, state );\r\n         break;\r\n#endif\r\n\r\n      case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:\r\n         stb_textedit_prep_selection_at_cursor(state);\r\n         // move selection right\r\n         ++state->select_end;\r\n         stb_textedit_clamp(str, state);\r\n         state->cursor = state->select_end;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_DOWN:\r\n      case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {\r\n         StbFindState find;\r\n         StbTexteditRow row;\r\n         int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;\r\n\r\n         if (state->single_line) {\r\n            // on windows, up&down in single-line behave like left&right\r\n            key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);\r\n            goto retry;\r\n         }\r\n\r\n         if (sel)\r\n            stb_textedit_prep_selection_at_cursor(state);\r\n         else if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_move_to_last(str,state);\r\n\r\n         // compute current position of cursor point\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);\r\n\r\n         // now find character position down a row\r\n         if (find.length) {\r\n            float goal_x = state->has_preferred_x ? state->preferred_x : find.x;\r\n            float x;\r\n            int start = find.first_char + find.length;\r\n            state->cursor = start;\r\n            STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);\r\n            x = row.x0;\r\n            for (i=0; i < row.num_chars; ++i) {\r\n               float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);\r\n               #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE\r\n               if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)\r\n                  break;\r\n               #endif\r\n               x += dx;\r\n               if (x > goal_x)\r\n                  break;\r\n               ++state->cursor;\r\n            }\r\n            stb_textedit_clamp(str, state);\r\n\r\n            state->has_preferred_x = 1;\r\n            state->preferred_x = goal_x;\r\n\r\n            if (sel)\r\n               state->select_end = state->cursor;\r\n         }\r\n         break;\r\n      }\r\n         \r\n      case STB_TEXTEDIT_K_UP:\r\n      case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {\r\n         StbFindState find;\r\n         StbTexteditRow row;\r\n         int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;\r\n\r\n         if (state->single_line) {\r\n            // on windows, up&down become left&right\r\n            key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);\r\n            goto retry;\r\n         }\r\n\r\n         if (sel)\r\n            stb_textedit_prep_selection_at_cursor(state);\r\n         else if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_move_to_first(state);\r\n\r\n         // compute current position of cursor point\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);\r\n\r\n         // can only go up if there's a previous row\r\n         if (find.prev_first != find.first_char) {\r\n            // now find character position up a row\r\n            float goal_x = state->has_preferred_x ? state->preferred_x : find.x;\r\n            float x;\r\n            state->cursor = find.prev_first;\r\n            STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);\r\n            x = row.x0;\r\n            for (i=0; i < row.num_chars; ++i) {\r\n               float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);\r\n               #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE\r\n               if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)\r\n                  break;\r\n               #endif\r\n               x += dx;\r\n               if (x > goal_x)\r\n                  break;\r\n               ++state->cursor;\r\n            }\r\n            stb_textedit_clamp(str, state);\r\n\r\n            state->has_preferred_x = 1;\r\n            state->preferred_x = goal_x;\r\n\r\n            if (sel)\r\n               state->select_end = state->cursor;\r\n         }\r\n         break;\r\n      }\r\n\r\n      case STB_TEXTEDIT_K_DELETE:\r\n      case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT:\r\n         if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_delete_selection(str, state);\r\n         else {\r\n            int n = STB_TEXTEDIT_STRINGLEN(str);\r\n            if (state->cursor < n)\r\n               stb_textedit_delete(str, state, state->cursor, 1);\r\n         }\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n      case STB_TEXTEDIT_K_BACKSPACE:\r\n      case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT:\r\n         if (STB_TEXT_HAS_SELECTION(state))\r\n            stb_textedit_delete_selection(str, state);\r\n         else {\r\n            stb_textedit_clamp(str, state);\r\n            if (state->cursor > 0) {\r\n               stb_textedit_delete(str, state, state->cursor-1, 1);\r\n               --state->cursor;\r\n            }\r\n         }\r\n         state->has_preferred_x = 0;\r\n         break;\r\n         \r\n#ifdef STB_TEXTEDIT_K_TEXTSTART2\r\n      case STB_TEXTEDIT_K_TEXTSTART2:\r\n#endif\r\n      case STB_TEXTEDIT_K_TEXTSTART:\r\n         state->cursor = state->select_start = state->select_end = 0;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n#ifdef STB_TEXTEDIT_K_TEXTEND2\r\n      case STB_TEXTEDIT_K_TEXTEND2:\r\n#endif\r\n      case STB_TEXTEDIT_K_TEXTEND:\r\n         state->cursor = STB_TEXTEDIT_STRINGLEN(str);\r\n         state->select_start = state->select_end = 0;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n        \r\n#ifdef STB_TEXTEDIT_K_TEXTSTART2\r\n      case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:\r\n#endif\r\n      case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:\r\n         stb_textedit_prep_selection_at_cursor(state);\r\n         state->cursor = state->select_end = 0;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n#ifdef STB_TEXTEDIT_K_TEXTEND2\r\n      case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:\r\n#endif\r\n      case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:\r\n         stb_textedit_prep_selection_at_cursor(state);\r\n         state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n\r\n#ifdef STB_TEXTEDIT_K_LINESTART2\r\n      case STB_TEXTEDIT_K_LINESTART2:\r\n#endif\r\n      case STB_TEXTEDIT_K_LINESTART:\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_move_to_first(state);\r\n         if (state->single_line)\r\n            state->cursor = 0;\r\n         else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)\r\n            --state->cursor;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n#ifdef STB_TEXTEDIT_K_LINEEND2\r\n      case STB_TEXTEDIT_K_LINEEND2:\r\n#endif\r\n      case STB_TEXTEDIT_K_LINEEND: {\r\n         int n = STB_TEXTEDIT_STRINGLEN(str);\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_move_to_first(state);\r\n         if (state->single_line)\r\n             state->cursor = n;\r\n         else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)\r\n             ++state->cursor;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n      }\r\n\r\n#ifdef STB_TEXTEDIT_K_LINESTART2\r\n      case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:\r\n#endif\r\n      case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_prep_selection_at_cursor(state);\r\n         if (state->single_line)\r\n            state->cursor = 0;\r\n         else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)\r\n            --state->cursor;\r\n         state->select_end = state->cursor;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n\r\n#ifdef STB_TEXTEDIT_K_LINEEND2\r\n      case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:\r\n#endif\r\n      case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {\r\n         int n = STB_TEXTEDIT_STRINGLEN(str);\r\n         stb_textedit_clamp(str, state);\r\n         stb_textedit_prep_selection_at_cursor(state);\r\n         if (state->single_line)\r\n             state->cursor = n;\r\n         else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)\r\n            ++state->cursor;\r\n         state->select_end = state->cursor;\r\n         state->has_preferred_x = 0;\r\n         break;\r\n      }\r\n\r\n// @TODO:\r\n//    STB_TEXTEDIT_K_PGUP      - move cursor up a page\r\n//    STB_TEXTEDIT_K_PGDOWN    - move cursor down a page\r\n   }\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n//      Undo processing\r\n//\r\n// @OPTIMIZE: the undo/redo buffer should be circular\r\n\r\nstatic void stb_textedit_flush_redo(StbUndoState *state)\r\n{\r\n   state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;\r\n   state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;\r\n}\r\n\r\n// discard the oldest entry in the undo list\r\nstatic void stb_textedit_discard_undo(StbUndoState *state)\r\n{\r\n   if (state->undo_point > 0) {\r\n      // if the 0th undo state has characters, clean those up\r\n      if (state->undo_rec[0].char_storage >= 0) {\r\n         int n = state->undo_rec[0].insert_length, i;\r\n         // delete n characters from all other records\r\n         state->undo_char_point = state->undo_char_point - (short) n;  // vsnet05\r\n         STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));\r\n         for (i=0; i < state->undo_point; ++i)\r\n            if (state->undo_rec[i].char_storage >= 0)\r\n               state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it\r\n      }\r\n      --state->undo_point;\r\n      STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0])));\r\n   }\r\n}\r\n\r\n// discard the oldest entry in the redo list--it's bad if this\r\n// ever happens, but because undo & redo have to store the actual\r\n// characters in different cases, the redo character buffer can\r\n// fill up even though the undo buffer didn't\r\nstatic void stb_textedit_discard_redo(StbUndoState *state)\r\n{\r\n   int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;\r\n\r\n   if (state->redo_point <= k) {\r\n      // if the k'th undo state has characters, clean those up\r\n      if (state->undo_rec[k].char_storage >= 0) {\r\n         int n = state->undo_rec[k].insert_length, i;\r\n         // delete n characters from all other records\r\n         state->redo_char_point = state->redo_char_point + (short) n; // vsnet05\r\n         STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));\r\n         for (i=state->redo_point; i < k; ++i)\r\n            if (state->undo_rec[i].char_storage >= 0)\r\n               state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05\r\n      }\r\n      STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));\r\n      ++state->redo_point;\r\n   }\r\n}\r\n\r\nstatic StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)\r\n{\r\n   // any time we create a new undo record, we discard redo\r\n   stb_textedit_flush_redo(state);\r\n\r\n   // if we have no free records, we have to make room, by sliding the\r\n   // existing records down\r\n   if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)\r\n      stb_textedit_discard_undo(state);\r\n\r\n   // if the characters to store won't possibly fit in the buffer, we can't undo\r\n   if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {\r\n      state->undo_point = 0;\r\n      state->undo_char_point = 0;\r\n      return NULL;\r\n   }\r\n\r\n   // if we don't have enough free characters in the buffer, we have to make room\r\n   while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)\r\n      stb_textedit_discard_undo(state);\r\n\r\n   return &state->undo_rec[state->undo_point++];\r\n}\r\n\r\nstatic STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)\r\n{\r\n   StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);\r\n   if (r == NULL)\r\n      return NULL;\r\n\r\n   r->where = pos;\r\n   r->insert_length = (short) insert_len;\r\n   r->delete_length = (short) delete_len;\r\n\r\n   if (insert_len == 0) {\r\n      r->char_storage = -1;\r\n      return NULL;\r\n   } else {\r\n      r->char_storage = state->undo_char_point;\r\n      state->undo_char_point = state->undo_char_point + (short) insert_len;\r\n      return &state->undo_char[r->char_storage];\r\n   }\r\n}\r\n\r\nstatic void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n{\r\n   StbUndoState *s = &state->undostate;\r\n   StbUndoRecord u, *r;\r\n   if (s->undo_point == 0)\r\n      return;\r\n\r\n   // we need to do two things: apply the undo record, and create a redo record\r\n   u = s->undo_rec[s->undo_point-1];\r\n   r = &s->undo_rec[s->redo_point-1];\r\n   r->char_storage = -1;\r\n\r\n   r->insert_length = u.delete_length;\r\n   r->delete_length = u.insert_length;\r\n   r->where = u.where;\r\n\r\n   if (u.delete_length) {\r\n      // if the undo record says to delete characters, then the redo record will\r\n      // need to re-insert the characters that get deleted, so we need to store\r\n      // them.\r\n\r\n      // there are three cases:\r\n      //    there's enough room to store the characters\r\n      //    characters stored for *redoing* don't leave room for redo\r\n      //    characters stored for *undoing* don't leave room for redo\r\n      // if the last is true, we have to bail\r\n\r\n      if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {\r\n         // the undo records take up too much character space; there's no space to store the redo characters\r\n         r->insert_length = 0;\r\n      } else {\r\n         int i;\r\n\r\n         // there's definitely room to store the characters eventually\r\n         while (s->undo_char_point + u.delete_length > s->redo_char_point) {\r\n            // there's currently not enough room, so discard a redo record\r\n            stb_textedit_discard_redo(s);\r\n            // should never happen:\r\n            if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)\r\n               return;\r\n         }\r\n         r = &s->undo_rec[s->redo_point-1];\r\n\r\n         r->char_storage = s->redo_char_point - u.delete_length;\r\n         s->redo_char_point = s->redo_char_point - (short) u.delete_length;\r\n\r\n         // now save the characters\r\n         for (i=0; i < u.delete_length; ++i)\r\n            s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);\r\n      }\r\n\r\n      // now we can carry out the deletion\r\n      STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);\r\n   }\r\n\r\n   // check type of recorded action:\r\n   if (u.insert_length) {\r\n      // easy case: was a deletion, so we need to insert n characters\r\n      STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);\r\n      s->undo_char_point -= u.insert_length;\r\n   }\r\n\r\n   state->cursor = u.where + u.insert_length;\r\n\r\n   s->undo_point--;\r\n   s->redo_point--;\r\n}\r\n\r\nstatic void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)\r\n{\r\n   StbUndoState *s = &state->undostate;\r\n   StbUndoRecord *u, r;\r\n   if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)\r\n      return;\r\n\r\n   // we need to do two things: apply the redo record, and create an undo record\r\n   u = &s->undo_rec[s->undo_point];\r\n   r = s->undo_rec[s->redo_point];\r\n\r\n   // we KNOW there must be room for the undo record, because the redo record\r\n   // was derived from an undo record\r\n\r\n   u->delete_length = r.insert_length;\r\n   u->insert_length = r.delete_length;\r\n   u->where = r.where;\r\n   u->char_storage = -1;\r\n\r\n   if (r.delete_length) {\r\n      // the redo record requires us to delete characters, so the undo record\r\n      // needs to store the characters\r\n\r\n      if (s->undo_char_point + u->insert_length > s->redo_char_point) {\r\n         u->insert_length = 0;\r\n         u->delete_length = 0;\r\n      } else {\r\n         int i;\r\n         u->char_storage = s->undo_char_point;\r\n         s->undo_char_point = s->undo_char_point + u->insert_length;\r\n\r\n         // now save the characters\r\n         for (i=0; i < u->insert_length; ++i)\r\n            s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i);\r\n      }\r\n\r\n      STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);\r\n   }\r\n\r\n   if (r.insert_length) {\r\n      // easy case: need to insert n characters\r\n      STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);\r\n      s->redo_char_point += r.insert_length;\r\n   }\r\n\r\n   state->cursor = r.where + r.insert_length;\r\n\r\n   s->undo_point++;\r\n   s->redo_point++;\r\n}\r\n\r\nstatic void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)\r\n{\r\n   stb_text_createundo(&state->undostate, where, 0, length);\r\n}\r\n\r\nstatic void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)\r\n{\r\n   int i;\r\n   STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);\r\n   if (p) {\r\n      for (i=0; i < length; ++i)\r\n         p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);\r\n   }\r\n}\r\n\r\nstatic void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)\r\n{\r\n   int i;\r\n   STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);\r\n   if (p) {\r\n      for (i=0; i < old_length; ++i)\r\n         p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);\r\n   }\r\n}\r\n\r\n// reset the state to default\r\nstatic void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)\r\n{\r\n   state->undostate.undo_point = 0;\r\n   state->undostate.undo_char_point = 0;\r\n   state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;\r\n   state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;\r\n   state->select_end = state->select_start = 0;\r\n   state->cursor = 0;\r\n   state->has_preferred_x = 0;\r\n   state->preferred_x = 0;\r\n   state->cursor_at_end_of_line = 0;\r\n   state->initialized = 1;\r\n   state->single_line = (unsigned char) is_single_line;\r\n   state->insert_mode = 0;\r\n}\r\n\r\n// API initialize\r\nstatic void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)\r\n{\r\n   stb_textedit_clear_state(state, is_single_line);\r\n}\r\n#endif//STB_TEXTEDIT_IMPLEMENTATION\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/GUI/imgui/stb_truetype.h",
    "content": "// stb_truetype.h - v1.14 - public domain\r\n// authored from 2009-2016 by Sean Barrett / RAD Game Tools\r\n//\r\n//   This library processes TrueType files:\r\n//        parse files\r\n//        extract glyph metrics\r\n//        extract glyph shapes\r\n//        render glyphs to one-channel bitmaps with antialiasing (box filter)\r\n//\r\n//   Todo:\r\n//        non-MS cmaps\r\n//        crashproof on bad data\r\n//        hinting? (no longer patented)\r\n//        cleartype-style AA?\r\n//        optimize: use simple memory allocator for intermediates\r\n//        optimize: build edge-list directly from curves\r\n//        optimize: rasterize directly from curves?\r\n//\r\n// ADDITIONAL CONTRIBUTORS\r\n//\r\n//   Mikko Mononen: compound shape support, more cmap formats\r\n//   Tor Andersson: kerning, subpixel rendering\r\n//   Dougall Johnson: OpenType / Type 2 font handling\r\n//\r\n//   Misc other:\r\n//       Ryan Gordon\r\n//       Simon Glass\r\n//       github:IntellectualKitty\r\n//\r\n//   Bug/warning reports/fixes:\r\n//       \"Zer\" on mollyrocket (with fix)\r\n//       Cass Everitt\r\n//       stoiko (Haemimont Games)\r\n//       Brian Hook \r\n//       Walter van Niftrik\r\n//       David Gow\r\n//       David Given\r\n//       Ivan-Assen Ivanov\r\n//       Anthony Pesch\r\n//       Johan Duparc\r\n//       Hou Qiming\r\n//       Fabian \"ryg\" Giesen\r\n//       Martins Mozeiko\r\n//       Cap Petschulat\r\n//       Omar Cornut\r\n//       github:aloucks\r\n//       Peter LaValle\r\n//       Sergey Popov\r\n//       Giumo X. Clanjor\r\n//       Higor Euripedes\r\n//       Thomas Fields\r\n//       Derek Vinyard\r\n//\r\n// VERSION HISTORY\r\n//\r\n//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, num-fonts-in-TTC function\r\n//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual\r\n//   1.11 (2016-04-02) fix unused-variable warning\r\n//   1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef\r\n//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly\r\n//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges\r\n//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;\r\n//                     variant PackFontRanges to pack and render in separate phases;\r\n//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);\r\n//                     fixed an assert() bug in the new rasterizer\r\n//                     replace assert() with STBTT_assert() in new rasterizer\r\n//\r\n//   Full history can be found at the end of this file.\r\n//\r\n// LICENSE\r\n//\r\n//   This software is dual-licensed to the public domain and under the following\r\n//   license: you are granted a perpetual, irrevocable license to copy, modify,\r\n//   publish, and distribute this file as you see fit.\r\n//\r\n// USAGE\r\n//\r\n//   Include this file in whatever places neeed to refer to it. In ONE C/C++\r\n//   file, write:\r\n//      #define STB_TRUETYPE_IMPLEMENTATION\r\n//   before the #include of this file. This expands out the actual\r\n//   implementation into that C/C++ file.\r\n//\r\n//   To make the implementation private to the file that generates the implementation,\r\n//      #define STBTT_STATIC\r\n//\r\n//   Simple 3D API (don't ship this, but it's fine for tools and quick start)\r\n//           stbtt_BakeFontBitmap()               -- bake a font to a bitmap for use as texture\r\n//           stbtt_GetBakedQuad()                 -- compute quad to draw for a given char\r\n//\r\n//   Improved 3D API (more shippable):\r\n//           #include \"stb_rect_pack.h\"           -- optional, but you really want it\r\n//           stbtt_PackBegin()\r\n//           stbtt_PackSetOversample()            -- for improved quality on small fonts\r\n//           stbtt_PackFontRanges()               -- pack and renders\r\n//           stbtt_PackEnd()\r\n//           stbtt_GetPackedQuad()\r\n//\r\n//   \"Load\" a font file from a memory buffer (you have to keep the buffer loaded)\r\n//           stbtt_InitFont()\r\n//           stbtt_GetFontOffsetForIndex()        -- indexing for TTC font collections\r\n//           stbtt_GetNumberOfFonts()             -- number of fonts for TTC font collections\r\n//\r\n//   Render a unicode codepoint to a bitmap\r\n//           stbtt_GetCodepointBitmap()           -- allocates and returns a bitmap\r\n//           stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide\r\n//           stbtt_GetCodepointBitmapBox()        -- how big the bitmap must be\r\n//\r\n//   Character advance/positioning\r\n//           stbtt_GetCodepointHMetrics()\r\n//           stbtt_GetFontVMetrics()\r\n//           stbtt_GetCodepointKernAdvance()\r\n//\r\n//   Starting with version 1.06, the rasterizer was replaced with a new,\r\n//   faster and generally-more-precise rasterizer. The new rasterizer more\r\n//   accurately measures pixel coverage for anti-aliasing, except in the case\r\n//   where multiple shapes overlap, in which case it overestimates the AA pixel\r\n//   coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If\r\n//   this turns out to be a problem, you can re-enable the old rasterizer with\r\n//        #define STBTT_RASTERIZER_VERSION 1\r\n//   which will incur about a 15% speed hit.\r\n//\r\n// ADDITIONAL DOCUMENTATION\r\n//\r\n//   Immediately after this block comment are a series of sample programs.\r\n//\r\n//   After the sample programs is the \"header file\" section. This section\r\n//   includes documentation for each API function.\r\n//\r\n//   Some important concepts to understand to use this library:\r\n//\r\n//      Codepoint\r\n//         Characters are defined by unicode codepoints, e.g. 65 is\r\n//         uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is\r\n//         the hiragana for \"ma\".\r\n//\r\n//      Glyph\r\n//         A visual character shape (every codepoint is rendered as\r\n//         some glyph)\r\n//\r\n//      Glyph index\r\n//         A font-specific integer ID representing a glyph\r\n//\r\n//      Baseline\r\n//         Glyph shapes are defined relative to a baseline, which is the\r\n//         bottom of uppercase characters. Characters extend both above\r\n//         and below the baseline.\r\n//\r\n//      Current Point\r\n//         As you draw text to the screen, you keep track of a \"current point\"\r\n//         which is the origin of each character. The current point's vertical\r\n//         position is the baseline. Even \"baked fonts\" use this model.\r\n//\r\n//      Vertical Font Metrics\r\n//         The vertical qualities of the font, used to vertically position\r\n//         and space the characters. See docs for stbtt_GetFontVMetrics.\r\n//\r\n//      Font Size in Pixels or Points\r\n//         The preferred interface for specifying font sizes in stb_truetype\r\n//         is to specify how tall the font's vertical extent should be in pixels.\r\n//         If that sounds good enough, skip the next paragraph.\r\n//\r\n//         Most font APIs instead use \"points\", which are a common typographic\r\n//         measurement for describing font size, defined as 72 points per inch.\r\n//         stb_truetype provides a point API for compatibility. However, true\r\n//         \"per inch\" conventions don't make much sense on computer displays\r\n//         since they different monitors have different number of pixels per\r\n//         inch. For example, Windows traditionally uses a convention that\r\n//         there are 96 pixels per inch, thus making 'inch' measurements have\r\n//         nothing to do with inches, and thus effectively defining a point to\r\n//         be 1.333 pixels. Additionally, the TrueType font data provides\r\n//         an explicit scale factor to scale a given font's glyphs to points,\r\n//         but the author has observed that this scale factor is often wrong\r\n//         for non-commercial fonts, thus making fonts scaled in points\r\n//         according to the TrueType spec incoherently sized in practice.\r\n//\r\n// ADVANCED USAGE\r\n//\r\n//   Quality:\r\n//\r\n//    - Use the functions with Subpixel at the end to allow your characters\r\n//      to have subpixel positioning. Since the font is anti-aliased, not\r\n//      hinted, this is very import for quality. (This is not possible with\r\n//      baked fonts.)\r\n//\r\n//    - Kerning is now supported, and if you're supporting subpixel rendering\r\n//      then kerning is worth using to give your text a polished look.\r\n//\r\n//   Performance:\r\n//\r\n//    - Convert Unicode codepoints to glyph indexes and operate on the glyphs;\r\n//      if you don't do this, stb_truetype is forced to do the conversion on\r\n//      every call.\r\n//\r\n//    - There are a lot of memory allocations. We should modify it to take\r\n//      a temp buffer and allocate from the temp buffer (without freeing),\r\n//      should help performance a lot.\r\n//\r\n// NOTES\r\n//\r\n//   The system uses the raw data found in the .ttf file without changing it\r\n//   and without building auxiliary data structures. This is a bit inefficient\r\n//   on little-endian systems (the data is big-endian), but assuming you're\r\n//   caching the bitmaps or glyph shapes this shouldn't be a big deal.\r\n//\r\n//   It appears to be very hard to programmatically determine what font a\r\n//   given file is in a general way. I provide an API for this, but I don't\r\n//   recommend it.\r\n//\r\n//\r\n// SOURCE STATISTICS (based on v0.6c, 2050 LOC)\r\n//\r\n//   Documentation & header file        520 LOC  \\___ 660 LOC documentation\r\n//   Sample code                        140 LOC  /\r\n//   Truetype parsing                   620 LOC  ---- 620 LOC TrueType\r\n//   Software rasterization             240 LOC  \\                           .\r\n//   Curve tesselation                  120 LOC   \\__ 550 LOC Bitmap creation\r\n//   Bitmap management                  100 LOC   /\r\n//   Baked bitmap interface              70 LOC  /\r\n//   Font name matching & access        150 LOC  ---- 150 \r\n//   C runtime library abstraction       60 LOC  ----  60\r\n//\r\n//\r\n// PERFORMANCE MEASUREMENTS FOR 1.06:\r\n//\r\n//                      32-bit     64-bit\r\n//   Previous release:  8.83 s     7.68 s\r\n//   Pool allocations:  7.72 s     6.34 s\r\n//   Inline sort     :  6.54 s     5.65 s\r\n//   New rasterizer  :  5.63 s     5.00 s\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////\r\n////\r\n////  SAMPLE PROGRAMS\r\n////\r\n//\r\n//  Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless\r\n//\r\n#if 0\r\n#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation\r\n#include \"stb_truetype.h\"\r\n\r\nunsigned char ttf_buffer[1<<20];\r\nunsigned char temp_bitmap[512*512];\r\n\r\nstbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs\r\nGLuint ftex;\r\n\r\nvoid my_stbtt_initfont(void)\r\n{\r\n   fread(ttf_buffer, 1, 1<<20, fopen(\"c:/windows/fonts/times.ttf\", \"rb\"));\r\n   stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!\r\n   // can free ttf_buffer at this point\r\n   glGenTextures(1, &ftex);\r\n   glBindTexture(GL_TEXTURE_2D, ftex);\r\n   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);\r\n   // can free temp_bitmap at this point\r\n   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r\n}\r\n\r\nvoid my_stbtt_print(float x, float y, char *text)\r\n{\r\n   // assume orthographic projection with units = screen pixels, origin at top left\r\n   glEnable(GL_TEXTURE_2D);\r\n   glBindTexture(GL_TEXTURE_2D, ftex);\r\n   glBegin(GL_QUADS);\r\n   while (*text) {\r\n      if (*text >= 32 && *text < 128) {\r\n         stbtt_aligned_quad q;\r\n         stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9\r\n         glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);\r\n         glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);\r\n         glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);\r\n         glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);\r\n      }\r\n      ++text;\r\n   }\r\n   glEnd();\r\n}\r\n#endif\r\n//\r\n//\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Complete program (this compiles): get a single bitmap, print as ASCII art\r\n//\r\n#if 0\r\n#include <stdio.h>\r\n#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation\r\n#include \"stb_truetype.h\"\r\n\r\nchar ttf_buffer[1<<25];\r\n\r\nint main(int argc, char **argv)\r\n{\r\n   stbtt_fontinfo font;\r\n   unsigned char *bitmap;\r\n   int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);\r\n\r\n   fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : \"c:/windows/fonts/arialbd.ttf\", \"rb\"));\r\n\r\n   stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));\r\n   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);\r\n\r\n   for (j=0; j < h; ++j) {\r\n      for (i=0; i < w; ++i)\r\n         putchar(\" .:ioVM@\"[bitmap[j*w+i]>>5]);\r\n      putchar('\\n');\r\n   }\r\n   return 0;\r\n}\r\n#endif \r\n//\r\n// Output:\r\n//\r\n//     .ii.\r\n//    @@@@@@.\r\n//   V@Mio@@o\r\n//   :i.  V@V\r\n//     :oM@@M\r\n//   :@@@MM@M\r\n//   @@o  o@M\r\n//  :@@.  M@M\r\n//   @@@o@@@@\r\n//   :M@@V:@@.\r\n//  \r\n//////////////////////////////////////////////////////////////////////////////\r\n// \r\n// Complete program: print \"Hello World!\" banner, with bugs\r\n//\r\n#if 0\r\nchar buffer[24<<20];\r\nunsigned char screen[20][79];\r\n\r\nint main(int arg, char **argv)\r\n{\r\n   stbtt_fontinfo font;\r\n   int i,j,ascent,baseline,ch=0;\r\n   float scale, xpos=2; // leave a little padding in case the character extends left\r\n   char *text = \"Heljo World!\"; // intentionally misspelled to show 'lj' brokenness\r\n\r\n   fread(buffer, 1, 1000000, fopen(\"c:/windows/fonts/arialbd.ttf\", \"rb\"));\r\n   stbtt_InitFont(&font, buffer, 0);\r\n\r\n   scale = stbtt_ScaleForPixelHeight(&font, 15);\r\n   stbtt_GetFontVMetrics(&font, &ascent,0,0);\r\n   baseline = (int) (ascent*scale);\r\n\r\n   while (text[ch]) {\r\n      int advance,lsb,x0,y0,x1,y1;\r\n      float x_shift = xpos - (float) floor(xpos);\r\n      stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);\r\n      stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);\r\n      stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);\r\n      // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong\r\n      // because this API is really for baking character bitmaps into textures. if you want to render\r\n      // a sequence of characters, you really need to render each bitmap to a temp buffer, then\r\n      // \"alpha blend\" that into the working buffer\r\n      xpos += (advance * scale);\r\n      if (text[ch+1])\r\n         xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);\r\n      ++ch;\r\n   }\r\n\r\n   for (j=0; j < 20; ++j) {\r\n      for (i=0; i < 78; ++i)\r\n         putchar(\" .:ioVM@\"[screen[j][i]>>5]);\r\n      putchar('\\n');\r\n   }\r\n\r\n   return 0;\r\n}\r\n#endif\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////\r\n////\r\n////   INTEGRATION WITH YOUR CODEBASE\r\n////\r\n////   The following sections allow you to supply alternate definitions\r\n////   of C library functions used by stb_truetype.\r\n\r\n#ifdef STB_TRUETYPE_IMPLEMENTATION\r\n   // #define your own (u)stbtt_int8/16/32 before including to override this\r\n   #ifndef stbtt_uint8\r\n   typedef unsigned char   stbtt_uint8;\r\n   typedef signed   char   stbtt_int8;\r\n   typedef unsigned short  stbtt_uint16;\r\n   typedef signed   short  stbtt_int16;\r\n   typedef unsigned int    stbtt_uint32;\r\n   typedef signed   int    stbtt_int32;\r\n   #endif\r\n\r\n   typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];\r\n   typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];\r\n\r\n   // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h\r\n   #ifndef STBTT_ifloor\r\n   #include <math.h>\r\n   #define STBTT_ifloor(x)   ((int) floor(x))\r\n   #define STBTT_iceil(x)    ((int) ceil(x))\r\n   #endif\r\n\r\n   #ifndef STBTT_sqrt\r\n   #include <math.h>\r\n   #define STBTT_sqrt(x)      sqrt(x)\r\n   #endif\r\n\r\n   #ifndef STBTT_fabs\r\n   #include <math.h>\r\n   #define STBTT_fabs(x)      fabs(x)\r\n   #endif\r\n\r\n   // #define your own functions \"STBTT_malloc\" / \"STBTT_free\" to avoid malloc.h\r\n   #ifndef STBTT_malloc\r\n   #include <stdlib.h>\r\n   #define STBTT_malloc(x,u)  ((void)(u),malloc(x))\r\n   #define STBTT_free(x,u)    ((void)(u),free(x))\r\n   #endif\r\n\r\n   #ifndef STBTT_assert\r\n   #include <assert.h>\r\n   #define STBTT_assert(x)    assert(x)\r\n   #endif\r\n\r\n   #ifndef STBTT_strlen\r\n   #include <string.h>\r\n   #define STBTT_strlen(x)    strlen(x)\r\n   #endif\r\n\r\n   #ifndef STBTT_memcpy\r\n   #include <memory.h>\r\n   #define STBTT_memcpy       memcpy\r\n   #define STBTT_memset       memset\r\n   #endif\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n///////////////////////////////////////////////////////////////////////////////\r\n////\r\n////   INTERFACE\r\n////\r\n////\r\n\r\n#ifndef __STB_INCLUDE_STB_TRUETYPE_H__\r\n#define __STB_INCLUDE_STB_TRUETYPE_H__\r\n\r\n#ifdef STBTT_STATIC\r\n#define STBTT_DEF static\r\n#else\r\n#define STBTT_DEF extern\r\n#endif\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n// private structure\r\ntypedef struct\r\n{\r\n   unsigned char *data;\r\n   int cursor;\r\n   int size;\r\n} stbtt__buf;\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// TEXTURE BAKING API\r\n//\r\n// If you use this API, you only have to call two functions ever.\r\n//\r\n\r\ntypedef struct\r\n{\r\n   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap\r\n   float xoff,yoff,xadvance;\r\n} stbtt_bakedchar;\r\n\r\nSTBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)\r\n                                float pixel_height,                     // height of font in pixels\r\n                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in\r\n                                int first_char, int num_chars,          // characters to bake\r\n                                stbtt_bakedchar *chardata);             // you allocate this, it's num_chars long\r\n// if return is positive, the first unused row of the bitmap\r\n// if return is negative, returns the negative of the number of characters that fit\r\n// if return is 0, no characters fit and no rows were used\r\n// This uses a very crappy packing.\r\n\r\ntypedef struct\r\n{\r\n   float x0,y0,s0,t0; // top-left\r\n   float x1,y1,s1,t1; // bottom-right\r\n} stbtt_aligned_quad;\r\n\r\nSTBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph,  // same data as above\r\n                               int char_index,             // character to display\r\n                               float *xpos, float *ypos,   // pointers to current position in screen pixel space\r\n                               stbtt_aligned_quad *q,      // output: quad to draw\r\n                               int opengl_fillrule);       // true if opengl fill rule; false if DX9 or earlier\r\n// Call GetBakedQuad with char_index = 'character - first_char', and it\r\n// creates the quad you need to draw and advances the current position.\r\n//\r\n// The coordinate system used assumes y increases downwards.\r\n//\r\n// Characters will extend both above and below the current position;\r\n// see discussion of \"BASELINE\" above.\r\n//\r\n// It's inefficient; you might want to c&p it and optimize it.\r\n\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// NEW TEXTURE BAKING API\r\n//\r\n// This provides options for packing multiple fonts into one atlas, not\r\n// perfectly but better than nothing.\r\n\r\ntypedef struct\r\n{\r\n   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap\r\n   float xoff,yoff,xadvance;\r\n   float xoff2,yoff2;\r\n} stbtt_packedchar;\r\n\r\ntypedef struct stbtt_pack_context stbtt_pack_context;\r\ntypedef struct stbtt_fontinfo stbtt_fontinfo;\r\n#ifndef STB_RECT_PACK_VERSION\r\ntypedef struct stbrp_rect stbrp_rect;\r\n#endif\r\n\r\nSTBTT_DEF int  stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);\r\n// Initializes a packing context stored in the passed-in stbtt_pack_context.\r\n// Future calls using this context will pack characters into the bitmap passed\r\n// in here: a 1-channel bitmap that is width * height. stride_in_bytes is\r\n// the distance from one row to the next (or 0 to mean they are packed tightly\r\n// together). \"padding\" is the amount of padding to leave between each\r\n// character (normally you want '1' for bitmaps you'll use as textures with\r\n// bilinear filtering).\r\n//\r\n// Returns 0 on failure, 1 on success.\r\n\r\nSTBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc);\r\n// Cleans up the packing context and frees all memory.\r\n\r\n#define STBTT_POINT_SIZE(x)   (-(x))\r\n\r\nSTBTT_DEF int  stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,\r\n                                int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);\r\n// Creates character bitmaps from the font_index'th font found in fontdata (use\r\n// font_index=0 if you don't know what that is). It creates num_chars_in_range\r\n// bitmaps for characters with unicode values starting at first_unicode_char_in_range\r\n// and increasing. Data for how to render them is stored in chardata_for_range;\r\n// pass these to stbtt_GetPackedQuad to get back renderable quads.\r\n//\r\n// font_size is the full height of the character from ascender to descender,\r\n// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed\r\n// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()\r\n// and pass that result as 'font_size':\r\n//       ...,                  20 , ... // font max minus min y is 20 pixels tall\r\n//       ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall\r\n\r\ntypedef struct\r\n{\r\n   float font_size;\r\n   int first_unicode_codepoint_in_range;  // if non-zero, then the chars are continuous, and this is the first codepoint\r\n   int *array_of_unicode_codepoints;       // if non-zero, then this is an array of unicode codepoints\r\n   int num_chars;\r\n   stbtt_packedchar *chardata_for_range; // output\r\n   unsigned char h_oversample, v_oversample; // don't set these, they're used internally\r\n} stbtt_pack_range;\r\n\r\nSTBTT_DEF int  stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);\r\n// Creates character bitmaps from multiple ranges of characters stored in\r\n// ranges. This will usually create a better-packed bitmap than multiple\r\n// calls to stbtt_PackFontRange. Note that you can call this multiple\r\n// times within a single PackBegin/PackEnd.\r\n\r\nSTBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);\r\n// Oversampling a font increases the quality by allowing higher-quality subpixel\r\n// positioning, and is especially valuable at smaller text sizes.\r\n//\r\n// This function sets the amount of oversampling for all following calls to\r\n// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given\r\n// pack context. The default (no oversampling) is achieved by h_oversample=1\r\n// and v_oversample=1. The total number of pixels required is\r\n// h_oversample*v_oversample larger than the default; for example, 2x2\r\n// oversampling requires 4x the storage of 1x1. For best results, render\r\n// oversampled textures with bilinear filtering. Look at the readme in\r\n// stb/tests/oversample for information about oversampled fonts\r\n//\r\n// To use with PackFontRangesGather etc., you must set it before calls\r\n// call to PackFontRangesGatherRects.\r\n\r\nSTBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph,  // same data as above\r\n                               int char_index,             // character to display\r\n                               float *xpos, float *ypos,   // pointers to current position in screen pixel space\r\n                               stbtt_aligned_quad *q,      // output: quad to draw\r\n                               int align_to_integer);\r\n\r\nSTBTT_DEF int  stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);\r\nSTBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);\r\nSTBTT_DEF int  stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);\r\n// Calling these functions in sequence is roughly equivalent to calling\r\n// stbtt_PackFontRanges(). If you more control over the packing of multiple\r\n// fonts, or if you want to pack custom data into a font texture, take a look\r\n// at the source to of stbtt_PackFontRanges() and create a custom version \r\n// using these functions, e.g. call GatherRects multiple times,\r\n// building up a single array of rects, then call PackRects once,\r\n// then call RenderIntoRects repeatedly. This may result in a\r\n// better packing than calling PackFontRanges multiple times\r\n// (or it may not).\r\n\r\n// this is an opaque structure that you shouldn't mess with which holds\r\n// all the context needed from PackBegin to PackEnd.\r\nstruct stbtt_pack_context {\r\n   void *user_allocator_context;\r\n   void *pack_info;\r\n   int   width;\r\n   int   height;\r\n   int   stride_in_bytes;\r\n   int   padding;\r\n   unsigned int   h_oversample, v_oversample;\r\n   unsigned char *pixels;\r\n   void  *nodes;\r\n};\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// FONT LOADING\r\n//\r\n//\r\n\r\nSTBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);\r\n// This function will determine the number of fonts in a font file.  TrueType\r\n// collection (.ttc) files may contain multiple fonts, while TrueType font\r\n// (.ttf) files only contain one font. The number of fonts can be used for\r\n// indexing with the previous function where the index is between zero and one\r\n// less than the total fonts. If an error occurs, -1 is returned.\r\n\r\nSTBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);\r\n// Each .ttf/.ttc file may have more than one font. Each font has a sequential\r\n// index number starting from 0. Call this function to get the font offset for\r\n// a given index; it returns -1 if the index is out of range. A regular .ttf\r\n// file will only define one font and it always be at offset 0, so it will\r\n// return '0' for index 0, and -1 for all other indices.\r\n\r\n// The following structure is defined publically so you can declare one on\r\n// the stack or as a global or etc, but you should treat it as opaque.\r\nstruct stbtt_fontinfo\r\n{\r\n   void           * userdata;\r\n   unsigned char  * data;              // pointer to .ttf file\r\n   int              fontstart;         // offset of start of font\r\n\r\n   int numGlyphs;                     // number of glyphs, needed for range checking\r\n\r\n   int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf\r\n   int index_map;                     // a cmap mapping for our chosen character encoding\r\n   int indexToLocFormat;              // format needed to map from glyph index to glyph\r\n\r\n   stbtt__buf cff;                    // cff font data\r\n   stbtt__buf charstrings;            // the charstring index\r\n   stbtt__buf gsubrs;                 // global charstring subroutines index\r\n   stbtt__buf subrs;                  // private charstring subroutines index\r\n   stbtt__buf fontdicts;              // array of font dicts\r\n   stbtt__buf fdselect;               // map from glyph to fontdict\r\n};\r\n\r\nSTBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);\r\n// Given an offset into the file that defines a font, this function builds\r\n// the necessary cached info for the rest of the system. You must allocate\r\n// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't\r\n// need to do anything special to free it, because the contents are pure\r\n// value data with no additional data structures. Returns 0 on failure.\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// CHARACTER TO GLYPH-INDEX CONVERSIOn\r\n\r\nSTBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);\r\n// If you're going to perform multiple operations on the same character\r\n// and you want a speed-up, call this function with the character you're\r\n// going to process, then use glyph-based functions instead of the\r\n// codepoint-based functions.\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// CHARACTER PROPERTIES\r\n//\r\n\r\nSTBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);\r\n// computes a scale factor to produce a font whose \"height\" is 'pixels' tall.\r\n// Height is measured as the distance from the highest ascender to the lowest\r\n// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics\r\n// and computing:\r\n//       scale = pixels / (ascent - descent)\r\n// so if you prefer to measure height by the ascent only, use a similar calculation.\r\n\r\nSTBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);\r\n// computes a scale factor to produce a font whose EM size is mapped to\r\n// 'pixels' tall. This is probably what traditional APIs compute, but\r\n// I'm not positive.\r\n\r\nSTBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);\r\n// ascent is the coordinate above the baseline the font extends; descent\r\n// is the coordinate below the baseline the font extends (i.e. it is typically negative)\r\n// lineGap is the spacing between one row's descent and the next row's ascent...\r\n// so you should advance the vertical position by \"*ascent - *descent + *lineGap\"\r\n//   these are expressed in unscaled coordinates, so you must multiply by\r\n//   the scale factor for a given size\r\n\r\nSTBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);\r\n// the bounding box around all possible characters\r\n\r\nSTBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);\r\n// leftSideBearing is the offset from the current horizontal position to the left edge of the character\r\n// advanceWidth is the offset from the current horizontal position to the next horizontal position\r\n//   these are expressed in unscaled coordinates\r\n\r\nSTBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);\r\n// an additional amount to add to the 'advance' value between ch1 and ch2\r\n\r\nSTBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);\r\n// Gets the bounding box of the visible part of the glyph, in unscaled coordinates\r\n\r\nSTBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);\r\nSTBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);\r\nSTBTT_DEF int  stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);\r\n// as above, but takes one or more glyph indices for greater efficiency\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// GLYPH SHAPES (you probably don't need these, but they have to go before\r\n// the bitmaps for C declaration-order reasons)\r\n//\r\n\r\n#ifndef STBTT_vmove // you can predefine these to use different values (but why?)\r\n   enum {\r\n      STBTT_vmove=1,\r\n      STBTT_vline,\r\n      STBTT_vcurve,\r\n      STBTT_vcubic\r\n   };\r\n#endif\r\n\r\n#ifndef stbtt_vertex // you can predefine this to use different values\r\n                   // (we share this with other code at RAD)\r\n   #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file\r\n   typedef struct\r\n   {\r\n      stbtt_vertex_type x,y,cx,cy,cx1,cy1;\r\n      unsigned char type,padding;\r\n   } stbtt_vertex;\r\n#endif\r\n\r\nSTBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);\r\n// returns non-zero if nothing is drawn for this glyph\r\n\r\nSTBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);\r\nSTBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);\r\n// returns # of vertices and fills *vertices with the pointer to them\r\n//   these are expressed in \"unscaled\" coordinates\r\n//\r\n// The shape is a series of countours. Each one starts with\r\n// a STBTT_moveto, then consists of a series of mixed\r\n// STBTT_lineto and STBTT_curveto segments. A lineto\r\n// draws a line from previous endpoint to its x,y; a curveto\r\n// draws a quadratic bezier from previous endpoint to\r\n// its x,y, using cx,cy as the bezier control point.\r\n\r\nSTBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);\r\n// frees the data allocated above\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// BITMAP RENDERING\r\n//\r\n\r\nSTBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);\r\n// frees the bitmap allocated below\r\n\r\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);\r\n// allocates a large-enough single-channel 8bpp bitmap and renders the\r\n// specified character/glyph at the specified scale into it, with\r\n// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).\r\n// *width & *height are filled out with the width & height of the bitmap,\r\n// which is stored left-to-right, top-to-bottom.\r\n//\r\n// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap\r\n\r\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);\r\n// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel\r\n// shift for the character\r\n\r\nSTBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);\r\n// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap\r\n// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap\r\n// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the\r\n// width and height and positioning info for it first.\r\n\r\nSTBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);\r\n// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel\r\n// shift for the character\r\n\r\nSTBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);\r\n// get the bbox of the bitmap centered around the glyph origin; so the\r\n// bitmap width is ix1-ix0, height is iy1-iy0, and location to place\r\n// the bitmap top left is (leftSideBearing*scale,iy0).\r\n// (Note that the bitmap uses y-increases-down, but the shape uses\r\n// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)\r\n\r\nSTBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);\r\n// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel\r\n// shift for the character\r\n\r\n// the following functions are equivalent to the above functions, but operate\r\n// on glyph indices instead of Unicode codepoints (for efficiency)\r\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);\r\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);\r\nSTBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);\r\nSTBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);\r\nSTBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);\r\nSTBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);\r\n\r\n\r\n// @TODO: don't expose this structure\r\ntypedef struct\r\n{\r\n   int w,h,stride;\r\n   unsigned char *pixels;\r\n} stbtt__bitmap;\r\n\r\n// rasterize a shape with quadratic beziers into a bitmap\r\nSTBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result,        // 1-channel bitmap to draw into\r\n                               float flatness_in_pixels,     // allowable error of curve in pixels\r\n                               stbtt_vertex *vertices,       // array of vertices defining shape\r\n                               int num_verts,                // number of vertices in above array\r\n                               float scale_x, float scale_y, // scale applied to input vertices\r\n                               float shift_x, float shift_y, // translation applied to input vertices\r\n                               int x_off, int y_off,         // another translation applied to input\r\n                               int invert,                   // if non-zero, vertically flip shape\r\n                               void *userdata);              // context for to STBTT_MALLOC\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Finding the right font...\r\n//\r\n// You should really just solve this offline, keep your own tables\r\n// of what font is what, and don't try to get it out of the .ttf file.\r\n// That's because getting it out of the .ttf file is really hard, because\r\n// the names in the file can appear in many possible encodings, in many\r\n// possible languages, and e.g. if you need a case-insensitive comparison,\r\n// the details of that depend on the encoding & language in a complex way\r\n// (actually underspecified in truetype, but also gigantic).\r\n//\r\n// But you can use the provided functions in two possible ways:\r\n//     stbtt_FindMatchingFont() will use *case-sensitive* comparisons on\r\n//             unicode-encoded names to try to find the font you want;\r\n//             you can run this before calling stbtt_InitFont()\r\n//\r\n//     stbtt_GetFontNameString() lets you get any of the various strings\r\n//             from the file yourself and do your own comparisons on them.\r\n//             You have to have called stbtt_InitFont() first.\r\n\r\n\r\nSTBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);\r\n// returns the offset (not index) of the font that matches, or -1 if none\r\n//   if you use STBTT_MACSTYLE_DONTCARE, use a font name like \"Arial Bold\".\r\n//   if you use any other flag, use a font name like \"Arial\"; this checks\r\n//     the 'macStyle' header field; i don't know if fonts set this consistently\r\n#define STBTT_MACSTYLE_DONTCARE     0\r\n#define STBTT_MACSTYLE_BOLD         1\r\n#define STBTT_MACSTYLE_ITALIC       2\r\n#define STBTT_MACSTYLE_UNDERSCORE   4\r\n#define STBTT_MACSTYLE_NONE         8   // <= not same as 0, this makes us check the bitfield is 0\r\n\r\nSTBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);\r\n// returns 1/0 whether the first string interpreted as utf8 is identical to\r\n// the second string interpreted as big-endian utf16... useful for strings from next func\r\n\r\nSTBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);\r\n// returns the string (which may be big-endian double byte, e.g. for unicode)\r\n// and puts the length in bytes in *length.\r\n//\r\n// some of the values for the IDs are below; for more see the truetype spec:\r\n//     http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html\r\n//     http://www.microsoft.com/typography/otspec/name.htm\r\n\r\nenum { // platformID\r\n   STBTT_PLATFORM_ID_UNICODE   =0,\r\n   STBTT_PLATFORM_ID_MAC       =1,\r\n   STBTT_PLATFORM_ID_ISO       =2,\r\n   STBTT_PLATFORM_ID_MICROSOFT =3\r\n};\r\n\r\nenum { // encodingID for STBTT_PLATFORM_ID_UNICODE\r\n   STBTT_UNICODE_EID_UNICODE_1_0    =0,\r\n   STBTT_UNICODE_EID_UNICODE_1_1    =1,\r\n   STBTT_UNICODE_EID_ISO_10646      =2,\r\n   STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,\r\n   STBTT_UNICODE_EID_UNICODE_2_0_FULL=4\r\n};\r\n\r\nenum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT\r\n   STBTT_MS_EID_SYMBOL        =0,\r\n   STBTT_MS_EID_UNICODE_BMP   =1,\r\n   STBTT_MS_EID_SHIFTJIS      =2,\r\n   STBTT_MS_EID_UNICODE_FULL  =10\r\n};\r\n\r\nenum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes\r\n   STBTT_MAC_EID_ROMAN        =0,   STBTT_MAC_EID_ARABIC       =4,\r\n   STBTT_MAC_EID_JAPANESE     =1,   STBTT_MAC_EID_HEBREW       =5,\r\n   STBTT_MAC_EID_CHINESE_TRAD =2,   STBTT_MAC_EID_GREEK        =6,\r\n   STBTT_MAC_EID_KOREAN       =3,   STBTT_MAC_EID_RUSSIAN      =7\r\n};\r\n\r\nenum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...\r\n       // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs\r\n   STBTT_MS_LANG_ENGLISH     =0x0409,   STBTT_MS_LANG_ITALIAN     =0x0410,\r\n   STBTT_MS_LANG_CHINESE     =0x0804,   STBTT_MS_LANG_JAPANESE    =0x0411,\r\n   STBTT_MS_LANG_DUTCH       =0x0413,   STBTT_MS_LANG_KOREAN      =0x0412,\r\n   STBTT_MS_LANG_FRENCH      =0x040c,   STBTT_MS_LANG_RUSSIAN     =0x0419,\r\n   STBTT_MS_LANG_GERMAN      =0x0407,   STBTT_MS_LANG_SPANISH     =0x0409,\r\n   STBTT_MS_LANG_HEBREW      =0x040d,   STBTT_MS_LANG_SWEDISH     =0x041D\r\n};\r\n\r\nenum { // languageID for STBTT_PLATFORM_ID_MAC\r\n   STBTT_MAC_LANG_ENGLISH      =0 ,   STBTT_MAC_LANG_JAPANESE     =11,\r\n   STBTT_MAC_LANG_ARABIC       =12,   STBTT_MAC_LANG_KOREAN       =23,\r\n   STBTT_MAC_LANG_DUTCH        =4 ,   STBTT_MAC_LANG_RUSSIAN      =32,\r\n   STBTT_MAC_LANG_FRENCH       =1 ,   STBTT_MAC_LANG_SPANISH      =6 ,\r\n   STBTT_MAC_LANG_GERMAN       =2 ,   STBTT_MAC_LANG_SWEDISH      =5 ,\r\n   STBTT_MAC_LANG_HEBREW       =10,   STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,\r\n   STBTT_MAC_LANG_ITALIAN      =3 ,   STBTT_MAC_LANG_CHINESE_TRAD =19\r\n};\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif // __STB_INCLUDE_STB_TRUETYPE_H__\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n///////////////////////////////////////////////////////////////////////////////\r\n////\r\n////   IMPLEMENTATION\r\n////\r\n////\r\n\r\n#ifdef STB_TRUETYPE_IMPLEMENTATION\r\n\r\n#ifndef STBTT_MAX_OVERSAMPLE\r\n#define STBTT_MAX_OVERSAMPLE   8\r\n#endif\r\n\r\n#if STBTT_MAX_OVERSAMPLE > 255\r\n#error \"STBTT_MAX_OVERSAMPLE cannot be > 255\"\r\n#endif\r\n\r\ntypedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];\r\n\r\n#ifndef STBTT_RASTERIZER_VERSION\r\n#define STBTT_RASTERIZER_VERSION 2\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\n#define STBTT__NOTUSED(v)  (void)(v)\r\n#else\r\n#define STBTT__NOTUSED(v)  (void)sizeof(v)\r\n#endif\r\n\r\n//////////////////////////////////////////////////////////////////////////\r\n//\r\n// stbtt__buf helpers to parse data from file\r\n//\r\n\r\nstatic stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)\r\n{\r\n   if (b->cursor >= b->size)\r\n      return 0;\r\n   return b->data[b->cursor++];\r\n}\r\n\r\nstatic stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)\r\n{\r\n   if (b->cursor >= b->size)\r\n      return 0;\r\n   return b->data[b->cursor];\r\n}\r\n\r\nstatic void stbtt__buf_seek(stbtt__buf *b, int o)\r\n{\r\n   STBTT_assert(!(o > b->size || o < 0));\r\n   b->cursor = (o > b->size || o < 0) ? b->size : o;\r\n}\r\n\r\nstatic void stbtt__buf_skip(stbtt__buf *b, int o)\r\n{\r\n   stbtt__buf_seek(b, b->cursor + o);\r\n}\r\n\r\nstatic stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)\r\n{\r\n   stbtt_uint32 v = 0;\r\n   int i;\r\n   STBTT_assert(n >= 1 && n <= 4);\r\n   for (i = 0; i < n; i++)\r\n      v = (v << 8) | stbtt__buf_get8(b);\r\n   return v;\r\n}\r\n\r\nstatic stbtt__buf stbtt__new_buf(const void *p, size_t size)\r\n{\r\n   stbtt__buf r;\r\n   STBTT_assert(size < 0x40000000);\r\n   r.data = (stbtt_uint8*) p;\r\n   r.size = (int) size;\r\n   r.cursor = 0;\r\n   return r;\r\n}\r\n\r\n#define stbtt__buf_get16(b)  stbtt__buf_get((b), 2)\r\n#define stbtt__buf_get32(b)  stbtt__buf_get((b), 4)\r\n\r\nstatic stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)\r\n{\r\n   stbtt__buf r = stbtt__new_buf(NULL, 0);\r\n   if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;\r\n   r.data = b->data + o;\r\n   r.size = s;\r\n   return r;\r\n}\r\n\r\nstatic stbtt__buf stbtt__cff_get_index(stbtt__buf *b)\r\n{\r\n   int count, start, offsize;\r\n   start = b->cursor;\r\n   count = stbtt__buf_get16(b);\r\n   if (count) {\r\n      offsize = stbtt__buf_get8(b);\r\n      STBTT_assert(offsize >= 1 && offsize <= 4);\r\n      stbtt__buf_skip(b, offsize * count);\r\n      stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);\r\n   }\r\n   return stbtt__buf_range(b, start, b->cursor - start);\r\n}\r\n\r\nstatic stbtt_uint32 stbtt__cff_int(stbtt__buf *b)\r\n{\r\n   int b0 = stbtt__buf_get8(b);\r\n   if (b0 >= 32 && b0 <= 246)       return b0 - 139;\r\n   else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;\r\n   else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;\r\n   else if (b0 == 28)               return stbtt__buf_get16(b);\r\n   else if (b0 == 29)               return stbtt__buf_get32(b);\r\n   STBTT_assert(0);\r\n   return 0;\r\n}\r\n\r\nstatic void stbtt__cff_skip_operand(stbtt__buf *b) {\r\n   int v, b0 = stbtt__buf_peek8(b);\r\n   STBTT_assert(b0 >= 28);\r\n   if (b0 == 30) {\r\n      stbtt__buf_skip(b, 1);\r\n      while (b->cursor < b->size) {\r\n         v = stbtt__buf_get8(b);\r\n         if ((v & 0xF) == 0xF || (v >> 4) == 0xF)\r\n            break;\r\n      }\r\n   } else {\r\n      stbtt__cff_int(b);\r\n   }\r\n}\r\n\r\nstatic stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)\r\n{\r\n   stbtt__buf_seek(b, 0);\r\n   while (b->cursor < b->size) {\r\n      int start = b->cursor, end, op;\r\n      while (stbtt__buf_peek8(b) >= 28)\r\n         stbtt__cff_skip_operand(b);\r\n      end = b->cursor;\r\n      op = stbtt__buf_get8(b);\r\n      if (op == 12)  op = stbtt__buf_get8(b) | 0x100;\r\n      if (op == key) return stbtt__buf_range(b, start, end-start);\r\n   }\r\n   return stbtt__buf_range(b, 0, 0);\r\n}\r\n\r\nstatic void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)\r\n{\r\n   int i;\r\n   stbtt__buf operands = stbtt__dict_get(b, key);\r\n   for (i = 0; i < outcount && operands.cursor < operands.size; i++)\r\n      out[i] = stbtt__cff_int(&operands);\r\n}\r\n\r\nstatic int stbtt__cff_index_count(stbtt__buf *b)\r\n{\r\n   stbtt__buf_seek(b, 0);\r\n   return stbtt__buf_get16(b);\r\n}\r\n\r\nstatic stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)\r\n{\r\n   int count, offsize, start, end;\r\n   stbtt__buf_seek(&b, 0);\r\n   count = stbtt__buf_get16(&b);\r\n   offsize = stbtt__buf_get8(&b);\r\n   STBTT_assert(i >= 0 && i < count);\r\n   STBTT_assert(offsize >= 1 && offsize <= 4);\r\n   stbtt__buf_skip(&b, i*offsize);\r\n   start = stbtt__buf_get(&b, offsize);\r\n   end = stbtt__buf_get(&b, offsize);\r\n   return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////\r\n//\r\n// accessors to parse data from file\r\n//\r\n\r\n// on platforms that don't allow misaligned reads, if we want to allow\r\n// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE\r\n\r\n#define ttBYTE(p)     (* (stbtt_uint8 *) (p))\r\n#define ttCHAR(p)     (* (stbtt_int8 *) (p))\r\n#define ttFixed(p)    ttLONG(p)\r\n\r\nstatic stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }\r\nstatic stbtt_int16 ttSHORT(stbtt_uint8 *p)   { return p[0]*256 + p[1]; }\r\nstatic stbtt_uint32 ttULONG(stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }\r\nstatic stbtt_int32 ttLONG(stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }\r\n\r\n#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))\r\n#define stbtt_tag(p,str)           stbtt_tag4(p,str[0],str[1],str[2],str[3])\r\n\r\nstatic int stbtt__isfont(stbtt_uint8 *font)\r\n{\r\n   // check the version number\r\n   if (stbtt_tag4(font, '1',0,0,0))  return 1; // TrueType 1\r\n   if (stbtt_tag(font, \"typ1\"))   return 1; // TrueType with type 1 font -- we don't support this!\r\n   if (stbtt_tag(font, \"OTTO\"))   return 1; // OpenType with CFF\r\n   if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0\r\n   if (stbtt_tag(font, \"true\"))   return 1; // Apple specification for TrueType fonts\r\n   return 0;\r\n}\r\n\r\n// @OPTIMIZE: binary search\r\nstatic stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)\r\n{\r\n   stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);\r\n   stbtt_uint32 tabledir = fontstart + 12;\r\n   stbtt_int32 i;\r\n   for (i=0; i < num_tables; ++i) {\r\n      stbtt_uint32 loc = tabledir + 16*i;\r\n      if (stbtt_tag(data+loc+0, tag))\r\n         return ttULONG(data+loc+8);\r\n   }\r\n   return 0;\r\n}\r\n\r\nstatic int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)\r\n{\r\n   // if it's just a font, there's only one valid index\r\n   if (stbtt__isfont(font_collection))\r\n      return index == 0 ? 0 : -1;\r\n\r\n   // check if it's a TTC\r\n   if (stbtt_tag(font_collection, \"ttcf\")) {\r\n      // version 1?\r\n      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {\r\n         stbtt_int32 n = ttLONG(font_collection+8);\r\n         if (index >= n)\r\n            return -1;\r\n         return ttULONG(font_collection+12+index*4);\r\n      }\r\n   }\r\n   return -1;\r\n}\r\n\r\nstatic int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)\r\n{\r\n   // if it's just a font, there's only one valid font\r\n   if (stbtt__isfont(font_collection))\r\n      return 1;\r\n\r\n   // check if it's a TTC\r\n   if (stbtt_tag(font_collection, \"ttcf\")) {\r\n      // version 1?\r\n      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {\r\n         return ttLONG(font_collection+8);\r\n      }\r\n   }\r\n   return 0;\r\n}\r\n\r\nstatic stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)\r\n{\r\n   stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };\r\n   stbtt__buf pdict;\r\n   stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);\r\n   if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);\r\n   pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);\r\n   stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);\r\n   if (!subrsoff) return stbtt__new_buf(NULL, 0);\r\n   stbtt__buf_seek(&cff, private_loc[1]+subrsoff);\r\n   return stbtt__cff_get_index(&cff);\r\n}\r\n\r\nstatic int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)\r\n{\r\n   stbtt_uint32 cmap, t;\r\n   stbtt_int32 i,numTables;\r\n\r\n   info->data = data;\r\n   info->fontstart = fontstart;\r\n   info->cff = stbtt__new_buf(NULL, 0);\r\n\r\n   cmap = stbtt__find_table(data, fontstart, \"cmap\");       // required\r\n   info->loca = stbtt__find_table(data, fontstart, \"loca\"); // required\r\n   info->head = stbtt__find_table(data, fontstart, \"head\"); // required\r\n   info->glyf = stbtt__find_table(data, fontstart, \"glyf\"); // required\r\n   info->hhea = stbtt__find_table(data, fontstart, \"hhea\"); // required\r\n   info->hmtx = stbtt__find_table(data, fontstart, \"hmtx\"); // required\r\n   info->kern = stbtt__find_table(data, fontstart, \"kern\"); // not required\r\n\r\n   if (!cmap || !info->head || !info->hhea || !info->hmtx)\r\n      return 0;\r\n   if (info->glyf) {\r\n      // required for truetype\r\n      if (!info->loca) return 0;\r\n   } else {\r\n      // initialization for CFF / Type2 fonts (OTF)\r\n      stbtt__buf b, topdict, topdictidx;\r\n      stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;\r\n      stbtt_uint32 cff;\r\n\r\n      cff = stbtt__find_table(data, fontstart, \"CFF \");\r\n      if (!cff) return 0;\r\n\r\n      info->fontdicts = stbtt__new_buf(NULL, 0);\r\n      info->fdselect = stbtt__new_buf(NULL, 0);\r\n\r\n      // @TODO this should use size from table (not 512MB)\r\n      info->cff = stbtt__new_buf(data+cff, 512*1024*1024);\r\n      b = info->cff;\r\n\r\n      // read the header\r\n      stbtt__buf_skip(&b, 2);\r\n      stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize\r\n\r\n      // @TODO the name INDEX could list multiple fonts,\r\n      // but we just use the first one.\r\n      stbtt__cff_get_index(&b);  // name INDEX\r\n      topdictidx = stbtt__cff_get_index(&b);\r\n      topdict = stbtt__cff_index_get(topdictidx, 0);\r\n      stbtt__cff_get_index(&b);  // string INDEX\r\n      info->gsubrs = stbtt__cff_get_index(&b);\r\n\r\n      stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);\r\n      stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);\r\n      stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);\r\n      stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);\r\n      info->subrs = stbtt__get_subrs(b, topdict);\r\n\r\n      // we only support Type 2 charstrings\r\n      if (cstype != 2) return 0;\r\n      if (charstrings == 0) return 0;\r\n\r\n      if (fdarrayoff) {\r\n         // looks like a CID font\r\n         if (!fdselectoff) return 0;\r\n         stbtt__buf_seek(&b, fdarrayoff);\r\n         info->fontdicts = stbtt__cff_get_index(&b);\r\n         info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);\r\n      }\r\n\r\n      stbtt__buf_seek(&b, charstrings);\r\n      info->charstrings = stbtt__cff_get_index(&b);\r\n   }\r\n\r\n   t = stbtt__find_table(data, fontstart, \"maxp\");\r\n   if (t)\r\n      info->numGlyphs = ttUSHORT(data+t+4);\r\n   else\r\n      info->numGlyphs = 0xffff;\r\n\r\n   // find a cmap encoding table we understand *now* to avoid searching\r\n   // later. (todo: could make this installable)\r\n   // the same regardless of glyph.\r\n   numTables = ttUSHORT(data + cmap + 2);\r\n   info->index_map = 0;\r\n   for (i=0; i < numTables; ++i) {\r\n      stbtt_uint32 encoding_record = cmap + 4 + 8 * i;\r\n      // find an encoding we understand:\r\n      switch(ttUSHORT(data+encoding_record)) {\r\n         case STBTT_PLATFORM_ID_MICROSOFT:\r\n            switch (ttUSHORT(data+encoding_record+2)) {\r\n               case STBTT_MS_EID_UNICODE_BMP:\r\n               case STBTT_MS_EID_UNICODE_FULL:\r\n                  // MS/Unicode\r\n                  info->index_map = cmap + ttULONG(data+encoding_record+4);\r\n                  break;\r\n            }\r\n            break;\r\n        case STBTT_PLATFORM_ID_UNICODE:\r\n            // Mac/iOS has these\r\n            // all the encodingIDs are unicode, so we don't bother to check it\r\n            info->index_map = cmap + ttULONG(data+encoding_record+4);\r\n            break;\r\n      }\r\n   }\r\n   if (info->index_map == 0)\r\n      return 0;\r\n\r\n   info->indexToLocFormat = ttUSHORT(data+info->head + 50);\r\n   return 1;\r\n}\r\n\r\nSTBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)\r\n{\r\n   stbtt_uint8 *data = info->data;\r\n   stbtt_uint32 index_map = info->index_map;\r\n\r\n   stbtt_uint16 format = ttUSHORT(data + index_map + 0);\r\n   if (format == 0) { // apple byte encoding\r\n      stbtt_int32 bytes = ttUSHORT(data + index_map + 2);\r\n      if (unicode_codepoint < bytes-6)\r\n         return ttBYTE(data + index_map + 6 + unicode_codepoint);\r\n      return 0;\r\n   } else if (format == 6) {\r\n      stbtt_uint32 first = ttUSHORT(data + index_map + 6);\r\n      stbtt_uint32 count = ttUSHORT(data + index_map + 8);\r\n      if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)\r\n         return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);\r\n      return 0;\r\n   } else if (format == 2) {\r\n      STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean\r\n      return 0;\r\n   } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges\r\n      stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;\r\n      stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;\r\n      stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);\r\n      stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;\r\n\r\n      // do a binary search of the segments\r\n      stbtt_uint32 endCount = index_map + 14;\r\n      stbtt_uint32 search = endCount;\r\n\r\n      if (unicode_codepoint > 0xffff)\r\n         return 0;\r\n\r\n      // they lie from endCount .. endCount + segCount\r\n      // but searchRange is the nearest power of two, so...\r\n      if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))\r\n         search += rangeShift*2;\r\n\r\n      // now decrement to bias correctly to find smallest\r\n      search -= 2;\r\n      while (entrySelector) {\r\n         stbtt_uint16 end;\r\n         searchRange >>= 1;\r\n         end = ttUSHORT(data + search + searchRange*2);\r\n         if (unicode_codepoint > end)\r\n            search += searchRange*2;\r\n         --entrySelector;\r\n      }\r\n      search += 2;\r\n\r\n      {\r\n         stbtt_uint16 offset, start;\r\n         stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);\r\n\r\n         STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));\r\n         start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);\r\n         if (unicode_codepoint < start)\r\n            return 0;\r\n\r\n         offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);\r\n         if (offset == 0)\r\n            return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));\r\n\r\n         return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);\r\n      }\r\n   } else if (format == 12 || format == 13) {\r\n      stbtt_uint32 ngroups = ttULONG(data+index_map+12);\r\n      stbtt_int32 low,high;\r\n      low = 0; high = (stbtt_int32)ngroups;\r\n      // Binary search the right group.\r\n      while (low < high) {\r\n         stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high\r\n         stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);\r\n         stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);\r\n         if ((stbtt_uint32) unicode_codepoint < start_char)\r\n            high = mid;\r\n         else if ((stbtt_uint32) unicode_codepoint > end_char)\r\n            low = mid+1;\r\n         else {\r\n            stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);\r\n            if (format == 12)\r\n               return start_glyph + unicode_codepoint-start_char;\r\n            else // format == 13\r\n               return start_glyph;\r\n         }\r\n      }\r\n      return 0; // not found\r\n   }\r\n   // @TODO\r\n   STBTT_assert(0);\r\n   return 0;\r\n}\r\n\r\nSTBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)\r\n{\r\n   return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);\r\n}\r\n\r\nstatic void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)\r\n{\r\n   v->type = type;\r\n   v->x = (stbtt_int16) x;\r\n   v->y = (stbtt_int16) y;\r\n   v->cx = (stbtt_int16) cx;\r\n   v->cy = (stbtt_int16) cy;\r\n}\r\n\r\nstatic int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)\r\n{\r\n   int g1,g2;\r\n\r\n   STBTT_assert(!info->cff.size);\r\n\r\n   if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range\r\n   if (info->indexToLocFormat >= 2)    return -1; // unknown index->glyph map format\r\n\r\n   if (info->indexToLocFormat == 0) {\r\n      g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;\r\n      g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;\r\n   } else {\r\n      g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);\r\n      g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);\r\n   }\r\n\r\n   return g1==g2 ? -1 : g1; // if length is 0, return -1\r\n}\r\n\r\nstatic int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);\r\n\r\nSTBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)\r\n{\r\n   if (info->cff.size) {\r\n      stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);\r\n   } else {\r\n      int g = stbtt__GetGlyfOffset(info, glyph_index);\r\n      if (g < 0) return 0;\r\n\r\n      if (x0) *x0 = ttSHORT(info->data + g + 2);\r\n      if (y0) *y0 = ttSHORT(info->data + g + 4);\r\n      if (x1) *x1 = ttSHORT(info->data + g + 6);\r\n      if (y1) *y1 = ttSHORT(info->data + g + 8);\r\n   }\r\n   return 1;\r\n}\r\n\r\nSTBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)\r\n{\r\n   return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);\r\n}\r\n\r\nSTBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)\r\n{\r\n   stbtt_int16 numberOfContours;\r\n   int g;\r\n   if (info->cff.size)\r\n      return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;\r\n   g = stbtt__GetGlyfOffset(info, glyph_index);\r\n   if (g < 0) return 1;\r\n   numberOfContours = ttSHORT(info->data + g);\r\n   return numberOfContours == 0;\r\n}\r\n\r\nstatic int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,\r\n    stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)\r\n{\r\n   if (start_off) {\r\n      if (was_off)\r\n         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);\r\n      stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);\r\n   } else {\r\n      if (was_off)\r\n         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);\r\n      else\r\n         stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);\r\n   }\r\n   return num_vertices;\r\n}\r\n\r\nstatic int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)\r\n{\r\n   stbtt_int16 numberOfContours;\r\n   stbtt_uint8 *endPtsOfContours;\r\n   stbtt_uint8 *data = info->data;\r\n   stbtt_vertex *vertices=0;\r\n   int num_vertices=0;\r\n   int g = stbtt__GetGlyfOffset(info, glyph_index);\r\n\r\n   *pvertices = NULL;\r\n\r\n   if (g < 0) return 0;\r\n\r\n   numberOfContours = ttSHORT(data + g);\r\n\r\n   if (numberOfContours > 0) {\r\n      stbtt_uint8 flags=0,flagcount;\r\n      stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;\r\n      stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;\r\n      stbtt_uint8 *points;\r\n      endPtsOfContours = (data + g + 10);\r\n      ins = ttUSHORT(data + g + 10 + numberOfContours * 2);\r\n      points = data + g + 10 + numberOfContours * 2 + 2 + ins;\r\n\r\n      n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);\r\n\r\n      m = n + 2*numberOfContours;  // a loose bound on how many vertices we might need\r\n      vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);\r\n      if (vertices == 0)\r\n         return 0;\r\n\r\n      next_move = 0;\r\n      flagcount=0;\r\n\r\n      // in first pass, we load uninterpreted data into the allocated array\r\n      // above, shifted to the end of the array so we won't overwrite it when\r\n      // we create our final data starting from the front\r\n\r\n      off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated\r\n\r\n      // first load flags\r\n\r\n      for (i=0; i < n; ++i) {\r\n         if (flagcount == 0) {\r\n            flags = *points++;\r\n            if (flags & 8)\r\n               flagcount = *points++;\r\n         } else\r\n            --flagcount;\r\n         vertices[off+i].type = flags;\r\n      }\r\n\r\n      // now load x coordinates\r\n      x=0;\r\n      for (i=0; i < n; ++i) {\r\n         flags = vertices[off+i].type;\r\n         if (flags & 2) {\r\n            stbtt_int16 dx = *points++;\r\n            x += (flags & 16) ? dx : -dx; // ???\r\n         } else {\r\n            if (!(flags & 16)) {\r\n               x = x + (stbtt_int16) (points[0]*256 + points[1]);\r\n               points += 2;\r\n            }\r\n         }\r\n         vertices[off+i].x = (stbtt_int16) x;\r\n      }\r\n\r\n      // now load y coordinates\r\n      y=0;\r\n      for (i=0; i < n; ++i) {\r\n         flags = vertices[off+i].type;\r\n         if (flags & 4) {\r\n            stbtt_int16 dy = *points++;\r\n            y += (flags & 32) ? dy : -dy; // ???\r\n         } else {\r\n            if (!(flags & 32)) {\r\n               y = y + (stbtt_int16) (points[0]*256 + points[1]);\r\n               points += 2;\r\n            }\r\n         }\r\n         vertices[off+i].y = (stbtt_int16) y;\r\n      }\r\n\r\n      // now convert them to our format\r\n      num_vertices=0;\r\n      sx = sy = cx = cy = scx = scy = 0;\r\n      for (i=0; i < n; ++i) {\r\n         flags = vertices[off+i].type;\r\n         x     = (stbtt_int16) vertices[off+i].x;\r\n         y     = (stbtt_int16) vertices[off+i].y;\r\n\r\n         if (next_move == i) {\r\n            if (i != 0)\r\n               num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);\r\n\r\n            // now start the new one               \r\n            start_off = !(flags & 1);\r\n            if (start_off) {\r\n               // if we start off with an off-curve point, then when we need to find a point on the curve\r\n               // where we can start, and we need to save some state for when we wraparound.\r\n               scx = x;\r\n               scy = y;\r\n               if (!(vertices[off+i+1].type & 1)) {\r\n                  // next point is also a curve point, so interpolate an on-point curve\r\n                  sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;\r\n                  sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;\r\n               } else {\r\n                  // otherwise just use the next point as our start point\r\n                  sx = (stbtt_int32) vertices[off+i+1].x;\r\n                  sy = (stbtt_int32) vertices[off+i+1].y;\r\n                  ++i; // we're using point i+1 as the starting point, so skip it\r\n               }\r\n            } else {\r\n               sx = x;\r\n               sy = y;\r\n            }\r\n            stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);\r\n            was_off = 0;\r\n            next_move = 1 + ttUSHORT(endPtsOfContours+j*2);\r\n            ++j;\r\n         } else {\r\n            if (!(flags & 1)) { // if it's a curve\r\n               if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint\r\n                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);\r\n               cx = x;\r\n               cy = y;\r\n               was_off = 1;\r\n            } else {\r\n               if (was_off)\r\n                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);\r\n               else\r\n                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);\r\n               was_off = 0;\r\n            }\r\n         }\r\n      }\r\n      num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);\r\n   } else if (numberOfContours == -1) {\r\n      // Compound shapes.\r\n      int more = 1;\r\n      stbtt_uint8 *comp = data + g + 10;\r\n      num_vertices = 0;\r\n      vertices = 0;\r\n      while (more) {\r\n         stbtt_uint16 flags, gidx;\r\n         int comp_num_verts = 0, i;\r\n         stbtt_vertex *comp_verts = 0, *tmp = 0;\r\n         float mtx[6] = {1,0,0,1,0,0}, m, n;\r\n         \r\n         flags = ttSHORT(comp); comp+=2;\r\n         gidx = ttSHORT(comp); comp+=2;\r\n\r\n         if (flags & 2) { // XY values\r\n            if (flags & 1) { // shorts\r\n               mtx[4] = ttSHORT(comp); comp+=2;\r\n               mtx[5] = ttSHORT(comp); comp+=2;\r\n            } else {\r\n               mtx[4] = ttCHAR(comp); comp+=1;\r\n               mtx[5] = ttCHAR(comp); comp+=1;\r\n            }\r\n         }\r\n         else {\r\n            // @TODO handle matching point\r\n            STBTT_assert(0);\r\n         }\r\n         if (flags & (1<<3)) { // WE_HAVE_A_SCALE\r\n            mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;\r\n            mtx[1] = mtx[2] = 0;\r\n         } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE\r\n            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;\r\n            mtx[1] = mtx[2] = 0;\r\n            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;\r\n         } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO\r\n            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;\r\n            mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;\r\n            mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;\r\n            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;\r\n         }\r\n         \r\n         // Find transformation scales.\r\n         m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);\r\n         n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);\r\n\r\n         // Get indexed glyph.\r\n         comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);\r\n         if (comp_num_verts > 0) {\r\n            // Transform vertices.\r\n            for (i = 0; i < comp_num_verts; ++i) {\r\n               stbtt_vertex* v = &comp_verts[i];\r\n               stbtt_vertex_type x,y;\r\n               x=v->x; y=v->y;\r\n               v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));\r\n               v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));\r\n               x=v->cx; y=v->cy;\r\n               v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));\r\n               v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));\r\n            }\r\n            // Append vertices.\r\n            tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);\r\n            if (!tmp) {\r\n               if (vertices) STBTT_free(vertices, info->userdata);\r\n               if (comp_verts) STBTT_free(comp_verts, info->userdata);\r\n               return 0;\r\n            }\r\n            if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));\r\n            STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));\r\n            if (vertices) STBTT_free(vertices, info->userdata);\r\n            vertices = tmp;\r\n            STBTT_free(comp_verts, info->userdata);\r\n            num_vertices += comp_num_verts;\r\n         }\r\n         // More components ?\r\n         more = flags & (1<<5);\r\n      }\r\n   } else if (numberOfContours < 0) {\r\n      // @TODO other compound variations?\r\n      STBTT_assert(0);\r\n   } else {\r\n      // numberOfCounters == 0, do nothing\r\n   }\r\n\r\n   *pvertices = vertices;\r\n   return num_vertices;\r\n}\r\n\r\ntypedef struct\r\n{\r\n   int bounds;\r\n   int started;\r\n   float first_x, first_y;\r\n   float x, y;\r\n   stbtt_int32 min_x, max_x, min_y, max_y;\r\n\r\n   stbtt_vertex *pvertices;\r\n   int num_vertices;\r\n} stbtt__csctx;\r\n\r\n#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}\r\n\r\nstatic void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)\r\n{\r\n   if (x > c->max_x || !c->started) c->max_x = x;\r\n   if (y > c->max_y || !c->started) c->max_y = y;\r\n   if (x < c->min_x || !c->started) c->min_x = x;\r\n   if (y < c->min_y || !c->started) c->min_y = y;\r\n   c->started = 1;\r\n}\r\n\r\nstatic void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)\r\n{\r\n   if (c->bounds) {\r\n      stbtt__track_vertex(c, x, y);\r\n      if (type == STBTT_vcubic) {\r\n         stbtt__track_vertex(c, cx, cy);\r\n         stbtt__track_vertex(c, cx1, cy1);\r\n      }\r\n   } else {\r\n      stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);\r\n      c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;\r\n      c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;\r\n   }\r\n   c->num_vertices++;\r\n}\r\n\r\nstatic void stbtt__csctx_close_shape(stbtt__csctx *ctx)\r\n{\r\n   if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)\r\n      stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);\r\n}\r\n\r\nstatic void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)\r\n{\r\n   stbtt__csctx_close_shape(ctx);\r\n   ctx->first_x = ctx->x = ctx->x + dx;\r\n   ctx->first_y = ctx->y = ctx->y + dy;\r\n   stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);\r\n}\r\n\r\nstatic void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)\r\n{\r\n   ctx->x += dx;\r\n   ctx->y += dy;\r\n   stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);\r\n}\r\n\r\nstatic void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)\r\n{\r\n   float cx1 = ctx->x + dx1;\r\n   float cy1 = ctx->y + dy1;\r\n   float cx2 = cx1 + dx2;\r\n   float cy2 = cy1 + dy2;\r\n   ctx->x = cx2 + dx3;\r\n   ctx->y = cy2 + dy3;\r\n   stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);\r\n}\r\n\r\nstatic stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)\r\n{\r\n   int count = stbtt__cff_index_count(&idx);\r\n   int bias = 107;\r\n   if (count >= 33900)\r\n      bias = 32768;\r\n   else if (count >= 1240)\r\n      bias = 1131;\r\n   n += bias;\r\n   if (n < 0 || n >= count)\r\n      return stbtt__new_buf(NULL, 0);\r\n   return stbtt__cff_index_get(idx, n);\r\n}\r\n\r\nstatic stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)\r\n{\r\n   stbtt__buf fdselect = info->fdselect;\r\n   int nranges, start, end, v, fmt, fdselector = -1, i;\r\n\r\n   stbtt__buf_seek(&fdselect, 0);\r\n   fmt = stbtt__buf_get8(&fdselect);\r\n   if (fmt == 0) {\r\n      // untested\r\n      stbtt__buf_skip(&fdselect, glyph_index);\r\n      fdselector = stbtt__buf_get8(&fdselect);\r\n   } else if (fmt == 3) {\r\n      nranges = stbtt__buf_get16(&fdselect);\r\n      start = stbtt__buf_get16(&fdselect);\r\n      for (i = 0; i < nranges; i++) {\r\n         v = stbtt__buf_get8(&fdselect);\r\n         end = stbtt__buf_get16(&fdselect);\r\n         if (glyph_index >= start && glyph_index < end) {\r\n            fdselector = v;\r\n            break;\r\n         }\r\n         start = end;\r\n      }\r\n   }\r\n   if (fdselector == -1) stbtt__new_buf(NULL, 0);\r\n   return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));\r\n}\r\n\r\nstatic int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)\r\n{\r\n   int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;\r\n   int has_subrs = 0, clear_stack;\r\n   float s[48];\r\n   stbtt__buf subr_stack[10], subrs = info->subrs, b;\r\n   float f;\r\n\r\n#define STBTT__CSERR(s) (0)\r\n\r\n   // this currently ignores the initial width value, which isn't needed if we have hmtx\r\n   b = stbtt__cff_index_get(info->charstrings, glyph_index);\r\n   while (b.cursor < b.size) {\r\n      i = 0;\r\n      clear_stack = 1;\r\n      b0 = stbtt__buf_get8(&b);\r\n      switch (b0) {\r\n      // @TODO implement hinting\r\n      case 0x13: // hintmask\r\n      case 0x14: // cntrmask\r\n         if (in_header)\r\n            maskbits += (sp / 2); // implicit \"vstem\"\r\n         in_header = 0;\r\n         stbtt__buf_skip(&b, (maskbits + 7) / 8);\r\n         break;\r\n\r\n      case 0x01: // hstem\r\n      case 0x03: // vstem\r\n      case 0x12: // hstemhm\r\n      case 0x17: // vstemhm\r\n         maskbits += (sp / 2);\r\n         break;\r\n\r\n      case 0x15: // rmoveto\r\n         in_header = 0;\r\n         if (sp < 2) return STBTT__CSERR(\"rmoveto stack\");\r\n         stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);\r\n         break;\r\n      case 0x04: // vmoveto\r\n         in_header = 0;\r\n         if (sp < 1) return STBTT__CSERR(\"vmoveto stack\");\r\n         stbtt__csctx_rmove_to(c, 0, s[sp-1]);\r\n         break;\r\n      case 0x16: // hmoveto\r\n         in_header = 0;\r\n         if (sp < 1) return STBTT__CSERR(\"hmoveto stack\");\r\n         stbtt__csctx_rmove_to(c, s[sp-1], 0);\r\n         break;\r\n\r\n      case 0x05: // rlineto\r\n         if (sp < 2) return STBTT__CSERR(\"rlineto stack\");\r\n         for (; i + 1 < sp; i += 2)\r\n            stbtt__csctx_rline_to(c, s[i], s[i+1]);\r\n         break;\r\n\r\n      // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical\r\n      // starting from a different place.\r\n\r\n      case 0x07: // vlineto\r\n         if (sp < 1) return STBTT__CSERR(\"vlineto stack\");\r\n         goto vlineto;\r\n      case 0x06: // hlineto\r\n         if (sp < 1) return STBTT__CSERR(\"hlineto stack\");\r\n         for (;;) {\r\n            if (i >= sp) break;\r\n            stbtt__csctx_rline_to(c, s[i], 0);\r\n            i++;\r\n      vlineto:\r\n            if (i >= sp) break;\r\n            stbtt__csctx_rline_to(c, 0, s[i]);\r\n            i++;\r\n         }\r\n         break;\r\n\r\n      case 0x1F: // hvcurveto\r\n         if (sp < 4) return STBTT__CSERR(\"hvcurveto stack\");\r\n         goto hvcurveto;\r\n      case 0x1E: // vhcurveto\r\n         if (sp < 4) return STBTT__CSERR(\"vhcurveto stack\");\r\n         for (;;) {\r\n            if (i + 3 >= sp) break;\r\n            stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);\r\n            i += 4;\r\n      hvcurveto:\r\n            if (i + 3 >= sp) break;\r\n            stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);\r\n            i += 4;\r\n         }\r\n         break;\r\n\r\n      case 0x08: // rrcurveto\r\n         if (sp < 6) return STBTT__CSERR(\"rcurveline stack\");\r\n         for (; i + 5 < sp; i += 6)\r\n            stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);\r\n         break;\r\n\r\n      case 0x18: // rcurveline\r\n         if (sp < 8) return STBTT__CSERR(\"rcurveline stack\");\r\n         for (; i + 5 < sp - 2; i += 6)\r\n            stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);\r\n         if (i + 1 >= sp) return STBTT__CSERR(\"rcurveline stack\");\r\n         stbtt__csctx_rline_to(c, s[i], s[i+1]);\r\n         break;\r\n\r\n      case 0x19: // rlinecurve\r\n         if (sp < 8) return STBTT__CSERR(\"rlinecurve stack\");\r\n         for (; i + 1 < sp - 6; i += 2)\r\n            stbtt__csctx_rline_to(c, s[i], s[i+1]);\r\n         if (i + 5 >= sp) return STBTT__CSERR(\"rlinecurve stack\");\r\n         stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);\r\n         break;\r\n\r\n      case 0x1A: // vvcurveto\r\n      case 0x1B: // hhcurveto\r\n         if (sp < 4) return STBTT__CSERR(\"(vv|hh)curveto stack\");\r\n         f = 0.0;\r\n         if (sp & 1) { f = s[i]; i++; }\r\n         for (; i + 3 < sp; i += 4) {\r\n            if (b0 == 0x1B)\r\n               stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);\r\n            else\r\n               stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);\r\n            f = 0.0;\r\n         }\r\n         break;\r\n\r\n      case 0x0A: // callsubr\r\n         if (!has_subrs) {\r\n            if (info->fdselect.size)\r\n               subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);\r\n            has_subrs = 1;\r\n         }\r\n         // fallthrough\r\n      case 0x1D: // callgsubr\r\n         if (sp < 1) return STBTT__CSERR(\"call(g|)subr stack\");\r\n         v = (int) s[--sp];\r\n         if (subr_stack_height >= 10) return STBTT__CSERR(\"recursion limit\");\r\n         subr_stack[subr_stack_height++] = b;\r\n         b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);\r\n         if (b.size == 0) return STBTT__CSERR(\"subr not found\");\r\n         b.cursor = 0;\r\n         clear_stack = 0;\r\n         break;\r\n\r\n      case 0x0B: // return\r\n         if (subr_stack_height <= 0) return STBTT__CSERR(\"return outside subr\");\r\n         b = subr_stack[--subr_stack_height];\r\n         clear_stack = 0;\r\n         break;\r\n\r\n      case 0x0E: // endchar\r\n         stbtt__csctx_close_shape(c);\r\n         return 1;\r\n\r\n      case 0x0C: { // two-byte escape\r\n         float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;\r\n         float dx, dy;\r\n         int b1 = stbtt__buf_get8(&b);\r\n         switch (b1) {\r\n         // @TODO These \"flex\" implementations ignore the flex-depth and resolution,\r\n         // and always draw beziers.\r\n         case 0x22: // hflex\r\n            if (sp < 7) return STBTT__CSERR(\"hflex stack\");\r\n            dx1 = s[0];\r\n            dx2 = s[1];\r\n            dy2 = s[2];\r\n            dx3 = s[3];\r\n            dx4 = s[4];\r\n            dx5 = s[5];\r\n            dx6 = s[6];\r\n            stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);\r\n            stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);\r\n            break;\r\n\r\n         case 0x23: // flex\r\n            if (sp < 13) return STBTT__CSERR(\"flex stack\");\r\n            dx1 = s[0];\r\n            dy1 = s[1];\r\n            dx2 = s[2];\r\n            dy2 = s[3];\r\n            dx3 = s[4];\r\n            dy3 = s[5];\r\n            dx4 = s[6];\r\n            dy4 = s[7];\r\n            dx5 = s[8];\r\n            dy5 = s[9];\r\n            dx6 = s[10];\r\n            dy6 = s[11];\r\n            //fd is s[12]\r\n            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);\r\n            stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);\r\n            break;\r\n\r\n         case 0x24: // hflex1\r\n            if (sp < 9) return STBTT__CSERR(\"hflex1 stack\");\r\n            dx1 = s[0];\r\n            dy1 = s[1];\r\n            dx2 = s[2];\r\n            dy2 = s[3];\r\n            dx3 = s[4];\r\n            dx4 = s[5];\r\n            dx5 = s[6];\r\n            dy5 = s[7];\r\n            dx6 = s[8];\r\n            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);\r\n            stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));\r\n            break;\r\n\r\n         case 0x25: // flex1\r\n            if (sp < 11) return STBTT__CSERR(\"flex1 stack\");\r\n            dx1 = s[0];\r\n            dy1 = s[1];\r\n            dx2 = s[2];\r\n            dy2 = s[3];\r\n            dx3 = s[4];\r\n            dy3 = s[5];\r\n            dx4 = s[6];\r\n            dy4 = s[7];\r\n            dx5 = s[8];\r\n            dy5 = s[9];\r\n            dx6 = dy6 = s[10];\r\n            dx = dx1+dx2+dx3+dx4+dx5;\r\n            dy = dy1+dy2+dy3+dy4+dy5;\r\n            if (STBTT_fabs(dx) > STBTT_fabs(dy))\r\n               dy6 = -dy;\r\n            else\r\n               dx6 = -dx;\r\n            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);\r\n            stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);\r\n            break;\r\n\r\n         default:\r\n            return STBTT__CSERR(\"unimplemented\");\r\n         }\r\n      } break;\r\n\r\n      default:\r\n         if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))\r\n            return STBTT__CSERR(\"reserved operator\");\r\n\r\n         // push immediate\r\n         if (b0 == 255) {\r\n            f = (float)stbtt__buf_get32(&b) / 0x10000;\r\n         } else {\r\n            stbtt__buf_skip(&b, -1);\r\n            f = (float)(stbtt_int16)stbtt__cff_int(&b);\r\n         }\r\n         if (sp >= 48) return STBTT__CSERR(\"push stack overflow\");\r\n         s[sp++] = f;\r\n         clear_stack = 0;\r\n         break;\r\n      }\r\n      if (clear_stack) sp = 0;\r\n   }\r\n   return STBTT__CSERR(\"no endchar\");\r\n\r\n#undef STBTT__CSERR\r\n}\r\n\r\nstatic int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)\r\n{\r\n   // runs the charstring twice, once to count and once to output (to avoid realloc)\r\n   stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);\r\n   stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);\r\n   if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {\r\n      *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);\r\n      output_ctx.pvertices = *pvertices;\r\n      if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {\r\n         STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);\r\n         return output_ctx.num_vertices;\r\n      }\r\n   }\r\n   *pvertices = NULL;\r\n   return 0;\r\n}\r\n\r\nstatic int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)\r\n{\r\n   stbtt__csctx c = STBTT__CSCTX_INIT(1);\r\n   int r = stbtt__run_charstring(info, glyph_index, &c);\r\n   if (x0) {\r\n      *x0 = r ? c.min_x : 0;\r\n      *y0 = r ? c.min_y : 0;\r\n      *x1 = r ? c.max_x : 0;\r\n      *y1 = r ? c.max_y : 0;\r\n   }\r\n   return r ? c.num_vertices : 0;\r\n}\r\n\r\nSTBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)\r\n{\r\n   if (!info->cff.size)\r\n      return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);\r\n   else\r\n      return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)\r\n{\r\n   stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);\r\n   if (glyph_index < numOfLongHorMetrics) {\r\n      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*glyph_index);\r\n      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);\r\n   } else {\r\n      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));\r\n      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));\r\n   }\r\n}\r\n\r\nSTBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)\r\n{\r\n   stbtt_uint8 *data = info->data + info->kern;\r\n   stbtt_uint32 needle, straw;\r\n   int l, r, m;\r\n\r\n   // we only look at the first table. it must be 'horizontal' and format 0.\r\n   if (!info->kern)\r\n      return 0;\r\n   if (ttUSHORT(data+2) < 1) // number of tables, need at least 1\r\n      return 0;\r\n   if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format\r\n      return 0;\r\n\r\n   l = 0;\r\n   r = ttUSHORT(data+10) - 1;\r\n   needle = glyph1 << 16 | glyph2;\r\n   while (l <= r) {\r\n      m = (l + r) >> 1;\r\n      straw = ttULONG(data+18+(m*6)); // note: unaligned read\r\n      if (needle < straw)\r\n         r = m - 1;\r\n      else if (needle > straw)\r\n         l = m + 1;\r\n      else\r\n         return ttSHORT(data+22+(m*6));\r\n   }\r\n   return 0;\r\n}\r\n\r\nSTBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)\r\n{\r\n   if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs\r\n      return 0;\r\n   return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)\r\n{\r\n   stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)\r\n{\r\n   if (ascent ) *ascent  = ttSHORT(info->data+info->hhea + 4);\r\n   if (descent) *descent = ttSHORT(info->data+info->hhea + 6);\r\n   if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)\r\n{\r\n   *x0 = ttSHORT(info->data + info->head + 36);\r\n   *y0 = ttSHORT(info->data + info->head + 38);\r\n   *x1 = ttSHORT(info->data + info->head + 40);\r\n   *y1 = ttSHORT(info->data + info->head + 42);\r\n}\r\n\r\nSTBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)\r\n{\r\n   int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);\r\n   return (float) height / fheight;\r\n}\r\n\r\nSTBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)\r\n{\r\n   int unitsPerEm = ttUSHORT(info->data + info->head + 18);\r\n   return pixels / unitsPerEm;\r\n}\r\n\r\nSTBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)\r\n{\r\n   STBTT_free(v, info->userdata);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// antialiasing software rasterizer\r\n//\r\n\r\nSTBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)\r\n{\r\n   int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning\r\n   if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {\r\n      // e.g. space character\r\n      if (ix0) *ix0 = 0;\r\n      if (iy0) *iy0 = 0;\r\n      if (ix1) *ix1 = 0;\r\n      if (iy1) *iy1 = 0;\r\n   } else {\r\n      // move to integral bboxes (treating pixels as little squares, what pixels get touched)?\r\n      if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);\r\n      if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);\r\n      if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);\r\n      if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);\r\n   }\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)\r\n{\r\n   stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)\r\n{\r\n   stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)\r\n{\r\n   stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n//  Rasterizer\r\n\r\ntypedef struct stbtt__hheap_chunk\r\n{\r\n   struct stbtt__hheap_chunk *next;\r\n} stbtt__hheap_chunk;\r\n\r\ntypedef struct stbtt__hheap\r\n{\r\n   struct stbtt__hheap_chunk *head;\r\n   void   *first_free;\r\n   int    num_remaining_in_head_chunk;\r\n} stbtt__hheap;\r\n\r\nstatic void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)\r\n{\r\n   if (hh->first_free) {\r\n      void *p = hh->first_free;\r\n      hh->first_free = * (void **) p;\r\n      return p;\r\n   } else {\r\n      if (hh->num_remaining_in_head_chunk == 0) {\r\n         int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);\r\n         stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);\r\n         if (c == NULL)\r\n            return NULL;\r\n         c->next = hh->head;\r\n         hh->head = c;\r\n         hh->num_remaining_in_head_chunk = count;\r\n      }\r\n      --hh->num_remaining_in_head_chunk;\r\n      return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk;\r\n   }\r\n}\r\n\r\nstatic void stbtt__hheap_free(stbtt__hheap *hh, void *p)\r\n{\r\n   *(void **) p = hh->first_free;\r\n   hh->first_free = p;\r\n}\r\n\r\nstatic void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)\r\n{\r\n   stbtt__hheap_chunk *c = hh->head;\r\n   while (c) {\r\n      stbtt__hheap_chunk *n = c->next;\r\n      STBTT_free(c, userdata);\r\n      c = n;\r\n   }\r\n}\r\n\r\ntypedef struct stbtt__edge {\r\n   float x0,y0, x1,y1;\r\n   int invert;\r\n} stbtt__edge;\r\n\r\n\r\ntypedef struct stbtt__active_edge\r\n{\r\n   struct stbtt__active_edge *next;\r\n   #if STBTT_RASTERIZER_VERSION==1\r\n   int x,dx;\r\n   float ey;\r\n   int direction;\r\n   #elif STBTT_RASTERIZER_VERSION==2\r\n   float fx,fdx,fdy;\r\n   float direction;\r\n   float sy;\r\n   float ey;\r\n   #else\r\n   #error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\r\n   #endif\r\n} stbtt__active_edge;\r\n\r\n#if STBTT_RASTERIZER_VERSION == 1\r\n#define STBTT_FIXSHIFT   10\r\n#define STBTT_FIX        (1 << STBTT_FIXSHIFT)\r\n#define STBTT_FIXMASK    (STBTT_FIX-1)\r\n\r\nstatic stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)\r\n{\r\n   stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);\r\n   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);\r\n   STBTT_assert(z != NULL);\r\n   if (!z) return z;\r\n   \r\n   // round dx down to avoid overshooting\r\n   if (dxdy < 0)\r\n      z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);\r\n   else\r\n      z->dx = STBTT_ifloor(STBTT_FIX * dxdy);\r\n\r\n   z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount\r\n   z->x -= off_x * STBTT_FIX;\r\n\r\n   z->ey = e->y1;\r\n   z->next = 0;\r\n   z->direction = e->invert ? 1 : -1;\r\n   return z;\r\n}\r\n#elif STBTT_RASTERIZER_VERSION == 2\r\nstatic stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)\r\n{\r\n   stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);\r\n   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);\r\n   STBTT_assert(z != NULL);\r\n   //STBTT_assert(e->y0 <= start_point);\r\n   if (!z) return z;\r\n   z->fdx = dxdy;\r\n   z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;\r\n   z->fx = e->x0 + dxdy * (start_point - e->y0);\r\n   z->fx -= off_x;\r\n   z->direction = e->invert ? 1.0f : -1.0f;\r\n   z->sy = e->y0;\r\n   z->ey = e->y1;\r\n   z->next = 0;\r\n   return z;\r\n}\r\n#else\r\n#error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\r\n#endif\r\n\r\n#if STBTT_RASTERIZER_VERSION == 1\r\n// note: this routine clips fills that extend off the edges... ideally this\r\n// wouldn't happen, but it could happen if the truetype glyph bounding boxes\r\n// are wrong, or if the user supplies a too-small bitmap\r\nstatic void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)\r\n{\r\n   // non-zero winding fill\r\n   int x0=0, w=0;\r\n\r\n   while (e) {\r\n      if (w == 0) {\r\n         // if we're currently at zero, we need to record the edge start point\r\n         x0 = e->x; w += e->direction;\r\n      } else {\r\n         int x1 = e->x; w += e->direction;\r\n         // if we went to zero, we need to draw\r\n         if (w == 0) {\r\n            int i = x0 >> STBTT_FIXSHIFT;\r\n            int j = x1 >> STBTT_FIXSHIFT;\r\n\r\n            if (i < len && j >= 0) {\r\n               if (i == j) {\r\n                  // x0,x1 are the same pixel, so compute combined coverage\r\n                  scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);\r\n               } else {\r\n                  if (i >= 0) // add antialiasing for x0\r\n                     scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);\r\n                  else\r\n                     i = -1; // clip\r\n\r\n                  if (j < len) // add antialiasing for x1\r\n                     scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);\r\n                  else\r\n                     j = len; // clip\r\n\r\n                  for (++i; i < j; ++i) // fill pixels between x0 and x1\r\n                     scanline[i] = scanline[i] + (stbtt_uint8) max_weight;\r\n               }\r\n            }\r\n         }\r\n      }\r\n      \r\n      e = e->next;\r\n   }\r\n}\r\n\r\nstatic void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)\r\n{\r\n   stbtt__hheap hh = { 0, 0, 0 };\r\n   stbtt__active_edge *active = NULL;\r\n   int y,j=0;\r\n   int max_weight = (255 / vsubsample);  // weight per vertical scanline\r\n   int s; // vertical subsample index\r\n   unsigned char scanline_data[512], *scanline;\r\n\r\n   if (result->w > 512)\r\n      scanline = (unsigned char *) STBTT_malloc(result->w, userdata);\r\n   else\r\n      scanline = scanline_data;\r\n\r\n   y = off_y * vsubsample;\r\n   e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;\r\n\r\n   while (j < result->h) {\r\n      STBTT_memset(scanline, 0, result->w);\r\n      for (s=0; s < vsubsample; ++s) {\r\n         // find center of pixel for this scanline\r\n         float scan_y = y + 0.5f;\r\n         stbtt__active_edge **step = &active;\r\n\r\n         // update all active edges;\r\n         // remove all active edges that terminate before the center of this scanline\r\n         while (*step) {\r\n            stbtt__active_edge * z = *step;\r\n            if (z->ey <= scan_y) {\r\n               *step = z->next; // delete from list\r\n               STBTT_assert(z->direction);\r\n               z->direction = 0;\r\n               stbtt__hheap_free(&hh, z);\r\n            } else {\r\n               z->x += z->dx; // advance to position for current scanline\r\n               step = &((*step)->next); // advance through list\r\n            }\r\n         }\r\n\r\n         // resort the list if needed\r\n         for(;;) {\r\n            int changed=0;\r\n            step = &active;\r\n            while (*step && (*step)->next) {\r\n               if ((*step)->x > (*step)->next->x) {\r\n                  stbtt__active_edge *t = *step;\r\n                  stbtt__active_edge *q = t->next;\r\n\r\n                  t->next = q->next;\r\n                  q->next = t;\r\n                  *step = q;\r\n                  changed = 1;\r\n               }\r\n               step = &(*step)->next;\r\n            }\r\n            if (!changed) break;\r\n         }\r\n\r\n         // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline\r\n         while (e->y0 <= scan_y) {\r\n            if (e->y1 > scan_y) {\r\n               stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);\r\n               if (z != NULL) {\r\n                  // find insertion point\r\n                  if (active == NULL)\r\n                     active = z;\r\n                  else if (z->x < active->x) {\r\n                     // insert at front\r\n                     z->next = active;\r\n                     active = z;\r\n                  } else {\r\n                     // find thing to insert AFTER\r\n                     stbtt__active_edge *p = active;\r\n                     while (p->next && p->next->x < z->x)\r\n                        p = p->next;\r\n                     // at this point, p->next->x is NOT < z->x\r\n                     z->next = p->next;\r\n                     p->next = z;\r\n                  }\r\n               }\r\n            }\r\n            ++e;\r\n         }\r\n\r\n         // now process all active edges in XOR fashion\r\n         if (active)\r\n            stbtt__fill_active_edges(scanline, result->w, active, max_weight);\r\n\r\n         ++y;\r\n      }\r\n      STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);\r\n      ++j;\r\n   }\r\n\r\n   stbtt__hheap_cleanup(&hh, userdata);\r\n\r\n   if (scanline != scanline_data)\r\n      STBTT_free(scanline, userdata);\r\n}\r\n\r\n#elif STBTT_RASTERIZER_VERSION == 2\r\n\r\n// the edge passed in here does not cross the vertical line at x or the vertical line at x+1\r\n// (i.e. it has already been clipped to those)\r\nstatic void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)\r\n{\r\n   if (y0 == y1) return;\r\n   STBTT_assert(y0 < y1);\r\n   STBTT_assert(e->sy <= e->ey);\r\n   if (y0 > e->ey) return;\r\n   if (y1 < e->sy) return;\r\n   if (y0 < e->sy) {\r\n      x0 += (x1-x0) * (e->sy - y0) / (y1-y0);\r\n      y0 = e->sy;\r\n   }\r\n   if (y1 > e->ey) {\r\n      x1 += (x1-x0) * (e->ey - y1) / (y1-y0);\r\n      y1 = e->ey;\r\n   }\r\n\r\n   if (x0 == x)\r\n      STBTT_assert(x1 <= x+1);\r\n   else if (x0 == x+1)\r\n      STBTT_assert(x1 >= x);\r\n   else if (x0 <= x)\r\n      STBTT_assert(x1 <= x);\r\n   else if (x0 >= x+1)\r\n      STBTT_assert(x1 >= x+1);\r\n   else\r\n      STBTT_assert(x1 >= x && x1 <= x+1);\r\n\r\n   if (x0 <= x && x1 <= x)\r\n      scanline[x] += e->direction * (y1-y0);\r\n   else if (x0 >= x+1 && x1 >= x+1)\r\n      ;\r\n   else {\r\n      STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);\r\n      scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position\r\n   }\r\n}\r\n\r\nstatic void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)\r\n{\r\n   float y_bottom = y_top+1;\r\n\r\n   while (e) {\r\n      // brute force every pixel\r\n\r\n      // compute intersection points with top & bottom\r\n      STBTT_assert(e->ey >= y_top);\r\n\r\n      if (e->fdx == 0) {\r\n         float x0 = e->fx;\r\n         if (x0 < len) {\r\n            if (x0 >= 0) {\r\n               stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);\r\n               stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);\r\n            } else {\r\n               stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);\r\n            }\r\n         }\r\n      } else {\r\n         float x0 = e->fx;\r\n         float dx = e->fdx;\r\n         float xb = x0 + dx;\r\n         float x_top, x_bottom;\r\n         float sy0,sy1;\r\n         float dy = e->fdy;\r\n         STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);\r\n\r\n         // compute endpoints of line segment clipped to this scanline (if the\r\n         // line segment starts on this scanline. x0 is the intersection of the\r\n         // line with y_top, but that may be off the line segment.\r\n         if (e->sy > y_top) {\r\n            x_top = x0 + dx * (e->sy - y_top);\r\n            sy0 = e->sy;\r\n         } else {\r\n            x_top = x0;\r\n            sy0 = y_top;\r\n         }\r\n         if (e->ey < y_bottom) {\r\n            x_bottom = x0 + dx * (e->ey - y_top);\r\n            sy1 = e->ey;\r\n         } else {\r\n            x_bottom = xb;\r\n            sy1 = y_bottom;\r\n         }\r\n\r\n         if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {\r\n            // from here on, we don't have to range check x values\r\n\r\n            if ((int) x_top == (int) x_bottom) {\r\n               float height;\r\n               // simple case, only spans one pixel\r\n               int x = (int) x_top;\r\n               height = sy1 - sy0;\r\n               STBTT_assert(x >= 0 && x < len);\r\n               scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2)  * height;\r\n               scanline_fill[x] += e->direction * height; // everything right of this pixel is filled\r\n            } else {\r\n               int x,x1,x2;\r\n               float y_crossing, step, sign, area;\r\n               // covers 2+ pixels\r\n               if (x_top > x_bottom) {\r\n                  // flip scanline vertically; signed area is the same\r\n                  float t;\r\n                  sy0 = y_bottom - (sy0 - y_top);\r\n                  sy1 = y_bottom - (sy1 - y_top);\r\n                  t = sy0, sy0 = sy1, sy1 = t;\r\n                  t = x_bottom, x_bottom = x_top, x_top = t;\r\n                  dx = -dx;\r\n                  dy = -dy;\r\n                  t = x0, x0 = xb, xb = t;\r\n               }\r\n\r\n               x1 = (int) x_top;\r\n               x2 = (int) x_bottom;\r\n               // compute intersection with y axis at x1+1\r\n               y_crossing = (x1+1 - x0) * dy + y_top;\r\n\r\n               sign = e->direction;\r\n               // area of the rectangle covered from y0..y_crossing\r\n               area = sign * (y_crossing-sy0);\r\n               // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)\r\n               scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);\r\n\r\n               step = sign * dy;\r\n               for (x = x1+1; x < x2; ++x) {\r\n                  scanline[x] += area + step/2;\r\n                  area += step;\r\n               }\r\n               y_crossing += dy * (x2 - (x1+1));\r\n\r\n               STBTT_assert(STBTT_fabs(area) <= 1.01f);\r\n\r\n               scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);\r\n\r\n               scanline_fill[x2] += sign * (sy1-sy0);\r\n            }\r\n         } else {\r\n            // if edge goes outside of box we're drawing, we require\r\n            // clipping logic. since this does not match the intended use\r\n            // of this library, we use a different, very slow brute\r\n            // force implementation\r\n            int x;\r\n            for (x=0; x < len; ++x) {\r\n               // cases:\r\n               //\r\n               // there can be up to two intersections with the pixel. any intersection\r\n               // with left or right edges can be handled by splitting into two (or three)\r\n               // regions. intersections with top & bottom do not necessitate case-wise logic.\r\n               //\r\n               // the old way of doing this found the intersections with the left & right edges,\r\n               // then used some simple logic to produce up to three segments in sorted order\r\n               // from top-to-bottom. however, this had a problem: if an x edge was epsilon\r\n               // across the x border, then the corresponding y position might not be distinct\r\n               // from the other y segment, and it might ignored as an empty segment. to avoid\r\n               // that, we need to explicitly produce segments based on x positions.\r\n\r\n               // rename variables to clear pairs\r\n               float y0 = y_top;\r\n               float x1 = (float) (x);\r\n               float x2 = (float) (x+1);\r\n               float x3 = xb;\r\n               float y3 = y_bottom;\r\n               float y1,y2;\r\n\r\n               // x = e->x + e->dx * (y-y_top)\r\n               // (y-y_top) = (x - e->x) / e->dx\r\n               // y = (x - e->x) / e->dx + y_top\r\n               y1 = (x - x0) / dx + y_top;\r\n               y2 = (x+1 - x0) / dx + y_top;\r\n\r\n               if (x0 < x1 && x3 > x2) {         // three segments descending down-right\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);\r\n               } else if (x3 < x1 && x0 > x2) {  // three segments descending down-left\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);\r\n               } else if (x0 < x1 && x3 > x1) {  // two segments across x, down-right\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);\r\n               } else if (x3 < x1 && x0 > x1) {  // two segments across x, down-left\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);\r\n               } else if (x0 < x2 && x3 > x2) {  // two segments across x+1, down-right\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);\r\n               } else if (x3 < x2 && x0 > x2) {  // two segments across x+1, down-left\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);\r\n               } else {  // one segment\r\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);\r\n               }\r\n            }\r\n         }\r\n      }\r\n      e = e->next;\r\n   }\r\n}\r\n\r\n// directly AA rasterize edges w/o supersampling\r\nstatic void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)\r\n{\r\n   stbtt__hheap hh = { 0, 0, 0 };\r\n   stbtt__active_edge *active = NULL;\r\n   int y,j=0, i;\r\n   float scanline_data[129], *scanline, *scanline2;\r\n\r\n   STBTT__NOTUSED(vsubsample);\r\n\r\n   if (result->w > 64)\r\n      scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);\r\n   else\r\n      scanline = scanline_data;\r\n\r\n   scanline2 = scanline + result->w;\r\n\r\n   y = off_y;\r\n   e[n].y0 = (float) (off_y + result->h) + 1;\r\n\r\n   while (j < result->h) {\r\n      // find center of pixel for this scanline\r\n      float scan_y_top    = y + 0.0f;\r\n      float scan_y_bottom = y + 1.0f;\r\n      stbtt__active_edge **step = &active;\r\n\r\n      STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));\r\n      STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));\r\n\r\n      // update all active edges;\r\n      // remove all active edges that terminate before the top of this scanline\r\n      while (*step) {\r\n         stbtt__active_edge * z = *step;\r\n         if (z->ey <= scan_y_top) {\r\n            *step = z->next; // delete from list\r\n            STBTT_assert(z->direction);\r\n            z->direction = 0;\r\n            stbtt__hheap_free(&hh, z);\r\n         } else {\r\n            step = &((*step)->next); // advance through list\r\n         }\r\n      }\r\n\r\n      // insert all edges that start before the bottom of this scanline\r\n      while (e->y0 <= scan_y_bottom) {\r\n         if (e->y0 != e->y1) {\r\n            stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);\r\n            if (z != NULL) {\r\n               STBTT_assert(z->ey >= scan_y_top);\r\n               // insert at front\r\n               z->next = active;\r\n               active = z;\r\n            }\r\n         }\r\n         ++e;\r\n      }\r\n\r\n      // now process all active edges\r\n      if (active)\r\n         stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);\r\n\r\n      {\r\n         float sum = 0;\r\n         for (i=0; i < result->w; ++i) {\r\n            float k;\r\n            int m;\r\n            sum += scanline2[i];\r\n            k = scanline[i] + sum;\r\n            k = (float) STBTT_fabs(k)*255 + 0.5f;\r\n            m = (int) k;\r\n            if (m > 255) m = 255;\r\n            result->pixels[j*result->stride + i] = (unsigned char) m;\r\n         }\r\n      }\r\n      // advance all the edges\r\n      step = &active;\r\n      while (*step) {\r\n         stbtt__active_edge *z = *step;\r\n         z->fx += z->fdx; // advance to position for current scanline\r\n         step = &((*step)->next); // advance through list\r\n      }\r\n\r\n      ++y;\r\n      ++j;\r\n   }\r\n\r\n   stbtt__hheap_cleanup(&hh, userdata);\r\n\r\n   if (scanline != scanline_data)\r\n      STBTT_free(scanline, userdata);\r\n}\r\n#else\r\n#error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\r\n#endif\r\n\r\n#define STBTT__COMPARE(a,b)  ((a)->y0 < (b)->y0)\r\n\r\nstatic void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)\r\n{\r\n   int i,j;\r\n   for (i=1; i < n; ++i) {\r\n      stbtt__edge t = p[i], *a = &t;\r\n      j = i;\r\n      while (j > 0) {\r\n         stbtt__edge *b = &p[j-1];\r\n         int c = STBTT__COMPARE(a,b);\r\n         if (!c) break;\r\n         p[j] = p[j-1];\r\n         --j;\r\n      }\r\n      if (i != j)\r\n         p[j] = t;\r\n   }\r\n}\r\n\r\nstatic void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)\r\n{\r\n   /* threshhold for transitioning to insertion sort */\r\n   while (n > 12) {\r\n      stbtt__edge t;\r\n      int c01,c12,c,m,i,j;\r\n\r\n      /* compute median of three */\r\n      m = n >> 1;\r\n      c01 = STBTT__COMPARE(&p[0],&p[m]);\r\n      c12 = STBTT__COMPARE(&p[m],&p[n-1]);\r\n      /* if 0 >= mid >= end, or 0 < mid < end, then use mid */\r\n      if (c01 != c12) {\r\n         /* otherwise, we'll need to swap something else to middle */\r\n         int z;\r\n         c = STBTT__COMPARE(&p[0],&p[n-1]);\r\n         /* 0>mid && mid<n:  0>n => n; 0<n => 0 */\r\n         /* 0<mid && mid>n:  0>n => 0; 0<n => n */\r\n         z = (c == c12) ? 0 : n-1;\r\n         t = p[z];\r\n         p[z] = p[m];\r\n         p[m] = t;\r\n      }\r\n      /* now p[m] is the median-of-three */\r\n      /* swap it to the beginning so it won't move around */\r\n      t = p[0];\r\n      p[0] = p[m];\r\n      p[m] = t;\r\n\r\n      /* partition loop */\r\n      i=1;\r\n      j=n-1;\r\n      for(;;) {\r\n         /* handling of equality is crucial here */\r\n         /* for sentinels & efficiency with duplicates */\r\n         for (;;++i) {\r\n            if (!STBTT__COMPARE(&p[i], &p[0])) break;\r\n         }\r\n         for (;;--j) {\r\n            if (!STBTT__COMPARE(&p[0], &p[j])) break;\r\n         }\r\n         /* make sure we haven't crossed */\r\n         if (i >= j) break;\r\n         t = p[i];\r\n         p[i] = p[j];\r\n         p[j] = t;\r\n\r\n         ++i;\r\n         --j;\r\n      }\r\n      /* recurse on smaller side, iterate on larger */\r\n      if (j < (n-i)) {\r\n         stbtt__sort_edges_quicksort(p,j);\r\n         p = p+i;\r\n         n = n-i;\r\n      } else {\r\n         stbtt__sort_edges_quicksort(p+i, n-i);\r\n         n = j;\r\n      }\r\n   }\r\n}\r\n\r\nstatic void stbtt__sort_edges(stbtt__edge *p, int n)\r\n{\r\n   stbtt__sort_edges_quicksort(p, n);\r\n   stbtt__sort_edges_ins_sort(p, n);\r\n}\r\n\r\ntypedef struct\r\n{\r\n   float x,y;\r\n} stbtt__point;\r\n\r\nstatic void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)\r\n{\r\n   float y_scale_inv = invert ? -scale_y : scale_y;\r\n   stbtt__edge *e;\r\n   int n,i,j,k,m;\r\n#if STBTT_RASTERIZER_VERSION == 1\r\n   int vsubsample = result->h < 8 ? 15 : 5;\r\n#elif STBTT_RASTERIZER_VERSION == 2\r\n   int vsubsample = 1;\r\n#else\r\n   #error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\r\n#endif\r\n   // vsubsample should divide 255 evenly; otherwise we won't reach full opacity\r\n\r\n   // now we have to blow out the windings into explicit edge lists\r\n   n = 0;\r\n   for (i=0; i < windings; ++i)\r\n      n += wcount[i];\r\n\r\n   e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel\r\n   if (e == 0) return;\r\n   n = 0;\r\n\r\n   m=0;\r\n   for (i=0; i < windings; ++i) {\r\n      stbtt__point *p = pts + m;\r\n      m += wcount[i];\r\n      j = wcount[i]-1;\r\n      for (k=0; k < wcount[i]; j=k++) {\r\n         int a=k,b=j;\r\n         // skip the edge if horizontal\r\n         if (p[j].y == p[k].y)\r\n            continue;\r\n         // add edge from j to k to the list\r\n         e[n].invert = 0;\r\n         if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {\r\n            e[n].invert = 1;\r\n            a=j,b=k;\r\n         }\r\n         e[n].x0 = p[a].x * scale_x + shift_x;\r\n         e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;\r\n         e[n].x1 = p[b].x * scale_x + shift_x;\r\n         e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;\r\n         ++n;\r\n      }\r\n   }\r\n\r\n   // now sort the edges by their highest point (should snap to integer, and then by x)\r\n   //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);\r\n   stbtt__sort_edges(e, n);\r\n\r\n   // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule\r\n   stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);\r\n\r\n   STBTT_free(e, userdata);\r\n}\r\n\r\nstatic void stbtt__add_point(stbtt__point *points, int n, float x, float y)\r\n{\r\n   if (!points) return; // during first pass, it's unallocated\r\n   points[n].x = x;\r\n   points[n].y = y;\r\n}\r\n\r\n// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching\r\nstatic int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)\r\n{\r\n   // midpoint\r\n   float mx = (x0 + 2*x1 + x2)/4;\r\n   float my = (y0 + 2*y1 + y2)/4;\r\n   // versus directly drawn line\r\n   float dx = (x0+x2)/2 - mx;\r\n   float dy = (y0+y2)/2 - my;\r\n   if (n > 16) // 65536 segments on one curve better be enough!\r\n      return 1;\r\n   if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA\r\n      stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);\r\n      stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);\r\n   } else {\r\n      stbtt__add_point(points, *num_points,x2,y2);\r\n      *num_points = *num_points+1;\r\n   }\r\n   return 1;\r\n}\r\n\r\nstatic void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)\r\n{\r\n   // @TODO this \"flatness\" calculation is just made-up nonsense that seems to work well enough\r\n   float dx0 = x1-x0;\r\n   float dy0 = y1-y0;\r\n   float dx1 = x2-x1;\r\n   float dy1 = y2-y1;\r\n   float dx2 = x3-x2;\r\n   float dy2 = y3-y2;\r\n   float dx = x3-x0;\r\n   float dy = y3-y0;\r\n   float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));\r\n   float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);\r\n   float flatness_squared = longlen*longlen-shortlen*shortlen;\r\n\r\n   if (n > 16) // 65536 segments on one curve better be enough!\r\n      return;\r\n\r\n   if (flatness_squared > objspace_flatness_squared) {\r\n      float x01 = (x0+x1)/2;\r\n      float y01 = (y0+y1)/2;\r\n      float x12 = (x1+x2)/2;\r\n      float y12 = (y1+y2)/2;\r\n      float x23 = (x2+x3)/2;\r\n      float y23 = (y2+y3)/2;\r\n\r\n      float xa = (x01+x12)/2;\r\n      float ya = (y01+y12)/2;\r\n      float xb = (x12+x23)/2;\r\n      float yb = (y12+y23)/2;\r\n\r\n      float mx = (xa+xb)/2;\r\n      float my = (ya+yb)/2;\r\n\r\n      stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);\r\n      stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);\r\n   } else {\r\n      stbtt__add_point(points, *num_points,x3,y3);\r\n      *num_points = *num_points+1;\r\n   }\r\n}\r\n\r\n// returns number of contours\r\nstatic stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)\r\n{\r\n   stbtt__point *points=0;\r\n   int num_points=0;\r\n\r\n   float objspace_flatness_squared = objspace_flatness * objspace_flatness;\r\n   int i,n=0,start=0, pass;\r\n\r\n   // count how many \"moves\" there are to get the contour count\r\n   for (i=0; i < num_verts; ++i)\r\n      if (vertices[i].type == STBTT_vmove)\r\n         ++n;\r\n\r\n   *num_contours = n;\r\n   if (n == 0) return 0;\r\n\r\n   *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);\r\n\r\n   if (*contour_lengths == 0) {\r\n      *num_contours = 0;\r\n      return 0;\r\n   }\r\n\r\n   // make two passes through the points so we don't need to realloc\r\n   for (pass=0; pass < 2; ++pass) {\r\n      float x=0,y=0;\r\n      if (pass == 1) {\r\n         points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);\r\n         if (points == NULL) goto error;\r\n      }\r\n      num_points = 0;\r\n      n= -1;\r\n      for (i=0; i < num_verts; ++i) {\r\n         switch (vertices[i].type) {\r\n            case STBTT_vmove:\r\n               // start the next contour\r\n               if (n >= 0)\r\n                  (*contour_lengths)[n] = num_points - start;\r\n               ++n;\r\n               start = num_points;\r\n\r\n               x = vertices[i].x, y = vertices[i].y;\r\n               stbtt__add_point(points, num_points++, x,y);\r\n               break;\r\n            case STBTT_vline:\r\n               x = vertices[i].x, y = vertices[i].y;\r\n               stbtt__add_point(points, num_points++, x, y);\r\n               break;\r\n            case STBTT_vcurve:\r\n               stbtt__tesselate_curve(points, &num_points, x,y,\r\n                                        vertices[i].cx, vertices[i].cy,\r\n                                        vertices[i].x,  vertices[i].y,\r\n                                        objspace_flatness_squared, 0);\r\n               x = vertices[i].x, y = vertices[i].y;\r\n               break;\r\n            case STBTT_vcubic:\r\n               stbtt__tesselate_cubic(points, &num_points, x,y,\r\n                                        vertices[i].cx, vertices[i].cy,\r\n                                        vertices[i].cx1, vertices[i].cy1,\r\n                                        vertices[i].x,  vertices[i].y,\r\n                                        objspace_flatness_squared, 0);\r\n               x = vertices[i].x, y = vertices[i].y;\r\n               break;\r\n         }\r\n      }\r\n      (*contour_lengths)[n] = num_points - start;\r\n   }\r\n\r\n   return points;\r\nerror:\r\n   STBTT_free(points, userdata);\r\n   STBTT_free(*contour_lengths, userdata);\r\n   *contour_lengths = 0;\r\n   *num_contours = 0;\r\n   return NULL;\r\n}\r\n\r\nSTBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)\r\n{\r\n   float scale = scale_x > scale_y ? scale_y : scale_x;\r\n   int winding_count, *winding_lengths;\r\n   stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);\r\n   if (windings) {\r\n      stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);\r\n      STBTT_free(winding_lengths, userdata);\r\n      STBTT_free(windings, userdata);\r\n   }\r\n}\r\n\r\nSTBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)\r\n{\r\n   STBTT_free(bitmap, userdata);\r\n}\r\n\r\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)\r\n{\r\n   int ix0,iy0,ix1,iy1;\r\n   stbtt__bitmap gbm;\r\n   stbtt_vertex *vertices;   \r\n   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);\r\n\r\n   if (scale_x == 0) scale_x = scale_y;\r\n   if (scale_y == 0) {\r\n      if (scale_x == 0) {\r\n         STBTT_free(vertices, info->userdata);\r\n         return NULL;\r\n      }\r\n      scale_y = scale_x;\r\n   }\r\n\r\n   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);\r\n\r\n   // now we get the size\r\n   gbm.w = (ix1 - ix0);\r\n   gbm.h = (iy1 - iy0);\r\n   gbm.pixels = NULL; // in case we error\r\n\r\n   if (width ) *width  = gbm.w;\r\n   if (height) *height = gbm.h;\r\n   if (xoff  ) *xoff   = ix0;\r\n   if (yoff  ) *yoff   = iy0;\r\n   \r\n   if (gbm.w && gbm.h) {\r\n      gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);\r\n      if (gbm.pixels) {\r\n         gbm.stride = gbm.w;\r\n\r\n         stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);\r\n      }\r\n   }\r\n   STBTT_free(vertices, info->userdata);\r\n   return gbm.pixels;\r\n}   \r\n\r\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)\r\n{\r\n   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);\r\n}\r\n\r\nSTBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)\r\n{\r\n   int ix0,iy0;\r\n   stbtt_vertex *vertices;\r\n   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);\r\n   stbtt__bitmap gbm;   \r\n\r\n   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);\r\n   gbm.pixels = output;\r\n   gbm.w = out_w;\r\n   gbm.h = out_h;\r\n   gbm.stride = out_stride;\r\n\r\n   if (gbm.w && gbm.h)\r\n      stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);\r\n\r\n   STBTT_free(vertices, info->userdata);\r\n}\r\n\r\nSTBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)\r\n{\r\n   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);\r\n}\r\n\r\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)\r\n{\r\n   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);\r\n}   \r\n\r\nSTBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)\r\n{\r\n   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));\r\n}\r\n\r\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)\r\n{\r\n   return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);\r\n}   \r\n\r\nSTBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)\r\n{\r\n   stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// bitmap baking\r\n//\r\n// This is SUPER-CRAPPY packing to keep source code small\r\n\r\nstatic int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)\r\n                                float pixel_height,                     // height of font in pixels\r\n                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in\r\n                                int first_char, int num_chars,          // characters to bake\r\n                                stbtt_bakedchar *chardata)\r\n{\r\n   float scale;\r\n   int x,y,bottom_y, i;\r\n   stbtt_fontinfo f;\r\n   f.userdata = NULL;\r\n   if (!stbtt_InitFont(&f, data, offset))\r\n      return -1;\r\n   STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels\r\n   x=y=1;\r\n   bottom_y = 1;\r\n\r\n   scale = stbtt_ScaleForPixelHeight(&f, pixel_height);\r\n\r\n   for (i=0; i < num_chars; ++i) {\r\n      int advance, lsb, x0,y0,x1,y1,gw,gh;\r\n      int g = stbtt_FindGlyphIndex(&f, first_char + i);\r\n      stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);\r\n      stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);\r\n      gw = x1-x0;\r\n      gh = y1-y0;\r\n      if (x + gw + 1 >= pw)\r\n         y = bottom_y, x = 1; // advance to next row\r\n      if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row\r\n         return -i;\r\n      STBTT_assert(x+gw < pw);\r\n      STBTT_assert(y+gh < ph);\r\n      stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);\r\n      chardata[i].x0 = (stbtt_int16) x;\r\n      chardata[i].y0 = (stbtt_int16) y;\r\n      chardata[i].x1 = (stbtt_int16) (x + gw);\r\n      chardata[i].y1 = (stbtt_int16) (y + gh);\r\n      chardata[i].xadvance = scale * advance;\r\n      chardata[i].xoff     = (float) x0;\r\n      chardata[i].yoff     = (float) y0;\r\n      x = x + gw + 1;\r\n      if (y+gh+1 > bottom_y)\r\n         bottom_y = y+gh+1;\r\n   }\r\n   return bottom_y;\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)\r\n{\r\n   float d3d_bias = opengl_fillrule ? 0 : -0.5f;\r\n   float ipw = 1.0f / pw, iph = 1.0f / ph;\r\n   stbtt_bakedchar *b = chardata + char_index;\r\n   int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);\r\n   int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);\r\n\r\n   q->x0 = round_x + d3d_bias;\r\n   q->y0 = round_y + d3d_bias;\r\n   q->x1 = round_x + b->x1 - b->x0 + d3d_bias;\r\n   q->y1 = round_y + b->y1 - b->y0 + d3d_bias;\r\n\r\n   q->s0 = b->x0 * ipw;\r\n   q->t0 = b->y0 * iph;\r\n   q->s1 = b->x1 * ipw;\r\n   q->t1 = b->y1 * iph;\r\n\r\n   *xpos += b->xadvance;\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// rectangle packing replacement routines if you don't have stb_rect_pack.h\r\n//\r\n\r\n#ifndef STB_RECT_PACK_VERSION\r\n\r\ntypedef int stbrp_coord;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////\r\n//                                                                                //\r\n//                                                                                //\r\n// COMPILER WARNING ?!?!?                                                         //\r\n//                                                                                //\r\n//                                                                                //\r\n// if you get a compile warning due to these symbols being defined more than      //\r\n// once, move #include \"stb_rect_pack.h\" before #include \"stb_truetype.h\"         //\r\n//                                                                                //\r\n////////////////////////////////////////////////////////////////////////////////////\r\n\r\ntypedef struct\r\n{\r\n   int width,height;\r\n   int x,y,bottom_y;\r\n} stbrp_context;\r\n\r\ntypedef struct\r\n{\r\n   unsigned char x;\r\n} stbrp_node;\r\n\r\nstruct stbrp_rect\r\n{\r\n   stbrp_coord x,y;\r\n   int id,w,h,was_packed;\r\n};\r\n\r\nstatic void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)\r\n{\r\n   con->width  = pw;\r\n   con->height = ph;\r\n   con->x = 0;\r\n   con->y = 0;\r\n   con->bottom_y = 0;\r\n   STBTT__NOTUSED(nodes);\r\n   STBTT__NOTUSED(num_nodes);   \r\n}\r\n\r\nstatic void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)\r\n{\r\n   int i;\r\n   for (i=0; i < num_rects; ++i) {\r\n      if (con->x + rects[i].w > con->width) {\r\n         con->x = 0;\r\n         con->y = con->bottom_y;\r\n      }\r\n      if (con->y + rects[i].h > con->height)\r\n         break;\r\n      rects[i].x = con->x;\r\n      rects[i].y = con->y;\r\n      rects[i].was_packed = 1;\r\n      con->x += rects[i].w;\r\n      if (con->y + rects[i].h > con->bottom_y)\r\n         con->bottom_y = con->y + rects[i].h;\r\n   }\r\n   for (   ; i < num_rects; ++i)\r\n      rects[i].was_packed = 0;\r\n}\r\n#endif\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// bitmap baking\r\n//\r\n// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If\r\n// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.\r\n\r\nSTBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)\r\n{\r\n   stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context)            ,alloc_context);\r\n   int            num_nodes = pw - padding;\r\n   stbrp_node    *nodes   = (stbrp_node    *) STBTT_malloc(sizeof(*nodes  ) * num_nodes,alloc_context);\r\n\r\n   if (context == NULL || nodes == NULL) {\r\n      if (context != NULL) STBTT_free(context, alloc_context);\r\n      if (nodes   != NULL) STBTT_free(nodes  , alloc_context);\r\n      return 0;\r\n   }\r\n\r\n   spc->user_allocator_context = alloc_context;\r\n   spc->width = pw;\r\n   spc->height = ph;\r\n   spc->pixels = pixels;\r\n   spc->pack_info = context;\r\n   spc->nodes = nodes;\r\n   spc->padding = padding;\r\n   spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;\r\n   spc->h_oversample = 1;\r\n   spc->v_oversample = 1;\r\n\r\n   stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);\r\n\r\n   if (pixels)\r\n      STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels\r\n\r\n   return 1;\r\n}\r\n\r\nSTBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc)\r\n{\r\n   STBTT_free(spc->nodes    , spc->user_allocator_context);\r\n   STBTT_free(spc->pack_info, spc->user_allocator_context);\r\n}\r\n\r\nSTBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)\r\n{\r\n   STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);\r\n   STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);\r\n   if (h_oversample <= STBTT_MAX_OVERSAMPLE)\r\n      spc->h_oversample = h_oversample;\r\n   if (v_oversample <= STBTT_MAX_OVERSAMPLE)\r\n      spc->v_oversample = v_oversample;\r\n}\r\n\r\n#define STBTT__OVER_MASK  (STBTT_MAX_OVERSAMPLE-1)\r\n\r\nstatic void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)\r\n{\r\n   unsigned char buffer[STBTT_MAX_OVERSAMPLE];\r\n   int safe_w = w - kernel_width;\r\n   int j;\r\n   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze\r\n   for (j=0; j < h; ++j) {\r\n      int i;\r\n      unsigned int total;\r\n      STBTT_memset(buffer, 0, kernel_width);\r\n\r\n      total = 0;\r\n\r\n      // make kernel_width a constant in common cases so compiler can optimize out the divide\r\n      switch (kernel_width) {\r\n         case 2:\r\n            for (i=0; i <= safe_w; ++i) {\r\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\r\n               pixels[i] = (unsigned char) (total / 2);\r\n            }\r\n            break;\r\n         case 3:\r\n            for (i=0; i <= safe_w; ++i) {\r\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\r\n               pixels[i] = (unsigned char) (total / 3);\r\n            }\r\n            break;\r\n         case 4:\r\n            for (i=0; i <= safe_w; ++i) {\r\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\r\n               pixels[i] = (unsigned char) (total / 4);\r\n            }\r\n            break;\r\n         case 5:\r\n            for (i=0; i <= safe_w; ++i) {\r\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\r\n               pixels[i] = (unsigned char) (total / 5);\r\n            }\r\n            break;\r\n         default:\r\n            for (i=0; i <= safe_w; ++i) {\r\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\r\n               pixels[i] = (unsigned char) (total / kernel_width);\r\n            }\r\n            break;\r\n      }\r\n\r\n      for (; i < w; ++i) {\r\n         STBTT_assert(pixels[i] == 0);\r\n         total -= buffer[i & STBTT__OVER_MASK];\r\n         pixels[i] = (unsigned char) (total / kernel_width);\r\n      }\r\n\r\n      pixels += stride_in_bytes;\r\n   }\r\n}\r\n\r\nstatic void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)\r\n{\r\n   unsigned char buffer[STBTT_MAX_OVERSAMPLE];\r\n   int safe_h = h - kernel_width;\r\n   int j;\r\n   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze\r\n   for (j=0; j < w; ++j) {\r\n      int i;\r\n      unsigned int total;\r\n      STBTT_memset(buffer, 0, kernel_width);\r\n\r\n      total = 0;\r\n\r\n      // make kernel_width a constant in common cases so compiler can optimize out the divide\r\n      switch (kernel_width) {\r\n         case 2:\r\n            for (i=0; i <= safe_h; ++i) {\r\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\r\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 2);\r\n            }\r\n            break;\r\n         case 3:\r\n            for (i=0; i <= safe_h; ++i) {\r\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\r\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 3);\r\n            }\r\n            break;\r\n         case 4:\r\n            for (i=0; i <= safe_h; ++i) {\r\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\r\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 4);\r\n            }\r\n            break;\r\n         case 5:\r\n            for (i=0; i <= safe_h; ++i) {\r\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\r\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 5);\r\n            }\r\n            break;\r\n         default:\r\n            for (i=0; i <= safe_h; ++i) {\r\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\r\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\r\n               pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);\r\n            }\r\n            break;\r\n      }\r\n\r\n      for (; i < h; ++i) {\r\n         STBTT_assert(pixels[i*stride_in_bytes] == 0);\r\n         total -= buffer[i & STBTT__OVER_MASK];\r\n         pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);\r\n      }\r\n\r\n      pixels += 1;\r\n   }\r\n}\r\n\r\nstatic float stbtt__oversample_shift(int oversample)\r\n{\r\n   if (!oversample)\r\n      return 0.0f;\r\n\r\n   // The prefilter is a box filter of width \"oversample\",\r\n   // which shifts phase by (oversample - 1)/2 pixels in\r\n   // oversampled space. We want to shift in the opposite\r\n   // direction to counter this.\r\n   return (float)-(oversample - 1) / (2.0f * (float)oversample);\r\n}\r\n\r\n// rects array must be big enough to accommodate all characters in the given ranges\r\nSTBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)\r\n{\r\n   int i,j,k;\r\n\r\n   k=0;\r\n   for (i=0; i < num_ranges; ++i) {\r\n      float fh = ranges[i].font_size;\r\n      float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);\r\n      ranges[i].h_oversample = (unsigned char) spc->h_oversample;\r\n      ranges[i].v_oversample = (unsigned char) spc->v_oversample;\r\n      for (j=0; j < ranges[i].num_chars; ++j) {\r\n         int x0,y0,x1,y1;\r\n         int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];\r\n         int glyph = stbtt_FindGlyphIndex(info, codepoint);\r\n         stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,\r\n                                         scale * spc->h_oversample,\r\n                                         scale * spc->v_oversample,\r\n                                         0,0,\r\n                                         &x0,&y0,&x1,&y1);\r\n         rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);\r\n         rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);\r\n         ++k;\r\n      }\r\n   }\r\n\r\n   return k;\r\n}\r\n\r\n// rects array must be big enough to accommodate all characters in the given ranges\r\nSTBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)\r\n{\r\n   int i,j,k, return_value = 1;\r\n\r\n   // save current values\r\n   int old_h_over = spc->h_oversample;\r\n   int old_v_over = spc->v_oversample;\r\n\r\n   k = 0;\r\n   for (i=0; i < num_ranges; ++i) {\r\n      float fh = ranges[i].font_size;\r\n      float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);\r\n      float recip_h,recip_v,sub_x,sub_y;\r\n      spc->h_oversample = ranges[i].h_oversample;\r\n      spc->v_oversample = ranges[i].v_oversample;\r\n      recip_h = 1.0f / spc->h_oversample;\r\n      recip_v = 1.0f / spc->v_oversample;\r\n      sub_x = stbtt__oversample_shift(spc->h_oversample);\r\n      sub_y = stbtt__oversample_shift(spc->v_oversample);\r\n      for (j=0; j < ranges[i].num_chars; ++j) {\r\n         stbrp_rect *r = &rects[k];\r\n         if (r->was_packed) {\r\n            stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];\r\n            int advance, lsb, x0,y0,x1,y1;\r\n            int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];\r\n            int glyph = stbtt_FindGlyphIndex(info, codepoint);\r\n            stbrp_coord pad = (stbrp_coord) spc->padding;\r\n\r\n            // pad on left and top\r\n            r->x += pad;\r\n            r->y += pad;\r\n            r->w -= pad;\r\n            r->h -= pad;\r\n            stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);\r\n            stbtt_GetGlyphBitmapBox(info, glyph,\r\n                                    scale * spc->h_oversample,\r\n                                    scale * spc->v_oversample,\r\n                                    &x0,&y0,&x1,&y1);\r\n            stbtt_MakeGlyphBitmapSubpixel(info,\r\n                                          spc->pixels + r->x + r->y*spc->stride_in_bytes,\r\n                                          r->w - spc->h_oversample+1,\r\n                                          r->h - spc->v_oversample+1,\r\n                                          spc->stride_in_bytes,\r\n                                          scale * spc->h_oversample,\r\n                                          scale * spc->v_oversample,\r\n                                          0,0,\r\n                                          glyph);\r\n\r\n            if (spc->h_oversample > 1)\r\n               stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,\r\n                                  r->w, r->h, spc->stride_in_bytes,\r\n                                  spc->h_oversample);\r\n\r\n            if (spc->v_oversample > 1)\r\n               stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,\r\n                                  r->w, r->h, spc->stride_in_bytes,\r\n                                  spc->v_oversample);\r\n\r\n            bc->x0       = (stbtt_int16)  r->x;\r\n            bc->y0       = (stbtt_int16)  r->y;\r\n            bc->x1       = (stbtt_int16) (r->x + r->w);\r\n            bc->y1       = (stbtt_int16) (r->y + r->h);\r\n            bc->xadvance =                scale * advance;\r\n            bc->xoff     =       (float)  x0 * recip_h + sub_x;\r\n            bc->yoff     =       (float)  y0 * recip_v + sub_y;\r\n            bc->xoff2    =                (x0 + r->w) * recip_h + sub_x;\r\n            bc->yoff2    =                (y0 + r->h) * recip_v + sub_y;\r\n         } else {\r\n            return_value = 0; // if any fail, report failure\r\n         }\r\n\r\n         ++k;\r\n      }\r\n   }\r\n\r\n   // restore original values\r\n   spc->h_oversample = old_h_over;\r\n   spc->v_oversample = old_v_over;\r\n\r\n   return return_value;\r\n}\r\n\r\nSTBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)\r\n{\r\n   stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);\r\n}\r\n\r\nSTBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)\r\n{\r\n   stbtt_fontinfo info;\r\n   int i,j,n, return_value = 1;\r\n   //stbrp_context *context = (stbrp_context *) spc->pack_info;\r\n   stbrp_rect    *rects;\r\n\r\n   // flag all characters as NOT packed\r\n   for (i=0; i < num_ranges; ++i)\r\n      for (j=0; j < ranges[i].num_chars; ++j)\r\n         ranges[i].chardata_for_range[j].x0 =\r\n         ranges[i].chardata_for_range[j].y0 =\r\n         ranges[i].chardata_for_range[j].x1 =\r\n         ranges[i].chardata_for_range[j].y1 = 0;\r\n\r\n   n = 0;\r\n   for (i=0; i < num_ranges; ++i)\r\n      n += ranges[i].num_chars;\r\n         \r\n   rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);\r\n   if (rects == NULL)\r\n      return 0;\r\n\r\n   info.userdata = spc->user_allocator_context;\r\n   stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));\r\n\r\n   n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);\r\n\r\n   stbtt_PackFontRangesPackRects(spc, rects, n);\r\n  \r\n   return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);\r\n\r\n   STBTT_free(rects, spc->user_allocator_context);\r\n   return return_value;\r\n}\r\n\r\nSTBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,\r\n            int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)\r\n{\r\n   stbtt_pack_range range;\r\n   range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;\r\n   range.array_of_unicode_codepoints = NULL;\r\n   range.num_chars                   = num_chars_in_range;\r\n   range.chardata_for_range          = chardata_for_range;\r\n   range.font_size                   = font_size;\r\n   return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);\r\n}\r\n\r\nSTBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)\r\n{\r\n   float ipw = 1.0f / pw, iph = 1.0f / ph;\r\n   stbtt_packedchar *b = chardata + char_index;\r\n\r\n   if (align_to_integer) {\r\n      float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);\r\n      float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);\r\n      q->x0 = x;\r\n      q->y0 = y;\r\n      q->x1 = x + b->xoff2 - b->xoff;\r\n      q->y1 = y + b->yoff2 - b->yoff;\r\n   } else {\r\n      q->x0 = *xpos + b->xoff;\r\n      q->y0 = *ypos + b->yoff;\r\n      q->x1 = *xpos + b->xoff2;\r\n      q->y1 = *ypos + b->yoff2;\r\n   }\r\n\r\n   q->s0 = b->x0 * ipw;\r\n   q->t0 = b->y0 * iph;\r\n   q->s1 = b->x1 * ipw;\r\n   q->t1 = b->y1 * iph;\r\n\r\n   *xpos += b->xadvance;\r\n}\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n//\r\n// font name matching -- recommended not to use this\r\n//\r\n\r\n// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string\r\nstatic stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) \r\n{\r\n   stbtt_int32 i=0;\r\n\r\n   // convert utf16 to utf8 and compare the results while converting\r\n   while (len2) {\r\n      stbtt_uint16 ch = s2[0]*256 + s2[1];\r\n      if (ch < 0x80) {\r\n         if (i >= len1) return -1;\r\n         if (s1[i++] != ch) return -1;\r\n      } else if (ch < 0x800) {\r\n         if (i+1 >= len1) return -1;\r\n         if (s1[i++] != 0xc0 + (ch >> 6)) return -1;\r\n         if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;\r\n      } else if (ch >= 0xd800 && ch < 0xdc00) {\r\n         stbtt_uint32 c;\r\n         stbtt_uint16 ch2 = s2[2]*256 + s2[3];\r\n         if (i+3 >= len1) return -1;\r\n         c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;\r\n         if (s1[i++] != 0xf0 + (c >> 18)) return -1;\r\n         if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;\r\n         if (s1[i++] != 0x80 + ((c >>  6) & 0x3f)) return -1;\r\n         if (s1[i++] != 0x80 + ((c      ) & 0x3f)) return -1;\r\n         s2 += 2; // plus another 2 below\r\n         len2 -= 2;\r\n      } else if (ch >= 0xdc00 && ch < 0xe000) {\r\n         return -1;\r\n      } else {\r\n         if (i+2 >= len1) return -1;\r\n         if (s1[i++] != 0xe0 + (ch >> 12)) return -1;\r\n         if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;\r\n         if (s1[i++] != 0x80 + ((ch     ) & 0x3f)) return -1;\r\n      }\r\n      s2 += 2;\r\n      len2 -= 2;\r\n   }\r\n   return i;\r\n}\r\n\r\nstatic int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) \r\n{\r\n   return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);\r\n}\r\n\r\n// returns results in whatever encoding you request... but note that 2-byte encodings\r\n// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare\r\nSTBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)\r\n{\r\n   stbtt_int32 i,count,stringOffset;\r\n   stbtt_uint8 *fc = font->data;\r\n   stbtt_uint32 offset = font->fontstart;\r\n   stbtt_uint32 nm = stbtt__find_table(fc, offset, \"name\");\r\n   if (!nm) return NULL;\r\n\r\n   count = ttUSHORT(fc+nm+2);\r\n   stringOffset = nm + ttUSHORT(fc+nm+4);\r\n   for (i=0; i < count; ++i) {\r\n      stbtt_uint32 loc = nm + 6 + 12 * i;\r\n      if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)\r\n          && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {\r\n         *length = ttUSHORT(fc+loc+8);\r\n         return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));\r\n      }\r\n   }\r\n   return NULL;\r\n}\r\n\r\nstatic int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)\r\n{\r\n   stbtt_int32 i;\r\n   stbtt_int32 count = ttUSHORT(fc+nm+2);\r\n   stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);\r\n\r\n   for (i=0; i < count; ++i) {\r\n      stbtt_uint32 loc = nm + 6 + 12 * i;\r\n      stbtt_int32 id = ttUSHORT(fc+loc+6);\r\n      if (id == target_id) {\r\n         // find the encoding\r\n         stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);\r\n\r\n         // is this a Unicode encoding?\r\n         if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {\r\n            stbtt_int32 slen = ttUSHORT(fc+loc+8);\r\n            stbtt_int32 off = ttUSHORT(fc+loc+10);\r\n\r\n            // check if there's a prefix match\r\n            stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);\r\n            if (matchlen >= 0) {\r\n               // check for target_id+1 immediately following, with same encoding & language\r\n               if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {\r\n                  slen = ttUSHORT(fc+loc+12+8);\r\n                  off = ttUSHORT(fc+loc+12+10);\r\n                  if (slen == 0) {\r\n                     if (matchlen == nlen)\r\n                        return 1;\r\n                  } else if (matchlen < nlen && name[matchlen] == ' ') {\r\n                     ++matchlen;\r\n                     if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))\r\n                        return 1;\r\n                  }\r\n               } else {\r\n                  // if nothing immediately following\r\n                  if (matchlen == nlen)\r\n                     return 1;\r\n               }\r\n            }\r\n         }\r\n\r\n         // @TODO handle other encodings\r\n      }\r\n   }\r\n   return 0;\r\n}\r\n\r\nstatic int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)\r\n{\r\n   stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);\r\n   stbtt_uint32 nm,hd;\r\n   if (!stbtt__isfont(fc+offset)) return 0;\r\n\r\n   // check italics/bold/underline flags in macStyle...\r\n   if (flags) {\r\n      hd = stbtt__find_table(fc, offset, \"head\");\r\n      if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;\r\n   }\r\n\r\n   nm = stbtt__find_table(fc, offset, \"name\");\r\n   if (!nm) return 0;\r\n\r\n   if (flags) {\r\n      // if we checked the macStyle flags, then just check the family and ignore the subfamily\r\n      if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))  return 1;\r\n      if (stbtt__matchpair(fc, nm, name, nlen,  1, -1))  return 1;\r\n      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;\r\n   } else {\r\n      if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))  return 1;\r\n      if (stbtt__matchpair(fc, nm, name, nlen,  1,  2))  return 1;\r\n      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;\r\n   }\r\n\r\n   return 0;\r\n}\r\n\r\nstatic int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)\r\n{\r\n   stbtt_int32 i;\r\n   for (i=0;;++i) {\r\n      stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);\r\n      if (off < 0) return off;\r\n      if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))\r\n         return off;\r\n   }\r\n}\r\n\r\n#if defined(__GNUC__) || defined(__clang__)\r\n#pragma GCC diagnostic push\r\n#pragma GCC diagnostic ignored \"-Wcast-qual\"\r\n#endif\r\n\r\nSTBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,\r\n                                float pixel_height, unsigned char *pixels, int pw, int ph,\r\n                                int first_char, int num_chars, stbtt_bakedchar *chardata)\r\n{\r\n   return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);\r\n}\r\n\r\nSTBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)\r\n{\r\n   return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);   \r\n}\r\n\r\nSTBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)\r\n{\r\n   return stbtt_GetNumberOfFonts_internal((unsigned char *) data);\r\n}\r\n\r\nSTBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)\r\n{\r\n   return stbtt_InitFont_internal(info, (unsigned char *) data, offset);\r\n}\r\n\r\nSTBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)\r\n{\r\n   return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);\r\n}\r\n\r\nSTBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)\r\n{\r\n   return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);\r\n}\r\n\r\n#if defined(__GNUC__) || defined(__clang__)\r\n#pragma GCC diagnostic pop\r\n#endif\r\n\r\n#endif // STB_TRUETYPE_IMPLEMENTATION\r\n\r\n\r\n// FULL VERSION HISTORY\r\n//\r\n//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual\r\n//   1.11 (2016-04-02) fix unused-variable warning\r\n//   1.10 (2016-04-02) allow user-defined fabs() replacement\r\n//                     fix memory leak if fontsize=0.0\r\n//                     fix warning from duplicate typedef\r\n//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges\r\n//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges\r\n//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;\r\n//                     allow PackFontRanges to pack and render in separate phases;\r\n//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);\r\n//                     fixed an assert() bug in the new rasterizer\r\n//                     replace assert() with STBTT_assert() in new rasterizer\r\n//   1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)\r\n//                     also more precise AA rasterizer, except if shapes overlap\r\n//                     remove need for STBTT_sort\r\n//   1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC\r\n//   1.04 (2015-04-15) typo in example\r\n//   1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes\r\n//   1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++\r\n//   1.01 (2014-12-08) fix subpixel position when oversampling to exactly match\r\n//                        non-oversampled; STBTT_POINT_SIZE for packed case only\r\n//   1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling\r\n//   0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)\r\n//   0.9  (2014-08-07) support certain mac/iOS fonts without an MS platformID\r\n//   0.8b (2014-07-07) fix a warning\r\n//   0.8  (2014-05-25) fix a few more warnings\r\n//   0.7  (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back\r\n//   0.6c (2012-07-24) improve documentation\r\n//   0.6b (2012-07-20) fix a few more warnings\r\n//   0.6  (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,\r\n//                        stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty\r\n//   0.5  (2011-12-09) bugfixes:\r\n//                        subpixel glyph renderer computed wrong bounding box\r\n//                        first vertex of shape can be off-curve (FreeSans)\r\n//   0.4b (2011-12-03) fixed an error in the font baking example\r\n//   0.4  (2011-12-01) kerning, subpixel rendering (tor)\r\n//                    bugfixes for:\r\n//                        codepoint-to-glyph conversion using table fmt=12\r\n//                        codepoint-to-glyph conversion using table fmt=4\r\n//                        stbtt_GetBakedQuad with non-square texture (Zer)\r\n//                    updated Hello World! sample to use kerning and subpixel\r\n//                    fixed some warnings\r\n//   0.3  (2009-06-24) cmap fmt=12, compound shapes (MM)\r\n//                    userdata, malloc-from-userdata, non-zero fill (stb)\r\n//   0.2  (2009-03-11) Fix unsigned/signed char warnings\r\n//   0.1  (2009-03-09) First public release\r\n//\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/PerfStat/PerfStat.cpp",
    "content": "#include \"pch.h\"\r\n\r\n#include \"PerfStat.h\"\r\n\r\n#include <fstream>\r\n#include <iostream>\r\n\r\nusing namespace ART;\r\nusing namespace std;\r\n\r\n\r\nPerfCounterReport::PerfCounterReport(const char* reportFileName) :\r\n\t_isCapturing(false), _isInsideFrame(false), _numCounters(0)\r\n{\r\n\tSetReportFileName(reportFileName);\r\n}\r\n\r\nvoid PerfCounterReport::SetReportFileName(const char* path) {\r\n\t_reportFileName = path;\r\n}\r\n\r\nvoid PerfCounterReport::BeginCapture() {\r\n\tART_ASSERT(!_isCapturing && _reportFileName.size() > 0);\r\n\t_isCapturing = true;\r\n\t_isInsideFrame = false;\r\n\r\n\t_counterSlots.clear();\r\n\t_frameCounterValues.clear();\r\n}\r\n\r\nvoid PerfCounterReport::BeginFrame() {\r\n\tART_ASSERT(_isCapturing && !_isInsideFrame);\r\n\t_isInsideFrame = true;\r\n\r\n\t// add a new record to the counter values\r\n\tstd::vector<float> frameStats(_numCounters, 0);\r\n\t_frameCounterValues.push_back(frameStats);\r\n}\r\n\r\nvoid PerfCounterReport::StoreCounterValue(const char* name, float value) {\r\n\tART_ASSERT(_isInsideFrame);\r\n\r\n\tauto& currFrameStats = _frameCounterValues[_frameCounterValues.size() - 1];\r\n\r\n\t// counter exists?\r\n\tuint32_t ctrSlot = uint32_t(-1);\r\n\tif (_counterSlots.find(name) != _counterSlots.end()) {\r\n\t\tctrSlot = _counterSlots[name];\r\n\t}\r\n\telse {\r\n\t\t// add a new counter slot\r\n\t\t_counterSlots[name] = _numCounters;\r\n\t\tctrSlot = _numCounters;\r\n\t\t\r\n\t\t_numCounters++;\r\n\t\tcurrFrameStats.resize(_numCounters);\r\n\t}\r\n\r\n\tART_ASSERT(ctrSlot < currFrameStats.size());\r\n\tcurrFrameStats[ctrSlot] = value;\r\n}\r\n\r\nvoid PerfCounterReport::EndFrame() {\r\n\tART_ASSERT(_isInsideFrame);\r\n\t_isInsideFrame = false;\r\n}\r\n\r\nvoid PerfCounterReport::EndCaptureAndSaveReport() {\r\n\tART_ASSERT(_isCapturing && !_isInsideFrame);\r\n\t_isCapturing = false;\r\n\r\n\tofstream reportFile(_reportFileName.c_str());\r\n\tif (!reportFile) {\r\n\t\tcout << \"Unable to write perf report file: \" << _reportFileName << endl;\r\n\t\treturn;\r\n\t}\r\n\r\n\t// right now we just simply dump each counter value in a row, where each column stands for a frame\r\n\t// later on we should structure the order of these timers to represent the rendering timeline\r\n\tfor (auto& ctr : _counterSlots) {\r\n\t\t\r\n\t\t// the first column is the counter name\r\n\t\treportFile << ctr.first << \", \";\r\n\r\n\t\tuint32_t ctrSlot = ctr.second;\r\n\t\tfor (auto& frame : _frameCounterValues) {\r\n\t\t\tif (ctrSlot < frame.size())\r\n\t\t\t\treportFile << frame[ctrSlot] << \", \";\r\n\t\t\telse\r\n\t\t\t\treportFile << -1 << \",\";\r\n\t\t}\r\n\t\treportFile << endl;\r\n\t}\r\n\r\n\treportFile.close();\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/PerfStat/PerfStat.h",
    "content": "#pragma once\r\n\r\n#include \"../CommonDefs.h\"\r\n\r\n#include <vector>\r\n#include <map>\r\n#include <string>\r\n\r\nnamespace ART {\r\n\r\n\r\n\tclass PerfCounterReport {\r\n\tpublic:\r\n\r\n\t\tPerfCounterReport(const char* reportFileName = \"\");\r\n\r\n\t\tvoid SetReportFileName(const char* path);\r\n\r\n\t\tvoid BeginCapture();\r\n\r\n\t\tvoid BeginFrame();\r\n\t\tvoid StoreCounterValue(const char* name, float value);\r\n\t\tvoid EndFrame();\r\n\r\n\t\tvoid EndCaptureAndSaveReport();\r\n\r\n\tprotected:\r\n\t\tstd::map<std::string, uint32_t>\t\t_counterSlots;\r\n\r\n\t\tstd::vector<std::vector<float>>\t\t_frameCounterValues;\r\n\r\n\t\tstd::string\t\t\t\t\t\t\t_reportFileName;\r\n\r\n\t\tbool\t\t\t\t\t\t\t\t_isCapturing;\r\n\t\tbool\t\t\t\t\t\t\t\t_isInsideFrame;\r\n\r\n\t\tsize_t\t\t\t\t\t\t\t\t_numCounters;\r\n\t};\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Sequencer/FrameSequencer.cpp",
    "content": "#include \"pch.h\"\r\n\r\n#include \"FrameSequencer.h\"\r\n\r\n#include \"PixelBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"EngineProfiling.h\"\r\n\r\n#include \"document.h\"\r\n#include \"writer.h\"\r\n#include \"prettywriter.h\"\r\n#include \"stringbuffer.h\"\r\n\r\n#include <iostream>\r\n#include <fstream>\r\n#include <sstream>\r\n#include <ctime>\r\n\r\nusing namespace ART;\r\nusing namespace std::experimental;\r\nusing namespace std::chrono;\r\n\r\n#pragma warning(disable: 4996)\r\n\r\nvoid FrameSequencer::BeginCapture(const FrameSequence& sequence) {\r\n\tART_ASSERT(!_isCapturing && sequence.EndTime > sequence.StartTime && sequence.CaptureFPS <= sequence.FPS && sequence.CaptureFPS > 0);\r\n\t_isCapturing = true;\r\n\r\n\t_currSequence = sequence;\r\n\t_frameCtr = -60; // we skip the first frames to let TAA + mblur \"settle\" when an animation is reset\r\n\t_captureFrameCtr = -1;\r\n\t_numFrames = (int)((sequence.EndTime - sequence.StartTime) * sequence.CaptureFPS);\r\n\t_spf = 1.0f / sequence.FPS;\r\n\t_captureSPF = 1.0f / sequence.CaptureFPS;\r\n\r\n\t_timeSinceLastCapture = 0; // we want to capture the first frame\r\n\t_currTime = sequence.StartTime;\r\n\t\r\n\tfilesystem::path capturePath = _captureRootFolder / filesystem::path(_currSequence.Name);\r\n\tif (!exists(capturePath))\r\n\t\tfilesystem::create_directory(capturePath);\r\n\r\n\t_ctrReport.SetReportFileName((capturePath / filesystem::path(\"perfreport.csv\")).generic_string().c_str());\r\n\t_ctrReport.BeginCapture();\r\n}\r\n\r\nvoid FrameSequencer::EndCapture() {\r\n\t_isCapturing = false;\r\n\t_ctrReport.EndCaptureAndSaveReport();\r\n}\r\n\r\nvoid FrameSequencer::CaptureOne(const char*) {\r\n\r\n\t_isCapturingSingleFrame = true;\r\n}\r\n\r\nvoid FrameSequencer::FinishFrame() {\r\n\tif (_isCapturing) {\r\n\t\tcaptureIfNeeded();\r\n\t\tGraphics::SetOfflineTimestep(GetSecondsPerFrame());\r\n\t}\r\n\telse {\r\n\t\tGraphics::SetOfflineTimestep(0);\r\n\r\n\t\tif (_isCapturingSingleFrame) {\r\n\t\t\t_isCapturingSingleFrame = false;\r\n\r\n\t\t\tstd::time_t now = system_clock::to_time_t(system_clock::now());\r\n\t\t\tchar buf[255];\r\n\t\t\tstd::strftime(buf, sizeof(buf), \"Capture-%Y-%m-%d-%H-%M-%S\", std::localtime(&now));\r\n\t\t\t\r\n\t\t\tfilesystem::path capturePath = _captureRootFolder / filesystem::path(\"Screenshots\");\r\n\t\t\tif (!exists(capturePath))\r\n\t\t\t\tfilesystem::create_directory(capturePath);\r\n\r\n\t\t\tCaptureToFile((capturePath / filesystem::path(buf)).generic_string(), true);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool FrameSequencer::CaptureToFile(const std::string& path, bool dumpProfilerData) {\r\n\t\r\n\tif (!_srcBuffer)\r\n\t\treturn false;\r\n\r\n\tconst std::string imgPath = path + std::string(\".tga\");\r\n\tconst std::string profilePath = path + std::string(\"_profile.json\");\r\n\r\n\tstd::wstring& wpath = std::wstring(imgPath.begin(), imgPath.end());\r\n\t_srcBuffer->ExportToTGA(wpath);\r\n\r\n\tif(dumpProfilerData)\r\n\t\twriteProfilerJson(profilePath);\r\n\r\n\treturn true;\r\n}\r\n\r\nbool FrameSequencer::captureIfNeeded() {\r\n\tif (!_isCapturing) return false;\r\n\r\n\t_ctrReport.BeginFrame();\r\n\tEngineProfiling::FillPerfDataForLastFrame(_ctrReport);\r\n\t_ctrReport.EndFrame();\r\n\r\n\t_frameCtr++;\r\n\r\n\tif (_frameCtr <= 0) return true; // skipped frames\r\n\r\n\tif (_currTime > _currSequence.EndTime || _captureFrameCtr >= _frameCtr) {\r\n\t\tEndCapture();\r\n\t\treturn true;\r\n\t}\r\n\r\n\t_timeSinceLastCapture += _spf;\r\n\t_currTime += _spf;\r\n\tif (_timeSinceLastCapture < _captureSPF)\r\n\t\treturn true;\r\n\r\n\t_timeSinceLastCapture -= _captureSPF;\r\n\t_captureFrameCtr++;\r\n\r\n\tstd::string zeroPrefix;\r\n\r\n\tif (_captureFrameCtr < 9)\r\n\t\tzeroPrefix = \"000\";\r\n\telse if (_captureFrameCtr < 99)\r\n\t\tzeroPrefix = \"00\";\r\n\telse if (_captureFrameCtr < 999)\r\n\t\tzeroPrefix = \"0\";\r\n\r\n\t\r\n\tstd::stringstream strm;\r\n\tstrm << \"frame\" << zeroPrefix << _captureFrameCtr + 1;\r\n\r\n\tfilesystem::path capturePath = _captureRootFolder / filesystem::path(_currSequence.Name);\r\n\r\n\treturn true;//CaptureToFile((capturePath / filesystem::path(strm.str())).generic_string(), false); // in frame sequence mode we capture an entire report, not a single frame dump\r\n}\r\n\r\nvoid FrameSequencer::writeProfilerJson(const std::string& path) {\r\n\tEngineProfiling::WriteLastFrameToJson(path);\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Sequencer/FrameSequencer.h",
    "content": "#pragma once\r\n\r\n#include \"../CommonDefs.h\"\r\n\r\n#include \"../PerfStat/PerfStat.h\"\r\n\r\n#include <string>\r\n#include <filesystem>\r\n\r\nclass PixelBuffer;\r\n\r\nnamespace ART {\r\n\r\n\tstruct FrameSequence {\r\n\t\tstd::string Name;\r\n\t\tfloat\t\tStartTime;\r\n\t\tfloat\t\tEndTime;\r\n\t\tfloat\t\tFPS;\r\n\t\tfloat\t\tCaptureFPS;\t\t// we may want to save memory and bandwidth by dropping frames. CaptureFPS <= FPS\r\n\t};\r\n\t\r\n\tclass FrameSequencer {\r\n\tpublic:\r\n\t\tFrameSequencer():\r\n\t\t\t_srcBuffer(nullptr),\r\n\t\t\t_isCapturing(false),\r\n\t\t\t_isCapturingSingleFrame(false)\r\n\t\t{}\r\n\r\n\t\t// Set the GPU buffer to capture\r\n\t\tvoid SetSrcBuffer(PixelBuffer* buffer) {\r\n\t\t\t_srcBuffer = buffer;\r\n\t\t}\r\n\t\tPixelBuffer* GetSrcBuffer() {\r\n\t\t\treturn _srcBuffer;\r\n\t\t}\r\n\r\n\t\tvoid SetDstRootFolder(const std::string& path) {\r\n\t\t\t_captureRootFolder = path;\r\n\t\t}\r\n\r\n\t\tvoid GetDstRootFolder(std::string& path) const {\r\n\t\t\tpath = _captureRootFolder.generic_string();\r\n\t\t}\r\n\r\n\t\tvoid FinishFrame(); // should be called once the status of the captured buffers is finalized\r\n\r\n\t\tbool CaptureToFile(const std::string& path, bool dumpProfilerData);\r\n\r\n\t\tvoid BeginCapture(const FrameSequence& sequence); // TO DO: define a custom folder for the frames\r\n\r\n\t\t// captures ther next frame only\r\n\t\t// the file name, unless otherwise specified, will be based on the current time\r\n\t\tvoid CaptureOne(const char* filename = nullptr);\r\n\r\n\t\tvoid EndCapture();\r\n\r\n\t\tbool IsCapturing() const {\r\n\t\t\treturn _isCapturing;\r\n\t\t}\r\n\r\n\t\tbool IsCapturingSingleFrame() const {\r\n\t\t\treturn _isCapturingSingleFrame;\r\n\t\t}\r\n\t\t\r\n\t\t// returns the timestep between frames in seconds (the inverse of FPS)\r\n\t\t// Only has a meaning while capturing a sequence (between BeginCapture() and EndCapture())\r\n\t\tfloat GetSecondsPerFrame() const {\r\n\t\t\treturn _spf;\r\n\t\t}\r\n\r\n\t\tint GetCurrFrameID() const {\r\n\t\t\treturn _captureFrameCtr;\r\n\t\t}\r\n\r\n\t\tint GetTotalFrameCnt() const {\r\n\t\t\treturn _numFrames;\r\n\t\t}\r\n\r\n\tprotected:\r\n\r\n\t\t// checks if the elapsed time reached the desired capture rate and performs the\r\n\t\t// capture if needed\r\n\t\tbool captureIfNeeded();\r\n\r\n\t\t// makes the engine profiler dump its last timings into a Json file\r\n\t\tvoid writeProfilerJson(const std::string& path);\r\n\r\n\t\tPixelBuffer*\t\t_srcBuffer;\r\n\r\n\t\tbool\t\t\t\t_isCapturing;\r\n\t\tbool\t\t\t\t_isCapturingSingleFrame;\r\n\r\n\t\tFrameSequence\t\t_currSequence;\r\n\t\tPerfCounterReport\t_ctrReport;\r\n\r\n\t\tint\t\t\t\t\t_frameCtr;\r\n\t\tint\t\t\t\t\t_captureFrameCtr;\r\n\t\tint\t\t\t\t\t_numFrames;\r\n\t\tfloat\t\t\t\t_spf; // seconds per frame\r\n\t\tfloat\t\t\t\t_captureSPF;\r\n\r\n\t\tfloat\t\t\t\t_timeSinceLastCapture;\r\n\t\tfloat\t\t\t\t_currTime;\r\n\r\n\t\tstd::experimental::filesystem::path\t_captureRootFolder;\r\n\t};\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ART/Wddm22Defs.h",
    "content": "#pragma once\r\n//#define WDDM22\r\n\r\n// -- define different device and commandlist for systems with or without WDDM2.2 support\r\n#ifdef WDDM22\r\n#define DX12_DEVICE\tID3D12Device2\r\n#define DX12_GRAPHICSCOMMANDLIST ID3D12GraphicsCommandList1\r\n#else\r\n#define DX12_DEVICE ID3D12Device\r\n#define DX12_GRAPHICSCOMMANDLIST ID3D12GraphicsCommandList\r\n#endif"
  },
  {
    "path": "MiniEngine/Core/BitonicSort.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"BitonicSort.h\"\r\n#include \"RootSignature.h\"\r\n#include \"PipelineState.h\"\r\n#include \"CommandContext.h\"\r\n#include \"ReadbackBuffer.h\"\r\n#include \"Math/Common.h\"\r\n#include \"Math/Random.h\"\r\n\r\n#include \"CompiledShaders/BitonicIndirectArgsCS.h\"\r\n#include \"CompiledShaders/Bitonic32PreSortCS.h\"\r\n#include \"CompiledShaders/Bitonic32InnerSortCS.h\"\r\n#include \"CompiledShaders/Bitonic32OuterSortCS.h\"\r\n#include \"CompiledShaders/Bitonic64PreSortCS.h\"\r\n#include \"CompiledShaders/Bitonic64InnerSortCS.h\"\r\n#include \"CompiledShaders/Bitonic64OuterSortCS.h\"\r\n\r\nnamespace BitonicSort\r\n{\r\n    IndirectArgsBuffer s_DispatchArgs;\r\n\r\n    RootSignature s_RootSignature;\r\n    ComputePSO s_BitonicIndirectArgsCS;\r\n    ComputePSO s_Bitonic32PreSortCS;\r\n    ComputePSO s_Bitonic32InnerSortCS;\r\n    ComputePSO s_Bitonic32OuterSortCS;\r\n    ComputePSO s_Bitonic64PreSortCS;\r\n    ComputePSO s_Bitonic64InnerSortCS;\r\n    ComputePSO s_Bitonic64OuterSortCS;\r\n\r\n    // Called once by Core to initialize shaders\r\n    void Initialize(void);\r\n    void Shutdown(void);\r\n}\r\n\r\nvoid BitonicSort::Initialize( void )\r\n{\t\r\n    s_DispatchArgs.Create(L\"Bitonic sort dispatch args\", 22*23/2, 12);\r\n\r\n    s_RootSignature.Reset(4, 0);\r\n    s_RootSignature[0].InitAsConstants(0, 2);\r\n    s_RootSignature[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1);\r\n    s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 1);\r\n    s_RootSignature[3].InitAsConstants(1, 2);\r\n    s_RootSignature.Finalize(L\"Bitonic Sort\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(s_RootSignature); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO(s_BitonicIndirectArgsCS, g_pBitonicIndirectArgsCS);\r\n    CreatePSO(s_Bitonic32PreSortCS,    g_pBitonic32PreSortCS);\r\n    CreatePSO(s_Bitonic32InnerSortCS,  g_pBitonic32InnerSortCS);\r\n    CreatePSO(s_Bitonic32OuterSortCS,  g_pBitonic32OuterSortCS);\r\n    CreatePSO(s_Bitonic64PreSortCS,    g_pBitonic64PreSortCS);\r\n    CreatePSO(s_Bitonic64InnerSortCS,  g_pBitonic64InnerSortCS);\r\n    CreatePSO(s_Bitonic64OuterSortCS,  g_pBitonic64OuterSortCS);\r\n\r\n#undef CreatePSO\r\n}\r\n\r\nvoid BitonicSort::Shutdown( void )\r\n{\r\n    s_DispatchArgs.Destroy();\r\n}\r\n\r\nvoid BitonicSort::Sort( \r\n    ComputeContext& Context,\r\n    GpuBuffer& KeyIndexList,\r\n    GpuBuffer& CounterBuffer,\r\n    uint32_t CounterOffset,\r\n    bool IsPartiallyPreSorted,\r\n    bool SortAscending\r\n)\r\n{\r\n    const uint32_t ElementSizeBytes = KeyIndexList.GetElementSize();\r\n    const uint32_t MaxNumElements = KeyIndexList.GetElementCount();\r\n    const uint32_t AlignedMaxNumElements = Math::AlignPowerOfTwo(MaxNumElements);\r\n    const uint32_t MaxIterations = Math::Log2(std::max(2048u, AlignedMaxNumElements)) - 10;\r\n\r\n    ASSERT(ElementSizeBytes == 4 || ElementSizeBytes == 8, \"Invalid key-index list for bitonic sort\");\r\n\r\n    Context.SetRootSignature(s_RootSignature);\r\n\r\n    // This controls two things.  It is a key that will sort to the end, and it is a mask used to\r\n    // determine whether the current group should sort ascending or descending.\r\n    Context.SetConstants(3, CounterOffset, SortAscending ? 0xffffffff : 0);\r\n\r\n    // Generate execute indirect arguments\r\n    Context.SetPipelineState(s_BitonicIndirectArgsCS);\r\n    Context.TransitionResource(CounterBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(s_DispatchArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.SetConstants(0, MaxIterations);\r\n    Context.SetDynamicDescriptor(1, 0, CounterBuffer.GetSRV());\r\n    Context.SetDynamicDescriptor(2, 0, s_DispatchArgs.GetUAV());\r\n    Context.Dispatch(1, 1, 1);\r\n\r\n    // Pre-Sort the buffer up to k = 2048.  This also pads the list with invalid indices\r\n    // that will drift to the end of the sorted list.\r\n    Context.TransitionResource(s_DispatchArgs, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n    Context.TransitionResource(KeyIndexList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.InsertUAVBarrier(KeyIndexList);\r\n    Context.SetDynamicDescriptor(2, 0, KeyIndexList.GetUAV());\r\n\r\n    if (!IsPartiallyPreSorted)\r\n    {\r\n        Context.SetPipelineState(ElementSizeBytes == 4 ? s_Bitonic32PreSortCS : s_Bitonic64PreSortCS);\r\n        Context.DispatchIndirect(s_DispatchArgs, 0);\r\n        Context.InsertUAVBarrier(KeyIndexList);\r\n    }\r\n\r\n    uint32_t IndirectArgsOffset = 12;\r\n\r\n    // We have already pre-sorted up through k = 2048 when first writing our list, so\r\n    // we continue sorting with k = 4096.  For unnecessarily large values of k, these\r\n    // indirect dispatches will be skipped over with thread counts of 0.\r\n\r\n    for (uint32_t k = 4096; k <= AlignedMaxNumElements; k *= 2)\r\n    {\r\n        Context.SetPipelineState(ElementSizeBytes == 4 ? s_Bitonic32OuterSortCS : s_Bitonic64OuterSortCS);\r\n\r\n        for (uint32_t j = k / 2; j >= 2048; j /= 2)\r\n        {\r\n            Context.SetConstants(0, k, j);\r\n            Context.DispatchIndirect(s_DispatchArgs, IndirectArgsOffset);\r\n            Context.InsertUAVBarrier(KeyIndexList);\r\n            IndirectArgsOffset += 12;\r\n        }\r\n\r\n        Context.SetPipelineState(ElementSizeBytes == 4 ? s_Bitonic32InnerSortCS : s_Bitonic64InnerSortCS);\r\n        Context.DispatchIndirect(s_DispatchArgs, IndirectArgsOffset);\r\n        Context.InsertUAVBarrier(KeyIndexList);\r\n        IndirectArgsOffset += 12;\r\n    }\r\n}\r\n\r\ntemplate <typename T>\r\ninline void VerifySort(T* List, uint32_t ListLength, bool bAscending)\r\n{\r\n    const T IndexMask = Math::AlignPowerOfTwo(ListLength) - 1;\r\n\r\n    for (uint32_t i = 0; i < ListLength - 1; ++i)\r\n    {\r\n        ASSERT((List[i] & IndexMask) < ListLength, \"Corrupted list index detected\");\r\n\r\n        if (bAscending)\r\n        {\r\n            ASSERT(List[i] <= List[i + 1], \"Invalid sort order:  non-ascending\");\r\n        }\r\n        else\r\n        {\r\n            ASSERT(List[i] >= List[i + 1], \"Invalid sort order:  non-descending\");\r\n        }\r\n    }\r\n\r\n    ASSERT((List[ListLength - 1] & IndexMask) < ListLength, \"Corrupted list index detected\");\r\n}\r\n\r\nvoid TestBitonicSort(uint32_t ListSize, bool b64Bit, bool bAscending)\r\n{\r\n    const uint32_t SizeOfElem = b64Bit ? sizeof(uint64_t) : sizeof(uint32_t);\r\n    const uint32_t IndexMask = Math::AlignPowerOfTwo(ListSize) - 1;\r\n\r\n    // Allocate memory for list on CPU\r\n    void* BufferPtr = std::malloc(ListSize * SizeOfElem);\r\n\r\n    // Initialize list with random keys and valid indices\r\n    if (b64Bit)\r\n    {\r\n        uint64_t* BufferPtr64 = (uint64_t*)BufferPtr;\r\n        for (uint32_t i = 0; i < ListSize; ++i)\r\n            BufferPtr64[i] = ((uint64_t)(uint32_t)Math::g_RNG.NextInt() << 32 | i);\r\n    }\r\n    else\r\n    {\r\n        uint32_t* BufferPtr32 = (uint32_t*)BufferPtr;\r\n        for (uint32_t i = 0; i < ListSize; ++i)\r\n            BufferPtr32[i] = (((uint32_t)Math::g_RNG.NextInt() & ~IndexMask) | i);\r\n    }\r\n\r\n    // Upload list to GPU\r\n    ByteAddressBuffer RandomListGpu;\r\n    RandomListGpu.Create(L\"GPU Sort List\", ListSize, SizeOfElem, BufferPtr);\r\n    std::free(BufferPtr);\r\n\r\n    // Put the list size in GPU memory\r\n    __declspec(align(16)) uint32_t ListCounter[1] = { ListSize };\r\n    ByteAddressBuffer RandomListCount;\r\n    RandomListCount.Create(L\"GPU List Counter\", 1, sizeof(uint32_t), ListCounter);\r\n\r\n    // Allocate readback buffers to view data with the CPU\r\n    ReadbackBuffer IndirectArgs;\r\n    IndirectArgs.Create(L\"Readback Indirect Args\", 22 * 23 / 2, 12);\r\n\r\n    ReadbackBuffer ReadbackList;\r\n    ReadbackList.Create(L\"Random List For Sort\", ListSize, SizeOfElem);\r\n\r\n    // Begin GPU work of sorting.  Then copy results back to CPU.\r\n    ComputeContext& Ctx = ComputeContext::Begin(L\"Bitonic Sort Test\");\r\n    BitonicSort::Sort(Ctx, RandomListGpu, RandomListCount, 0, false, bAscending);\r\n    Ctx.CopyBuffer(IndirectArgs, BitonicSort::s_DispatchArgs);\r\n    Ctx.CopyBuffer(ReadbackList, RandomListGpu);\r\n    Ctx.Finish(true);\r\n\r\n    typedef uint32_t Args[3];\r\n    Args* iArgs = (Args*)IndirectArgs.Map();\r\n    BufferPtr = ReadbackList.Map();\r\n\r\n    // Scan through all items to ensure they are sorted in the proper order and that\r\n    // their sort index is in the right range (uncorrupted).\r\n    if (b64Bit)\r\n        VerifySort((uint64_t*)BufferPtr, ListSize, bAscending);\r\n    else\r\n        VerifySort((uint32_t*)BufferPtr, ListSize, bAscending);\r\n\r\n    ReadbackList.Unmap();\r\n    IndirectArgs.Unmap();\r\n}\r\n\r\nvoid BitonicSort::Test( void )\r\n{\r\n    for (uint32_t ThreadGroupCount = 1; ThreadGroupCount < 256; ++ThreadGroupCount)\r\n    {\r\n        uint32_t ListSize = 500 * ThreadGroupCount;\r\n        TestBitonicSort(ListSize, true, true);\r\n        TestBitonicSort(ListSize, true, false);\r\n        TestBitonicSort(ListSize, false, true);\r\n        TestBitonicSort(ListSize, false, false);\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/BitonicSort.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//\r\n// Bitonic Sort is a highly parallel sorting algorithm well-suited to the\r\n// GPU.  It has a complexity of O( N*(log N)^2 ), which is inferior to most\r\n// traditional sorting algorithms, but because GPUs have so many threads,\r\n// and because each thread can be utilized, the algorithm can fully load\r\n// the GPU, taking advantage of its high ALU and bandwidth capabilities.\r\n// \r\n// Another reason why sorting on the GPU is useful is when the GPU is creating\r\n// work on its own timeline and needs to sort the work without CPU intervention.\r\n// One example in MiniEngine is with GPU simulated particle systems.  Before\r\n// rendering the particles, it is beneficial to sort the particles and render\r\n// them either front-to-back or back-to-front.\r\n//\r\n// The way a bitonic sort works is by iteratively sorting groups of increasing\r\n// size and then blending the sorted groups together to form larger sorted\r\n// groups.  The core of the algorithm can be expressed like so:\r\n//\r\n// for (k = 2; k < NumItems; k *= 2)      // k = group size\r\n//     for (j = k / 2; j > 0; j /= 2)     // j = compare distance\r\n//         for (i = 0; i < NumItems; ++i) // i = element index\r\n//             if (ShouldSwap(i, i ^ j))  // Are the two in proper order?\r\n//                 Swap(i, i ^ j)         // If not, swap them\r\n//\r\n// In this modified form of bitonic sort, all groups of size k are sorted in\r\n// the same direction.  This facilitates sorting lists with non-power-of-two\r\n// lengths.  So the ShouldSwap() test is informed only by the intent to have\r\n// an ascending or descending list.  If sorting ascending, null items should\r\n// have a sort key of 0xffffffff to guarantee sorting to the end.  Likewise,\r\n// sorting descending has a null item of 0x00000000.\r\n//\r\n// The value of the null item is also useful in the key comparison.  Notice\r\n// that with ascending lists, we want A < B, and with descending lists, we\r\n// want A > B.  So if they are reversed, we must swap them.  By using the\r\n// null item value, we can automatically reverse the test like so:\r\n//\r\n// Descending:  Swap if (A < B) == (A ^ 0x00000000 < B ^ 0x00000000)\r\n// Ascending:   Swap if (A > B) == (~A < ~B) == (A ^ 0xffffffff < B ^ 0xffffffff)\r\n// Generalized: Swap if (A ^ NullItem) < (B ^ NullItem)\r\n//\r\n// As an optimization, you can pre-sort the list for k values up to 2048 in\r\n// LDS before writing to memory.  (You do not have to write null items at the\r\n// end of your list to memory.)  It is always better for the caller of this\r\n// system to pre-sort their list as they create it.\r\n//\r\n// The expected usage of this API is that you will have an array of data of\r\n// unspecified stride.  You will generate a list of sort keys and array index\r\n// pairs to pass to the system to be sorted.  The sorted key/index pairs can\r\n// then be used to reorder your data array (with a double buffer) or you can\r\n// read your data array in place using indirection.\r\n//\r\n// We also expect that consumers of this system have a GPU-visible count of\r\n// items.  This probably came from an AppendBuffer (structured buffer with an\r\n// atomic counter).  So you will need to provide the counter buffer as well as\r\n// the offset to the counter.\r\n//\r\n// Also note that key/index pairs may be packed into 32-bit words with the key\r\n// in the most significant bits.  Sorting 32-bit elements is faster than sorting\r\n// 64-bit elements because it uses less bandwidth.\r\n\r\n#pragma once\r\n\r\n#include \"GpuBuffer.h\"\r\n\r\nnamespace BitonicSort\r\n{\r\n    void Sort(\r\n        // An existing compute context\r\n        ComputeContext& Context,\r\n\r\n        // List to be sorted.  If element size is 4 bytes, it is assumed the key and index are packed\r\n        // together with the key in the most significant bytes.  If element size is 8 bytes, the key\r\n        // is assumed in the upper 4 bytes (i.e. uint2.y).\r\n        GpuBuffer& KeyIndexList,\r\n\r\n        // A buffer containing the count of items to be sorted.\r\n        GpuBuffer& CountBuffer,\r\n\r\n        // Offset into counter buffer to find count for this list.  Must be a multiple of 4 bytes.\r\n        uint32_t CounterOffset,\r\n\r\n        // Pass 'true' if the list has already been sorted for k values up to 2048.  That is, each\r\n        // group of 2048 is already sorted.  This is common because you can combine generating a\r\n        // sort key list with sorting thread groups in groupshared (LDS) memory.\r\n        bool IsPartiallyPreSorted,\r\n\r\n        // True to sort in ascending order (smallest to largest).  False to sort in descending order.\r\n        bool SortAscending\r\n    );\r\n\r\n    void Test( void );\r\n\r\n} // namespace BitonicSort\r\n"
  },
  {
    "path": "MiniEngine/Core/BuddyAllocator.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Jack Elliott\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"BuddyAllocator.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandListManager.h\"\r\n#include \"CommandContext.h\"\r\n\r\nusing namespace Graphics;\r\nusing namespace std;\r\n\r\nBuddyBlock::BuddyBlock(uint32_t heapOffset, uint32_t totalSize, uint32_t unpaddedSize) :\r\n    m_pBuffer(nullptr)\r\n    , m_pBackingHeap(nullptr)\r\n    , m_offset(heapOffset)\r\n    , m_fenceValue(0)\r\n    , m_size(totalSize)\r\n    , m_unpaddedSize(unpaddedSize)\r\n{};\r\n\r\nvoid BuddyBlock::InitPlaced(ID3D12Heap* pBackingHeap, uint32_t numElements, uint32_t elementSize, const void* initialData)\r\n{\r\n    m_pBuffer = new ByteAddressBuffer();\r\n    m_pBackingHeap = pBackingHeap;\r\n\r\n    const wstring name(L\"Buddy Block\");\r\n    m_pBuffer->CreatePlaced(name, m_pBackingHeap, uint32_t(m_offset), numElements, elementSize, initialData);\r\n}\r\n\r\nvoid BuddyBlock::InitFromResource(ByteAddressBuffer* pBuffer, uint32_t numElements, uint32_t elementSize, const void* initialData)\r\n{\r\n    m_pBuffer = pBuffer;\r\n\r\n    if (initialData)\r\n    {\r\n        CommandContext::InitializeBuffer(*pBuffer, initialData, numElements * elementSize, m_offset);\r\n    }\r\n}\r\n\r\nvoid BuddyBlock::Destroy()\r\n{\r\n    m_pBuffer->Destroy();\r\n    m_pBuffer = nullptr;\r\n}\r\n\r\nBuddyAllocator::BuddyAllocator(kBuddyAllocationStrategy allocationStrategy, D3D12_HEAP_TYPE heapType, size_t maxBlockSize, size_t MinBlockSize, size_t baseOffset)\r\n    : m_allocationStrategy(allocationStrategy)\r\n    , m_heapType(heapType)\r\n    , m_baseOffset(baseOffset)\r\n    , m_maxBlockSize(maxBlockSize)\r\n    , m_minBlockSize(MinBlockSize)\r\n    , m_pBackingHeap(nullptr)\r\n#if defined(PROFILE) || defined(_DEBUG)\r\n    , m_SpaceUsed(0)\r\n    , m_InternalFragmentation(0)\r\n#endif\r\n{\r\n    ASSERT(Math::IsDivisible(maxBlockSize, m_minBlockSize));\r\n    ASSERT(Math::IsPowerOfTwo(maxBlockSize / m_minBlockSize));\r\n\r\n    m_maxOrder = UnitSizeToOrder(SizeToUnitSize(maxBlockSize));\r\n\r\n    Reset();\r\n}\r\n\r\nvoid BuddyAllocator::Initialize()\r\n{\r\n    if (m_allocationStrategy == kBuddyAllocationStrategy::kPlacedResourceStrategy)\r\n    {\r\n        D3D12_HEAP_PROPERTIES heapProps = CD3DX12_HEAP_PROPERTIES(m_heapType);\r\n\r\n        D3D12_HEAP_DESC desc = {};\r\n        desc.SizeInBytes = m_maxBlockSize;\r\n        desc.Properties = heapProps;\r\n        desc.Alignment = MIN_PLACED_BUFFER_SIZE;\r\n        desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;\r\n\r\n        ASSERT_SUCCEEDED(g_Device->CreateHeap(&desc, MY_IID_PPV_ARGS(&m_pBackingHeap)));\r\n    }\r\n    else\r\n    {\r\n        m_BackingResource.Create(L\"Buddy Allocator Backing Resource\", uint32_t(m_maxBlockSize), 1, nullptr);\r\n    }\r\n}\r\n\r\nvoid BuddyAllocator::Destroy()\r\n{\r\n    if (m_allocationStrategy == kBuddyAllocationStrategy::kPlacedResourceStrategy)\r\n    {\r\n        m_pBackingHeap->Release();\r\n    }\r\n    else\r\n    {\r\n        m_BackingResource.Destroy();\r\n    }\r\n}\r\n\r\nsize_t BuddyAllocator::AllocateBlock(UINT order)\r\n{\r\n    size_t offset;\r\n\r\n    if (order > m_maxOrder)\r\n    {\r\n        throw(std::bad_alloc()); // Can't allocate a block that large  \r\n    }\r\n\r\n    auto it = m_freeBlocks[order].begin();\r\n\r\n    if (it == m_freeBlocks[order].end())\r\n    {\r\n        // No free nodes in the requested pool.  Try to find a higher-order block and split it.  \r\n        size_t left = AllocateBlock(order + 1);\r\n\r\n        size_t size = OrderToUnitSize(order);\r\n\r\n        size_t right = left + size;\r\n\r\n        m_freeBlocks[order].insert(right); // Add the right block to the free pool  \r\n\r\n        offset = left; // Return the left block  \r\n    }\r\n\r\n    else\r\n    {\r\n        offset = *it;\r\n\r\n        // Remove the block from the free list  \r\n        m_freeBlocks[order].erase(it);\r\n    }\r\n\r\n    return offset;\r\n}\r\n\r\nvoid BuddyAllocator::DeallocateBlock(size_t offset, UINT order)\r\n{\r\n    // See if the buddy block is free  \r\n    size_t size = OrderToUnitSize(order);\r\n\r\n    size_t buddy = GetBuddyOffset(offset, size);\r\n\r\n    auto it = m_freeBlocks[order].find(buddy);\r\n\r\n    if (it != m_freeBlocks[order].end())\r\n    {\r\n        // Deallocate merged blocks  \r\n        DeallocateBlock(min(offset, buddy), order + 1);\r\n        // Remove the buddy from the free list  \r\n        m_freeBlocks[order].erase(it);\r\n    }\r\n    else\r\n    {\r\n        // Add the block to the free list  \r\n        m_freeBlocks[order].insert(offset); // throw(std::bad_alloc) \r\n    }\r\n}\r\n\r\nBuddyBlock* BuddyAllocator::Allocate(uint32_t numElements, uint32_t elementSize, const void* initialData)\r\n{\r\n    size_t size = numElements * elementSize;\r\n    size_t unitSize = SizeToUnitSize(size);\r\n    UINT order = UnitSizeToOrder(unitSize);\r\n\r\n    try\r\n    {\r\n        size_t offset = AllocateBlock(order);\r\n        uint32_t paddedSize = uint32_t(OrderToUnitSize(order) * m_minBlockSize);\r\n\r\n        uint32_t blockOffset = uint32_t(m_baseOffset + (offset * m_minBlockSize));\r\n\r\n        INCREASE_BUDDY_COUNTER(m_SpaceUsed, paddedSize);\r\n        INCREASE_BUDDY_COUNTER(m_InternalFragmentation, (paddedSize - size));\r\n\r\n        BuddyBlock* pBlock = new BuddyBlock(blockOffset, //offset\r\n            paddedSize, //total size (padded to fit a block)\r\n            numElements * elementSize);\r\n            \r\n        if (m_allocationStrategy == kBuddyAllocationStrategy::kPlacedResourceStrategy)\r\n        {\r\n            pBlock->InitPlaced(m_pBackingHeap, numElements, elementSize, initialData);\r\n        }\r\n        else\r\n        {\r\n            //TODO: To be truely thread-safe this operation should be atomic to guard against\r\n            //      the case in which blocks from this allocator are used on multiple threads \r\n            //      (because it's really only 1 resource underneath)\r\n            pBlock->InitFromResource(&m_BackingResource, numElements, elementSize, initialData);\r\n        }\r\n\r\n        return pBlock;\r\n    }\r\n\r\n    catch (std::bad_alloc&)\r\n    {\r\n        // There are no blocks available for the requested size so  \r\n        // return the NULL block type  \r\n        return new BuddyBlock();\r\n    }\r\n}\r\n\r\n/*\r\nvoid BuddyAllocator::Deallocate(BuddyBlock* pBlock)\r\n{\r\n    pBlock->m_fenceValue = g_CommandManager.GetNextFenceValue();\r\n    m_deferredDeletionQueue.push(pBlock);\r\n}\r\n*/\r\n\r\nvoid BuddyAllocator::DeallocateInternal(BuddyBlock* pBlock)\r\n{\r\n    ASSERT(IsOwner(*pBlock));\r\n\r\n    size_t offset = SizeToUnitSize(pBlock->GetOffset() - m_baseOffset);\r\n\r\n    size_t size = SizeToUnitSize(pBlock->GetSize());\r\n\r\n    UINT order = UnitSizeToOrder(size);\r\n\r\n    try\r\n    {\r\n        DeallocateBlock(offset, order); // throw(std::bad_alloc)\r\n\r\n        DECREASE_BUDDY_COUNTER(m_SpaceUsed, size);\r\n        DECREASE_BUDDY_COUNTER(m_InternalFragmentation, (size - pBlock->m_unpaddedSize));\r\n        \r\n        if (m_allocationStrategy == kBuddyAllocationStrategy::kPlacedResourceStrategy)\r\n        {\r\n            // Release the resource\r\n            pBlock->Destroy();\r\n        }\r\n        delete(pBlock);\r\n    }\r\n\r\n    catch (std::bad_alloc&)\r\n    {\r\n        // Deallocate failed trying to add the free block to the pool  \r\n        // resulting in a leak.  Unfortunately there is not much we can do.  \r\n        // Fortunately this is expected to be extremely rare as the storage  \r\n        // needed for each deallocate is very small.  \r\n    }\r\n};\r\n\r\n/*\r\nvoid BuddyAllocator::CleanUpAllocations()\r\n{\r\n    while (m_deferredDeletionQueue.empty() == false &&\r\n        g_CommandManager.IsFenceComplete(m_deferredDeletionQueue.front()->m_fenceValue))\r\n    {\r\n        BuddyBlock* pBlock = m_deferredDeletionQueue.front();\r\n        m_deferredDeletionQueue.pop();\r\n\r\n        DeallocateInternal(pBlock);\r\n    }\r\n}*/\r\n"
  },
  {
    "path": "MiniEngine/Core/BuddyAllocator.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author: Jack Elliott.\r\n//\r\n// Allocates blocks from a fixed range using buddy allocation method.\r\n// Buddy allocation allows reasonably fast allocation of arbitrary size blocks\r\n// with minimal fragmentation and provides efficient reuse of freed ranges.\r\n// When a block is de-allocated an attempt is made to merge it with it's \r\n// neighbour (buddy) if it is contiguous and free.\r\n// Based on reference implementation by Bill Kristiansen\r\n//  \r\n\r\n#pragma once\r\n\r\n#include \"GpuBuffer.h\"\r\n#include <vector>\r\n#include <queue>\r\n#include <mutex>\r\n#include <set>\r\n\r\n// Unfortunately the api restricts the minimum size of a placed buffer resource to 64k\r\n#define MIN_PLACED_BUFFER_SIZE (64 * 1024)\r\n\r\n#if defined(PROFILE) || defined(_DEBUG)\r\n#define INCREASE_BUDDY_COUNTER(A, B) (A = A + B);\r\n#define DECREASE_BUDDY_COUNTER(A, B) (A = A - B);\r\n#else\r\n#define INCREASE_BUDDY_COUNTER(A, B)\r\n#define DECREASE_BUDDY_COUNTER(A, B)\r\n#endif\r\n\r\nenum kBuddyAllocationStrategy\r\n{\r\n    // This strategy uses Placed Resources to sub-allocate a buffer out of an underlying ID3D12Heap.\r\n    // The benefit of this is that each buffer can have it's own resource state and can be treated\r\n    // as any other buffer. The downside of this strategy is the API limitiation which enforces\r\n    // the minimum buffer size to 64k leading to large internal fragmentation in the allocator\r\n    kPlacedResourceStrategy,\r\n    // The alternative is to manualy sub-allocate out of a single large buffer which allows block\r\n    // allocation granularity down to 1 byte. However, this strategy is only really valid for buffers which\r\n    // will be treated as read-only after their creation (i.e. most Index and Vertex buffers). This \r\n    // is because the underlying resource can only have one state at a time.\r\n    kManualSubAllocationStrategy\r\n};\r\n\r\nstruct BuddyBlock\r\n{\r\n    ByteAddressBuffer* m_pBuffer;\r\n    ID3D12Heap* m_pBackingHeap;\r\n\r\n    size_t m_offset;\r\n    size_t m_size;\r\n    size_t m_unpaddedSize;\r\n    uint64_t m_fenceValue;\r\n\r\n    inline size_t GetOffset() const { return m_offset; }\r\n    inline size_t GetSize() const { return m_size; }\r\n\r\n    BuddyBlock() : m_pBuffer(nullptr), m_pBackingHeap(nullptr), m_offset(0), m_size(0), m_unpaddedSize(0), m_fenceValue(0) {};\r\n\r\n    BuddyBlock(uint32_t heapOffset, uint32_t totalSize, uint32_t unpaddedSize);\r\n\r\n    void InitPlaced(ID3D12Heap* pBackingHeap, uint32_t numElements, uint32_t elementSize, const void* initialData = nullptr);\r\n\r\n    void InitFromResource(ByteAddressBuffer* pBuffer, uint32_t numElements, uint32_t elementSize, const void* initialData = nullptr);\r\n\r\n    void Destroy();\r\n};\r\n\r\nclass BuddyAllocator\r\n{\r\npublic:\r\n\r\n    BuddyAllocator(kBuddyAllocationStrategy allocationStrategy, D3D12_HEAP_TYPE heapType, size_t maxBlockSize, size_t minBlockSize = MIN_PLACED_BUFFER_SIZE, size_t baseOffset = 0);\r\n\r\n    void Initialize();\r\n\r\n    void Destroy();\r\n\r\n    BuddyBlock* Allocate(uint32_t numElements, uint32_t elementSize, const void* initialData = nullptr);\r\n\r\n    void Deallocate(BuddyBlock* pBlock);\r\n\r\n    inline bool IsOwner(const BuddyBlock &block)\r\n    {\r\n        return block.GetOffset() >= m_baseOffset && block.GetSize() <= m_maxBlockSize;\r\n    }\r\n\r\n    inline void Reset()\r\n    {\r\n        // Clear the free blocks collection  \r\n        m_freeBlocks.clear();\r\n\r\n        // Initialize the pool with a free inner block of max inner block size  \r\n        m_freeBlocks.resize(m_maxOrder + 1);\r\n        m_freeBlocks[m_maxOrder].insert((size_t)0);\r\n    }\r\n\r\n    void CleanUpAllocations();\r\n\r\nprivate:\r\n    ID3D12Heap* m_pBackingHeap;\r\n    ByteAddressBuffer m_BackingResource;\r\n\r\n    const D3D12_HEAP_TYPE m_heapType;\r\n\r\n    std::queue<BuddyBlock*> m_deferredDeletionQueue;\r\n    std::vector<std::set<size_t>> m_freeBlocks;\r\n    UINT m_maxOrder;\r\n    const size_t m_baseOffset;\r\n    const size_t m_maxBlockSize;\r\n    const size_t m_minBlockSize;\r\n\r\n    const kBuddyAllocationStrategy m_allocationStrategy;\r\n\r\n    inline size_t SizeToUnitSize(size_t size) const\r\n    {\r\n        return (size + (m_minBlockSize - 1)) / m_minBlockSize;\r\n    }\r\n\r\n    inline UINT UnitSizeToOrder(size_t size) const\r\n    {\r\n        return Math::Log2(size); // Log2 rounds up fractions to next whole value\r\n    }\r\n\r\n    inline size_t GetBuddyOffset(const size_t &offset, const size_t &size)\r\n    {\r\n        return offset ^ size;\r\n    }\r\n\r\n    void DeallocateInternal(BuddyBlock* pBlock);\r\n\r\n    size_t OrderToUnitSize(UINT order) const { return ((size_t)1) << order; }\r\n    size_t AllocateBlock(UINT order);\r\n    void DeallocateBlock(size_t offset, UINT order);\r\n\r\n#if defined(PROFILE) || defined(_DEBUG)\r\n    size_t m_SpaceUsed;\r\n    size_t m_InternalFragmentation;\r\n#endif\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/BufferManager.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"BufferManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"EsramAllocator.h\"\r\n#include \"TemporalEffects.h\"\r\n\r\nnamespace Graphics\r\n{\r\n    DepthBuffer g_SceneDepthBuffers[NUM_SCENE_BUFFERS];\r\n    ColorBuffer g_SceneColorBuffers[NUM_SCENE_BUFFERS];\r\n    ColorBuffer g_SceneColorBuffers2x[NUM_SCENE_BUFFERS];\r\n    DepthBuffer g_SceneDepthBuffers2x[NUM_SCENE_BUFFERS];\r\n    ColorBuffer g_SceneColorBuffers4x[NUM_SCENE_BUFFERS];\r\n    DepthBuffer g_SceneDepthBuffers4x[NUM_SCENE_BUFFERS];\r\n    ColorBuffer g_SceneColorBuffers8x[NUM_SCENE_BUFFERS];\r\n    DepthBuffer g_SceneDepthBuffers8x[NUM_SCENE_BUFFERS];\r\n    ColorBuffer g_SceneColorBuffersCB2x[NUM_CHECKER_BUFFERS];\r\n    DepthBuffer g_SceneDepthBuffersCB2x[NUM_CHECKER_BUFFERS];\r\n    \r\n    ColorBuffer *g_pCheckerboardColors[2];\r\n    DepthBuffer *g_pCheckerboardDepths[2];\r\n\r\n    ColorBuffer *g_pSceneColorBuffer;\r\n    DepthBuffer *g_pSceneDepthBuffer;\r\n\r\n    ColorBuffer *g_pMsaaColor;\r\n    DepthBuffer *g_pMsaaDepth;\r\n\r\n    ColorBuffer g_PostEffectsBuffer;\r\n    ColorBuffer g_VelocityBuffer;\r\n    ColorBuffer g_OverlayBuffer;\r\n    ColorBuffer g_HorizontalBuffer;\r\n\r\n    ShadowBuffer g_ShadowBuffer;\r\n\r\n    ColorBuffer g_SSAOFullScreen(Color(1.0f, 1.0f, 1.0f));\r\n    ColorBuffer g_LinearDepth[2];\r\n    ColorBuffer g_MinMaxDepth8;\r\n    ColorBuffer g_MinMaxDepth16;\r\n    ColorBuffer g_MinMaxDepth32;\r\n    ColorBuffer g_DepthDownsize1;\r\n    ColorBuffer g_DepthDownsize2;\r\n    ColorBuffer g_DepthDownsize3;\r\n    ColorBuffer g_DepthDownsize4;\r\n    ColorBuffer g_DepthTiled1;\r\n    ColorBuffer g_DepthTiled2;\r\n    ColorBuffer g_DepthTiled3;\r\n    ColorBuffer g_DepthTiled4;\r\n    ColorBuffer g_AOMerged1;\r\n    ColorBuffer g_AOMerged2;\r\n    ColorBuffer g_AOMerged3;\r\n    ColorBuffer g_AOMerged4;\r\n    ColorBuffer g_AOSmooth1;\r\n    ColorBuffer g_AOSmooth2;\r\n    ColorBuffer g_AOSmooth3;\r\n    ColorBuffer g_AOHighQuality1;\r\n    ColorBuffer g_AOHighQuality2;\r\n    ColorBuffer g_AOHighQuality3;\r\n    ColorBuffer g_AOHighQuality4;\r\n\r\n    ColorBuffer g_DoFTileClass[2];\r\n    ColorBuffer g_DoFPresortBuffer;\r\n    ColorBuffer g_DoFPrefilter;\r\n    ColorBuffer g_DoFBlurColor[2];\r\n    ColorBuffer g_DoFBlurAlpha[2];\r\n    StructuredBuffer g_DoFWorkQueue;\r\n    StructuredBuffer g_DoFFastQueue;\r\n    StructuredBuffer g_DoFFixupQueue;\r\n\r\n    ColorBuffer g_MotionPrepBuffer;\r\n    ColorBuffer g_LumaBuffer;\r\n    ColorBuffer g_TemporalColor[2];\r\n    ColorBuffer g_aBloomUAV1[2];\t// 640x384 (1/3)\r\n    ColorBuffer g_aBloomUAV2[2];\t// 320x192 (1/6)  \r\n    ColorBuffer g_aBloomUAV3[2];\t// 160x96  (1/12)\r\n    ColorBuffer g_aBloomUAV4[2];\t// 80x48   (1/24)\r\n    ColorBuffer g_aBloomUAV5[2];\t// 40x24   (1/48)\r\n    ColorBuffer g_LumaLR;\r\n    ByteAddressBuffer g_Histogram;\r\n    ByteAddressBuffer g_FXAAWorkCounters;\r\n    ByteAddressBuffer g_FXAAWorkQueue;\r\n    TypedBuffer g_FXAAColorQueue(DXGI_FORMAT_R11G11B10_FLOAT);\r\n\r\n    // For testing GenerateMipMaps()\r\n    ColorBuffer g_GenMipsBuffer;\r\n\r\n    // For variance map mipmapping\r\n    ColorBuffer g_VarianceMap[2];\r\n\r\n    // TODO: DRR - We should wrap D3D12 \r\n    // specific functionaltiy in a class\r\n    ID3D12Heap *g_pHeap;\r\n    \r\n    UINT64 SceneBufferOffsets[NUM_SCENE_BUFFERS];\r\n    UINT64 ColorBufferOffsets[NUM_SCENE_BUFFERS];\r\n    UINT64 DepthBufferOffsets[NUM_SCENE_BUFFERS];\r\n    UINT64 CbrColorBufferOffsets[NUM_CHECKER_BUFFERS];\r\n    UINT64 CbrDepthBufferOffsets[NUM_CHECKER_BUFFERS];\r\n    \r\n    DXGI_FORMAT DefaultHdrColorFormat = DXGI_FORMAT_R11G11B10_FLOAT;\r\n}\r\n\r\nvoid Graphics::InitializeRenderingBuffers(uint32_t bufferWidth, uint32_t bufferHeight)\r\n{\r\n    GraphicsContext& InitContext = GraphicsContext::Begin();\r\n\r\n    const uint32_t bufferWidth1 = (bufferWidth + 1) / 2;\r\n    const uint32_t bufferWidth2 = (bufferWidth + 3) / 4;\r\n    const uint32_t bufferWidth3 = (bufferWidth + 7) / 8;\r\n    const uint32_t bufferWidth4 = (bufferWidth + 15) / 16;\r\n    const uint32_t bufferWidth5 = (bufferWidth + 31) / 32;\r\n    const uint32_t bufferWidth6 = (bufferWidth + 63) / 64;\r\n    const uint32_t bufferHeight1 = (bufferHeight + 1) / 2;\r\n    const uint32_t bufferHeight2 = (bufferHeight + 3) / 4;\r\n    const uint32_t bufferHeight3 = (bufferHeight + 7) / 8;\r\n    const uint32_t bufferHeight4 = (bufferHeight + 15) / 16;\r\n    const uint32_t bufferHeight5 = (bufferHeight + 31) / 32;\r\n    const uint32_t bufferHeight6 = (bufferHeight + 63) / 64;\r\n\r\n    EsramAllocator esram;\r\n\r\n    esram.PushStack(); // Top\r\n\r\n    // DRR - We could use separate heaps so the generic color one doesn't need 4MB MSAA alignment\r\n    esram.PushStack(); // Heap\r\n    {\r\n        D3D12_HEAP_PROPERTIES heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);\r\n\r\n        UINT64 MaxSceneBufferSize;\r\n        {\r\n            D3D12_RESOURCE_DESC desc = PixelBuffer::CreateResourceDesc(bufferWidth, bufferHeight, 1, 1, DefaultHdrColorFormat, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);\r\n            D3D12_RESOURCE_ALLOCATION_INFO allocInfo = g_Device->GetResourceAllocationInfo( 0, 1, &desc );\r\n            // these all share the same heap so we can alias them - because of that they all must have the worst alignment case\r\n            MaxSceneBufferSize = ALIGN(allocInfo.SizeInBytes, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT);\r\n        }\r\n\r\n        UINT64 MaxDepthSize;\r\n        {\r\n            D3D12_RESOURCE_DESC desc = PixelBuffer::CreateResourceDesc(bufferWidth, bufferHeight, 1, 1, DSV_FORMAT, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);\r\n            desc.SampleDesc.Count = 8;\r\n\r\n            D3D12_RESOURCE_ALLOCATION_INFO allocInfo = g_Device->GetResourceAllocationInfo( 0, 1, &desc );\r\n            // these all share the same heap so we can alias them - because of that they all must have the worst alignment case\r\n            MaxDepthSize = ALIGN(allocInfo.SizeInBytes, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT);\r\n        }\r\n\r\n        UINT64 MaxColorSize;\r\n        {\r\n            D3D12_RESOURCE_DESC desc = PixelBuffer::CreateResourceDesc(bufferWidth, bufferHeight, 1, 1, DefaultHdrColorFormat, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);\r\n            desc.SampleDesc.Count = 8;\r\n\r\n            D3D12_RESOURCE_ALLOCATION_INFO allocInfo = g_Device->GetResourceAllocationInfo( 0, 1, &desc );\r\n            // these all share the same heap so we can alias them - because of that they all must have the worst alignment case\r\n            MaxColorSize = ALIGN(allocInfo.SizeInBytes, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT);\r\n        }\r\n\r\n        UINT64 CbColorAlignedOffset;\r\n        {\r\n            D3D12_RESOURCE_DESC desc = PixelBuffer::CreateResourceDesc(bufferWidth1, bufferHeight1, 1, 1, DefaultHdrColorFormat, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);\r\n            desc.SampleDesc.Count = 2;\r\n\r\n            D3D12_RESOURCE_ALLOCATION_INFO allocInfo = g_Device->GetResourceAllocationInfo( 0, 1, &desc );\r\n            // these all share the same heap so we can alias them - because of that they all must have the worst alignment case\r\n            CbColorAlignedOffset = ALIGN(allocInfo.SizeInBytes, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT);\r\n        }\r\n\r\n        UINT64 CbDepthAlignedOffset;\r\n        {\r\n            D3D12_RESOURCE_DESC desc = PixelBuffer::CreateResourceDesc(bufferWidth1, bufferHeight1, 1, 1, DSV_FORMAT, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);\r\n            desc.SampleDesc.Count = 2;\r\n\r\n            D3D12_RESOURCE_ALLOCATION_INFO allocInfo = g_Device->GetResourceAllocationInfo( 0, 1, &desc );\r\n            // these all share the same heap so we can alias them - because of that they all must have the worst alignment case\r\n            CbDepthAlignedOffset = ALIGN(allocInfo.SizeInBytes, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT);\r\n        }\r\n\r\n\r\n        UINT64 CbColorOffset = 0;\r\n        UINT64 CbDepthOffset = 0;\r\n        UINT64 HeapSize = 0;\r\n        UINT CbIndex = 0;\r\n        int i;\r\n\r\n        for ( i = 0; i < NUM_SCENE_BUFFERS; i++ )\r\n        {\r\n            SceneBufferOffsets[i] = HeapSize;    HeapSize += MaxSceneBufferSize;\r\n            ColorBufferOffsets[i] = HeapSize;    HeapSize += MaxColorSize;\r\n            DepthBufferOffsets[i] = HeapSize;    HeapSize += MaxDepthSize;\r\n\r\n            CbrColorBufferOffsets[i] = ColorBufferOffsets[CbIndex] + CbColorOffset; //this will fix a scene buffer overwrite, but i'd rather figure it out\r\n            CbrDepthBufferOffsets[i] = DepthBufferOffsets[CbIndex] + CbDepthOffset;\r\n\r\n            // cbr frames are only half the resolution\r\n            // so we can pack 2 cbr buffers into the space normally consumed by a single color buffer\r\n            CbColorOffset ^= CbColorAlignedOffset;\r\n            CbDepthOffset ^= CbDepthAlignedOffset;\r\n\r\n            CbIndex += (i & 0x1);\r\n        }\r\n\r\n        // cbr has two extra frames for the temporal element\r\n        for (; i < NUM_CHECKER_BUFFERS; i++ )\r\n        {\r\n            CbrColorBufferOffsets[i] = ColorBufferOffsets[CbIndex] + CbColorOffset;\r\n            CbrDepthBufferOffsets[i] = DepthBufferOffsets[CbIndex] + CbDepthOffset;\r\n\r\n            CbColorOffset ^= CbColorAlignedOffset;\r\n            CbDepthOffset ^= CbDepthAlignedOffset;\r\n\r\n            CbIndex += (i & 0x1);\r\n        }\r\n\r\n        D3D12_HEAP_DESC desc = {};\r\n        {\r\n            desc.SizeInBytes = HeapSize;\r\n            desc.Properties = heapProps;\r\n            desc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;\r\n            desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES;\r\n\r\n            ASSERT_SUCCEEDED(g_Device->CreateHeap(&desc, MY_IID_PPV_ARGS(&g_pHeap)));\r\n        }\r\n\r\n        esram.PopStack(); // Heap\r\n    }\r\n\r\n    esram.PushStack(); // HDR\r\n    {\r\n        int i;\r\n\r\n        for ( i = 0; i < NUM_SCENE_BUFFERS; i++ )\r\n        {\r\n            g_SceneColorBuffers[i].CreatePlaced(L\"Scene Color Buffer \" + std::to_wstring(i), bufferWidth, bufferHeight, 1, DefaultHdrColorFormat, g_pHeap, SceneBufferOffsets[i]);\r\n            g_SceneDepthBuffers[i].CreatePlaced(L\"Scene Depth Buffer \" + std::to_wstring(i), bufferWidth, bufferHeight, 1, DSV_FORMAT, g_pHeap, DepthBufferOffsets[i]);\r\n\r\n            // Setup the buffers for MSAA\r\n            g_SceneColorBuffers2x[i].SetMsaaMode(2, 2);\r\n            g_SceneColorBuffers2x[i].CreatePlaced(L\"Offscreen Color Buffer 2xMSAA \" + std::to_wstring(i), bufferWidth, bufferHeight, 1, DefaultHdrColorFormat, g_pHeap, ColorBufferOffsets[i]);\r\n            g_SceneDepthBuffers2x[i].CreatePlaced(L\"Offscreen Depth Buffer 2xMSAA \" + std::to_wstring(i), bufferWidth, bufferHeight, 2, DSV_FORMAT, g_pHeap, DepthBufferOffsets[i]);\r\n\r\n            g_SceneColorBuffers4x[i].SetMsaaMode(4, 4);\r\n            g_SceneColorBuffers4x[i].CreatePlaced(L\"Offscreen Color Buffer 4xMSAA \" + std::to_wstring(i), bufferWidth, bufferHeight, 1, DefaultHdrColorFormat, g_pHeap, ColorBufferOffsets[i]);\r\n            g_SceneDepthBuffers4x[i].CreatePlaced(L\"Offscreen Depth Buffer 4xMSAA \" + std::to_wstring(i), bufferWidth, bufferHeight, 4, DSV_FORMAT, g_pHeap, DepthBufferOffsets[i]);\r\n\r\n            g_SceneColorBuffers8x[i].SetMsaaMode(8, 8);\r\n            g_SceneColorBuffers8x[i].CreatePlaced(L\"Offscreen Color Buffer 8xMSAA \" + std::to_wstring(i), bufferWidth, bufferHeight, 1, DefaultHdrColorFormat, g_pHeap, ColorBufferOffsets[i]);\r\n            g_SceneDepthBuffers8x[i].CreatePlaced(L\"Offscreen Depth Buffer 8xMSAA \" + std::to_wstring(i), bufferWidth, bufferHeight, 8, DSV_FORMAT, g_pHeap, DepthBufferOffsets[i]);\r\n\r\n            g_SceneColorBuffersCB2x[i].SetMsaaMode(2, 2);\r\n            g_SceneColorBuffersCB2x[i].CreatePlaced(L\"Offscreen Color Buffer 2xCheckerboard \" + std::to_wstring(i), bufferWidth1, bufferHeight1, 1, DefaultHdrColorFormat, g_pHeap, CbrColorBufferOffsets[i]);\r\n            g_SceneDepthBuffersCB2x[i].CreatePlaced(L\"Offscreen Depth Buffer 2xCheckerboard \" + std::to_wstring(i), bufferWidth1, bufferHeight1, 2, DSV_FORMAT, g_pHeap, CbrDepthBufferOffsets[i]);\r\n        }\r\n\r\n        // cbr has two extra frames for the temporal element\r\n        for (; i < NUM_CHECKER_BUFFERS; i++ )\r\n        {\r\n            g_SceneColorBuffersCB2x[i].SetMsaaMode(2, 2);\r\n            g_SceneColorBuffersCB2x[i].CreatePlaced(L\"Offscreen Color Buffer 2xCheckerboard \" + std::to_wstring(i), bufferWidth1, bufferHeight1, 1, DefaultHdrColorFormat, g_pHeap, CbrColorBufferOffsets[i]);\r\n            g_SceneDepthBuffersCB2x[i].CreatePlaced(L\"Offscreen Depth Buffer 2xCheckerboard \" + std::to_wstring(i), bufferWidth1, bufferHeight1, 2, DSV_FORMAT, g_pHeap, CbrDepthBufferOffsets[i]);\r\n        }\r\n\r\n        // DRR - can stay full res (see notes.md)\r\n        g_VelocityBuffer.Create(L\"Motion Vectors\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R16G16B16A16_FLOAT);\r\n\r\n        // DRR - can stay full res (see notes.md)\r\n        g_PostEffectsBuffer.Create(L\"Post Effects Buffer\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R32_UINT);\r\n\r\n        esram.PopStack();\r\n    }\r\n\r\n    g_pSceneColorBuffer = &g_SceneColorBuffers[0];\r\n    g_pSceneDepthBuffer = &g_SceneDepthBuffers[0];\r\n\r\n    g_pCheckerboardColors[0] = NULL;\r\n    g_pCheckerboardColors[1] = NULL;\r\n    g_pCheckerboardDepths[0] = NULL;\r\n    g_pCheckerboardDepths[1] = NULL;\r\n    g_pMsaaColor = NULL;\r\n    g_pMsaaDepth = NULL;\r\n\r\n\r\n    esram.PushStack(); // Linear Depth\r\n    {\r\n        g_LinearDepth[0].Create(L\"Linear Depth 0\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R16_UNORM);\r\n        g_LinearDepth[1].Create(L\"Linear Depth 1\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R16_UNORM);\r\n        g_MinMaxDepth8.Create(L\"MinMaxDepth 8x8\", bufferWidth3, bufferHeight3, 1, DXGI_FORMAT_R32_UINT, esram);\r\n        g_MinMaxDepth16.Create(L\"MinMaxDepth 16x16\", bufferWidth4, bufferHeight4, 1, DXGI_FORMAT_R32_UINT, esram);\r\n        g_MinMaxDepth32.Create(L\"MinMaxDepth 32x32\", bufferWidth5, bufferHeight5, 1, DXGI_FORMAT_R32_UINT, esram);\r\n        esram.PopStack(); // Linear Depth\r\n    }\r\n\r\n\r\n    esram.PushStack();\t// Begin generating SSAO\r\n    {\r\n        g_SSAOFullScreen.Create(L\"SSAO Full Res\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R8_UNORM);\r\n        g_DepthDownsize1.Create(L\"Depth Down-Sized 1\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R32_FLOAT, esram);\r\n        g_DepthDownsize2.Create(L\"Depth Down-Sized 2\", bufferWidth2, bufferHeight2, 1, DXGI_FORMAT_R32_FLOAT, esram);\r\n        g_DepthDownsize3.Create(L\"Depth Down-Sized 3\", bufferWidth3, bufferHeight3, 1, DXGI_FORMAT_R32_FLOAT, esram);\r\n        g_DepthDownsize4.Create(L\"Depth Down-Sized 4\", bufferWidth4, bufferHeight4, 1, DXGI_FORMAT_R32_FLOAT, esram);\r\n        g_DepthTiled1.CreateArray(L\"Depth De-Interleaved 1\", bufferWidth3, bufferHeight3, 16, DXGI_FORMAT_R16_FLOAT, esram);\r\n        g_DepthTiled2.CreateArray(L\"Depth De-Interleaved 2\", bufferWidth4, bufferHeight4, 16, DXGI_FORMAT_R16_FLOAT, esram);\r\n        g_DepthTiled3.CreateArray(L\"Depth De-Interleaved 3\", bufferWidth5, bufferHeight5, 16, DXGI_FORMAT_R16_FLOAT, esram);\r\n        g_DepthTiled4.CreateArray(L\"Depth De-Interleaved 4\", bufferWidth6, bufferHeight6, 16, DXGI_FORMAT_R16_FLOAT, esram);\r\n        g_AOMerged1.Create(L\"AO Re-Interleaved 1\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOMerged2.Create(L\"AO Re-Interleaved 2\", bufferWidth2, bufferHeight2, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOMerged3.Create(L\"AO Re-Interleaved 3\", bufferWidth3, bufferHeight3, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOMerged4.Create(L\"AO Re-Interleaved 4\", bufferWidth4, bufferHeight4, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOSmooth1.Create(L\"AO Smoothed 1\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOSmooth2.Create(L\"AO Smoothed 2\", bufferWidth2, bufferHeight2, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOSmooth3.Create(L\"AO Smoothed 3\", bufferWidth3, bufferHeight3, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOHighQuality1.Create(L\"AO High Quality 1\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOHighQuality2.Create(L\"AO High Quality 2\", bufferWidth2, bufferHeight2, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOHighQuality3.Create(L\"AO High Quality 3\", bufferWidth3, bufferHeight3, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_AOHighQuality4.Create(L\"AO High Quality 4\", bufferWidth4, bufferHeight4, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        esram.PopStack();\t// End generating SSAO\r\n    }\r\n\r\n    esram.PushStack();\t// shadow\r\n        g_ShadowBuffer.Create(L\"Shadow Map\", 8192, 8192, esram);\r\n    esram.PopStack();\t// shadow\r\n\r\n    esram.PushStack();\t// Begin depth of field\r\n    {\r\n        g_DoFTileClass[0].Create(L\"DoF Tile Classification Buffer 0\", bufferWidth4, bufferHeight4, 1, DXGI_FORMAT_R11G11B10_FLOAT);\r\n        g_DoFTileClass[1].Create(L\"DoF Tile Classification Buffer 1\", bufferWidth4, bufferHeight4, 1, DXGI_FORMAT_R11G11B10_FLOAT);\r\n\r\n        g_DoFPresortBuffer.Create(L\"DoF Presort Buffer\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R11G11B10_FLOAT, esram);\r\n        g_DoFPrefilter.Create(L\"DoF PreFilter Buffer\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R11G11B10_FLOAT, esram);\r\n        g_DoFBlurColor[0].Create(L\"DoF Blur Color\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R11G11B10_FLOAT, esram);\r\n        g_DoFBlurColor[1].Create(L\"DoF Blur Color\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R11G11B10_FLOAT, esram);\r\n        g_DoFBlurAlpha[0].Create(L\"DoF FG Alpha\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_DoFBlurAlpha[1].Create(L\"DoF FG Alpha\", bufferWidth1, bufferHeight1, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_DoFWorkQueue.Create(L\"DoF Work Queue\", bufferWidth4 * bufferHeight4, 4, esram);\r\n        g_DoFFastQueue.Create(L\"DoF Fast Queue\", bufferWidth4 * bufferHeight4, 4, esram);\r\n        g_DoFFixupQueue.Create(L\"DoF Fixup Queue\", bufferWidth4 * bufferHeight4, 4, esram);\r\n        esram.PopStack();\t// End depth of field\r\n    }\r\n\r\n    \r\n    esram.PushStack();\t// Variance map creation\r\n    {\r\n        g_VarianceMap[0].Create(L\"Variance Map 0\", bufferWidth, bufferHeight, 0, DXGI_FORMAT_R16G16B16A16_FLOAT);\r\n        g_VarianceMap[1].Create(L\"Variance Map 1\", bufferWidth, bufferHeight, 0, DXGI_FORMAT_R16G16_FLOAT);\r\n\r\n        g_TemporalColor[0].Create(L\"Temporal Color 0\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R16G16B16A16_FLOAT);\r\n        g_TemporalColor[1].Create(L\"Temporal Color 1\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R16G16B16A16_FLOAT);\r\n        TemporalEffects::ClearHistory(InitContext);\r\n        esram.PopStack();\t// variance\r\n    }\r\n\r\n    esram.PushStack();\t// Begin motion blur\r\n        g_MotionPrepBuffer.Create(L\"Motion Blur Prep\", bufferWidth1, bufferHeight1, 1, HDR_MOTION_FORMAT, esram);\r\n    esram.PopStack();\t// End motion blur\r\n\r\n    esram.PushStack();\t// Begin post processing\r\n    {\r\n        // This is useful for storing per-pixel weights such as motion strength or pixel luminance\r\n        g_LumaBuffer.Create(L\"Luminance\", bufferWidth, bufferHeight, 1, DXGI_FORMAT_R8_UNORM, esram);\r\n        g_Histogram.Create(L\"Histogram\", 256, 4, esram);\r\n\r\n        // Divisible by 128 so that after dividing by 16, we still have multiples of 8x8 tiles.  The bloom\r\n        // dimensions must be at least 1/4 native resolution to avoid undersampling.\r\n        //uint32_t kBloomWidth = bufferWidth > 2560 ? Math::AlignUp(bufferWidth / 4, 128) : 640;\r\n        //uint32_t kBloomHeight = bufferHeight > 1440 ? Math::AlignUp(bufferHeight / 4, 128) : 384;\r\n        uint32_t kBloomWidth = bufferWidth > 2560 ? 1280 : 640;\r\n        uint32_t kBloomHeight = bufferHeight > 1440 ? 768 : 384;\r\n\r\n        esram.PushStack();\t// Begin bloom and tone mapping\r\n            g_LumaLR.Create(L\"Luma Buffer\", kBloomWidth, kBloomHeight, 1, DXGI_FORMAT_R8_UINT, esram);\r\n            g_aBloomUAV1[0].Create(L\"Bloom Buffer 1a\", kBloomWidth, kBloomHeight, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV1[1].Create(L\"Bloom Buffer 1b\", kBloomWidth, kBloomHeight, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV2[0].Create(L\"Bloom Buffer 2a\", kBloomWidth / 2, kBloomHeight / 2, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV2[1].Create(L\"Bloom Buffer 2b\", kBloomWidth / 2, kBloomHeight / 2, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV3[0].Create(L\"Bloom Buffer 3a\", kBloomWidth / 4, kBloomHeight / 4, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV3[1].Create(L\"Bloom Buffer 3b\", kBloomWidth / 4, kBloomHeight / 4, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV4[0].Create(L\"Bloom Buffer 4a\", kBloomWidth / 8, kBloomHeight / 8, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV4[1].Create(L\"Bloom Buffer 4b\", kBloomWidth / 8, kBloomHeight / 8, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV5[0].Create(L\"Bloom Buffer 5a\", kBloomWidth / 16, kBloomHeight / 16, 1, DefaultHdrColorFormat, esram);\r\n            g_aBloomUAV5[1].Create(L\"Bloom Buffer 5b\", kBloomWidth / 16, kBloomHeight / 16, 1, DefaultHdrColorFormat, esram);\r\n        esram.PopStack();\t// End tone mapping\r\n\r\n        esram.PushStack();\t// Begin antialiasing\r\n            const uint32_t kFXAAWorkSize = bufferWidth * bufferHeight / 4 + 128;\r\n            g_FXAAWorkQueue.Create(L\"FXAA Work Queue\", kFXAAWorkSize, sizeof(uint32_t), esram);\r\n            g_FXAAColorQueue.Create(L\"FXAA Color Queue\", kFXAAWorkSize, sizeof(uint32_t), esram);\r\n            g_FXAAWorkCounters.Create(L\"FXAA Work Counters\", 2, sizeof(uint32_t));\r\n            InitContext.ClearUAV(g_FXAAWorkCounters);\r\n        esram.PopStack();\t// End antialiasing\r\n\r\n        esram.PushStack(); // GenerateMipMaps() test\r\n            g_GenMipsBuffer.Create(L\"GenMips\", bufferWidth, bufferHeight, 0, DXGI_FORMAT_R11G11B10_FLOAT, esram);\r\n        esram.PopStack();\r\n\r\n        g_OverlayBuffer.Create(L\"UI Overlay\", g_DisplayWidth, g_DisplayHeight, 1, DXGI_FORMAT_R8G8B8A8_UNORM, esram);\r\n        g_HorizontalBuffer.Create(L\"Bicubic Intermediate\", g_DisplayWidth, bufferHeight, 1, DefaultHdrColorFormat, esram);\r\n\r\n        esram.PopStack(); // end post processing\r\n    }\r\n\r\n    esram.PopStack(); // End final image\r\n\r\n    InitContext.Finish();\r\n}\r\n\r\nvoid Graphics::ResizeDisplayDependentBuffers(uint32_t NativeWidth, uint32_t NativeHeight)\r\n{\r\n    g_OverlayBuffer.Create(L\"UI Overlay\", g_DisplayWidth, g_DisplayHeight, 1, DXGI_FORMAT_R8G8B8A8_UNORM);\r\n    g_HorizontalBuffer.Create(L\"Bicubic Intermediate\", g_DisplayWidth, NativeHeight, 1, DefaultHdrColorFormat);\r\n}\r\n\r\nvoid Graphics::DestroyRenderingBuffers()\r\n{\r\n    g_pHeap->Release();\r\n\r\n    int i = 0;\r\n\r\n    for (i = 0; i < NUM_SCENE_BUFFERS; i++)\r\n    {\r\n        g_SceneDepthBuffers[i].Destroy();\r\n        g_SceneColorBuffers[i].Destroy();\r\n\r\n        g_SceneColorBuffers2x[i].Destroy();\r\n        g_SceneDepthBuffers2x[i].Destroy();\r\n        g_SceneColorBuffers4x[i].Destroy();\r\n        g_SceneDepthBuffers4x[i].Destroy();\r\n        g_SceneColorBuffers8x[i].Destroy();\r\n        g_SceneDepthBuffers8x[i].Destroy();\r\n\r\n        g_SceneColorBuffersCB2x[i].Destroy();\r\n        g_SceneDepthBuffersCB2x[i].Destroy();\r\n    }\r\n\r\n    for (; i < NUM_CHECKER_BUFFERS; i++)\r\n    {\r\n        g_SceneColorBuffersCB2x[i].Destroy();\r\n        g_SceneDepthBuffersCB2x[i].Destroy();\r\n    }\r\n\r\n    g_VelocityBuffer.Destroy();\r\n    g_OverlayBuffer.Destroy();\r\n    g_HorizontalBuffer.Destroy();\r\n    g_PostEffectsBuffer.Destroy();\r\n\r\n    g_ShadowBuffer.Destroy();\r\n\r\n    g_SSAOFullScreen.Destroy();\r\n    g_LinearDepth[0].Destroy();\r\n    g_LinearDepth[1].Destroy();\r\n    g_MinMaxDepth8.Destroy();\r\n    g_MinMaxDepth16.Destroy();\r\n    g_MinMaxDepth32.Destroy();\r\n    g_DepthDownsize1.Destroy();\r\n    g_DepthDownsize2.Destroy();\r\n    g_DepthDownsize3.Destroy();\r\n    g_DepthDownsize4.Destroy();\r\n    g_DepthTiled1.Destroy();\r\n    g_DepthTiled2.Destroy();\r\n    g_DepthTiled3.Destroy();\r\n    g_DepthTiled4.Destroy();\r\n    g_AOMerged1.Destroy();\r\n    g_AOMerged2.Destroy();\r\n    g_AOMerged3.Destroy();\r\n    g_AOMerged4.Destroy();\r\n    g_AOSmooth1.Destroy();\r\n    g_AOSmooth2.Destroy();\r\n    g_AOSmooth3.Destroy();\r\n    g_AOHighQuality1.Destroy();\r\n    g_AOHighQuality2.Destroy();\r\n    g_AOHighQuality3.Destroy();\r\n    g_AOHighQuality4.Destroy();\r\n\r\n    g_DoFTileClass[0].Destroy();\r\n    g_DoFTileClass[1].Destroy();\r\n    g_DoFPresortBuffer.Destroy();\r\n    g_DoFPrefilter.Destroy();\r\n    g_DoFBlurColor[0].Destroy();\r\n    g_DoFBlurColor[1].Destroy();\r\n    g_DoFBlurAlpha[0].Destroy();\r\n    g_DoFBlurAlpha[1].Destroy();\r\n    g_DoFWorkQueue.Destroy();\r\n    g_DoFFastQueue.Destroy();\r\n    g_DoFFixupQueue.Destroy();\r\n\r\n    g_MotionPrepBuffer.Destroy();\r\n    g_LumaBuffer.Destroy();\r\n    g_VarianceMap[0].Destroy();\r\n    g_VarianceMap[1].Destroy();\r\n    g_TemporalColor[0].Destroy();\r\n    g_TemporalColor[1].Destroy();\r\n    g_aBloomUAV1[0].Destroy();\r\n    g_aBloomUAV1[1].Destroy();\r\n    g_aBloomUAV2[0].Destroy();\r\n    g_aBloomUAV2[1].Destroy();\r\n    g_aBloomUAV3[0].Destroy();\r\n    g_aBloomUAV3[1].Destroy();\r\n    g_aBloomUAV4[0].Destroy();\r\n    g_aBloomUAV4[1].Destroy();\r\n    g_aBloomUAV5[0].Destroy();\r\n    g_aBloomUAV5[1].Destroy();\r\n    g_LumaLR.Destroy();\r\n    g_Histogram.Destroy();\r\n    g_FXAAWorkCounters.Destroy();\r\n    g_FXAAWorkQueue.Destroy();\r\n    g_FXAAColorQueue.Destroy();\r\n\r\n    g_GenMipsBuffer.Destroy();\r\n}\r\n\r\nvoid Graphics::RecreateCBRBuffers(int indexA, int indexB, int width, int height)\r\n{\r\n    g_SceneColorBuffersCB2x[indexA].RecreatePlaced( width, height, 1, DefaultHdrColorFormat, g_pHeap, CbrColorBufferOffsets[indexA] );\r\n    g_SceneDepthBuffersCB2x[indexA].RecreatePlaced( width, height, 2, DSV_FORMAT, g_pHeap, CbrDepthBufferOffsets[indexA] );\r\n    \r\n    g_SceneColorBuffersCB2x[indexB].RecreatePlaced( width, height, 1, DefaultHdrColorFormat, g_pHeap, CbrColorBufferOffsets[indexB] );\r\n    g_SceneDepthBuffersCB2x[indexB].RecreatePlaced( width, height, 2, DSV_FORMAT, g_pHeap, CbrDepthBufferOffsets[indexB] );\r\n}\r\n\r\nvoid Graphics::RecreateMsaaBuffers(int index, int msaaMode, int width, int height )\r\n{\r\n    int SampleCount = 0;\r\n\r\n    ColorBuffer *pColor;\r\n    DepthBuffer *pDepth;\r\n\r\n    switch ( msaaMode )\r\n    {\r\n    case 0: \r\n        pColor = &g_SceneColorBuffers2x[index];\r\n        pDepth = &g_SceneDepthBuffers2x[index];\r\n        SampleCount = 2;\r\n        break;\r\n    case 1:\r\n        pColor = &g_SceneColorBuffers4x[index];\r\n        pDepth = &g_SceneDepthBuffers4x[index];\r\n        SampleCount = 4;\r\n        break;\r\n    case 2:\r\n        pColor = &g_SceneColorBuffers8x[index];\r\n        pDepth = &g_SceneDepthBuffers8x[index];\r\n        SampleCount = 8;\r\n        break;\r\n\r\n    default:\r\n        break;\r\n    }\r\n\r\n    pColor->RecreatePlaced( width, height, 1, DefaultHdrColorFormat, g_pHeap, ColorBufferOffsets[index] );\r\n    pDepth->RecreatePlaced( width, height, SampleCount, DSV_FORMAT, g_pHeap, DepthBufferOffsets[index] );\r\n}\r\n\r\nvoid Graphics::RecreateSceneDepthBuffer(int index, int width, int height)\r\n{\r\n    g_SceneDepthBuffers[index].RecreatePlaced( width, height, 1, DSV_FORMAT, g_pHeap, DepthBufferOffsets[index] );\r\n}\r\n\r\nvoid Graphics::RecreateSceneColorBuffer(int index, int width, int height)\r\n{\r\n    g_SceneColorBuffers[index].RecreatePlaced( width, height, 1, DefaultHdrColorFormat, g_pHeap, SceneBufferOffsets[index] );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/BufferManager.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"ColorBuffer.h\"\r\n#include \"DepthBuffer.h\"\r\n#include \"ShadowBuffer.h\"\r\n#include \"GpuBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n\r\n#define ALIGN(value, alignment) (((value) + ((alignment) - 1)) / (alignment) * (alignment))\r\n#define T2X_COLOR_FORMAT DXGI_FORMAT_R10G10B10A2_UNORM\r\n#define HDR_MOTION_FORMAT DXGI_FORMAT_R16G16B16A16_FLOAT\r\n#define DSV_FORMAT DXGI_FORMAT_D32_FLOAT\r\n\r\n#define NUM_SCENE_BUFFERS   2\r\n#define NUM_CHECKER_BUFFERS (NUM_SCENE_BUFFERS + 2)   //need two extra for the temporal frame blending\r\n\r\nnamespace Graphics\r\n{\r\n    extern DepthBuffer g_SceneDepthBuffers[NUM_SCENE_BUFFERS];\r\n    extern ColorBuffer g_SceneColorBuffers[NUM_SCENE_BUFFERS];\r\n    extern ColorBuffer g_SceneColorBuffers2x[NUM_SCENE_BUFFERS];\r\n    extern DepthBuffer g_SceneDepthBuffers2x[NUM_SCENE_BUFFERS];\r\n    extern ColorBuffer g_SceneColorBuffers4x[NUM_SCENE_BUFFERS];\r\n    extern DepthBuffer g_SceneDepthBuffers4x[NUM_SCENE_BUFFERS];\r\n    extern ColorBuffer g_SceneColorBuffers8x[NUM_SCENE_BUFFERS];\r\n    extern DepthBuffer g_SceneDepthBuffers8x[NUM_SCENE_BUFFERS];\r\n    extern ColorBuffer g_SceneColorBuffersCB2x[NUM_CHECKER_BUFFERS]; //extra needed for temporal\r\n    extern DepthBuffer g_SceneDepthBuffersCB2x[NUM_CHECKER_BUFFERS]; //extra needed for temporal\r\n\r\n    extern ColorBuffer *g_pCheckerboardColors[2];\r\n    extern DepthBuffer *g_pCheckerboardDepths[2];\r\n    extern ColorBuffer *g_pSceneColorBuffer;\r\n    extern DepthBuffer *g_pSceneDepthBuffer;\r\n    extern ColorBuffer *g_pMsaaColor;\r\n    extern DepthBuffer *g_pMsaaDepth;\r\n\r\n    extern ColorBuffer g_PostEffectsBuffer;\t// R32_UINT (to support Read-Modify-Write with a UAV)\r\n    extern ColorBuffer g_OverlayBuffer;\t\t// R8G8B8A8_UNORM\r\n    extern ColorBuffer g_HorizontalBuffer;\t// For separable (bicubic) upsampling\r\n\r\n    extern ColorBuffer g_VelocityBuffer;\t// R10G10B10  (3D velocity)\r\n    extern ShadowBuffer g_ShadowBuffer;\r\n\r\n    extern ColorBuffer g_SSAOFullScreen;\t// R8_UNORM\r\n    extern ColorBuffer g_LinearDepth[2];\t// Normalized planar distance (0 at eye, 1 at far plane) computed from the SceneDepthBuffer\r\n    extern ColorBuffer g_MinMaxDepth8;\t\t// Min and max depth values of 8x8 tiles\r\n    extern ColorBuffer g_MinMaxDepth16;\t\t// Min and max depth values of 16x16 tiles\r\n    extern ColorBuffer g_MinMaxDepth32;\t\t// Min and max depth values of 16x16 tiles\r\n    extern ColorBuffer g_DepthDownsize1;\r\n    extern ColorBuffer g_DepthDownsize2;\r\n    extern ColorBuffer g_DepthDownsize3;\r\n    extern ColorBuffer g_DepthDownsize4;\r\n    extern ColorBuffer g_DepthTiled1;\r\n    extern ColorBuffer g_DepthTiled2;\r\n    extern ColorBuffer g_DepthTiled3;\r\n    extern ColorBuffer g_DepthTiled4;\r\n    extern ColorBuffer g_AOMerged1;\r\n    extern ColorBuffer g_AOMerged2;\r\n    extern ColorBuffer g_AOMerged3;\r\n    extern ColorBuffer g_AOMerged4;\r\n    extern ColorBuffer g_AOSmooth1;\r\n    extern ColorBuffer g_AOSmooth2;\r\n    extern ColorBuffer g_AOSmooth3;\r\n    extern ColorBuffer g_AOHighQuality1;\r\n    extern ColorBuffer g_AOHighQuality2;\r\n    extern ColorBuffer g_AOHighQuality3;\r\n    extern ColorBuffer g_AOHighQuality4;\r\n\r\n    extern ColorBuffer g_DoFTileClass[2];\r\n    extern ColorBuffer g_DoFPresortBuffer;\r\n    extern ColorBuffer g_DoFPrefilter;\r\n    extern ColorBuffer g_DoFBlurColor[2];\r\n    extern ColorBuffer g_DoFBlurAlpha[2];\r\n    extern StructuredBuffer g_DoFWorkQueue;\r\n    extern StructuredBuffer g_DoFFastQueue;\r\n    extern StructuredBuffer g_DoFFixupQueue;\r\n\r\n    extern ColorBuffer g_MotionPrepBuffer;\t\t// R10G10B10A2\r\n    extern ColorBuffer g_LumaBuffer;\r\n    extern ColorBuffer g_TemporalColor[2];\r\n\textern ColorBuffer g_VarianceMap[2];\t// R16G16B16A16 and R16G16\r\n\r\n    extern ColorBuffer g_aBloomUAV1[2];\t\t// 640x384 (1/3)\r\n    extern ColorBuffer g_aBloomUAV2[2];\t\t// 320x192 (1/6)  \r\n    extern ColorBuffer g_aBloomUAV3[2];\t\t// 160x96  (1/12)\r\n    extern ColorBuffer g_aBloomUAV4[2];\t\t// 80x48   (1/24)\r\n    extern ColorBuffer g_aBloomUAV5[2];\t\t// 40x24   (1/48)\r\n    extern ColorBuffer g_LumaLR;\r\n    extern ByteAddressBuffer g_Histogram;\r\n    extern ByteAddressBuffer g_FXAAWorkCounters;\r\n    extern ByteAddressBuffer g_FXAAWorkQueue;\r\n    extern TypedBuffer g_FXAAColorQueue;\r\n\r\n    void InitializeRenderingBuffers(uint32_t NativeWidth, uint32_t NativeHeight );\r\n    void ResizeDisplayDependentBuffers(uint32_t NativeWidth, uint32_t NativeHeight);\r\n    void DestroyRenderingBuffers();\r\n\r\n    void RecreateCBRBuffers(int indexA, int indexB, int width, int height);\r\n    void RecreateMsaaBuffers(int index, int msaaMode, int width, int height );\r\n    void RecreateSceneDepthBuffer(int index, int width, int height);\r\n    void RecreateSceneColorBuffer(int index, int width, int height);\r\n\r\n} // namespace Graphics\r\n"
  },
  {
    "path": "MiniEngine/Core/Camera.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"Camera.h\"\r\n#include <cmath>\r\n\r\nusing namespace Math;\r\n\r\nvoid BaseCamera::SetLookDirection( Vector3 forward, Vector3 up )\r\n{\r\n    // Given, but ensure normalization\r\n    Scalar forwardLenSq = LengthSquare(forward);\r\n    forward = Select(forward * RecipSqrt(forwardLenSq), -Vector3(kZUnitVector), forwardLenSq < Scalar(0.000001f));\r\n\r\n    // Deduce a valid, orthogonal right vector\r\n    Vector3 right = Cross(forward, up);\r\n    Scalar rightLenSq = LengthSquare(right);\r\n    right = Select(right * RecipSqrt(rightLenSq), Quaternion(Vector3(kYUnitVector), -XM_PIDIV2) * forward, rightLenSq < Scalar(0.000001f));\r\n\r\n    // Compute actual up vector\r\n    up = Cross(right, forward);\r\n\r\n    // Finish constructing basis\r\n    m_Basis = Matrix3(right, up, -forward);\r\n    m_CameraToWorld.SetRotation(Quaternion(m_Basis));\r\n}\r\n\r\nvoid BaseCamera::Update()\r\n{\r\n    m_PreviousViewProjMatrix = m_ViewProjMatrix;\r\n\r\n    m_ViewMatrix = Matrix4(~m_CameraToWorld);\r\n    m_ViewProjMatrix = m_ProjMatrix * m_ViewMatrix;\r\n    m_ReprojectMatrix = m_PreviousViewProjMatrix * Invert(GetViewProjMatrix());\r\n\r\n    m_FrustumVS = Frustum( m_ProjMatrix );\r\n    m_FrustumWS = m_CameraToWorld * m_FrustumVS;\r\n}\r\n\r\n\r\nvoid Camera::UpdateProjMatrix( void )\r\n{\r\n    float Y = 1.0f / std::tanf( m_VerticalFOV * 0.5f );\r\n    float X = Y * m_AspectRatio;\r\n\r\n    float Q1, Q2;\r\n\r\n    // ReverseZ puts far plane at Z=0 and near plane at Z=1.  This is never a bad idea, and it's\r\n    // actually a great idea with F32 depth buffers to redistribute precision more evenly across\r\n    // the entire range.  It requires clearing Z to 0.0f and using a GREATER variant depth test.\r\n    // Some care must also be done to properly reconstruct linear W in a pixel shader from hyperbolic Z.\r\n    if (m_ReverseZ)\r\n    {\r\n        Q1 = m_NearClip / (m_FarClip - m_NearClip);\r\n        Q2 = Q1 * m_FarClip;\r\n    }\r\n    else\r\n    {\r\n        Q1 = m_FarClip / (m_NearClip - m_FarClip);\r\n        Q2 = Q1 * m_NearClip;\r\n    }\r\n\r\n    SetProjMatrix( Matrix4(\r\n        Vector4( X, 0.0f, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, Y, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, 0.0f, Q1, -1.0f ),\r\n        Vector4( 0.0f, 0.0f, Q2, 0.0f )\r\n        ) );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Camera.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"VectorMath.h\"\r\n#include \"Math/Frustum.h\"\r\n\r\nnamespace Math\r\n{\r\n    class BaseCamera\r\n    {\r\n    public:\r\n\r\n        // Call this function once per frame and after you've changed any state.  This\r\n        // regenerates all matrices.  Calling it more or less than once per frame will break\r\n        // temporal effects and cause unpredictable results.\r\n        void Update();\r\n\r\n        // Public functions for controlling where the camera is and its orientation\r\n        void SetEyeAtUp( Vector3 eye, Vector3 at, Vector3 up );\r\n        void SetLookDirection( Vector3 forward, Vector3 up );\r\n        void SetRotation( Quaternion basisRotation );\r\n        void SetPosition( Vector3 worldPos );\r\n        void SetTransform( const AffineTransform& xform );\r\n        void SetTransform( const OrthogonalTransform& xform );\r\n\r\n        const Quaternion GetRotation() const { return m_CameraToWorld.GetRotation(); }\r\n        const Vector3 GetRightVec() const { return m_Basis.GetX(); }\r\n        const Vector3 GetUpVec() const { return m_Basis.GetY(); }\r\n        const Vector3 GetForwardVec() const { return -m_Basis.GetZ(); }\r\n        const Vector3 GetPosition() const { return m_CameraToWorld.GetTranslation(); }\r\n\r\n        // Accessors for reading the various matrices and frusta\r\n        const Matrix4& GetViewMatrix() const { return m_ViewMatrix; }\r\n        const Matrix4& GetProjMatrix() const { return m_ProjMatrix; }\r\n        const Matrix4& GetViewProjMatrix() const { return m_ViewProjMatrix; }\r\n        const Matrix4& GetReprojectionMatrix() const { return m_ReprojectMatrix; }\r\n        const Frustum& GetViewSpaceFrustum() const { return m_FrustumVS; }\r\n        const Frustum& GetWorldSpaceFrustum() const { return m_FrustumWS; }\r\n\r\n    protected:\r\n\r\n        BaseCamera() : m_CameraToWorld(kIdentity), m_Basis(kIdentity) {}\r\n\r\n        void SetProjMatrix( const Matrix4& ProjMat ) { m_ProjMatrix = ProjMat; }\r\n\r\n        OrthogonalTransform m_CameraToWorld;\r\n\r\n        // Redundant data cached for faster lookups.\r\n        Matrix3 m_Basis;\r\n\r\n        // Transforms homogeneous coordinates from world space to view space.  In this case, view space is defined as +X is\r\n        // to the right, +Y is up, and -Z is forward.  This has to match what the projection matrix expects, but you might\r\n        // also need to know what the convention is if you work in view space in a shader.\r\n        Matrix4 m_ViewMatrix;\t\t// i.e. \"World-to-View\" matrix\r\n\r\n        // The projection matrix transforms view space to clip space.  Once division by W has occurred, the final coordinates\r\n        // can be transformed by the viewport matrix to screen space.  The projection matrix is determined by the screen aspect \r\n        // and camera field of view.  A projection matrix can also be orthographic.  In that case, field of view would be defined\r\n        // in linear units, not angles.\r\n        Matrix4 m_ProjMatrix;\t\t// i.e. \"View-to-Projection\" matrix\r\n\r\n        // A concatenation of the view and projection matrices.\r\n        Matrix4 m_ViewProjMatrix;\t// i.e.  \"World-To-Projection\" matrix.\r\n\r\n        // The view-projection matrix from the previous frame\r\n        Matrix4 m_PreviousViewProjMatrix;\r\n\r\n        // Projects a clip-space coordinate to the previous frame (useful for temporal effects).\r\n        Matrix4 m_ReprojectMatrix;\r\n\r\n        Frustum m_FrustumVS;\t\t// View-space view frustum\r\n        Frustum m_FrustumWS;\t\t// World-space view frustum\r\n\r\n    };\r\n\r\n    class Camera : public BaseCamera\r\n    {\r\n    public:\r\n        Camera();\r\n\r\n        // Controls the view-to-projection matrix\r\n        void SetPerspectiveMatrix( float verticalFovRadians, float aspectHeightOverWidth, float nearZClip, float farZClip );\r\n        void SetFOV( float verticalFovInRadians ) { m_VerticalFOV = verticalFovInRadians; UpdateProjMatrix(); }\r\n        void SetAspectRatio( float heightOverWidth ) { m_AspectRatio = heightOverWidth; UpdateProjMatrix(); }\r\n        void SetZRange( float nearZ, float farZ) { m_NearClip = nearZ; m_FarClip = farZ; UpdateProjMatrix(); }\r\n        void ReverseZ( bool enable ) { m_ReverseZ = enable; UpdateProjMatrix(); }\r\n\r\n        float GetFOV() const { return m_VerticalFOV; }\r\n        float GetNearClip() const { return m_NearClip; }\r\n        float GetFarClip() const { return m_FarClip; }\r\n        float GetClearDepth() const { return m_ReverseZ ? 0.0f : 1.0f; }\r\n\r\n    private:\r\n\r\n        void UpdateProjMatrix( void );\r\n\r\n        float m_VerticalFOV;\t\t\t// Field of view angle in radians\r\n        float m_AspectRatio;\r\n        float m_NearClip;\r\n        float m_FarClip;\r\n        bool m_ReverseZ;\t\t\t\t// Invert near and far clip distances so that Z=0 is the far plane\r\n    };\r\n\r\n    inline void BaseCamera::SetEyeAtUp( Vector3 eye, Vector3 at, Vector3 up )\r\n    {\r\n        SetLookDirection(at - eye, up);\r\n        SetPosition(eye);\r\n    }\r\n\r\n    inline void BaseCamera::SetPosition( Vector3 worldPos )\r\n    {\r\n        m_CameraToWorld.SetTranslation( worldPos );\r\n    }\r\n\r\n    inline void BaseCamera::SetTransform( const AffineTransform& xform )\r\n    {\r\n        // By using these functions, we rederive an orthogonal transform.\r\n        SetLookDirection(-xform.GetZ(), xform.GetY());\r\n        SetPosition(xform.GetTranslation());\r\n    }\r\n\r\n    inline void BaseCamera::SetRotation( Quaternion basisRotation )\r\n    {\r\n        m_CameraToWorld.SetRotation(Normalize(basisRotation));\r\n        m_Basis = Matrix3(m_CameraToWorld.GetRotation());\r\n    }\r\n\r\n    inline Camera::Camera() : m_ReverseZ(true)\r\n    {\r\n        SetPerspectiveMatrix( XM_PIDIV4, 9.0f / 16.0f, 1.0f, 1000.0f );\r\n    }\r\n\r\n    inline void Camera::SetPerspectiveMatrix( float verticalFovRadians, float aspectHeightOverWidth, float nearZClip, float farZClip )\r\n    {\r\n        m_VerticalFOV = verticalFovRadians;\r\n        m_AspectRatio = aspectHeightOverWidth;\r\n        m_NearClip = nearZClip;\r\n        m_FarClip = farZClip;\r\n\r\n        UpdateProjMatrix();\r\n\r\n        m_PreviousViewProjMatrix = m_ViewProjMatrix;\r\n    }\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/CameraController.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"CameraController.h\"\r\n#include \"Camera.h\"\r\n#include \"GameInput.h\"\r\n\r\nusing namespace Math;\r\nusing namespace GameCore;\r\n\r\nCameraController::CameraController( Camera& camera, Vector3 worldUp ) : m_TargetCamera( camera )\r\n{\r\n    m_WorldUp = Normalize(worldUp);\r\n    m_WorldNorth = Normalize(Cross(m_WorldUp, Vector3(kXUnitVector)));\r\n    m_WorldEast = Cross(m_WorldNorth, m_WorldUp);\r\n\r\n    m_HorizontalLookSensitivity = 2.0f;\r\n    m_VerticalLookSensitivity = 2.0f;\r\n    m_MoveSpeed = 1000.0f;\r\n    m_StrafeSpeed = 1000.0f;\r\n    m_MouseSensitivityX = 1.0f;\r\n    m_MouseSensitivityY = 1.0f;\r\n\r\n    m_CurrentPitch = Sin(Dot(camera.GetForwardVec(), m_WorldUp));\r\n\r\n    Vector3 forward = Normalize(Cross(m_WorldUp, camera.GetRightVec()));\r\n    m_CurrentHeading = ATan2(-Dot(forward, m_WorldEast), Dot(forward, m_WorldNorth));\r\n\r\n    m_FineMovement = false;\r\n    m_FineRotation = false;\r\n    m_Momentum = true;\r\n\r\n    m_LastYaw = 0.0f;\r\n    m_LastPitch = 0.0f;\r\n    m_LastForward = 0.0f;\r\n    m_LastStrafe = 0.0f;\r\n    m_LastAscent = 0.0f;\r\n}\r\n\r\nvoid CameraController::SetSpeed(float speed) {\r\n\tm_MoveSpeed = speed;\r\n\tm_StrafeSpeed = speed;\r\n}\r\n\r\nvoid CameraController::Reset() {\r\n\tm_CurrentPitch = Sin(Dot(m_TargetCamera.GetForwardVec(), m_WorldUp));\r\n\r\n\tVector3 forward = Normalize(Cross(m_WorldUp, m_TargetCamera.GetRightVec()));\r\n\tm_CurrentHeading = ATan2(-Dot(forward, m_WorldEast), Dot(forward, m_WorldNorth));\r\n\r\n\tm_LastYaw = 0.0f;\r\n\tm_LastPitch = 0.0f;\r\n\tm_LastForward = 0.0f;\r\n\tm_LastStrafe = 0.0f;\r\n\tm_LastAscent = 0.0f;\r\n}\r\n\r\nnamespace Graphics\r\n{\r\n    extern EnumVar DebugZoom;\r\n}\r\n\r\nvoid CameraController::Update( float deltaTime )\r\n{\r\n    (deltaTime);\r\n\r\n    float timeScale = Graphics::DebugZoom == 0 ? 1.0f : Graphics::DebugZoom == 1 ? 0.5f : 0.25f;\r\n\r\n    if (GameInput::IsFirstPressed(GameInput::kLThumbClick) || GameInput::IsFirstPressed(GameInput::kKey_lshift))\r\n        m_FineMovement = !m_FineMovement;\r\n\r\n    if (GameInput::IsFirstPressed(GameInput::kRThumbClick))\r\n        m_FineRotation = !m_FineRotation;\r\n\r\n    float speedScale = (m_FineMovement ? 0.1f : 1.0f) * timeScale;\r\n    float panScale = (m_FineRotation ? 0.5f : 1.0f) * timeScale;\r\n\r\n    float yaw = GameInput::GetTimeCorrectedAnalogInput( GameInput::kAnalogRightStickX ) * m_HorizontalLookSensitivity * panScale;\r\n    float pitch = GameInput::GetTimeCorrectedAnalogInput( GameInput::kAnalogRightStickY ) * m_VerticalLookSensitivity * panScale;\r\n    float forward =\tm_MoveSpeed * speedScale * (\r\n        GameInput::GetTimeCorrectedAnalogInput( GameInput::kAnalogLeftStickY ) +\r\n        (GameInput::IsPressed( GameInput::kKey_w ) ? deltaTime : 0.0f) +\r\n        (GameInput::IsPressed( GameInput::kKey_s ) ? -deltaTime : 0.0f)\r\n        );\r\n    float strafe = m_StrafeSpeed * speedScale * (\r\n        GameInput::GetTimeCorrectedAnalogInput( GameInput::kAnalogLeftStickX  ) +\r\n        (GameInput::IsPressed( GameInput::kKey_d ) ? deltaTime : 0.0f) +\r\n        (GameInput::IsPressed( GameInput::kKey_a ) ? -deltaTime : 0.0f)\r\n        );\r\n    float ascent = m_StrafeSpeed * speedScale * (\r\n        GameInput::GetTimeCorrectedAnalogInput( GameInput::kAnalogRightTrigger ) -\r\n        GameInput::GetTimeCorrectedAnalogInput( GameInput::kAnalogLeftTrigger ) +\r\n        (GameInput::IsPressed( GameInput::kKey_e ) ? deltaTime : 0.0f) +\r\n        (GameInput::IsPressed( GameInput::kKey_q ) ? -deltaTime : 0.0f)\r\n        );\r\n\r\n    if (m_Momentum)\r\n    {\r\n        ApplyMomentum(m_LastYaw, yaw, deltaTime);\r\n        ApplyMomentum(m_LastPitch, pitch, deltaTime);\r\n        ApplyMomentum(m_LastForward, forward, deltaTime);\r\n        ApplyMomentum(m_LastStrafe, strafe, deltaTime);\r\n        ApplyMomentum(m_LastAscent, ascent, deltaTime);\r\n    }\r\n\r\n    // don't apply momentum to mouse inputs\r\n    yaw += GameInput::GetAnalogInput(GameInput::kAnalogMouseX) * m_MouseSensitivityX;\r\n    pitch += GameInput::GetAnalogInput(GameInput::kAnalogMouseY) * m_MouseSensitivityY;\r\n\r\n    m_CurrentPitch += pitch;\r\n    m_CurrentPitch = XMMin( XM_PIDIV2, m_CurrentPitch);\r\n    m_CurrentPitch = XMMax(-XM_PIDIV2, m_CurrentPitch);\r\n\r\n    m_CurrentHeading -= yaw;\r\n    if (m_CurrentHeading > XM_PI)\r\n        m_CurrentHeading -= XM_2PI;\r\n    else if (m_CurrentHeading <= -XM_PI)\r\n        m_CurrentHeading += XM_2PI; \r\n\r\n    Matrix3 orientation = Matrix3(m_WorldEast, m_WorldUp, -m_WorldNorth) * Matrix3::MakeYRotation( m_CurrentHeading ) * Matrix3::MakeXRotation( m_CurrentPitch );\r\n    Vector3 position = orientation * Vector3( strafe, ascent, -forward ) + m_TargetCamera.GetPosition();\r\n    m_TargetCamera.SetTransform( AffineTransform( orientation, position ) );\r\n    m_TargetCamera.Update();\r\n}\r\n\r\nvoid CameraController::ApplyMomentum( float& oldValue, float& newValue, float deltaTime )\r\n{\r\n    float blendedValue;\r\n    if (Abs(newValue) > Abs(oldValue))\r\n        blendedValue = Lerp(newValue, oldValue, Pow(0.6f, deltaTime * 60.0f));\r\n    else\r\n        blendedValue = Lerp(newValue, oldValue, Pow(0.8f, deltaTime * 60.0f));\r\n    oldValue = blendedValue;\r\n    newValue = blendedValue;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/CameraController.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"GameCore.h\"\r\n#include \"VectorMath.h\"\r\n\r\nnamespace Math\r\n{\r\n    class Camera;\r\n}\r\n\r\nnamespace GameCore\r\n{\r\n    using namespace Math;\r\n\r\n    class CameraController\r\n    {\r\n    public:\r\n        // Assumes worldUp is not the X basis vector\r\n        CameraController( Camera& camera, Vector3 worldUp );\r\n\r\n        void Update( float dt );\r\n\r\n\t\tvoid Reset();\r\n\r\n        void SlowMovement( bool enable ) { m_FineMovement = enable; }\r\n        void SlowRotation( bool enable ) { m_FineRotation = enable; }\r\n\r\n\t\tvoid SetSpeed(float speed);\r\n\r\n        void EnableMomentum( bool enable ) { m_Momentum = enable; }\r\n\r\n    private:\r\n        CameraController& operator=( const CameraController& ) {return *this;}\r\n\r\n        void ApplyMomentum( float& oldValue, float& newValue, float deltaTime );\r\n\r\n        Vector3 m_WorldUp;\r\n        Vector3 m_WorldNorth;\r\n        Vector3 m_WorldEast;\r\n        Camera& m_TargetCamera;\r\n        float m_HorizontalLookSensitivity;\r\n        float m_VerticalLookSensitivity;\r\n        float m_MoveSpeed;\r\n        float m_StrafeSpeed;\r\n        float m_MouseSensitivityX;\r\n        float m_MouseSensitivityY;\r\n\r\n        float m_CurrentHeading;\r\n        float m_CurrentPitch;\r\n\r\n        bool m_FineMovement;\r\n        bool m_FineRotation;\r\n        bool m_Momentum;\r\n\r\n        float m_LastYaw;\r\n        float m_LastPitch;\r\n        float m_LastForward;\r\n        float m_LastStrafe;\r\n        float m_LastAscent;\r\n    };\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Color.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"Color.h\"\r\n\r\nusing DirectX::XMVECTORU32;\r\n\r\nuint32_t Color::R11G11B10F(bool RoundToEven) const\r\n{\r\n#if 1\r\n    static const float kMaxVal = float(1 << 16);\r\n    static const float kF32toF16 = (1.0 / (1ull << 56)) * (1.0 / (1ull << 56));\r\n\r\n    union { float f; uint32_t u; } R, G, B;\r\n\r\n    R.f = Math::Clamp(m_value.f[0], 0.0f, kMaxVal) * kF32toF16;\r\n    G.f = Math::Clamp(m_value.f[1], 0.0f, kMaxVal) * kF32toF16;\r\n    B.f = Math::Clamp(m_value.f[2], 0.0f, kMaxVal) * kF32toF16;\r\n\r\n    if (RoundToEven)\r\n    {\r\n        // Bankers rounding:  2.5 -> 2.0  ;  3.5 -> 4.0\r\n        R.u += 0x0FFFF + ((R.u >> 16) & 1);\r\n        G.u += 0x0FFFF + ((G.u >> 16) & 1);\r\n        B.u += 0x1FFFF + ((B.u >> 17) & 1);\r\n    }\r\n    else\r\n    {\r\n        // Default rounding:  2.5 -> 3.0  ;  3.5 -> 4.0\r\n        R.u += 0x00010000;\r\n        G.u += 0x00010000;\r\n        B.u += 0x00020000;\r\n    }\r\n\r\n    R.u &= 0x0FFE0000;\r\n    G.u &= 0x0FFE0000;\r\n    B.u &= 0x0FFC0000;\r\n\r\n    return R.u >> 17 | G.u >> 6 | B.u << 4;\r\n\r\n#else // SSE\r\n\r\n    static XMVECTORU32 Scale = { 0x07800000, 0x07800000, 0x07800000, 0 }; // 2^-112\r\n    static XMVECTORU32 Round1 = { 0x00010000, 0x00010000, 0x00020000, 0 };\r\n    static XMVECTORU32 Round2 = { 0x0000FFFF, 0x0000FFFF, 0x0001FFFF, 0 };\r\n    static XMVECTORU32 Mask = { 0x0FFE0000, 0x0FFE0000, 0x0FFC0000, 0 };\r\n\r\n    // Treat the values like integers as we clamp to [0, +Inf].  This translates 32-bit specials\r\n    // to 16-bit specials (while also turning anything greater than MAX_HALF into +INF).\r\n    __m128i ti = _mm_max_epi32(_mm_castps_si128(m_value), _mm_setzero_si128());\r\n    ti = _mm_min_epi32(ti, _mm_set1_epi32(0x47800000)); // 2^16 = 65536.0f = INF\r\n\r\n    // Bias the exponent by -112 (-127 + 15) to denormalize values < 2^-14\r\n    ti = _mm_castps_si128(_mm_mul_ps(_mm_castsi128_ps(ti), Scale));\r\n\r\n    if (RoundToEven)\r\n    {\r\n        // Add 0x10000 when odd, 0x0FFFF when even (before truncating bits)\r\n        ti = _mm_add_epi32(ti, _mm_max_epi32(_mm_and_si128(_mm_srli_epi32(ti, 1), Round1), Round2));\r\n    }\r\n    else //if (RoundToNearest)\r\n    {\r\n        ti = _mm_add_epi32(ti, Round1);\r\n    }\r\n\r\n    XMVECTORU32 ret;\r\n    ret.v = _mm_castsi128_ps(_mm_and_si128(ti, Mask));\r\n    return ret.u[0] >> 17 | ret.u[1] >> 6 | ret.u[2] << 4;\r\n\r\n#endif\r\n}\r\n\r\nuint32_t Color::R9G9B9E5() const\r\n{\r\n#if 1\r\n    static const float kMaxVal = float(0x1FF << 7);\r\n    static const float kMinVal = float(1.f / (1 << 16));\r\n\r\n    // Clamp RGB to [0, 1.FF*2^16]\r\n    float r = Math::Clamp(m_value.f[0], 0.0f, kMaxVal);\r\n    float g = Math::Clamp(m_value.f[1], 0.0f, kMaxVal);\r\n    float b = Math::Clamp(m_value.f[2], 0.0f, kMaxVal);\r\n\r\n    // Compute the maximum channel, no less than 1.0*2^-15\r\n    float MaxChannel = Math::Max(Math::Max(r, g), Math::Max(b, kMinVal));\r\n\r\n    // Take the exponent of the maximum channel (rounding up the 9th bit) and\r\n    // add 15 to it.  When added to the channels, it causes the implicit '1.0'\r\n    // bit and the first 8 mantissa bits to be shifted down to the low 9 bits\r\n    // of the mantissa, rounding the truncated bits.\r\n    union { float f; int32_t i; } R, G, B, E;\r\n    E.f = MaxChannel;\r\n    E.i += 0x07804000; // Add 15 to the exponent and 0x4000 to the mantissa\r\n    E.i &= 0x7F800000; // Zero the mantissa\r\n\r\n    // This shifts the 9-bit values we need into the lowest bits, rounding as\r\n    // needed.  Note that if the channel has a smaller exponent than the max\r\n    // channel, it will shift even more.  This is intentional.\r\n    R.f = r + E.f;\r\n    G.f = g + E.f;\r\n    B.f = b + E.f;\r\n\r\n    // Convert the Bias to the correct exponent in the upper 5 bits.\r\n    E.i <<= 4;\r\n    E.i += 0x10000000;\r\n\r\n    // Combine the fields.  RGB floats have unwanted data in the upper 9\r\n    // bits.  Only red needs to mask them off because green and blue shift\r\n    // it out to the left.\r\n    return E.i | B.i << 18 | G.i << 9 | R.i & 511;\r\n\r\n#else // SSE\r\n\r\n    // Clamp RGB to [0, 1.FF*2^16]\r\n    __m128 kMaxVal = _mm_castsi128_ps(_mm_set1_epi32(0x477F8000));\r\n    __m128 rgb = _mm_min_ps(_mm_max_ps(m_value, _mm_setzero_ps()), kMaxVal);\r\n\r\n    // Compute the maximum channel, no less than 1.0*2^-15\r\n    __m128 kMinVal = _mm_castsi128_ps(_mm_set1_epi32(0x37800000));\r\n    __m128 MaxChannel = _mm_max_ps(rgb, kMinVal);\r\n    MaxChannel = _mm_max_ps( _mm_permute_ps(MaxChannel, _MM_SHUFFLE(3, 1, 0, 2)),\r\n        _mm_max_ps(_mm_permute_ps(MaxChannel, _MM_SHUFFLE(3, 0, 2, 1)), MaxChannel) );\r\n\r\n    // Add 15 to the exponent and 0x4000 to the mantissa\r\n    __m128i kBias15 = _mm_set1_epi32(0x07804000);\r\n    __m128i kExpMask = _mm_set1_epi32(0x7F800000);\r\n    __m128i Bias = _mm_and_si128(_mm_add_epi32(_mm_castps_si128(MaxChannel), kBias15), kExpMask);\r\n\r\n    // rgb += Bias\r\n    rgb = _mm_add_ps(rgb, _mm_castsi128_ps(Bias));\r\n\r\n    // Exp = (Bias << 4) + 0x10000000;\r\n    __m128i Exp = _mm_add_epi32(_mm_slli_epi32(Bias, 4), _mm_set1_epi32(0x10000000));\r\n\r\n    // Combine words\r\n    XMVECTORU32 ret;\r\n    ret.v = _mm_insert_ps(rgb, _mm_castsi128_ps(Exp), 0x30);\r\n    return ret.u[3] | ret.u[2] << 18 | ret.u[1] << 9 | ret.u[0] & 511;\r\n\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Color.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include <DirectXMath.h>\r\n\r\nusing namespace DirectX;\r\n\r\nclass Color\r\n{\r\npublic:\r\n    Color( ) : m_value(g_XMOne) {}\r\n    Color( FXMVECTOR vec );\r\n    Color( const XMVECTORF32& vec );\r\n    Color( float r, float g, float b, float a = 1.0f );\r\n    Color( uint16_t r, uint16_t g, uint16_t b, uint16_t a = 255, uint16_t bitDepth = 8 );\r\n    explicit Color( uint32_t rgbaLittleEndian );\r\n        \r\n    float R() const { return XMVectorGetX(m_value); }\r\n    float G() const { return XMVectorGetY(m_value); }\r\n    float B() const { return XMVectorGetZ(m_value); }\r\n    float A() const { return XMVectorGetW(m_value); }\r\n\r\n    bool operator==( const Color& rhs ) const { return XMVector4Equal(m_value, rhs.m_value); }\r\n    bool operator!=( const Color& rhs ) const { return !XMVector4Equal(m_value, rhs.m_value); }\r\n\r\n    void SetR( float r ) { m_value.f[0] = r; }\r\n    void SetG( float g ) { m_value.f[1] = g; }\r\n    void SetB( float b ) { m_value.f[2] = b; }\r\n    void SetA( float a ) { m_value.f[3] = a; }\r\n\r\n    float* GetPtr( void ) { return reinterpret_cast<float*>(this); }\r\n    float& operator[]( int idx ) { return GetPtr()[idx]; }\r\n\r\n    void SetRGB( float r, float g, float b ) { m_value.v = XMVectorSelect( m_value, XMVectorSet(r, g, b, b), g_XMMask3 ); }\r\n\r\n    Color ToSRGB() const;\r\n    Color FromSRGB() const;\r\n    Color ToREC709() const;\r\n    Color FromREC709() const;\r\n\r\n    // Probably want to convert to sRGB or Rec709 first\r\n    uint32_t R10G10B10A2() const;\r\n    uint32_t R8G8B8A8() const;\r\n\r\n    // Pack an HDR color into 32-bits\r\n    uint32_t R11G11B10F(bool RoundToEven=false) const;\r\n    uint32_t R9G9B9E5() const;\r\n\r\n    operator XMVECTOR() const { return m_value; }\r\n\r\nprivate:\r\n    XMVECTORF32 m_value;\r\n};\r\n\r\nINLINE Color Max( Color a, Color b ) { return Color(XMVectorMax(a, b)); }\r\nINLINE Color Min( Color a, Color b ) { return Color(XMVectorMin(a, b)); }\r\nINLINE Color Clamp( Color x, Color a, Color b ) { return Color(XMVectorClamp(x, a, b)); }\r\n\r\n\r\ninline Color::Color( FXMVECTOR vec )\r\n{\r\n    m_value.v = vec;\r\n}\r\n\r\ninline Color::Color( const XMVECTORF32& vec )\r\n{\r\n    m_value = vec;\r\n}\r\n\r\ninline Color::Color( float r, float g, float b, float a )\r\n{\r\n    m_value.v = XMVectorSet(r, g, b, a);\r\n}\r\n\r\ninline Color::Color( uint16_t r, uint16_t g, uint16_t b, uint16_t a, uint16_t bitDepth )\r\n{\r\n    m_value.v = XMVectorScale(XMVectorSet(r, g, b, a), 1.0f / ((1 << bitDepth) - 1));\r\n}\r\n\r\ninline Color::Color( uint32_t u32 )\r\n{\r\n    float r = (float)((u32 >>  0) & 0xFF);\r\n    float g = (float)((u32 >>  8) & 0xFF);\r\n    float b = (float)((u32 >> 16) & 0xFF);\r\n    float a = (float)((u32 >> 24) & 0xFF);\r\n    m_value.v = XMVectorScale( XMVectorSet(r, g, b, a), 1.0f / 255.0f );\r\n}\r\n\r\ninline Color Color::ToSRGB( void ) const\r\n{\r\n    XMVECTOR T = XMVectorSaturate(m_value);\r\n    XMVECTOR result = XMVectorSubtract(XMVectorScale(XMVectorPow(T, XMVectorReplicate(1.0f / 2.4f)), 1.055f), XMVectorReplicate(0.055f));\r\n    result = XMVectorSelect(result, XMVectorScale(T, 12.92f), XMVectorLess(T, XMVectorReplicate(0.0031308f)));\r\n    return XMVectorSelect(T, result, g_XMSelect1110);\r\n}\r\n\r\ninline Color Color::FromSRGB( void ) const\r\n{\r\n    XMVECTOR T = XMVectorSaturate(m_value);\r\n    XMVECTOR result = XMVectorPow(XMVectorScale(XMVectorAdd(T, XMVectorReplicate(0.055f)), 1.0f / 1.055f), XMVectorReplicate(2.4f));\r\n    result = XMVectorSelect(result, XMVectorScale(T, 1.0f / 12.92f), XMVectorLess(T, XMVectorReplicate(0.0031308f)));\r\n    return XMVectorSelect(T, result, g_XMSelect1110);\r\n}\r\n\r\ninline Color Color::ToREC709( void ) const\r\n{\r\n    XMVECTOR T = XMVectorSaturate(m_value);\r\n    XMVECTOR result = XMVectorSubtract(XMVectorScale(XMVectorPow(T, XMVectorReplicate(0.45f)), 1.099f), XMVectorReplicate(0.099f));\r\n    result = XMVectorSelect(result, XMVectorScale(T, 4.5f), XMVectorLess(T, XMVectorReplicate(0.0018f)));\r\n    return XMVectorSelect(T, result, g_XMSelect1110);\r\n}\r\n\r\ninline Color Color::FromREC709( void ) const\r\n{\r\n    XMVECTOR T = XMVectorSaturate(m_value);\r\n    XMVECTOR result = XMVectorPow(XMVectorScale(XMVectorAdd(T, XMVectorReplicate(0.099f)), 1.0f / 1.099f), XMVectorReplicate(1.0f / 0.45f));\r\n    result = XMVectorSelect(result, XMVectorScale(T, 1.0f / 4.5f), XMVectorLess(T, XMVectorReplicate(0.0081f)));\r\n    return XMVectorSelect(T, result, g_XMSelect1110);\r\n}\r\n\r\ninline uint32_t Color::R10G10B10A2( void ) const\r\n{\r\n    XMVECTOR result = XMVectorRound(XMVectorMultiply(XMVectorSaturate(m_value), XMVectorSet(1023.0f, 1023.0f, 1023.0f, 3.0f)));\r\n    result = _mm_castsi128_ps(_mm_cvttps_epi32(result));\r\n    uint32_t r = XMVectorGetIntX(result);\r\n    uint32_t g = XMVectorGetIntY(result);\r\n    uint32_t b = XMVectorGetIntZ(result);\r\n    uint32_t a = XMVectorGetIntW(result) >> 8;\r\n    return a << 30 | b << 20 | g << 10 | r;\r\n}\r\n\r\ninline uint32_t Color::R8G8B8A8( void ) const\r\n{\r\n    XMVECTOR result = XMVectorRound(XMVectorMultiply(XMVectorSaturate(m_value), XMVectorReplicate(255.0f)));\r\n    result = _mm_castsi128_ps(_mm_cvttps_epi32(result));\r\n    uint32_t r = XMVectorGetIntX(result);\r\n    uint32_t g = XMVectorGetIntY(result);\r\n    uint32_t b = XMVectorGetIntZ(result);\r\n    uint32_t a = XMVectorGetIntW(result);\r\n    return a << 24 | b << 16 | g << 8 | r;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ColorBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"ColorBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"EsramAllocator.h\"\r\n\r\nusing namespace Graphics;\r\n\r\n\r\nvoid ColorBuffer::CreateDerivedViews(DX12_DEVICE* Device, DXGI_FORMAT Format, uint32_t ArraySize, uint32_t NumMips)\r\n{\r\n    ASSERT(ArraySize == 1 || NumMips == 1, \"We don't support auto-mips on texture arrays\");\r\n\r\n    m_NumMipMaps = NumMips - 1;\r\n\r\n    D3D12_RENDER_TARGET_VIEW_DESC RTVDesc = {};\r\n    D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};\r\n    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n\r\n    RTVDesc.Format = Format;\r\n    UAVDesc.Format = GetUAVFormat(Format);\r\n    SRVDesc.Format = Format;\r\n    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n\r\n    if (ArraySize > 1)\r\n    {\r\n        RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;\r\n        RTVDesc.Texture2DArray.MipSlice = 0;\r\n        RTVDesc.Texture2DArray.FirstArraySlice = 0;\r\n        RTVDesc.Texture2DArray.ArraySize = (UINT)ArraySize;\r\n\r\n        UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;\r\n        UAVDesc.Texture2DArray.MipSlice = 0;\r\n        UAVDesc.Texture2DArray.FirstArraySlice = 0;\r\n        UAVDesc.Texture2DArray.ArraySize = (UINT)ArraySize;\r\n\r\n        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;\r\n        SRVDesc.Texture2DArray.MipLevels = NumMips;\r\n        SRVDesc.Texture2DArray.MostDetailedMip = 0;\r\n        SRVDesc.Texture2DArray.FirstArraySlice = 0;\r\n        SRVDesc.Texture2DArray.ArraySize = (UINT)ArraySize;\r\n    }\r\n    else if (m_FragmentCount > 1)\r\n    {\r\n        RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;\r\n        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;\r\n    }\r\n    else \r\n    {\r\n        RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;\r\n        RTVDesc.Texture2D.MipSlice = 0;\r\n\r\n        UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;\r\n        UAVDesc.Texture2D.MipSlice = 0;\r\n\r\n        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;\r\n        SRVDesc.Texture2D.MipLevels = NumMips;\r\n        SRVDesc.Texture2D.MostDetailedMip = 0;\r\n    }\r\n\r\n    if (m_SRVHandle.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n    {\r\n        m_RTVHandle = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\r\n        m_SRVHandle = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    }\r\n\r\n    ID3D12Resource* Resource = m_pResource.Get();\r\n\r\n    // Create the render target view\r\n    Device->CreateRenderTargetView(Resource, &RTVDesc, m_RTVHandle);\r\n\r\n    // Create the shader resource view\r\n    Device->CreateShaderResourceView(Resource, &SRVDesc, m_SRVHandle);\r\n\r\n    if (m_FragmentCount > 1)\r\n        return;\r\n\r\n\tif (m_Format == DXGI_FORMAT_B8G8R8A8_UNORM)\r\n\t\treturn;\r\n\r\n    // Create the UAVs for each mip level (RWTexture2D)\r\n\tfor (uint32_t i = 0; i < NumMips; ++i)\r\n    {\r\n        if (m_UAVHandle[i].ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n            m_UAVHandle[i] = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n\r\n        Device->CreateUnorderedAccessView(Resource, nullptr, &UAVDesc, m_UAVHandle[i]);\r\n\r\n        UAVDesc.Texture2D.MipSlice++;\r\n    }\r\n}\r\n\r\nvoid ColorBuffer::CreateFromSwapChain( const std::wstring& Name, ID3D12Resource* BaseResource )\r\n{\r\n    AssociateWithResource(Graphics::g_Device, Name, BaseResource, D3D12_RESOURCE_STATE_PRESENT);\r\n\r\n    //m_UAVHandle[0] = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    //Graphics::g_Device->CreateUnorderedAccessView(m_pResource.Get(), nullptr, nullptr, m_UAVHandle[0]);\r\n\r\n    m_RTVHandle = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\r\n    Graphics::g_Device->CreateRenderTargetView(m_pResource.Get(), nullptr, m_RTVHandle);\r\n}\r\n\r\nvoid ColorBuffer::Create(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n    DXGI_FORMAT Format, D3D12_GPU_VIRTUAL_ADDRESS VidMem)\r\n{\r\n    NumMips = (NumMips == 0 ? ComputeNumMips(Width, Height) : NumMips);\r\n    D3D12_RESOURCE_FLAGS Flags = CombineResourceFlags();\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeTex2D(Width, Height, 1, NumMips, Format, Flags);\r\n\r\n    ResourceDesc.SampleDesc.Count = m_FragmentCount;\r\n    ResourceDesc.SampleDesc.Quality = 0;\r\n\r\n    D3D12_CLEAR_VALUE ClearValue = {};\r\n    ClearValue.Format = Format;\r\n    ClearValue.Color[0] = m_ClearColor.R();\r\n    ClearValue.Color[1] = m_ClearColor.G();\r\n    ClearValue.Color[2] = m_ClearColor.B();\r\n    ClearValue.Color[3] = m_ClearColor.A();\r\n\r\n    CreateTextureResource(Graphics::g_Device, Name, ResourceDesc, ClearValue, VidMem);\r\n    CreateDerivedViews(Graphics::g_Device, Format, 1, NumMips);\r\n}\r\n\r\nvoid ColorBuffer::Create(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n    DXGI_FORMAT Format, EsramAllocator&)\r\n{\r\n    Create(Name, Width, Height, NumMips, Format);\r\n}\r\n\r\nvoid ColorBuffer::CreateArray( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t ArrayCount,\r\n    DXGI_FORMAT Format, D3D12_GPU_VIRTUAL_ADDRESS VidMem )\r\n{\r\n    D3D12_RESOURCE_FLAGS Flags = CombineResourceFlags();\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeTex2D(Width, Height, ArrayCount, 1, Format, Flags);\r\n\r\n    D3D12_CLEAR_VALUE ClearValue = {};\r\n    ClearValue.Format = Format;\r\n    ClearValue.Color[0] = m_ClearColor.R();\r\n    ClearValue.Color[1] = m_ClearColor.G();\r\n    ClearValue.Color[2] = m_ClearColor.B();\r\n    ClearValue.Color[3] = m_ClearColor.A();\r\n\r\n    CreateTextureResource(Graphics::g_Device, Name, ResourceDesc, ClearValue, VidMem);\r\n    CreateDerivedViews(Graphics::g_Device, Format, ArrayCount, 1);\r\n}\r\n\r\nvoid ColorBuffer::CreateArray( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t ArrayCount,\r\n    DXGI_FORMAT Format, EsramAllocator& )\r\n{\r\n    CreateArray(Name, Width, Height, ArrayCount, Format);\r\n}\r\n\r\nvoid ColorBuffer::CreatePlaced(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n    DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset)\r\n{\r\n    ConstructPlacedTexture(Name, Width, Height, NumMips, Format, Heap, HeapOffset, true);\r\n}\r\n\r\nvoid ColorBuffer::RecreatePlaced(uint32_t Width, uint32_t Height, uint32_t NumMips, DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset)\r\n{\r\n    ConstructPlacedTexture(L\"\", Width, Height, NumMips, Format, Heap, HeapOffset, false);\r\n}\r\n\r\nvoid ColorBuffer::GenerateMipMaps(CommandContext& BaseContext)\r\n{\r\n    if (m_NumMipMaps == 0)\r\n        return;\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n\r\n    Context.SetRootSignature(Graphics::g_GenerateMipsRS);\r\n\r\n    Context.TransitionResource(*this, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.SetDynamicDescriptor(1, 0, m_SRVHandle);\r\n\r\n    for (uint32_t TopMip = 0; TopMip < m_NumMipMaps; )\r\n    {\r\n        uint32_t SrcWidth = m_Width >> TopMip;\r\n        uint32_t SrcHeight = m_Height >> TopMip;\r\n        uint32_t DstWidth = SrcWidth >> 1;\r\n        uint32_t DstHeight = SrcHeight >> 1;\r\n\r\n        // Determine if the first downsample is more than 2:1.  This happens whenever\r\n        // the source width or height is odd.\r\n        uint32_t NonPowerOfTwo = (SrcWidth & 1) | (SrcHeight & 1) << 1;\r\n        if (m_Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)\r\n            Context.SetPipelineState(Graphics::g_GenerateMipsGammaPSO[NonPowerOfTwo]);\r\n        else\r\n            Context.SetPipelineState(Graphics::g_GenerateMipsLinearPSO[NonPowerOfTwo]);\r\n\r\n        // We can downsample up to four times, but if the ratio between levels is not\r\n        // exactly 2:1, we have to shift our blend weights, which gets complicated or\r\n        // expensive.  Maybe we can update the code later to compute sample weights for\r\n        // each successive downsample.  We use _BitScanForward to count number of zeros\r\n        // in the low bits.  Zeros indicate we can divide by two without truncating.\r\n        uint32_t AdditionalMips;\r\n        _BitScanForward((unsigned long*)&AdditionalMips,\r\n            (DstWidth == 1 ? DstHeight : DstWidth) | (DstHeight == 1 ? DstWidth : DstHeight));\r\n        uint32_t NumMips = 1 + (AdditionalMips > 3 ? 3 : AdditionalMips);\r\n        if (TopMip + NumMips > m_NumMipMaps)\r\n            NumMips = m_NumMipMaps - TopMip;\r\n\r\n        // These are clamped to 1 after computing additional mips because clamped\r\n        // dimensions should not limit us from downsampling multiple times.  (E.g.\r\n        // 16x1 -> 8x1 -> 4x1 -> 2x1 -> 1x1.)\r\n        if (DstWidth == 0)\r\n            DstWidth = 1;\r\n        if (DstHeight == 0)\r\n            DstHeight = 1;\r\n\r\n        Context.SetConstants(0, TopMip, NumMips, 1.0f / DstWidth, 1.0f / DstHeight);\r\n        Context.SetDynamicDescriptors(2, 0, NumMips, m_UAVHandle + TopMip + 1);\r\n        Context.Dispatch2D(DstWidth, DstHeight);\r\n\r\n        Context.InsertUAVBarrier(*this);\r\n\r\n        TopMip += NumMips;\r\n    }\r\n\r\n    Context.TransitionResource(*this, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |\r\n        D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n}\r\n\r\nvoid ColorBuffer::ConstructPlacedTexture(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n    DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset, bool isNew)\r\n{\r\n    NumMips = (NumMips == 0 ? ComputeNumMips(Width, Height) : NumMips);\r\n    D3D12_RESOURCE_FLAGS Flags = CombineResourceFlags();\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeTex2D(Width, Height, 1, NumMips, Format, Flags);\r\n\r\n    ResourceDesc.SampleDesc.Count = m_FragmentCount;\r\n    ResourceDesc.SampleDesc.Quality = 0;\r\n\r\n    D3D12_CLEAR_VALUE ClearValue = {};\r\n    ClearValue.Format = Format;\r\n    ClearValue.Color[0] = m_ClearColor.R();\r\n    ClearValue.Color[1] = m_ClearColor.G();\r\n    ClearValue.Color[2] = m_ClearColor.B();\r\n    ClearValue.Color[3] = m_ClearColor.A();\r\n\r\n    if (isNew)\r\n        CreatePlacedResource(Graphics::g_Device, Name, ResourceDesc, ClearValue, Heap, HeapOffset);\r\n    else\r\n        RecreatePlacedResource(Graphics::g_Device, ResourceDesc, ClearValue, Heap, HeapOffset);\r\n    \r\n    CreateDerivedViews(Graphics::g_Device, Format, 1, NumMips);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ColorBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"PixelBuffer.h\"\r\n#include \"Color.h\"\r\n\r\nclass EsramAllocator;\r\n\r\nclass ColorBuffer : public PixelBuffer\r\n{\r\npublic:\r\n    ColorBuffer( Color ClearColor = Color(0.0f, 0.0f, 0.0f, 0.0f)  )\r\n        : m_ClearColor(ClearColor), m_NumMipMaps(0), m_FragmentCount(1), m_SampleCount(1)\r\n    {\r\n        m_SRVHandle.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_RTVHandle.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        std::memset(m_UAVHandle, 0xFF, sizeof(m_UAVHandle));\r\n    }\r\n\r\n    // Create a color buffer from a swap chain buffer.  Unordered access is restricted.\r\n    void CreateFromSwapChain( const std::wstring& Name, ID3D12Resource* BaseResource );\r\n\r\n    // Create a color buffer.  If an address is supplied, memory will not be allocated.\r\n    // The vmem address allows you to alias buffers (which can be especially useful for\r\n    // reusing ESRAM across a frame.)\r\n    void Create(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n        DXGI_FORMAT Format, D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN);\r\n    \r\n    // Create a color buffer.  Memory will be allocated in ESRAM (on Xbox One).  On Windows,\r\n    // this functions the same as Create() without a video address.\r\n    void Create(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n        DXGI_FORMAT Format, EsramAllocator& Allocator);\r\n\r\n    // Create a color buffer.  If an address is supplied, memory will not be allocated.\r\n    // The vmem address allows you to alias buffers (which can be especially useful for\r\n    // reusing ESRAM across a frame.)\r\n    void CreateArray(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t ArrayCount,\r\n        DXGI_FORMAT Format, D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN);\r\n    \r\n    // Create a color buffer.  Memory will be allocated in ESRAM (on Xbox One).  On Windows,\r\n    // this functions the same as Create() without a video address.\r\n    void CreateArray(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t ArrayCount,\r\n        DXGI_FORMAT Format, EsramAllocator& Allocator);\r\n\r\n    void CreatePlaced(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n        DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset);\r\n\r\n    void RecreatePlaced(uint32_t Width, uint32_t Height, uint32_t NumMips, DXGI_FORMAT Format, \r\n        ID3D12Heap *Heap, UINT64 HeapOffset);\r\n\r\n    // Get pre-created CPU-visible descriptor handles\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetSRV(void) const { return m_SRVHandle; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetRTV(void) const { return m_RTVHandle; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetUAV(void) const { return m_UAVHandle[0]; }\r\n\r\n    void SetClearColor( Color ClearColor ) { m_ClearColor = ClearColor; }\r\n\r\n    void SetMsaaMode( uint32_t NumColorSamples, uint32_t NumCoverageSamples )\r\n    {\r\n        ASSERT(NumCoverageSamples >= NumColorSamples);\r\n        m_FragmentCount = NumColorSamples;\r\n        m_SampleCount = NumCoverageSamples;\r\n    }\r\n\r\n    Color GetClearColor(void) const { return m_ClearColor; }\r\n\r\n    // This will work for all texture sizes, but it's recommended for speed and quality\r\n    // that you use dimensions with powers of two (but not necessarily square.)  Pass\r\n    // 0 for ArrayCount to reserve space for mips at creation time.\r\n    void GenerateMipMaps(CommandContext& Context);\r\n\r\nprotected:\r\n\r\n    D3D12_RESOURCE_FLAGS CombineResourceFlags( void ) const\r\n    {\r\n        D3D12_RESOURCE_FLAGS Flags = D3D12_RESOURCE_FLAG_NONE;\r\n\r\n        if (Flags == D3D12_RESOURCE_FLAG_NONE && m_FragmentCount == 1)\r\n            Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;\r\n\r\n        return D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | Flags;\r\n    }\r\n\r\n    // Compute the number of texture levels needed to reduce to 1x1.  This uses\r\n    // _BitScanReverse to find the highest set bit.  Each dimension reduces by\r\n    // half and truncates bits.  The dimension 256 (0x100) has 9 mip levels, same\r\n    // as the dimension 511 (0x1FF).\r\n    static inline uint32_t ComputeNumMips(uint32_t Width, uint32_t Height)\r\n    {\r\n        uint32_t HighBit;\r\n        _BitScanReverse((unsigned long*)&HighBit, Width | Height);\r\n        return HighBit + 1;\r\n    }\r\n\r\n    void CreateDerivedViews(DX12_DEVICE* Device, DXGI_FORMAT Format, uint32_t ArraySize, uint32_t NumMips = 1);\r\n\r\n    void ConstructPlacedTexture(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumMips,\r\n        DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset, bool isNew);\r\n\r\n    Color m_ClearColor;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_SRVHandle;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_RTVHandle;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_UAVHandle[12];\r\n    uint32_t m_NumMipMaps; // number of texture sublevels\r\n    uint32_t m_FragmentCount;\r\n    uint32_t m_SampleCount;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandAllocatorPool.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"CommandAllocatorPool.h\"\r\n\r\nCommandAllocatorPool::CommandAllocatorPool(D3D12_COMMAND_LIST_TYPE Type) :\r\n    m_cCommandListType(Type),\r\n    m_Device(nullptr)\r\n{\r\n}\r\n\r\nCommandAllocatorPool::~CommandAllocatorPool()\r\n{\r\n    Shutdown();\r\n}\r\n\r\nvoid CommandAllocatorPool::Create(DX12_DEVICE * pDevice)\r\n{\r\n    m_Device = pDevice;\r\n}\r\n\r\nvoid CommandAllocatorPool::Shutdown()\r\n{\r\n    for (size_t i = 0; i < m_AllocatorPool.size(); ++i)\r\n        m_AllocatorPool[i]->Release();\r\n\r\n    m_AllocatorPool.clear();\r\n}\r\n\r\nID3D12CommandAllocator * CommandAllocatorPool::RequestAllocator(uint64_t CompletedFenceValue)\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(m_AllocatorMutex);\r\n\r\n    ID3D12CommandAllocator* pAllocator = nullptr;\r\n\r\n    if (!m_ReadyAllocators.empty())\r\n    {\r\n        std::pair<uint64_t, ID3D12CommandAllocator*>& AllocatorPair = m_ReadyAllocators.front();\r\n\r\n        if (AllocatorPair.first <= CompletedFenceValue)\r\n        {\r\n            pAllocator = AllocatorPair.second;\r\n            ASSERT_SUCCEEDED(pAllocator->Reset());\r\n            m_ReadyAllocators.pop();\r\n        }\r\n    }\r\n\r\n    // If no allocator's were ready to be reused, create a new one\r\n    if (pAllocator == nullptr)\r\n    {\r\n        ASSERT_SUCCEEDED(m_Device->CreateCommandAllocator(m_cCommandListType, MY_IID_PPV_ARGS(&pAllocator)));\r\n        wchar_t AllocatorName[32];\r\n        swprintf(AllocatorName, 32, L\"CommandAllocator %zu\", m_AllocatorPool.size());\r\n        pAllocator->SetName(AllocatorName);\r\n        m_AllocatorPool.push_back(pAllocator);\r\n    }\r\n\r\n    return pAllocator;\r\n}\r\n\r\nvoid CommandAllocatorPool::DiscardAllocator(uint64_t FenceValue, ID3D12CommandAllocator * Allocator)\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(m_AllocatorMutex);\r\n\r\n    // That fence value indicates we are free to reset the allocator\r\n    m_ReadyAllocators.push(std::make_pair(FenceValue, Allocator));\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandAllocatorPool.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\n#include <vector>\r\n#include <queue>\r\n#include <mutex>\r\n#include <stdint.h>\r\n\r\nclass CommandAllocatorPool\r\n{\r\npublic:\r\n    CommandAllocatorPool(D3D12_COMMAND_LIST_TYPE Type);\r\n    ~CommandAllocatorPool();\r\n\r\n    void Create(DX12_DEVICE* pDevice);\r\n    void Shutdown();\r\n\r\n    ID3D12CommandAllocator* RequestAllocator(uint64_t CompletedFenceValue);\r\n    void DiscardAllocator(uint64_t FenceValue, ID3D12CommandAllocator* Allocator);\r\n\r\n    inline size_t Size() { return m_AllocatorPool.size(); }\r\n\r\nprivate:\r\n    const D3D12_COMMAND_LIST_TYPE m_cCommandListType;\r\n\r\n    DX12_DEVICE* m_Device;\r\n    std::vector<ID3D12CommandAllocator*> m_AllocatorPool;\r\n    std::queue<std::pair<uint64_t, ID3D12CommandAllocator*>> m_ReadyAllocators;\r\n    std::mutex m_AllocatorMutex;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandContext.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"CommandContext.h\"\r\n#include \"ColorBuffer.h\"\r\n#include \"DepthBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"DescriptorHeap.h\"\r\n#include \"EngineProfiling.h\"\r\n\r\n#ifndef RELEASE\r\n\t#include <d3d11_2.h>\r\n#ifdef PIX\r\n   #include <pix3.h>\r\n#endif\r\n#endif\r\n\r\nusing namespace Graphics;\r\n\r\n\r\nvoid ContextManager::DestroyAllContexts(void)\r\n{\r\n    for (uint32_t i = 0; i < 4; ++i)\r\n        sm_ContextPool[i].clear();\r\n}\r\n\r\nCommandContext* ContextManager::AllocateContext(D3D12_COMMAND_LIST_TYPE Type)\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(sm_ContextAllocationMutex);\r\n\r\n    auto& AvailableContexts = sm_AvailableContexts[Type];\r\n\r\n    CommandContext* ret = nullptr;\r\n    if (AvailableContexts.empty())\r\n    {\r\n        ret = new CommandContext(Type);\r\n        sm_ContextPool[Type].emplace_back(ret);\r\n        ret->Initialize();\r\n    }\r\n    else\r\n    {\r\n        ret = AvailableContexts.front();\r\n        AvailableContexts.pop();\r\n        ret->Reset();\r\n    }\r\n    ASSERT(ret != nullptr);\r\n\r\n    ASSERT(ret->m_Type == Type);\r\n\r\n    return ret;\r\n}\r\n\r\nvoid ContextManager::FreeContext(CommandContext* UsedContext)\r\n{\r\n    ASSERT(UsedContext != nullptr);\r\n    std::lock_guard<std::mutex> LockGuard(sm_ContextAllocationMutex);\r\n    sm_AvailableContexts[UsedContext->m_Type].push(UsedContext);\r\n}\r\n\r\nvoid CommandContext::DestroyAllContexts(void)\r\n{\r\n    LinearAllocator::DestroyAll();\r\n    DynamicDescriptorHeap::DestroyAll();\r\n    g_ContextManager.DestroyAllContexts();\r\n}\r\n\r\nCommandContext& CommandContext::Begin( const std::wstring ID )\r\n{\r\n    CommandContext* NewContext = g_ContextManager.AllocateContext(D3D12_COMMAND_LIST_TYPE_DIRECT);\r\n    NewContext->SetID(ID);\r\n    if (ID.length() > 0)\r\n        EngineProfiling::BeginBlock(ID, NewContext);\r\n    return *NewContext;\r\n}\r\n\r\nComputeContext& ComputeContext::Begin(const std::wstring& ID, bool Async)\r\n{\r\n    ComputeContext& NewContext = g_ContextManager.AllocateContext(\r\n        Async ? D3D12_COMMAND_LIST_TYPE_COMPUTE : D3D12_COMMAND_LIST_TYPE_DIRECT)->GetComputeContext();\r\n    NewContext.SetID(ID);\r\n    if (ID.length() > 0)\r\n        EngineProfiling::BeginBlock(ID, &NewContext);\r\n    return NewContext;\r\n}\r\n\r\nuint64_t CommandContext::Flush(bool WaitForCompletion)\r\n{\r\n    FlushResourceBarriers();\r\n\r\n    ASSERT(m_CurrentAllocator != nullptr);\r\n\r\n    uint64_t FenceValue = g_CommandManager.GetQueue(m_Type).ExecuteCommandList(m_CommandList);\r\n\r\n    if (WaitForCompletion)\r\n        g_CommandManager.WaitForFence(FenceValue);\r\n\r\n    //\r\n    // Reset the command list and restore previous state\r\n    //\r\n\r\n    m_CommandList->Reset(m_CurrentAllocator, nullptr);\r\n\r\n    if (m_CurGraphicsRootSignature)\r\n    {\r\n        m_CommandList->SetGraphicsRootSignature(m_CurGraphicsRootSignature);\r\n        m_CommandList->SetPipelineState(m_CurGraphicsPipelineState);\r\n    }\r\n    if (m_CurComputeRootSignature)\r\n    {\r\n        m_CommandList->SetComputeRootSignature(m_CurComputeRootSignature);\r\n        m_CommandList->SetPipelineState(m_CurComputePipelineState);\r\n    }\r\n\r\n    BindDescriptorHeaps();\r\n\r\n    return FenceValue;\r\n}\r\n\r\nuint64_t CommandContext::Finish( bool WaitForCompletion )\r\n{\r\n    ASSERT(m_Type == D3D12_COMMAND_LIST_TYPE_DIRECT || m_Type == D3D12_COMMAND_LIST_TYPE_COMPUTE);\r\n\r\n    FlushResourceBarriers();\r\n\r\n    if (m_ID.length() > 0)\r\n        EngineProfiling::EndBlock(this);\r\n\r\n    ASSERT(m_CurrentAllocator != nullptr);\r\n\r\n    CommandQueue& Queue = g_CommandManager.GetQueue(m_Type);\r\n\r\n    uint64_t FenceValue = Queue.ExecuteCommandList(m_CommandList);\r\n    Queue.DiscardAllocator(FenceValue, m_CurrentAllocator);\r\n    m_CurrentAllocator = nullptr;\r\n\r\n    m_CpuLinearAllocator.CleanupUsedPages(FenceValue);\r\n    m_GpuLinearAllocator.CleanupUsedPages(FenceValue);\r\n    m_DynamicViewDescriptorHeap.CleanupUsedHeaps(FenceValue);\r\n    m_DynamicSamplerDescriptorHeap.CleanupUsedHeaps(FenceValue);\r\n\r\n    if (WaitForCompletion)\r\n        g_CommandManager.WaitForFence(FenceValue);\r\n\r\n    g_ContextManager.FreeContext(this);\r\n\r\n    return FenceValue;\r\n}\r\n\r\nCommandContext::CommandContext(D3D12_COMMAND_LIST_TYPE Type) :\r\n    m_Type(Type),\r\n    m_DynamicViewDescriptorHeap(*this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),\r\n    m_DynamicSamplerDescriptorHeap(*this, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),\r\n    m_CpuLinearAllocator(kCpuWritable), \r\n    m_GpuLinearAllocator(kGpuExclusive)\r\n{\r\n    m_OwningManager = nullptr;\r\n    m_CommandList = nullptr;\r\n    m_CurrentAllocator = nullptr;\r\n    ZeroMemory(m_CurrentDescriptorHeaps, sizeof(m_CurrentDescriptorHeaps));\r\n\r\n    m_CurGraphicsRootSignature = nullptr;\r\n    m_CurGraphicsPipelineState = nullptr;\r\n    m_CurComputeRootSignature = nullptr;\r\n    m_CurComputePipelineState = nullptr;\r\n    m_NumBarriersToFlush = 0;\r\n}\r\n\r\nCommandContext::~CommandContext( void )\r\n{\r\n    if (m_CommandList != nullptr)\r\n        m_CommandList->Release();\r\n}\r\n\r\nvoid CommandContext::Initialize(void)\r\n{\r\n    g_CommandManager.CreateNewCommandList(m_Type, &m_CommandList, &m_CurrentAllocator);\r\n}\r\n\r\nvoid CommandContext::Reset( void )\r\n{\r\n    // We only call Reset() on previously freed contexts.  The command list persists, but we must\r\n    // request a new allocator.\r\n    ASSERT(m_CommandList != nullptr && m_CurrentAllocator == nullptr);\r\n    m_CurrentAllocator = g_CommandManager.GetQueue(m_Type).RequestAllocator();\r\n    m_CommandList->Reset(m_CurrentAllocator, nullptr);\r\n\r\n    m_CurGraphicsRootSignature = nullptr;\r\n    m_CurGraphicsPipelineState = nullptr;\r\n    m_CurComputeRootSignature = nullptr;\r\n    m_CurComputePipelineState = nullptr;\r\n    m_NumBarriersToFlush = 0;\r\n\r\n    BindDescriptorHeaps();\r\n}\r\n\r\nvoid CommandContext::BindDescriptorHeaps( void )\r\n{\r\n    UINT NonNullHeaps = 0;\r\n    ID3D12DescriptorHeap* HeapsToBind[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];\r\n    for (UINT i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++i)\r\n    {\r\n        ID3D12DescriptorHeap* HeapIter = m_CurrentDescriptorHeaps[i];\r\n        if (HeapIter != nullptr)\r\n            HeapsToBind[NonNullHeaps++] = HeapIter;\r\n    }\r\n\r\n    if (NonNullHeaps > 0)\r\n        m_CommandList->SetDescriptorHeaps(NonNullHeaps, HeapsToBind);\r\n}\r\n\r\nvoid GraphicsContext::SetRenderTargets( UINT NumRTVs, const D3D12_CPU_DESCRIPTOR_HANDLE RTVs[], D3D12_CPU_DESCRIPTOR_HANDLE DSV )\r\n{\r\n    m_CommandList->OMSetRenderTargets( NumRTVs, RTVs, FALSE, &DSV );\r\n}\r\n\r\nvoid GraphicsContext::SetRenderTargets(UINT NumRTVs, const D3D12_CPU_DESCRIPTOR_HANDLE RTVs[])\r\n{\r\n    m_CommandList->OMSetRenderTargets(NumRTVs, RTVs, FALSE, nullptr);\r\n}\r\n\r\nvoid GraphicsContext::BeginQuery(ID3D12QueryHeap* QueryHeap, D3D12_QUERY_TYPE Type, UINT HeapIndex)\r\n{\r\n    m_CommandList->BeginQuery(QueryHeap, Type, HeapIndex);\r\n}\r\n\r\nvoid GraphicsContext::EndQuery(ID3D12QueryHeap* QueryHeap, D3D12_QUERY_TYPE Type, UINT HeapIndex)\r\n{\r\n    m_CommandList->EndQuery(QueryHeap, Type, HeapIndex);\r\n}\r\n\r\nvoid GraphicsContext::ResolveQueryData(ID3D12QueryHeap* QueryHeap, D3D12_QUERY_TYPE Type, UINT StartIndex, UINT NumQueries, ID3D12Resource* DestinationBuffer, UINT64 DestinationBufferOffset)\r\n{\r\n    m_CommandList->ResolveQueryData(QueryHeap, Type, StartIndex, NumQueries, DestinationBuffer, DestinationBufferOffset);\r\n}\r\n\r\nvoid GraphicsContext::ClearUAV( GpuBuffer& Target )\r\n{\r\n    // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs\r\n    // a shader to set all of the values).\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = m_DynamicViewDescriptorHeap.UploadDirect(Target.GetUAV());\r\n    const UINT ClearColor[4] = {};\r\n    m_CommandList->ClearUnorderedAccessViewUint(GpuVisibleHandle, Target.GetUAV(), Target.GetResource(), ClearColor, 0, nullptr);\r\n}\r\n\r\nvoid ComputeContext::ClearUAV( GpuBuffer& Target )\r\n{\r\n    // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs\r\n    // a shader to set all of the values).\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = m_DynamicViewDescriptorHeap.UploadDirect(Target.GetUAV());\r\n    const UINT ClearColor[4] = {};\r\n    m_CommandList->ClearUnorderedAccessViewUint(GpuVisibleHandle, Target.GetUAV(), Target.GetResource(), ClearColor, 0, nullptr);\r\n}\r\n\r\nvoid GraphicsContext::ClearUAV( ColorBuffer& Target )\r\n{\r\n    // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs\r\n    // a shader to set all of the values).\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = m_DynamicViewDescriptorHeap.UploadDirect(Target.GetUAV());\r\n    CD3DX12_RECT ClearRect(0, 0, (LONG)Target.GetWidth(), (LONG)Target.GetHeight());\r\n\r\n    //TODO: My Nvidia card is not clearing UAVs with either Float or Uint variants.\r\n    const float* ClearColor = Target.GetClearColor().GetPtr();\r\n    m_CommandList->ClearUnorderedAccessViewFloat(GpuVisibleHandle, Target.GetUAV(), Target.GetResource(), ClearColor, 1, &ClearRect);\r\n}\r\n\r\nvoid ComputeContext::ClearUAV( ColorBuffer& Target )\r\n{\r\n    // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs\r\n    // a shader to set all of the values).\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = m_DynamicViewDescriptorHeap.UploadDirect(Target.GetUAV());\r\n    CD3DX12_RECT ClearRect(0, 0, (LONG)Target.GetWidth(), (LONG)Target.GetHeight());\r\n\r\n    //TODO: My Nvidia card is not clearing UAVs with either Float or Uint variants.\r\n    const float* ClearColor = Target.GetClearColor().GetPtr();\r\n    m_CommandList->ClearUnorderedAccessViewFloat(GpuVisibleHandle, Target.GetUAV(), Target.GetResource(), ClearColor, 1, &ClearRect);\r\n}\r\n\r\nvoid GraphicsContext::ClearColor( ColorBuffer& Target )\r\n{\r\n    m_CommandList->ClearRenderTargetView(Target.GetRTV(), Target.GetClearColor().GetPtr(), 0, nullptr);\r\n}\r\n\r\nvoid GraphicsContext::ClearDepth( DepthBuffer& Target )\r\n{\r\n    m_CommandList->ClearDepthStencilView(Target.GetDSV(), D3D12_CLEAR_FLAG_DEPTH, Target.GetClearDepth(), Target.GetClearStencil(), 0, nullptr );\r\n}\r\n\r\nvoid GraphicsContext::ClearStencil( DepthBuffer& Target )\r\n{\r\n    m_CommandList->ClearDepthStencilView(Target.GetDSV(), D3D12_CLEAR_FLAG_STENCIL, Target.GetClearDepth(), Target.GetClearStencil(), 0, nullptr);\r\n}\r\n\r\nvoid GraphicsContext::ClearDepthAndStencil( DepthBuffer& Target )\r\n{\r\n    m_CommandList->ClearDepthStencilView(Target.GetDSV(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, Target.GetClearDepth(), Target.GetClearStencil(), 0, nullptr);\r\n}\r\n\r\nvoid GraphicsContext::SetViewportAndScissor( const D3D12_VIEWPORT& vp, const D3D12_RECT& rect )\r\n{\r\n    ASSERT(rect.left < rect.right && rect.top < rect.bottom);\r\n    m_CommandList->RSSetViewports( 1, &vp );\r\n    m_CommandList->RSSetScissorRects( 1, &rect );\r\n}\r\n\r\nvoid GraphicsContext::SetViewport( const D3D12_VIEWPORT& vp )\r\n{\r\n    m_CommandList->RSSetViewports( 1, &vp );\r\n}\r\n\r\nvoid GraphicsContext::SetViewport( FLOAT x, FLOAT y, FLOAT w, FLOAT h, FLOAT minDepth, FLOAT maxDepth )\r\n{\r\n    D3D12_VIEWPORT vp;\r\n    vp.Width = w;\r\n    vp.Height = h;\r\n    vp.MinDepth = minDepth;\r\n    vp.MaxDepth = maxDepth;\r\n    vp.TopLeftX = x;\r\n    vp.TopLeftY = y;\r\n    m_CommandList->RSSetViewports( 1, &vp );\r\n}\r\n\r\nvoid GraphicsContext::SetScissor( const D3D12_RECT& rect )\r\n{\r\n    ASSERT(rect.left < rect.right && rect.top < rect.bottom);\r\n    m_CommandList->RSSetScissorRects( 1, &rect );\r\n}\r\n\r\nvoid CommandContext::TransitionResource(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate)\r\n{\r\n    D3D12_RESOURCE_STATES OldState = Resource.m_UsageState;\r\n\r\n    if (m_Type == D3D12_COMMAND_LIST_TYPE_COMPUTE)\r\n    {\r\n        ASSERT((OldState & VALID_COMPUTE_QUEUE_RESOURCE_STATES) == OldState);\r\n        ASSERT((NewState & VALID_COMPUTE_QUEUE_RESOURCE_STATES) == NewState);\r\n    }\r\n\r\n    if (OldState != NewState)\r\n    {\r\n        ASSERT(m_NumBarriersToFlush < 16, \"Exceeded arbitrary limit on buffered barriers\");\r\n        D3D12_RESOURCE_BARRIER& BarrierDesc = m_ResourceBarrierBuffer[m_NumBarriersToFlush++];\r\n\r\n        BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        BarrierDesc.Transition.pResource = Resource.GetResource();\r\n        BarrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;\r\n        BarrierDesc.Transition.StateBefore = OldState;\r\n        BarrierDesc.Transition.StateAfter = NewState;\r\n\r\n        // Check to see if we already started the transition\r\n        if (NewState == Resource.m_TransitioningState)\r\n        {\r\n            BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_END_ONLY;\r\n            Resource.m_TransitioningState = (D3D12_RESOURCE_STATES)-1;\r\n        }\r\n        else\r\n            BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;\r\n\r\n        Resource.m_UsageState = NewState;\r\n    }\r\n    else if (NewState == D3D12_RESOURCE_STATE_UNORDERED_ACCESS)\r\n        InsertUAVBarrier(Resource, FlushImmediate);\r\n\r\n    if (FlushImmediate || m_NumBarriersToFlush == 16)\r\n        FlushResourceBarriers();\r\n}\r\n\r\nvoid CommandContext::BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate)\r\n{\r\n    // If it's already transitioning, finish that transition\r\n    if (Resource.m_TransitioningState != (D3D12_RESOURCE_STATES)-1)\r\n        TransitionResource(Resource, Resource.m_TransitioningState);\r\n\r\n    D3D12_RESOURCE_STATES OldState = Resource.m_UsageState;\r\n\r\n    if (OldState != NewState)\r\n    {\r\n        ASSERT(m_NumBarriersToFlush < 16, \"Exceeded arbitrary limit on buffered barriers\");\r\n        D3D12_RESOURCE_BARRIER& BarrierDesc = m_ResourceBarrierBuffer[m_NumBarriersToFlush++];\r\n\r\n        BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        BarrierDesc.Transition.pResource = Resource.GetResource();\r\n        BarrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;\r\n        BarrierDesc.Transition.StateBefore = OldState;\r\n        BarrierDesc.Transition.StateAfter = NewState;\r\n\r\n        BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY;\r\n\r\n        Resource.m_TransitioningState = NewState;\r\n    }\r\n\r\n    if (FlushImmediate || m_NumBarriersToFlush == 16)\r\n        FlushResourceBarriers();\r\n}\r\n\r\nvoid CommandContext::InsertUAVBarrier(GpuResource& Resource, bool FlushImmediate)\r\n{\r\n    ASSERT(m_NumBarriersToFlush < 16, \"Exceeded arbitrary limit on buffered barriers\");\r\n    D3D12_RESOURCE_BARRIER& BarrierDesc = m_ResourceBarrierBuffer[m_NumBarriersToFlush++];\r\n\r\n    BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n    BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;\r\n    BarrierDesc.UAV.pResource = Resource.GetResource();\r\n\r\n    if (FlushImmediate)\r\n        FlushResourceBarriers();\r\n}\r\n\r\nvoid CommandContext::InsertAliasBarrier(GpuResource& Before, GpuResource& After, bool FlushImmediate)\r\n{\r\n    ASSERT(m_NumBarriersToFlush < 16, \"Exceeded arbitrary limit on buffered barriers\");\r\n    D3D12_RESOURCE_BARRIER& BarrierDesc = m_ResourceBarrierBuffer[m_NumBarriersToFlush++];\r\n\r\n    BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n    BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;\r\n    BarrierDesc.Aliasing.pResourceBefore = Before.GetResource();\r\n    BarrierDesc.Aliasing.pResourceAfter = After.GetResource();\r\n\r\n    if (FlushImmediate)\r\n        FlushResourceBarriers();\r\n}\r\n\r\nvoid CommandContext::WriteBuffer( GpuResource& Dest, size_t DestOffset, const void* BufferData, size_t NumBytes )\r\n{\r\n    ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));\r\n    DynAlloc TempSpace = m_CpuLinearAllocator.Allocate( NumBytes, 512 );\r\n    SIMDMemCopy(TempSpace.DataPtr, BufferData, Math::DivideByMultiple(NumBytes, 16));\r\n    CopyBufferRegion(Dest, DestOffset, TempSpace.Buffer, TempSpace.Offset, NumBytes );\r\n}\r\n\r\nvoid CommandContext::FillBuffer( GpuResource& Dest, size_t DestOffset, DWParam Value, size_t NumBytes )\r\n{\r\n    DynAlloc TempSpace = m_CpuLinearAllocator.Allocate( NumBytes, 512 );\r\n    __m128 VectorValue = _mm_set1_ps(Value.Float);\r\n    SIMDMemFill(TempSpace.DataPtr, VectorValue, Math::DivideByMultiple(NumBytes, 16));\r\n    CopyBufferRegion(Dest, DestOffset, TempSpace.Buffer, TempSpace.Offset, NumBytes );\r\n}\r\n\r\nvoid CommandContext::InitializeTexture( GpuResource& Dest, UINT NumSubresources, D3D12_SUBRESOURCE_DATA SubData[] )\r\n{\r\n    UINT64 uploadBufferSize = GetRequiredIntermediateSize(Dest.GetResource(), 0, NumSubresources);\r\n\r\n    CommandContext& InitContext = CommandContext::Begin();\r\n\r\n    // copy data to the intermediate upload heap and then schedule a copy from the upload heap to the default texture\r\n    DynAlloc mem = InitContext.ReserveUploadMemory(uploadBufferSize);\r\n    UpdateSubresources(InitContext.m_CommandList, Dest.GetResource(), mem.Buffer.GetResource(), 0, 0, NumSubresources, SubData);\r\n    InitContext.TransitionResource(Dest, D3D12_RESOURCE_STATE_GENERIC_READ);\r\n\r\n    // Execute the command list and wait for it to finish so we can release the upload buffer\r\n    InitContext.Finish(true);\r\n}\r\n\r\nvoid CommandContext::CopySubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex)\r\n{\r\n    FlushResourceBarriers();\r\n\r\n    D3D12_TEXTURE_COPY_LOCATION DestLocation =\r\n    {\r\n        Dest.GetResource(),\r\n        D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,\r\n        DestSubIndex\r\n    };\r\n\r\n    D3D12_TEXTURE_COPY_LOCATION SrcLocation =\r\n    {\r\n        Src.GetResource(),\r\n        D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,\r\n        SrcSubIndex\r\n    };\r\n\r\n    m_CommandList->CopyTextureRegion(&DestLocation, 0, 0, 0, &SrcLocation, nullptr);\r\n}\r\n\r\nvoid CommandContext::ResolveSubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex, DXGI_FORMAT Format)\r\n{\r\n\tFlushResourceBarriers();\r\n\tm_CommandList->ResolveSubresource(Dest.GetResource(), DestSubIndex, Src.GetResource(), SrcSubIndex, Format);\r\n}\r\n\r\nvoid CommandContext::InitializeTextureArraySlice(GpuResource& Dest, UINT SliceIndex, GpuResource& Src)\r\n{\r\n    CommandContext& Context = CommandContext::Begin();\r\n\r\n    Context.TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);\r\n    Context.FlushResourceBarriers();\r\n\r\n    const D3D12_RESOURCE_DESC& DestDesc = Dest.GetResource()->GetDesc();\r\n    const D3D12_RESOURCE_DESC& SrcDesc = Src.GetResource()->GetDesc();\r\n\r\n    ASSERT(SliceIndex < DestDesc.DepthOrArraySize &&\r\n        SrcDesc.DepthOrArraySize == 1 &&\r\n        DestDesc.Width == SrcDesc.Width &&\r\n        DestDesc.Height == SrcDesc.Height &&\r\n        DestDesc.MipLevels <= SrcDesc.MipLevels\r\n        );\r\n\r\n    UINT SubResourceIndex = SliceIndex * DestDesc.MipLevels;\r\n\r\n    for (UINT i = 0; i < DestDesc.MipLevels; ++i)\r\n    {\r\n        D3D12_TEXTURE_COPY_LOCATION destCopyLocation =\r\n        {\r\n            Dest.GetResource(),\r\n            D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,\r\n            SubResourceIndex + i\r\n        };\r\n\r\n        D3D12_TEXTURE_COPY_LOCATION srcCopyLocation =\r\n        {\r\n            Src.GetResource(),\r\n            D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,\r\n            i\r\n        };\r\n\r\n        Context.m_CommandList->CopyTextureRegion(&destCopyLocation, 0, 0, 0, &srcCopyLocation, nullptr);\r\n    }\r\n\r\n    Context.TransitionResource(Dest, D3D12_RESOURCE_STATE_GENERIC_READ);\r\n    Context.Finish(true);\r\n}\r\n\r\nvoid CommandContext::ReadbackTexture2D(GpuResource& ReadbackBuffer, PixelBuffer& SrcBuffer)\r\n{\r\n    // The footprint may depend on the device of the resource, but we assume there is only one device.\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT PlacedFootprint;\r\n    g_Device->GetCopyableFootprints(&SrcBuffer.GetResource()->GetDesc(), 0, 1, 0, &PlacedFootprint, nullptr, nullptr, nullptr);\r\n\r\n    // This very short command list only issues one API call and will be synchronized so we can immediately read\r\n    // the buffer contents.\r\n    CommandContext& Context = CommandContext::Begin(L\"Copy texture to memory\");\r\n\r\n    Context.TransitionResource(SrcBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, true);\r\n\r\n    Context.m_CommandList->CopyTextureRegion(\r\n        &CD3DX12_TEXTURE_COPY_LOCATION(ReadbackBuffer.GetResource(), PlacedFootprint), 0, 0, 0,\r\n        &CD3DX12_TEXTURE_COPY_LOCATION(SrcBuffer.GetResource(), 0), nullptr);\r\n\r\n    Context.Finish(true);\r\n}\r\n\r\nvoid CommandContext::InitializeBuffer( GpuResource& Dest, const void* BufferData, size_t NumBytes, size_t Offset)\r\n{\r\n    CommandContext& InitContext = CommandContext::Begin();\r\n\r\n    DynAlloc mem = InitContext.ReserveUploadMemory(NumBytes);\r\n    SIMDMemCopy(mem.DataPtr, BufferData, Math::DivideByMultiple(NumBytes, 16));\r\n\r\n    // copy data to the intermediate upload heap and then schedule a copy from the upload heap to the default texture\r\n    InitContext.TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST, true);\r\n    InitContext.m_CommandList->CopyBufferRegion(Dest.GetResource(), Offset, mem.Buffer.GetResource(), 0, NumBytes);\r\n    InitContext.TransitionResource(Dest, D3D12_RESOURCE_STATE_GENERIC_READ, true);\r\n\r\n    // Execute the command list and wait for it to finish so we can release the upload buffer\r\n    InitContext.Finish(true);\r\n}\r\n\r\nvoid CommandContext::PIXBeginEvent(const wchar_t* label)\r\n{\r\n#ifdef PIX\r\n   ::PIXBeginEvent(m_CommandList, 0, label);\r\n#else\r\n   (label);\r\n#endif\r\n}\r\n\r\nvoid CommandContext::PIXEndEvent(void)\r\n{\r\n#ifdef PIX\r\n\t::PIXEndEvent(m_CommandList);\r\n#endif\r\n}\r\n\r\nvoid CommandContext::PIXSetMarker(const wchar_t* label)\r\n{\r\n#ifdef PIX\r\n   ::PIXSetMarker(m_CommandList, 0, label);\r\n#else\r\n   (label);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandContext.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"ART\\Wddm22Defs.h\"\r\n#include \"pch.h\"\r\n#include \"CommandListManager.h\"\r\n#include \"Color.h\"\r\n#include \"PipelineState.h\"\r\n#include \"RootSignature.h\"\r\n#include \"GpuBuffer.h\"\r\n#include \"TextureManager.h\"\r\n#include \"PixelBuffer.h\"\r\n#include \"DynamicDescriptorHeap.h\"\r\n#include \"LinearAllocator.h\"\r\n#include \"CommandSignature.h\"\r\n#include \"GraphicsCore.h\"\r\n#include <vector>\r\n\r\nclass ColorBuffer;\r\nclass DepthBuffer;\r\nclass Texture;\r\nclass GraphicsContext;\r\nclass ComputeContext;\r\n\r\nstruct DWParam\r\n{\r\n    DWParam( FLOAT f ) : Float(f) {}\r\n    DWParam( UINT u ) : Uint(u) {}\r\n    DWParam( INT i ) : Int(i) {}\r\n\r\n    void operator= ( FLOAT f ) { Float = f; }\r\n    void operator= ( UINT u ) { Uint = u; }\r\n    void operator= ( INT i ) { Int = i; }\r\n\r\n    union\r\n    {\r\n        FLOAT Float;\r\n        UINT Uint;\r\n        INT Int;\r\n    };\r\n};\r\n\r\n#define VALID_COMPUTE_QUEUE_RESOURCE_STATES \\\r\n    ( D3D12_RESOURCE_STATE_UNORDERED_ACCESS \\\r\n    | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE \\\r\n    | D3D12_RESOURCE_STATE_COPY_DEST \\\r\n    | D3D12_RESOURCE_STATE_COPY_SOURCE )\r\n\r\nclass ContextManager\r\n{\r\npublic:\r\n    ContextManager(void) {}\r\n\r\n    CommandContext* AllocateContext(D3D12_COMMAND_LIST_TYPE Type);\r\n    void FreeContext(CommandContext*);\r\n    void DestroyAllContexts();\r\n\r\nprivate:\r\n    std::vector<std::unique_ptr<CommandContext> > sm_ContextPool[4];\r\n    std::queue<CommandContext*> sm_AvailableContexts[4];\r\n    std::mutex sm_ContextAllocationMutex;\r\n};\r\n\r\nstruct NonCopyable\r\n{\r\n    NonCopyable() = default;\r\n    NonCopyable(const NonCopyable&) = delete;\r\n    NonCopyable & operator=(const NonCopyable&) = delete;\r\n};\r\n\r\nclass CommandContext : NonCopyable\r\n{\r\n    friend ContextManager;\r\nprivate:\r\n\r\n    CommandContext(D3D12_COMMAND_LIST_TYPE Type);\r\n\r\n    void Reset( void );\r\n\r\npublic:\r\n\r\n    ~CommandContext(void);\r\n\r\n    static void DestroyAllContexts(void);\r\n\r\n    static CommandContext& Begin(const std::wstring ID = L\"\");\r\n\r\n    // Flush existing commands to the GPU but keep the context alive\r\n    uint64_t Flush( bool WaitForCompletion = false );\r\n\r\n    // Flush existing commands and release the current context\r\n    uint64_t Finish( bool WaitForCompletion = false );\r\n\r\n    // Prepare to render by reserving a command list and command allocator\r\n    void Initialize(void);\r\n\r\n    GraphicsContext& GetGraphicsContext() {\r\n        ASSERT(m_Type != D3D12_COMMAND_LIST_TYPE_COMPUTE, \"Cannot convert async compute context to graphics\");\r\n        return reinterpret_cast<GraphicsContext&>(*this);\r\n    }\r\n\r\n    ComputeContext& GetComputeContext() {\r\n        return reinterpret_cast<ComputeContext&>(*this);\r\n    }\r\n\r\n    DX12_GRAPHICSCOMMANDLIST* GetCommandList() {\r\n        return m_CommandList;\r\n    }\r\n\r\n    void CopyBuffer( GpuResource& Dest, GpuResource& Src );\r\n    void CopyBufferRegion( GpuResource& Dest, size_t DestOffset, GpuResource& Src, size_t SrcOffset, size_t NumBytes );\r\n    void CopySubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex);\r\n\tvoid ResolveSubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex, DXGI_FORMAT Format);\r\n    void CopyCounter(GpuResource& Dest, size_t DestOffset, StructuredBuffer& Src);\r\n    void ResetCounter(StructuredBuffer& Buf, uint32_t Value = 0);\r\n\r\n    DynAlloc ReserveUploadMemory(size_t SizeInBytes)\r\n    {\r\n        return m_CpuLinearAllocator.Allocate(SizeInBytes);\r\n    }\r\n\r\n    static void InitializeTexture( GpuResource& Dest, UINT NumSubresources, D3D12_SUBRESOURCE_DATA SubData[] );\r\n    static void InitializeBuffer( GpuResource& Dest, const void* Data, size_t NumBytes, size_t Offset = 0);\r\n    static void InitializeTextureArraySlice(GpuResource& Dest, UINT SliceIndex, GpuResource& Src);\r\n    static void ReadbackTexture2D(GpuResource& ReadbackBuffer, PixelBuffer& SrcBuffer);\r\n\r\n    void WriteBuffer( GpuResource& Dest, size_t DestOffset, const void* Data, size_t NumBytes );\r\n    void FillBuffer( GpuResource& Dest, size_t DestOffset, DWParam Value, size_t NumBytes );\r\n\r\n    void TransitionResource(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);\r\n    void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);\r\n    void InsertUAVBarrier(GpuResource& Resource, bool FlushImmediate = false);\r\n    void InsertAliasBarrier(GpuResource& Before, GpuResource& After, bool FlushImmediate = false);\r\n    inline void FlushResourceBarriers(void);\r\n\r\n    void InsertTimeStamp( ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx );\r\n    void ResolveTimeStamps( ID3D12Resource* pReadbackHeap, ID3D12QueryHeap* pQueryHeap, uint32_t NumQueries );\r\n\t\r\n\tvoid BeginPipelineQuery(ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx);\r\n\tvoid EndPipelineQuery(ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx);\r\n\tvoid ResolvePipelineQueries(ID3D12Resource* pReadbackHeap, ID3D12QueryHeap* pQueryHeap, uint32_t NumQueries);\r\n\r\n\tvoid PIXBeginEvent(const wchar_t* label);\r\n    void PIXEndEvent(void);\r\n    void PIXSetMarker(const wchar_t* label);\r\n\r\n    void SetDescriptorHeap( D3D12_DESCRIPTOR_HEAP_TYPE Type, ID3D12DescriptorHeap* HeapPtr );\r\n    void SetDescriptorHeaps( UINT HeapCount, D3D12_DESCRIPTOR_HEAP_TYPE Type[], ID3D12DescriptorHeap* HeapPtrs[] );\r\n\r\n    void SetPredication(ID3D12Resource* Buffer, UINT64 BufferOffset, D3D12_PREDICATION_OP Op);\r\n\r\nprotected:\r\n\r\n    void BindDescriptorHeaps( void );\r\n\r\n    CommandListManager* m_OwningManager;\r\n    DX12_GRAPHICSCOMMANDLIST* m_CommandList;\r\n    ID3D12CommandAllocator* m_CurrentAllocator;\r\n\r\n    ID3D12RootSignature* m_CurGraphicsRootSignature;\r\n    ID3D12PipelineState* m_CurGraphicsPipelineState;\r\n    ID3D12RootSignature* m_CurComputeRootSignature;\r\n    ID3D12PipelineState* m_CurComputePipelineState;\r\n\r\n    DynamicDescriptorHeap m_DynamicViewDescriptorHeap;\t\t// HEAP_TYPE_CBV_SRV_UAV\r\n    DynamicDescriptorHeap m_DynamicSamplerDescriptorHeap;\t// HEAP_TYPE_SAMPLER\r\n\r\n    D3D12_RESOURCE_BARRIER m_ResourceBarrierBuffer[16];\r\n    UINT m_NumBarriersToFlush;\r\n\r\n    ID3D12DescriptorHeap* m_CurrentDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];\r\n\r\n    LinearAllocator m_CpuLinearAllocator;\r\n    LinearAllocator m_GpuLinearAllocator;\r\n\r\n    std::wstring m_ID;\r\n    void SetID(const std::wstring& ID) { m_ID = ID; }\r\n\r\n    D3D12_COMMAND_LIST_TYPE m_Type;\r\n};\r\n\r\nclass GraphicsContext : public CommandContext\r\n{\r\npublic:\r\n\r\n    static GraphicsContext& Begin(const std::wstring& ID = L\"\")\r\n    {\r\n        return CommandContext::Begin(ID).GetGraphicsContext();\r\n    }\r\n\r\n    void ClearUAV( GpuBuffer& Target );\r\n    void ClearUAV( ColorBuffer& Target );\r\n    void ClearColor( ColorBuffer& Target );\r\n    void ClearDepth( DepthBuffer& Target );\r\n    void ClearStencil( DepthBuffer& Target );\r\n    void ClearDepthAndStencil( DepthBuffer& Target );\r\n\r\n    void BeginQuery(ID3D12QueryHeap* QueryHeap, D3D12_QUERY_TYPE Type, UINT HeapIndex);\r\n    void EndQuery(ID3D12QueryHeap* QueryHeap, D3D12_QUERY_TYPE Type, UINT HeapIndex);\r\n    void ResolveQueryData(ID3D12QueryHeap* QueryHeap, D3D12_QUERY_TYPE Type, UINT StartIndex, UINT NumQueries, ID3D12Resource* DestinationBuffer, UINT64 DestinationBufferOffset);\r\n\r\n    void SetRootSignature( const RootSignature& RootSig );\r\n\r\n    void SetRenderTargets(UINT NumRTVs, const D3D12_CPU_DESCRIPTOR_HANDLE RTVs[]);\r\n    void SetRenderTargets(UINT NumRTVs, const D3D12_CPU_DESCRIPTOR_HANDLE RTVs[], D3D12_CPU_DESCRIPTOR_HANDLE DSV);\r\n    void SetRenderTarget(D3D12_CPU_DESCRIPTOR_HANDLE RTV ) { SetRenderTargets(1, &RTV); }\r\n    void SetRenderTarget(D3D12_CPU_DESCRIPTOR_HANDLE RTV, D3D12_CPU_DESCRIPTOR_HANDLE DSV ) { SetRenderTargets(1, &RTV, DSV); }\r\n    void SetDepthStencilTarget(D3D12_CPU_DESCRIPTOR_HANDLE DSV ) { SetRenderTargets(0, nullptr, DSV); }\r\n\r\n    void SetViewport( const D3D12_VIEWPORT& vp );\r\n    void SetViewport( FLOAT x, FLOAT y, FLOAT w, FLOAT h, FLOAT minDepth = 0.0f, FLOAT maxDepth = 1.0f );\r\n    void SetScissor( const D3D12_RECT& rect );\r\n    void SetScissor( UINT left, UINT top, UINT right, UINT bottom );\r\n    void SetViewportAndScissor( const D3D12_VIEWPORT& vp, const D3D12_RECT& rect );\r\n    void SetViewportAndScissor( UINT x, UINT y, UINT w, UINT h );\r\n    void SetStencilRef( UINT StencilRef );\r\n    void SetBlendFactor( Color BlendFactor );\r\n    void SetPrimitiveTopology( D3D12_PRIMITIVE_TOPOLOGY Topology );\r\n\r\n    void SetPipelineState( const GraphicsPSO& PSO );\r\n    void SetConstantArray( UINT RootIndex, UINT NumConstants, const void* pConstants );\r\n    void SetConstant( UINT RootIndex, DWParam Val, UINT Offset = 0 );\r\n    void SetConstants( UINT RootIndex, DWParam X );\r\n    void SetConstants( UINT RootIndex, DWParam X, DWParam Y );\r\n    void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z );\r\n    void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W );\r\n    void SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV );\r\n    void SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData );\r\n    void SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV, UINT64 Offset = 0);\r\n    void SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV, UINT64 Offset = 0);\r\n    void SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle );\r\n\r\n    void SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle );\r\n    void SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );\r\n    void SetDynamicSampler( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle );\r\n    void SetDynamicSamplers( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );\r\n\r\n    void SetIndexBuffer( const D3D12_INDEX_BUFFER_VIEW& IBView );\r\n    void SetVertexBuffer( UINT Slot, const D3D12_VERTEX_BUFFER_VIEW& VBView );\r\n    void SetVertexBuffers( UINT StartSlot, UINT Count, const D3D12_VERTEX_BUFFER_VIEW VBViews[] );\r\n    void SetDynamicVB( UINT Slot, size_t NumVertices, size_t VertexStride, const void* VBData );\r\n    void SetDynamicIB( size_t IndexCount, const uint16_t* IBData );\r\n    void SetDynamicSRV(UINT RootIndex, size_t BufferSize, const void* BufferData);\r\n\r\n    void Draw( UINT VertexCount, UINT VertexStartOffset = 0 );\r\n    void DrawIndexed(UINT IndexCount, UINT StartIndexLocation = 0, INT BaseVertexLocation = 0);\r\n    void DrawInstanced(UINT VertexCountPerInstance, UINT InstanceCount,\r\n        UINT StartVertexLocation = 0, UINT StartInstanceLocation = 0);\r\n    void DrawIndexedInstanced(UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation,\r\n        INT BaseVertexLocation, UINT StartInstanceLocation);\r\n    void DrawIndirect( GpuBuffer& ArgumentBuffer, uint64_t ArgumentBufferOffset = 0 );\r\n    void ExecuteIndirect(CommandSignature& CommandSig, GpuBuffer& ArgumentBuffer, uint64_t ArgumentStartOffset = 0,\r\n        uint32_t MaxCommands = 1, GpuBuffer* CommandCounterBuffer = nullptr, uint64_t CounterOffset = 0);\r\n\r\n\tvoid SetSamplePositions(UINT NumSamplesPerPixel, UINT NumPixels, D3D12_SAMPLE_POSITION *pSamplePositions);\r\n\r\nprivate:\r\n};\r\n\r\nclass ComputeContext : public CommandContext\r\n{\r\npublic:\r\n\r\n    static ComputeContext& Begin(const std::wstring& ID = L\"\", bool Async = false);\r\n\r\n    void ClearUAV( GpuBuffer& Target );\r\n    void ClearUAV( ColorBuffer& Target );\r\n\r\n    void SetRootSignature( const RootSignature& RootSig );\r\n\r\n    void SetPipelineState( const ComputePSO& PSO );\r\n    void SetConstantArray( UINT RootIndex, UINT NumConstants, const void* pConstants );\r\n    void SetConstant( UINT RootIndex, DWParam Val, UINT Offset = 0 );\r\n    void SetConstants( UINT RootIndex, DWParam X );\r\n    void SetConstants( UINT RootIndex, DWParam X, DWParam Y );\r\n    void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z );\r\n    void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W );\r\n    void SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV );\r\n    void SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData );\r\n    void SetDynamicSRV( UINT RootIndex, size_t BufferSize, const void* BufferData ); \r\n    void SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV, UINT64 Offset = 0);\r\n    void SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV, UINT64 Offset = 0);\r\n    void SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle );\r\n\r\n    void SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle );\r\n    void SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );\r\n    void SetDynamicSampler( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle );\r\n    void SetDynamicSamplers( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );\r\n\r\n    void Dispatch( size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1 );\r\n    void Dispatch1D( size_t ThreadCountX, size_t GroupSizeX = 64);\r\n    void Dispatch2D( size_t ThreadCountX, size_t ThreadCountY, size_t GroupSizeX = 8, size_t GroupSizeY = 8);\r\n    void Dispatch3D( size_t ThreadCountX, size_t ThreadCountY, size_t ThreadCountZ, size_t GroupSizeX, size_t GroupSizeY, size_t GroupSizeZ );\r\n    void DispatchIndirect( GpuBuffer& ArgumentBuffer, uint64_t ArgumentBufferOffset = 0 );\r\n    void ExecuteIndirect(CommandSignature& CommandSig, GpuBuffer& ArgumentBuffer, uint64_t ArgumentStartOffset = 0,\r\n        uint32_t MaxCommands = 1, GpuBuffer* CommandCounterBuffer = nullptr, uint64_t CounterOffset = 0);\r\n\r\nprivate:\r\n};\r\n\r\ninline void CommandContext::FlushResourceBarriers( void )\r\n{\r\n    if (m_NumBarriersToFlush > 0)\r\n    {\r\n        m_CommandList->ResourceBarrier(m_NumBarriersToFlush, m_ResourceBarrierBuffer);\r\n        m_NumBarriersToFlush = 0;\r\n    }\r\n}\r\n\r\ninline void GraphicsContext::SetRootSignature( const RootSignature& RootSig )\r\n{\r\n    if (RootSig.GetSignature() == m_CurGraphicsRootSignature)\r\n        return;\r\n\r\n    m_CommandList->SetGraphicsRootSignature(m_CurGraphicsRootSignature = RootSig.GetSignature());\r\n\r\n    m_DynamicViewDescriptorHeap.ParseGraphicsRootSignature(RootSig);\r\n    m_DynamicSamplerDescriptorHeap.ParseGraphicsRootSignature(RootSig);\r\n}\r\n\r\ninline void ComputeContext::SetRootSignature( const RootSignature& RootSig )\r\n{\r\n    if (RootSig.GetSignature() == m_CurComputeRootSignature)\r\n        return;\r\n\r\n    m_CommandList->SetComputeRootSignature(m_CurComputeRootSignature = RootSig.GetSignature());\r\n\r\n    m_DynamicViewDescriptorHeap.ParseComputeRootSignature(RootSig);\r\n    m_DynamicSamplerDescriptorHeap.ParseComputeRootSignature(RootSig);\r\n}\r\n\r\ninline void GraphicsContext::SetPipelineState( const GraphicsPSO& PSO )\r\n{\r\n    ID3D12PipelineState* PipelineState = PSO.GetPipelineStateObject();\r\n    if (PipelineState == m_CurGraphicsPipelineState)\r\n        return;\r\n\r\n    m_CommandList->SetPipelineState(PipelineState);\r\n    m_CurGraphicsPipelineState = PipelineState;\r\n}\r\n\r\ninline void ComputeContext::SetPipelineState( const ComputePSO& PSO )\r\n{\r\n    ID3D12PipelineState* PipelineState = PSO.GetPipelineStateObject();\r\n    if (PipelineState == m_CurComputePipelineState)\r\n        return;\r\n\r\n    m_CommandList->SetPipelineState(PipelineState);\r\n    m_CurComputePipelineState = PipelineState;\r\n}\r\n\r\ninline void GraphicsContext::SetViewportAndScissor( UINT x, UINT y, UINT w, UINT h )\r\n{\r\n    SetViewport((float)x, (float)y, (float)w, (float)h);\r\n    SetScissor(x, y, x + w, y + h);\r\n}\r\n\r\ninline void GraphicsContext::SetScissor( UINT left, UINT top, UINT right, UINT bottom )\r\n{\r\n    SetScissor(CD3DX12_RECT(left, top, right, bottom));\r\n}\r\n\r\ninline void GraphicsContext::SetStencilRef( UINT ref )\r\n{\r\n    m_CommandList->OMSetStencilRef( ref );\r\n}\r\n\r\ninline void GraphicsContext::SetBlendFactor( Color BlendFactor )\r\n{\r\n    m_CommandList->OMSetBlendFactor( BlendFactor.GetPtr() );\r\n}\r\n\r\ninline void GraphicsContext::SetPrimitiveTopology( D3D12_PRIMITIVE_TOPOLOGY Topology )\r\n{\r\n    m_CommandList->IASetPrimitiveTopology(Topology);\r\n}\r\n\r\ninline void ComputeContext::SetConstantArray( UINT RootEntry, UINT NumConstants, const void* pConstants )\r\n{\r\n    m_CommandList->SetComputeRoot32BitConstants( RootEntry, NumConstants, pConstants, 0 );\r\n}\r\n\r\ninline void ComputeContext::SetConstant( UINT RootEntry, DWParam Val, UINT Offset )\r\n{\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, Val.Uint, Offset );\r\n}\r\n\r\ninline void ComputeContext::SetConstants( UINT RootEntry, DWParam X )\r\n{\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, X.Uint, 0 );\r\n}\r\n\r\ninline void ComputeContext::SetConstants( UINT RootEntry, DWParam X, DWParam Y )\r\n{\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, X.Uint, 0 );\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, Y.Uint, 1 );\r\n}\r\n\r\ninline void ComputeContext::SetConstants( UINT RootEntry, DWParam X, DWParam Y, DWParam Z )\r\n{\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, X.Uint, 0 );\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, Y.Uint, 1 );\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, Z.Uint, 2 );\r\n}\r\n\r\ninline void ComputeContext::SetConstants( UINT RootEntry, DWParam X, DWParam Y, DWParam Z, DWParam W )\r\n{\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, X.Uint, 0 );\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, Y.Uint, 1 );\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, Z.Uint, 2 );\r\n    m_CommandList->SetComputeRoot32BitConstant( RootEntry, W.Uint, 3 );\r\n}\r\n\r\ninline void GraphicsContext::SetConstantArray( UINT RootIndex, UINT NumConstants, const void* pConstants )\r\n{\r\n    m_CommandList->SetGraphicsRoot32BitConstants( RootIndex, NumConstants, pConstants, 0 );\r\n}\r\n\r\ninline void GraphicsContext::SetConstant( UINT RootEntry, DWParam Val, UINT Offset )\r\n{\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootEntry, Val.Uint, Offset );\r\n}\r\n\r\ninline void GraphicsContext::SetConstants( UINT RootIndex, DWParam X )\r\n{\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );\r\n}\r\n\r\ninline void GraphicsContext::SetConstants( UINT RootIndex, DWParam X, DWParam Y )\r\n{\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );\r\n}\r\n\r\ninline void GraphicsContext::SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z )\r\n{\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, Z.Uint, 2 );\r\n}\r\n\r\ninline void GraphicsContext::SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W )\r\n{\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, Z.Uint, 2 );\r\n    m_CommandList->SetGraphicsRoot32BitConstant( RootIndex, W.Uint, 3 );\r\n}\r\n\r\ninline void ComputeContext::SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV )\r\n{\r\n    m_CommandList->SetComputeRootConstantBufferView(RootIndex, CBV);\r\n}\r\n\r\ninline void GraphicsContext::SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV )\r\n{\r\n    m_CommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData )\r\n{\r\n    ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));\r\n    DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);\r\n    //SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);\r\n    memcpy(cb.DataPtr, BufferData, BufferSize);\r\n    m_CommandList->SetGraphicsRootConstantBufferView(RootIndex, cb.GpuAddress);\r\n}\r\n\r\ninline void ComputeContext::SetDynamicConstantBufferView( UINT RootIndex, size_t BufferSize, const void* BufferData )\r\n{\r\n    ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));\r\n    DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);\r\n    //SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);\r\n    memcpy(cb.DataPtr, BufferData, BufferSize);\r\n    m_CommandList->SetComputeRootConstantBufferView(RootIndex, cb.GpuAddress);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicVB( UINT Slot, size_t NumVertices, size_t VertexStride, const void* VertexData )\r\n{\r\n    ASSERT(VertexData != nullptr && Math::IsAligned(VertexData, 16));\r\n\r\n    size_t BufferSize = Math::AlignUp(NumVertices * VertexStride, 16);\r\n    DynAlloc vb = m_CpuLinearAllocator.Allocate(BufferSize);\r\n\r\n    SIMDMemCopy(vb.DataPtr, VertexData, BufferSize >> 4);\r\n\r\n    D3D12_VERTEX_BUFFER_VIEW VBView;\r\n    VBView.BufferLocation = vb.GpuAddress;\r\n    VBView.SizeInBytes = (UINT)BufferSize;\r\n    VBView.StrideInBytes = (UINT)VertexStride;\r\n\r\n    m_CommandList->IASetVertexBuffers(Slot, 1, &VBView);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicIB( size_t IndexCount, const uint16_t* IndexData )\r\n{\r\n    ASSERT(IndexData != nullptr && Math::IsAligned(IndexData, 16));\r\n\r\n    size_t BufferSize = Math::AlignUp(IndexCount * sizeof(uint16_t), 16);\r\n    DynAlloc ib = m_CpuLinearAllocator.Allocate(BufferSize);\r\n\r\n    SIMDMemCopy(ib.DataPtr, IndexData, BufferSize >> 4);\r\n\r\n    D3D12_INDEX_BUFFER_VIEW IBView;\r\n    IBView.BufferLocation = ib.GpuAddress;\r\n    IBView.SizeInBytes = (UINT)(IndexCount * sizeof(uint16_t));\r\n    IBView.Format = DXGI_FORMAT_R16_UINT;\r\n\r\n    m_CommandList->IASetIndexBuffer(&IBView);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicSRV(UINT RootIndex, size_t BufferSize, const void* BufferData)\r\n{\r\n    ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));\r\n    DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);\r\n    SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);\r\n    m_CommandList->SetGraphicsRootShaderResourceView(RootIndex, cb.GpuAddress);\r\n}\r\n\r\ninline void ComputeContext::SetDynamicSRV(UINT RootIndex, size_t BufferSize, const void* BufferData)\r\n{\r\n    ASSERT(BufferData != nullptr && Math::IsAligned(BufferData, 16));\r\n    DynAlloc cb = m_CpuLinearAllocator.Allocate(BufferSize);\r\n    SIMDMemCopy(cb.DataPtr, BufferData, Math::AlignUp(BufferSize, 16) >> 4);\r\n    m_CommandList->SetComputeRootShaderResourceView(RootIndex, cb.GpuAddress);\r\n}\r\n\r\ninline void GraphicsContext::SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV, UINT64 Offset)\r\n{\r\n    ASSERT((SRV.m_UsageState & (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)) != 0);\r\n    m_CommandList->SetGraphicsRootShaderResourceView(RootIndex, SRV.GetGpuVirtualAddress() + Offset);\r\n}\r\n\r\ninline void ComputeContext::SetBufferSRV( UINT RootIndex, const GpuBuffer& SRV, UINT64 Offset)\r\n{\r\n    ASSERT((SRV.m_UsageState & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE) != 0);\r\n    m_CommandList->SetComputeRootShaderResourceView(RootIndex, SRV.GetGpuVirtualAddress() + Offset);\r\n}\r\n\r\ninline void GraphicsContext::SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV, UINT64 Offset)\r\n{\r\n    ASSERT((UAV.m_UsageState & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) != 0);\r\n    m_CommandList->SetGraphicsRootUnorderedAccessView(RootIndex, UAV.GetGpuVirtualAddress() + Offset);\r\n}\r\n\r\ninline void ComputeContext::SetBufferUAV( UINT RootIndex, const GpuBuffer& UAV, UINT64 Offset)\r\n{\r\n    ASSERT((UAV.m_UsageState & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) != 0);\r\n    m_CommandList->SetComputeRootUnorderedAccessView(RootIndex, UAV.GetGpuVirtualAddress() + Offset);\r\n}\r\n\r\ninline void ComputeContext::Dispatch( size_t GroupCountX, size_t GroupCountY, size_t GroupCountZ )\r\n{\r\n    FlushResourceBarriers();\r\n    m_DynamicViewDescriptorHeap.CommitComputeRootDescriptorTables(m_CommandList);\r\n    m_DynamicSamplerDescriptorHeap.CommitComputeRootDescriptorTables(m_CommandList);\r\n    m_CommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ);\r\n}\r\n\r\ninline void ComputeContext::Dispatch1D( size_t ThreadCountX, size_t GroupSizeX )\r\n{\r\n    Dispatch( Math::DivideByMultiple(ThreadCountX, GroupSizeX), 1, 1 );\r\n}\r\n\r\ninline void ComputeContext::Dispatch2D( size_t ThreadCountX, size_t ThreadCountY, size_t GroupSizeX, size_t GroupSizeY )\r\n{\r\n    Dispatch(\r\n        Math::DivideByMultiple(ThreadCountX, GroupSizeX),\r\n        Math::DivideByMultiple(ThreadCountY, GroupSizeY), 1);\r\n}\r\n\r\ninline void ComputeContext::Dispatch3D( size_t ThreadCountX, size_t ThreadCountY, size_t ThreadCountZ, size_t GroupSizeX, size_t GroupSizeY, size_t GroupSizeZ )\r\n{\r\n    Dispatch(\r\n        Math::DivideByMultiple(ThreadCountX, GroupSizeX),\r\n        Math::DivideByMultiple(ThreadCountY, GroupSizeY),\r\n        Math::DivideByMultiple(ThreadCountZ, GroupSizeZ));\r\n}\r\n\r\ninline void CommandContext::SetDescriptorHeap( D3D12_DESCRIPTOR_HEAP_TYPE Type, ID3D12DescriptorHeap* HeapPtr )\r\n{\r\n    if (m_CurrentDescriptorHeaps[Type] != HeapPtr)\r\n    {\r\n        m_CurrentDescriptorHeaps[Type] = HeapPtr;\r\n        BindDescriptorHeaps();\r\n    }\r\n}\r\n\r\ninline void CommandContext::SetDescriptorHeaps( UINT HeapCount, D3D12_DESCRIPTOR_HEAP_TYPE Type[], ID3D12DescriptorHeap* HeapPtrs[] )\r\n{\r\n    bool AnyChanged = false;\r\n\r\n    for (UINT i = 0; i < HeapCount; ++i)\r\n    {\r\n        if (m_CurrentDescriptorHeaps[Type[i]] != HeapPtrs[i])\r\n        {\r\n            m_CurrentDescriptorHeaps[Type[i]] = HeapPtrs[i];\r\n            AnyChanged = true;\r\n        }\r\n    }\r\n\r\n    if (AnyChanged)\r\n        BindDescriptorHeaps();\r\n}\r\n\r\ninline void CommandContext::SetPredication(ID3D12Resource* Buffer, UINT64 BufferOffset, D3D12_PREDICATION_OP Op)\r\n{\r\n    m_CommandList->SetPredication(Buffer, BufferOffset, Op);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle )\r\n{\r\n    SetDynamicDescriptors(RootIndex, Offset, 1, &Handle);\r\n}\r\n\r\ninline void ComputeContext::SetDynamicDescriptor( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle )\r\n{\r\n    SetDynamicDescriptors(RootIndex, Offset, 1, &Handle);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n{\r\n    m_DynamicViewDescriptorHeap.SetGraphicsDescriptorHandles(RootIndex, Offset, Count, Handles);\r\n}\r\n\r\ninline void ComputeContext::SetDynamicDescriptors( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n{\r\n    m_DynamicViewDescriptorHeap.SetComputeDescriptorHandles(RootIndex, Offset, Count, Handles);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicSampler( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle )\r\n{\r\n    SetDynamicSamplers(RootIndex, Offset, 1, &Handle);\r\n}\r\n\r\ninline void GraphicsContext::SetDynamicSamplers( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n{\r\n    m_DynamicSamplerDescriptorHeap.SetGraphicsDescriptorHandles(RootIndex, Offset, Count, Handles);\r\n}\r\n\r\ninline void ComputeContext::SetDynamicSampler( UINT RootIndex, UINT Offset, D3D12_CPU_DESCRIPTOR_HANDLE Handle )\r\n{\r\n    SetDynamicSamplers(RootIndex, Offset, 1, &Handle);\r\n}\r\n\r\ninline void ComputeContext::SetDynamicSamplers( UINT RootIndex, UINT Offset, UINT Count, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n{\r\n    m_DynamicSamplerDescriptorHeap.SetComputeDescriptorHandles(RootIndex, Offset, Count, Handles);\r\n}\r\n\r\ninline void GraphicsContext::SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle )\r\n{\r\n    m_CommandList->SetGraphicsRootDescriptorTable( RootIndex, FirstHandle );\r\n}\r\n\r\ninline void ComputeContext::SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle )\r\n{\r\n    m_CommandList->SetComputeRootDescriptorTable( RootIndex, FirstHandle );\r\n}\r\n\r\ninline void GraphicsContext::SetIndexBuffer( const D3D12_INDEX_BUFFER_VIEW& IBView )\r\n{\r\n    m_CommandList->IASetIndexBuffer(&IBView);\r\n}\r\n\r\ninline void GraphicsContext::SetVertexBuffer( UINT Slot, const D3D12_VERTEX_BUFFER_VIEW& VBView )\r\n{\r\n    SetVertexBuffers(Slot, 1, &VBView);\r\n}\r\n\r\ninline void GraphicsContext::SetVertexBuffers( UINT StartSlot, UINT Count, const D3D12_VERTEX_BUFFER_VIEW VBViews[] )\r\n{\r\n    m_CommandList->IASetVertexBuffers(StartSlot, Count, VBViews);\r\n}\r\n\r\ninline void GraphicsContext::Draw(UINT VertexCount, UINT VertexStartOffset)\r\n{\r\n    DrawInstanced(VertexCount, 1, VertexStartOffset, 0);\r\n}\r\n\r\ninline void GraphicsContext::DrawIndexed(UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation)\r\n{\r\n    DrawIndexedInstanced(IndexCount, 1, StartIndexLocation, BaseVertexLocation, 0);\r\n}\r\n\r\ninline void GraphicsContext::DrawInstanced(UINT VertexCountPerInstance, UINT InstanceCount,\r\n    UINT StartVertexLocation, UINT StartInstanceLocation)\r\n{\r\n    FlushResourceBarriers();\r\n    m_DynamicViewDescriptorHeap.CommitGraphicsRootDescriptorTables(m_CommandList);\r\n    m_DynamicSamplerDescriptorHeap.CommitGraphicsRootDescriptorTables(m_CommandList);\r\n    m_CommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);\r\n}\r\n\r\ninline void GraphicsContext::DrawIndexedInstanced(UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation,\r\n    INT BaseVertexLocation, UINT StartInstanceLocation)\r\n{\r\n    FlushResourceBarriers();\r\n    m_DynamicViewDescriptorHeap.CommitGraphicsRootDescriptorTables(m_CommandList);\r\n    m_DynamicSamplerDescriptorHeap.CommitGraphicsRootDescriptorTables(m_CommandList);\r\n    m_CommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);\r\n}\r\n\r\ninline void GraphicsContext::ExecuteIndirect(CommandSignature& CommandSig,\r\n    GpuBuffer& ArgumentBuffer, uint64_t ArgumentStartOffset,\r\n    uint32_t MaxCommands, GpuBuffer* CommandCounterBuffer, uint64_t CounterOffset)\r\n{\r\n    FlushResourceBarriers();\r\n    m_DynamicViewDescriptorHeap.CommitGraphicsRootDescriptorTables(m_CommandList);\r\n    m_DynamicSamplerDescriptorHeap.CommitGraphicsRootDescriptorTables(m_CommandList);\r\n    m_CommandList->ExecuteIndirect(CommandSig.GetSignature(), MaxCommands,\r\n        ArgumentBuffer.GetResource(), ArgumentStartOffset,\r\n        CommandCounterBuffer == nullptr ? nullptr : CommandCounterBuffer->GetResource(), CounterOffset);\r\n}\r\n\r\ninline void GraphicsContext::DrawIndirect(GpuBuffer& ArgumentBuffer, uint64_t ArgumentBufferOffset)\r\n{\r\n    ExecuteIndirect(Graphics::DrawIndirectCommandSignature, ArgumentBuffer, ArgumentBufferOffset);\r\n}\r\n\r\ninline void ComputeContext::ExecuteIndirect(CommandSignature& CommandSig,\r\n    GpuBuffer& ArgumentBuffer, uint64_t ArgumentStartOffset,\r\n    uint32_t MaxCommands, GpuBuffer* CommandCounterBuffer, uint64_t CounterOffset)\r\n{\r\n    FlushResourceBarriers();\r\n    m_DynamicViewDescriptorHeap.CommitComputeRootDescriptorTables(m_CommandList);\r\n    m_DynamicSamplerDescriptorHeap.CommitComputeRootDescriptorTables(m_CommandList);\r\n    m_CommandList->ExecuteIndirect(CommandSig.GetSignature(), MaxCommands,\r\n        ArgumentBuffer.GetResource(), ArgumentStartOffset,\r\n        CommandCounterBuffer == nullptr ? nullptr : CommandCounterBuffer->GetResource(), CounterOffset);\r\n}\r\n\r\ninline void ComputeContext::DispatchIndirect( GpuBuffer& ArgumentBuffer, uint64_t ArgumentBufferOffset )\r\n{\r\n    ExecuteIndirect(Graphics::DispatchIndirectCommandSignature, ArgumentBuffer, ArgumentBufferOffset);\r\n}\r\n\r\ninline void CommandContext::CopyBuffer( GpuResource& Dest, GpuResource& Src )\r\n{\r\n    TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);\r\n    TransitionResource(Src, D3D12_RESOURCE_STATE_COPY_SOURCE);\r\n    FlushResourceBarriers();\r\n    m_CommandList->CopyResource(Dest.GetResource(), Src.GetResource());\r\n}\r\n\r\ninline void CommandContext::CopyBufferRegion( GpuResource& Dest, size_t DestOffset, GpuResource& Src, size_t SrcOffset, size_t NumBytes )\r\n{\r\n    TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);\r\n    //TransitionResource(Src, D3D12_RESOURCE_STATE_COPY_SOURCE);\r\n    FlushResourceBarriers();\r\n    m_CommandList->CopyBufferRegion( Dest.GetResource(), DestOffset, Src.GetResource(), SrcOffset, NumBytes);\r\n}\r\n\r\ninline void CommandContext::CopyCounter(GpuResource& Dest, size_t DestOffset, StructuredBuffer& Src)\r\n{\r\n    TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST);\r\n    TransitionResource(Src.GetCounterBuffer(), D3D12_RESOURCE_STATE_COPY_SOURCE);\r\n    FlushResourceBarriers();\r\n    m_CommandList->CopyBufferRegion(Dest.GetResource(), DestOffset, Src.GetCounterBuffer().GetResource(), 0, 4);\r\n}\r\n\r\ninline void CommandContext::ResetCounter(StructuredBuffer& Buf, uint32_t Value )\r\n{\r\n    FillBuffer(Buf.GetCounterBuffer(), 0, Value, sizeof(uint32_t));\r\n    TransitionResource(Buf.GetCounterBuffer(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n}\r\n\r\ninline void CommandContext::InsertTimeStamp(ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx)\r\n{\r\n    m_CommandList->EndQuery(pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, QueryIdx);\r\n}\r\n\r\ninline void CommandContext::ResolveTimeStamps(ID3D12Resource* pReadbackHeap, ID3D12QueryHeap* pQueryHeap, uint32_t NumQueries)\r\n{\r\n    m_CommandList->ResolveQueryData(pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0, NumQueries, pReadbackHeap, 0);\r\n}\r\n\r\ninline void CommandContext::BeginPipelineQuery(ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx) {\r\n\tm_CommandList->BeginQuery(pQueryHeap, D3D12_QUERY_TYPE_PIPELINE_STATISTICS, QueryIdx);\r\n}\r\n\r\ninline void CommandContext::EndPipelineQuery(ID3D12QueryHeap* pQueryHeap, uint32_t QueryIdx) {\r\n\tm_CommandList->EndQuery(pQueryHeap, D3D12_QUERY_TYPE_PIPELINE_STATISTICS, QueryIdx);\r\n}\r\n\r\ninline void CommandContext::ResolvePipelineQueries(ID3D12Resource* pReadbackHeap, ID3D12QueryHeap* pQueryHeap, uint32_t NumQueries) {\r\n\tm_CommandList->ResolveQueryData(pQueryHeap, D3D12_QUERY_TYPE_PIPELINE_STATISTICS, 0, NumQueries, pReadbackHeap, 0);\r\n}\r\n\r\ninline void GraphicsContext::SetSamplePositions(UINT NumSamplesPerPixel, UINT NumPixels, D3D12_SAMPLE_POSITION *pSamplePositions)\r\n{\r\n#ifdef WDDM22\r\n\tm_CommandList->SetSamplePositions(NumSamplesPerPixel, NumPixels, pSamplePositions);\r\n#else\r\n\treturn;\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandListManager.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"CommandListManager.h\"\r\n\r\nCommandQueue::CommandQueue(D3D12_COMMAND_LIST_TYPE Type) :\r\n    m_Type(Type),\r\n    m_CommandQueue(nullptr),\r\n    m_pFence(nullptr),\r\n    m_NextFenceValue((uint64_t)Type << 56 | 1),\r\n    m_LastCompletedFenceValue((uint64_t)Type << 56),\r\n    m_AllocatorPool(Type)\r\n{\r\n}\r\n\r\nCommandQueue::~CommandQueue()\r\n{\r\n    Shutdown();\r\n}\r\n\r\nvoid CommandQueue::Shutdown()\r\n{\r\n    if (m_CommandQueue == nullptr)\r\n        return;\r\n\r\n    m_AllocatorPool.Shutdown();\r\n\r\n    CloseHandle(m_FenceEventHandle);\r\n\r\n    m_pFence->Release();\r\n    m_pFence = nullptr;\r\n\r\n    m_CommandQueue->Release();\r\n    m_CommandQueue = nullptr;\r\n}\r\n\r\nCommandListManager::CommandListManager() :\r\n    m_Device(nullptr),\r\n    m_GraphicsQueue(D3D12_COMMAND_LIST_TYPE_DIRECT),\r\n    m_ComputeQueue(D3D12_COMMAND_LIST_TYPE_COMPUTE),\r\n    m_CopyQueue(D3D12_COMMAND_LIST_TYPE_COPY)\r\n{\r\n}\r\n\r\nCommandListManager::~CommandListManager()\r\n{\r\n    Shutdown();\r\n}\r\n\r\nvoid CommandListManager::Shutdown()\r\n{\r\n    m_GraphicsQueue.Shutdown();\r\n    m_ComputeQueue.Shutdown();\r\n    m_CopyQueue.Shutdown();\r\n}\r\n\r\nvoid CommandQueue::Create(DX12_DEVICE* pDevice)\r\n{\r\n    ASSERT(pDevice != nullptr);\r\n    ASSERT(!IsReady());\r\n    ASSERT(m_AllocatorPool.Size() == 0);\r\n\r\n    D3D12_COMMAND_QUEUE_DESC QueueDesc = {};\r\n    QueueDesc.Type = m_Type;\r\n    QueueDesc.NodeMask = 1;\r\n    pDevice->CreateCommandQueue(&QueueDesc, MY_IID_PPV_ARGS(&m_CommandQueue));\r\n    m_CommandQueue->SetName(L\"CommandListManager::m_CommandQueue\");\r\n\r\n    ASSERT_SUCCEEDED(pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, MY_IID_PPV_ARGS(&m_pFence)));\r\n    m_pFence->SetName(L\"CommandListManager::m_pFence\");\r\n    m_pFence->Signal((uint64_t)m_Type << 56);\r\n\r\n    m_FenceEventHandle = CreateEvent(nullptr, false, false, nullptr);\r\n    ASSERT(m_FenceEventHandle != INVALID_HANDLE_VALUE);\r\n\r\n    m_AllocatorPool.Create(pDevice);\r\n\r\n    ASSERT(IsReady());\r\n}\r\n\r\nvoid CommandListManager::Create(DX12_DEVICE* pDevice)\r\n{\r\n    ASSERT(pDevice != nullptr);\r\n\r\n    m_Device = pDevice;\r\n\r\n    m_GraphicsQueue.Create(pDevice);\r\n    m_ComputeQueue.Create(pDevice);\r\n    m_CopyQueue.Create(pDevice);\r\n}\r\n\r\nvoid CommandListManager::CreateNewCommandList( D3D12_COMMAND_LIST_TYPE Type, DX12_GRAPHICSCOMMANDLIST** List, ID3D12CommandAllocator** Allocator )\r\n{\r\n    ASSERT(Type != D3D12_COMMAND_LIST_TYPE_BUNDLE, \"Bundles are not yet supported\");\r\n    switch (Type)\r\n    {\r\n    case D3D12_COMMAND_LIST_TYPE_DIRECT: *Allocator = m_GraphicsQueue.RequestAllocator(); break;\r\n    case D3D12_COMMAND_LIST_TYPE_BUNDLE: break;\r\n    case D3D12_COMMAND_LIST_TYPE_COMPUTE: *Allocator = m_ComputeQueue.RequestAllocator(); break;\r\n    case D3D12_COMMAND_LIST_TYPE_COPY: *Allocator = m_CopyQueue.RequestAllocator(); break;\r\n    }\r\n    \r\n    ASSERT_SUCCEEDED( m_Device->CreateCommandList(1, Type, *Allocator, nullptr, MY_IID_PPV_ARGS(List)) );\r\n    (*List)->SetName(L\"CommandList\");\r\n}\r\n\r\nuint64_t CommandQueue::ExecuteCommandList( ID3D12CommandList* List )\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(m_FenceMutex);\r\n\r\n    ASSERT_SUCCEEDED(((DX12_GRAPHICSCOMMANDLIST*)List)->Close());\r\n\r\n    // Kickoff the command list\r\n    m_CommandQueue->ExecuteCommandLists(1, &List);\r\n\r\n    // Signal the next fence value (with the GPU)\r\n    m_CommandQueue->Signal(m_pFence, m_NextFenceValue);\r\n\r\n    // And increment the fence value.  \r\n    return m_NextFenceValue++;\r\n}\r\n\r\nuint64_t CommandQueue::IncrementFence(void)\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(m_FenceMutex);\r\n    m_CommandQueue->Signal(m_pFence, m_NextFenceValue);\r\n    return m_NextFenceValue++;\r\n}\r\n\r\nbool CommandQueue::IsFenceComplete(uint64_t FenceValue)\r\n{\r\n    // Avoid querying the fence value by testing against the last one seen.\r\n    // The max() is to protect against an unlikely race condition that could cause the last\r\n    // completed fence value to regress.\r\n    if (FenceValue > m_LastCompletedFenceValue)\r\n        m_LastCompletedFenceValue = std::max(m_LastCompletedFenceValue, m_pFence->GetCompletedValue());\r\n\r\n    return FenceValue <= m_LastCompletedFenceValue;\r\n}\r\n\r\nnamespace Graphics\r\n{\r\n    extern CommandListManager g_CommandManager;\r\n}\r\n\r\nvoid CommandQueue::StallForFence(uint64_t FenceValue)\r\n{\r\n    CommandQueue& Producer = Graphics::g_CommandManager.GetQueue((D3D12_COMMAND_LIST_TYPE)(FenceValue >> 56));\r\n    m_CommandQueue->Wait(Producer.m_pFence, FenceValue);\r\n}\r\n\r\nvoid CommandQueue::StallForProducer(CommandQueue& Producer)\r\n{\r\n    ASSERT(Producer.m_NextFenceValue > 0);\r\n    m_CommandQueue->Wait(Producer.m_pFence, Producer.m_NextFenceValue - 1);\r\n}\r\n\r\nvoid CommandQueue::WaitForFence(uint64_t FenceValue)\r\n{\r\n    if (IsFenceComplete(FenceValue))\r\n        return;\r\n\r\n    // TODO:  Think about how this might affect a multi-threaded situation.  Suppose thread A\r\n    // wants to wait for fence 100, then thread B comes along and wants to wait for 99.  If\r\n    // the fence can only have one event set on completion, then thread B has to wait for \r\n    // 100 before it knows 99 is ready.  Maybe insert sequential events?\r\n    {\r\n        std::lock_guard<std::mutex> LockGuard(m_EventMutex);\r\n\r\n        m_pFence->SetEventOnCompletion(FenceValue, m_FenceEventHandle);\r\n        WaitForSingleObject(m_FenceEventHandle, INFINITE);\r\n        m_LastCompletedFenceValue = FenceValue;\r\n    }\r\n}\r\n\r\nvoid CommandListManager::WaitForFence(uint64_t FenceValue)\r\n{\r\n    CommandQueue& Producer = Graphics::g_CommandManager.GetQueue((D3D12_COMMAND_LIST_TYPE)(FenceValue >> 56));\r\n    Producer.WaitForFence(FenceValue);\r\n}\r\n\r\nID3D12CommandAllocator* CommandQueue::RequestAllocator()\r\n{\r\n    uint64_t CompletedFence = m_pFence->GetCompletedValue();\r\n\r\n    return m_AllocatorPool.RequestAllocator(CompletedFence);\r\n}\r\n\r\nvoid CommandQueue::DiscardAllocator(uint64_t FenceValue, ID3D12CommandAllocator* Allocator)\r\n{\r\n    m_AllocatorPool.DiscardAllocator(FenceValue, Allocator);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandListManager.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\n#include <vector>\r\n#include <queue>\r\n#include <mutex>\r\n#include <stdint.h>\r\n#include \"CommandAllocatorPool.h\"\r\n\r\nclass CommandQueue\r\n{\r\n    friend class CommandListManager;\r\n    friend class CommandContext;\r\n\r\npublic:\r\n    CommandQueue(D3D12_COMMAND_LIST_TYPE Type);\r\n    ~CommandQueue();\r\n\r\n    void Create(DX12_DEVICE* pDevice);\r\n    void Shutdown();\r\n\r\n    inline bool IsReady()\r\n    {\r\n        return m_CommandQueue != nullptr;\r\n    }\r\n\r\n    uint64_t IncrementFence(void);\r\n    bool IsFenceComplete(uint64_t FenceValue);\r\n    void StallForFence(uint64_t FenceValue);\r\n    void StallForProducer(CommandQueue& Producer);\r\n    void WaitForFence(uint64_t FenceValue);\r\n    void WaitForIdle(void) { WaitForFence(IncrementFence()); }\r\n\r\n    ID3D12CommandQueue* GetCommandQueue() { return m_CommandQueue; }\r\n\r\n    uint64_t GetNextFenceValue() { return m_NextFenceValue; }\r\n\r\nprivate:\r\n\r\n    uint64_t ExecuteCommandList(ID3D12CommandList* List);\r\n    ID3D12CommandAllocator* RequestAllocator(void);\r\n    void DiscardAllocator(uint64_t FenceValueForReset, ID3D12CommandAllocator* Allocator);\r\n\r\n    ID3D12CommandQueue* m_CommandQueue;\r\n\r\n    const D3D12_COMMAND_LIST_TYPE m_Type;\r\n\r\n    CommandAllocatorPool m_AllocatorPool;\r\n    std::mutex m_FenceMutex;\r\n    std::mutex m_EventMutex;\r\n\r\n    // Lifetime of these objects is managed by the descriptor cache\r\n    ID3D12Fence* m_pFence;\r\n    uint64_t m_NextFenceValue;\r\n    uint64_t m_LastCompletedFenceValue;\r\n    HANDLE m_FenceEventHandle;\r\n\r\n};\r\n\r\nclass CommandListManager\r\n{\r\n    friend class CommandContext;\r\n\r\npublic:\r\n    CommandListManager();\r\n    ~CommandListManager();\r\n\r\n    void Create(DX12_DEVICE* pDevice);\r\n    void Shutdown();\r\n\r\n    CommandQueue& GetGraphicsQueue(void) { return m_GraphicsQueue; }\r\n    CommandQueue& GetComputeQueue(void) { return m_ComputeQueue; }\r\n    CommandQueue& GetCopyQueue(void) { return m_CopyQueue; }\r\n\r\n    CommandQueue& GetQueue(D3D12_COMMAND_LIST_TYPE Type = D3D12_COMMAND_LIST_TYPE_DIRECT)\r\n    {\r\n        switch (Type)\r\n        {\r\n        case D3D12_COMMAND_LIST_TYPE_COMPUTE: return m_ComputeQueue;\r\n        case D3D12_COMMAND_LIST_TYPE_COPY: return m_CopyQueue;\r\n        default: return m_GraphicsQueue;\r\n        }\r\n    }\r\n\r\n    ID3D12CommandQueue* GetCommandQueue()\r\n    {\r\n        return m_GraphicsQueue.GetCommandQueue();\r\n    }\r\n\r\n    void CreateNewCommandList(\r\n        D3D12_COMMAND_LIST_TYPE Type,\r\n        DX12_GRAPHICSCOMMANDLIST** List,\r\n        ID3D12CommandAllocator** Allocator);\r\n\r\n    // Test to see if a fence has already been reached\r\n    bool IsFenceComplete(uint64_t FenceValue)\r\n    {\r\n        return GetQueue(D3D12_COMMAND_LIST_TYPE(FenceValue >> 56)).IsFenceComplete(FenceValue);\r\n    }\r\n\r\n    // The CPU will wait for a fence to reach a specified value\r\n    void WaitForFence(uint64_t FenceValue);\r\n\r\n    // The CPU will wait for all command queues to empty (so that the GPU is idle)\r\n    void IdleGPU(void)\r\n    {\r\n        m_GraphicsQueue.WaitForIdle();\r\n        m_ComputeQueue.WaitForIdle();\r\n        m_CopyQueue.WaitForIdle();\r\n    }\r\n\r\nprivate:\r\n\r\n    DX12_DEVICE* m_Device;\r\n\r\n    CommandQueue m_GraphicsQueue;\r\n    CommandQueue m_ComputeQueue;\r\n    CommandQueue m_CopyQueue;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandSignature.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"CommandSignature.h\"\r\n#include \"RootSignature.h\"\r\n#include \"GraphicsCore.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nvoid CommandSignature::Finalize( const RootSignature* RootSignature )\r\n{\r\n    if (m_Finalized)\r\n        return;\r\n\r\n    UINT ByteStride = 0;\r\n    bool RequiresRootSignature = false;\r\n\r\n    for (UINT i = 0; i < m_NumParameters; ++i)\r\n    {\r\n        switch (m_ParamArray[i].GetDesc().Type)\r\n        {\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:\r\n                ByteStride += sizeof(D3D12_DRAW_ARGUMENTS);\r\n                break;\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:\r\n                ByteStride += sizeof(D3D12_DRAW_INDEXED_ARGUMENTS);\r\n                break;\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:\r\n                ByteStride += sizeof(D3D12_DISPATCH_ARGUMENTS);\r\n                break;\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT:\r\n                ByteStride += m_ParamArray[i].GetDesc().Constant.Num32BitValuesToSet * 4;\r\n                RequiresRootSignature = true;\r\n                break;\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:\r\n                ByteStride += sizeof(D3D12_VERTEX_BUFFER_VIEW);\r\n                break;\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW:\r\n                ByteStride += sizeof(D3D12_INDEX_BUFFER_VIEW);\r\n                break;\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW:\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW:\r\n            case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW:\r\n                ByteStride += 8;\r\n                RequiresRootSignature = true;\r\n                break;\r\n        }\r\n    }\r\n\r\n    D3D12_COMMAND_SIGNATURE_DESC CommandSignatureDesc;\r\n    CommandSignatureDesc.ByteStride = ByteStride;\r\n    CommandSignatureDesc.NumArgumentDescs = m_NumParameters;\r\n    CommandSignatureDesc.pArgumentDescs = (const D3D12_INDIRECT_ARGUMENT_DESC*)m_ParamArray.get();\r\n    CommandSignatureDesc.NodeMask = 1;\r\n\r\n    Microsoft::WRL::ComPtr<ID3DBlob> pOutBlob, pErrorBlob;\r\n\r\n    ID3D12RootSignature* pRootSig = RootSignature ? RootSignature->GetSignature() : nullptr;\r\n    if (RequiresRootSignature)\r\n    {\r\n        ASSERT(pRootSig != nullptr);\r\n    }\r\n    else\r\n    {\r\n        pRootSig = nullptr;\r\n    }\r\n\r\n    ASSERT_SUCCEEDED( g_Device->CreateCommandSignature(&CommandSignatureDesc, pRootSig,\r\n        MY_IID_PPV_ARGS(&m_Signature)) );\r\n\r\n    m_Signature->SetName(L\"CommandSignature\");\r\n\r\n    m_Finalized = TRUE;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/CommandSignature.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\nclass RootSignature;\r\n\r\nclass IndirectParameter\r\n{\r\n    friend class CommandSignature;\r\npublic:\r\n\r\n    IndirectParameter() \r\n    {\r\n        m_IndirectParam.Type = (D3D12_INDIRECT_ARGUMENT_TYPE)0xFFFFFFFF;\r\n    }\r\n\r\n    void Draw(void)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;\r\n    }\r\n\r\n    void DrawIndexed(void)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;\r\n    }\r\n\r\n    void Dispatch(void)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;\r\n    }\r\n\r\n    void VertexBufferView(UINT Slot)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;\r\n        m_IndirectParam.VertexBuffer.Slot = Slot;\r\n    }\r\n\r\n    void IndexBufferView(void)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW;\r\n    }\r\n\r\n    void Constant(UINT RootParameterIndex, UINT DestOffsetIn32BitValues, UINT Num32BitValuesToSet)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;\r\n        m_IndirectParam.Constant.RootParameterIndex = RootParameterIndex;\r\n        m_IndirectParam.Constant.DestOffsetIn32BitValues = DestOffsetIn32BitValues;\r\n        m_IndirectParam.Constant.Num32BitValuesToSet = Num32BitValuesToSet;\r\n    }\r\n\r\n    void ConstantBufferView(UINT RootParameterIndex)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW;\r\n        m_IndirectParam.ConstantBufferView.RootParameterIndex = RootParameterIndex;\r\n    }\r\n\r\n    void ShaderResourceView(UINT RootParameterIndex)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW;\r\n        m_IndirectParam.ShaderResourceView.RootParameterIndex = RootParameterIndex;\r\n    }\r\n\r\n    void UnorderedAccessView(UINT RootParameterIndex)\r\n    {\r\n        m_IndirectParam.Type = D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW;\r\n        m_IndirectParam.UnorderedAccessView.RootParameterIndex = RootParameterIndex;\r\n    }\r\n\r\n    const D3D12_INDIRECT_ARGUMENT_DESC& GetDesc( void ) const { return m_IndirectParam; }\r\n\r\nprotected:\r\n\r\n    D3D12_INDIRECT_ARGUMENT_DESC m_IndirectParam;\r\n};\r\n\r\nclass CommandSignature\r\n{\r\npublic:\r\n\r\n    CommandSignature( UINT NumParams = 0 ) : m_Finalized(FALSE), m_NumParameters(NumParams)\r\n    {\r\n        Reset(NumParams);\r\n    }\r\n\r\n    void Destroy( void )\r\n    {\r\n        m_Signature = nullptr;\r\n        m_ParamArray = nullptr;\r\n    }\r\n\r\n    void Reset( UINT NumParams )\r\n    {\r\n        if (NumParams > 0)\r\n            m_ParamArray.reset(new IndirectParameter[NumParams]);\r\n        else\r\n            m_ParamArray = nullptr;\r\n\r\n        m_NumParameters = NumParams;\r\n    }\r\n\r\n    IndirectParameter& operator[] ( size_t EntryIndex )\r\n    {\r\n        ASSERT(EntryIndex < m_NumParameters);\r\n        return m_ParamArray.get()[EntryIndex];\r\n    }\r\n\r\n    const IndirectParameter& operator[] ( size_t EntryIndex ) const\r\n    {\r\n        ASSERT(EntryIndex < m_NumParameters);\r\n        return m_ParamArray.get()[EntryIndex];\r\n    }\r\n\r\n    void Finalize( const RootSignature* RootSignature = nullptr );\r\n\r\n    ID3D12CommandSignature* GetSignature() const { return m_Signature.Get(); }\r\n\r\nprotected:\r\n\r\n    BOOL m_Finalized;\r\n    UINT m_NumParameters;\r\n    std::unique_ptr<IndirectParameter[]> m_ParamArray;\r\n    Microsoft::WRL::ComPtr<ID3D12CommandSignature> m_Signature;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/Core_VS17.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Profile|x64\">\r\n      <Configuration>Profile</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{86A58508-0D6A-4786-A32F-01A301FDC6F3}</ProjectGuid>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <ProjectName>Core</ProjectName>\r\n    <RootNamespace>Core</RootNamespace>\r\n    <DefaultLanguage>en-US</DefaultLanguage>\r\n    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>\r\n    <ApplicationEnvironment>title</ApplicationEnvironment>\r\n    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\" />\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\" Label=\"PropertySheets\">\r\n    <Import Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Profile.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\r\n    <Import Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Release.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\r\n    <Import Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Debug.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup />\r\n  <ItemDefinitionGroup>\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\r\n      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r\n    </ClCompile>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Platform)'=='X64'\">\r\n    <Link>\r\n      <AdditionalDependencies>d3d11.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <SubSystem>Windows</SubSystem>\r\n      <DataExecutionPrevention>true</DataExecutionPrevention>\r\n      <TargetMachine>MachineX64</TargetMachine>\r\n    </Link>\r\n    <Manifest>\r\n      <EnableDPIAwareness>true</EnableDPIAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"ART\\Animation\\AnimatedValue.h\" />\r\n    <ClInclude Include=\"ART\\Animation\\AnimationController.h\" />\r\n    <ClInclude Include=\"ART\\Animation\\CameraAnimation.h\" />\r\n    <ClInclude Include=\"ART\\Animation\\SceneAnimation.h\" />\r\n    <ClInclude Include=\"ART\\Animation\\SerializationUtil.h\" />\r\n    <ClInclude Include=\"ART\\CommonDefs.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\AnimationWidget.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\GUICore.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\GUIUtil.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\IGUIWidget.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imconfig.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imgui.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imgui_impl_dx11.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imgui_internal.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\stb_rect_pack.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\stb_textedit.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\stb_truetype.h\" />\r\n    <ClInclude Include=\"ART\\GUI\\SequencerWidget.h\" />\r\n    <ClInclude Include=\"ART\\PerfStat\\PerfStat.h\" />\r\n    <ClInclude Include=\"ART\\Sequencer\\FrameSequencer.h\" />\r\n    <ClInclude Include=\"ART\\Wddm22Defs.h\" />\r\n    <ClInclude Include=\"BitonicSort.h\" />\r\n    <ClInclude Include=\"BuddyAllocator.h\" />\r\n    <ClInclude Include=\"BufferManager.h\" />\r\n    <ClInclude Include=\"Camera.h\" />\r\n    <ClInclude Include=\"CameraController.h\" />\r\n    <ClInclude Include=\"Color.h\" />\r\n    <ClInclude Include=\"ColorBuffer.h\" />\r\n    <ClInclude Include=\"CommandAllocatorPool.h\" />\r\n    <ClInclude Include=\"CommandContext.h\" />\r\n    <ClInclude Include=\"CommandListManager.h\" />\r\n    <ClInclude Include=\"CommandSignature.h\" />\r\n    <ClInclude Include=\"d3dx12.h\" />\r\n    <ClInclude Include=\"dds.h\" />\r\n    <ClInclude Include=\"DDSTextureLoader.h\" />\r\n    <ClInclude Include=\"DepthBuffer.h\" />\r\n    <ClInclude Include=\"DepthOfField.h\" />\r\n    <ClInclude Include=\"DynamicUploadBuffer.h\" />\r\n    <ClInclude Include=\"DynamicDescriptorHeap.h\" />\r\n    <ClInclude Include=\"DescriptorHeap.h\" />\r\n    <ClInclude Include=\"GpuBuffer.h\" />\r\n    <ClInclude Include=\"EngineProfiling.h\" />\r\n    <ClInclude Include=\"EsramAllocator.h\" />\r\n    <ClInclude Include=\"FileUtility.h\" />\r\n    <ClInclude Include=\"FXAA.h\" />\r\n    <ClInclude Include=\"GameInput.h\" />\r\n    <ClInclude Include=\"GpuResource.h\" />\r\n    <ClInclude Include=\"GpuCounterManager.h\" />\r\n    <ClInclude Include=\"GameCore.h\" />\r\n    <ClInclude Include=\"GraphicsCommon.h\" />\r\n    <ClInclude Include=\"GraphicsCore.h\" />\r\n    <ClInclude Include=\"GraphRenderer.h\" />\r\n    <ClInclude Include=\"Hash.h\" />\r\n    <ClInclude Include=\"LinearAllocator.h\" />\r\n    <ClInclude Include=\"Math\\BoundingPlane.h\" />\r\n    <ClInclude Include=\"Math\\BoundingSphere.h\" />\r\n    <ClInclude Include=\"Math\\Common.h\" />\r\n    <ClInclude Include=\"Math\\Frustum.h\" />\r\n    <ClInclude Include=\"Math\\Matrix3.h\" />\r\n    <ClInclude Include=\"Math\\Matrix4.h\" />\r\n    <ClInclude Include=\"Math\\Quaternion.h\" />\r\n    <ClInclude Include=\"Math\\Random.h\" />\r\n    <ClInclude Include=\"Math\\Scalar.h\" />\r\n    <ClInclude Include=\"Math\\Transform.h\" />\r\n    <ClInclude Include=\"Math\\Vector.h\" />\r\n    <ClInclude Include=\"MotionBlur.h\" />\r\n    <ClInclude Include=\"ParticleEffect.h\" />\r\n    <ClInclude Include=\"ParticleEffectManager.h\" />\r\n    <ClInclude Include=\"ParticleEffectProperties.h\" />\r\n    <ClInclude Include=\"ParticleShaderStructs.h\" />\r\n    <ClInclude Include=\"pch.h\" />\r\n    <ClInclude Include=\"PipelineState.h\" />\r\n    <ClInclude Include=\"PixelBuffer.h\" />\r\n    <ClInclude Include=\"PostEffects.h\" />\r\n    <ClInclude Include=\"EngineTuning.h\" />\r\n    <ClInclude Include=\"ReadbackBuffer.h\" />\r\n    <ClInclude Include=\"RootSignature.h\" />\r\n    <ClInclude Include=\"SamplerManager.h\" />\r\n    <ClInclude Include=\"ShadowBuffer.h\" />\r\n    <ClInclude Include=\"ShadowCamera.h\" />\r\n    <ClInclude Include=\"SSAO.h\" />\r\n    <ClInclude Include=\"SystemTime.h\" />\r\n    <ClInclude Include=\"TemporalEffects.h\" />\r\n    <ClInclude Include=\"TextRenderer.h\" />\r\n    <ClInclude Include=\"TextureManager.h\" />\r\n    <ClInclude Include=\"Utility.h\" />\r\n    <ClInclude Include=\"VectorMath.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"ART\\Animation\\AnimatedValue.cpp\" />\r\n    <ClCompile Include=\"ART\\Animation\\AnimationController.cpp\" />\r\n    <ClCompile Include=\"ART\\Animation\\CameraAnimation.cpp\" />\r\n    <ClCompile Include=\"ART\\Animation\\SceneAnimation.cpp\" />\r\n    <ClCompile Include=\"ART\\GUI\\AnimationWidget.cpp\" />\r\n    <ClCompile Include=\"ART\\GUI\\GUICore.cpp\" />\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">NotUsing</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui_demo.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">NotUsing</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui_draw.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">NotUsing</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui_impl_dx11.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">NotUsing</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\SequencerWidget.cpp\" />\r\n    <ClCompile Include=\"ART\\PerfStat\\PerfStat.cpp\" />\r\n    <ClCompile Include=\"ART\\Sequencer\\FrameSequencer.cpp\" />\r\n    <ClCompile Include=\"BitonicSort.cpp\" />\r\n    <ClCompile Include=\"BuddyAllocator.cpp\" />\r\n    <ClCompile Include=\"BufferManager.cpp\" />\r\n    <ClCompile Include=\"Camera.cpp\" />\r\n    <ClCompile Include=\"CameraController.cpp\" />\r\n    <ClCompile Include=\"Color.cpp\" />\r\n    <ClCompile Include=\"ColorBuffer.cpp\" />\r\n    <ClCompile Include=\"CommandAllocatorPool.cpp\" />\r\n    <ClCompile Include=\"CommandContext.cpp\" />\r\n    <ClCompile Include=\"CommandListManager.cpp\" />\r\n    <ClCompile Include=\"CommandSignature.cpp\" />\r\n    <ClCompile Include=\"DDSTextureLoader.cpp\" />\r\n    <ClCompile Include=\"DepthBuffer.cpp\" />\r\n    <ClCompile Include=\"DepthOfField.cpp\" />\r\n    <ClCompile Include=\"DynamicUploadBuffer.cpp\" />\r\n    <ClCompile Include=\"DynamicDescriptorHeap.cpp\" />\r\n    <ClCompile Include=\"DescriptorHeap.cpp\" />\r\n    <ClCompile Include=\"EngineProfiling.cpp\" />\r\n    <ClCompile Include=\"EngineTuning.cpp\" />\r\n    <ClCompile Include=\"FileUtility.cpp\" />\r\n    <ClCompile Include=\"FXAA.cpp\" />\r\n    <ClCompile Include=\"GameInput.cpp\" />\r\n    <ClCompile Include=\"GameCore.cpp\" />\r\n    <ClCompile Include=\"GpuBuffer.cpp\" />\r\n    <ClCompile Include=\"GpuCounterManager.cpp\" />\r\n    <ClCompile Include=\"GraphicsCommon.cpp\" />\r\n    <ClCompile Include=\"GraphicsCore.cpp\" />\r\n    <ClCompile Include=\"GraphRenderer.cpp\" />\r\n    <ClCompile Include=\"LinearAllocator.cpp\" />\r\n    <ClCompile Include=\"Math\\Frustum.cpp\" />\r\n    <ClCompile Include=\"Math\\Random.cpp\" />\r\n    <ClCompile Include=\"MotionBlur.cpp\" />\r\n    <ClCompile Include=\"ParticleEffect.cpp\" />\r\n    <ClCompile Include=\"ParticleEffectManager.cpp\" />\r\n    <ClCompile Include=\"ParticleEmissionProperties.cpp\" />\r\n    <ClCompile Include=\"pch.cpp\">\r\n      <PrecompiledHeader>Create</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PipelineState.cpp\" />\r\n    <ClCompile Include=\"PixelBuffer.cpp\" />\r\n    <ClCompile Include=\"PostEffects.cpp\" />\r\n    <ClCompile Include=\"ReadbackBuffer.cpp\" />\r\n    <ClCompile Include=\"RootSignature.cpp\" />\r\n    <ClCompile Include=\"SamplerManager.cpp\" />\r\n    <ClCompile Include=\"ShadowBuffer.cpp\" />\r\n    <ClCompile Include=\"ShadowCamera.cpp\" />\r\n    <ClCompile Include=\"SSAO.cpp\" />\r\n    <ClCompile Include=\"SystemTime.cpp\" />\r\n    <ClCompile Include=\"TemporalEffects.cpp\" />\r\n    <ClCompile Include=\"TextRenderer.cpp\" />\r\n    <ClCompile Include=\"TextureManager.cpp\" />\r\n    <ClCompile Include=\"Utility.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <FxCompile Include=\"Shaders\\AdaptExposureCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsampleBlendOutCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsampleCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsamplePreMinBlendOutCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsamplePreMinCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoPrepareDepthBuffers1CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoPrepareDepthBuffers2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoRender1CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AoRender2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ApplyBloom2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ApplyBloomCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\AverageLumaCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BicubicHorizontalUpsamplePS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicUpsampleGammaPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicUpsamplePS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicVerticalUpsamplePS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BilinearUpsamplePS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic32InnerSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\Bitonic32OuterSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\Bitonic32PreSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\Bitonic64InnerSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\Bitonic64OuterSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\Bitonic64PreSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BitonicIndirectArgsCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BloomExtractAndDownsampleHdrCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BloomExtractAndDownsampleLdrCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BlurCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BoundNeighborhoodCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\BufferCopyPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CameraMotionBlurPrePassCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\CameraMotionBlurPrePassLinearZCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\CameraVelocityCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\CopyBackPostBufferCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DebugDrawHistogramCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceHdr2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceHdrCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceLdr2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceLdrCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DebugSSAOCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFCombine2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFCombineCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFCombineFast2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFCombineFastCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFDebugBlueCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFDebugGreenCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFDebugRedCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFMedianFilterCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFMedianFilterFixupCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFMedianFilterSepAlphaCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPass1CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPass2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPass2DebugCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPass2FastCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPass2FixupCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPreFilterCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPreFilterFastCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFPreFilterFixupCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFTilePassCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DoFTilePassFixupCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DownsampleBloomAllCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\DownsampleBloomCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ExtractLumaCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_Luma2_CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_Luma_CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_RGB2_CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_RGB_CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2H2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2HDebug2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2HDebugCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2V2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2VDebug2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2VDebugCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateHistogramCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2HCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAPass2VCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaOddCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaOddXCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaOddYCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearOddCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearOddXCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearOddYCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\LinearizeDepthCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\MagnifyPixelsPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MotionBlurFinalPassCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\MotionBlurFinalPassPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MotionBlurPrePassCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FXAAResolveWorkQueueCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleBinCullingCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleDepthBoundsCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleDispatchIndirectArgsCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleFinalDispatchIndirectArgsCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleLargeBinCullingCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleNoSortVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticlePreSortCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticlePS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleSortIndirectArgsCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleSpawnCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileCullingCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRender2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFast2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastDynamic2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastDynamicCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastLowRes2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastLowResCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowDynamic2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowDynamicCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowLowRes2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowLowResCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleUpdateCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ParticleVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PerfGraphBackgroundVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PerfGraphPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PerfGraphVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PresentHDRPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PresentSDRPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ResolveTAACS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\SharpeningUpsampleGammaPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\SharpeningUpsamplePS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\SharpenTAACS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\TemporalBlendCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\TextAntialiasPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\TextShadowPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\TextVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ScreenQuadVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ToneMapHDR2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ToneMapHDRCS.hlsl\" />\r\n    <ClInclude Include=\"ART\\Animation\\AnimatedValue.inl\">\r\n      <FileType>Document</FileType>\r\n    </ClInclude>\r\n    <FxCompile Include=\"Shaders\\VarianceMapCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <None Include=\"Math\\Functions.inl\" />\r\n    <None Include=\"Shaders\\AoBlurAndUpsampleCS.hlsli\" />\r\n    <None Include=\"Shaders\\AoRenderCS.hlsli\" />\r\n    <None Include=\"Shaders\\BitonicSortCommon.hlsli\" />\r\n    <None Include=\"Shaders\\ColorSpaceUtility.hlsli\" />\r\n    <None Include=\"Shaders\\DoFCommon.hlsli\" />\r\n    <None Include=\"Shaders\\DoFRS.hlsli\" />\r\n    <None Include=\"Shaders\\FXAAPass1CS.hlsli\" />\r\n    <None Include=\"Shaders\\FXAAPass2CS.hlsli\" />\r\n    <None Include=\"Shaders\\FXAARootSignature.hlsli\" />\r\n    <None Include=\"Shaders\\GenerateMipsCS.hlsli\" />\r\n    <None Include=\"Shaders\\MotionBlurRS.hlsli\" />\r\n    <None Include=\"Shaders\\ParticleRS.hlsli\" />\r\n    <None Include=\"Shaders\\ParticleUpdateCommon.hlsli\" />\r\n    <None Include=\"Shaders\\ParticleUtility.hlsli\" />\r\n    <None Include=\"Shaders\\PerfGraphRS.hlsli\" />\r\n    <None Include=\"Shaders\\PixelPacking_LUV.hlsli\" />\r\n    <None Include=\"Shaders\\PixelPacking_R11G11B10.hlsli\" />\r\n    <None Include=\"Shaders\\PixelPacking_RGBE.hlsli\" />\r\n    <None Include=\"Shaders\\PixelPacking_RGBM.hlsli\" />\r\n    <None Include=\"Shaders\\PixelPacking_Velocity.hlsli\" />\r\n    <None Include=\"Shaders\\PostEffectsRS.hlsli\" />\r\n    <None Include=\"Shaders\\PresentRS.hlsli\" />\r\n    <None Include=\"Shaders\\ShaderUtility.hlsli\" />\r\n    <FxCompile Include=\"Shaders\\ToneMap2CS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ToneMapCS.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\UpsampleAndBlurCS.hlsl\" />\r\n    <None Include=\"Shaders\\PixelPacking.hlsli\" />\r\n    <None Include=\"Shaders\\SSAORS.hlsli\" />\r\n    <None Include=\"Shaders\\TextRS.hlsli\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ItemDefinitionGroup>\r\n    <Lib>\r\n      <AdditionalDependencies Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">d3d11.lib;d2d1.lib;dwrite.lib;d3dcompiler.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Lib>\r\n    <Lib>\r\n      <AdditionalDependencies Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">d3d11.lib;d2d1.lib;dwrite.lib;d3dcompiler.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Lib>\r\n    <Lib>\r\n      <AdditionalDependencies Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">d3d11.lib;d2d1.lib;dwrite.lib;d3dcompiler.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n    </Lib>\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">..\\zlib-1.2.11;..\\rapidjson-master\\include\\rapidjson;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">..\\zlib-1.2.11;..\\rapidjson-master\\include\\rapidjson;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">..\\zlib-1.2.11;..\\rapidjson-master\\include\\rapidjson;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n  </ItemDefinitionGroup>\r\n  <ImportGroup Label=\"ExtensionTargets\" />\r\n</Project>"
  },
  {
    "path": "MiniEngine/Core/Core_VS17.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <ClInclude Include=\"CameraController.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"FileUtility.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GameCore.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GameInput.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"pch.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"EngineTuning.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SystemTime.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Utility.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"BufferManager.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ColorBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DepthBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GraphicsCore.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"LinearAllocator.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"MotionBlur.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PixelBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PostEffects.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ShadowBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SSAO.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TextRenderer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"FXAA.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"EsramAllocator.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"EngineProfiling.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Color.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\BoundingPlane.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\BoundingSphere.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Common.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Frustum.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Matrix3.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Matrix4.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Quaternion.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Scalar.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Transform.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Vector.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Camera.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ShadowCamera.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GpuBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PipelineState.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"RootSignature.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Hash.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SamplerManager.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CommandContext.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DescriptorHeap.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DDSTextureLoader.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CommandListManager.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GpuResource.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CommandSignature.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"dds.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DynamicDescriptorHeap.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DepthOfField.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"VectorMath.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ParticleEffect.h\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ParticleEffectManager.h\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ParticleEffectProperties.h\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ParticleShaderStructs.h\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Math\\Random.h\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TextureManager.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GraphRenderer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CommandAllocatorPool.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"BuddyAllocator.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DynamicUploadBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TemporalEffects.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GraphicsCommon.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"BitonicSort.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ReadbackBuffer.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\CommonDefs.h\">\r\n      <Filter>Source Files\\ART</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Animation\\AnimatedValue.h\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Animation\\SerializationUtil.h\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Animation\\AnimatedValue.inl\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\GUICore.h\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imconfig.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imgui.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imgui_impl_dx11.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\imgui_internal.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\stb_rect_pack.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\stb_textedit.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\imgui\\stb_truetype.h\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Animation\\CameraAnimation.h\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Animation\\SceneAnimation.h\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Animation\\AnimationController.h\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\AnimationWidget.h\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Sequencer\\FrameSequencer.h\">\r\n      <Filter>Source Files\\ART\\Sequencer</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\SequencerWidget.h\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\IGUIWidget.h\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\GUI\\GUIUtil.h\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\PerfStat\\PerfStat.h\">\r\n      <Filter>Source Files\\ART\\PerfStat</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GpuCounterManager.h\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ART\\Wddm22Defs.h\">\r\n      <Filter>Source Files\\ART</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"SystemTime.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GameInput.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CameraController.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"pch.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"FileUtility.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GameCore.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"BufferManager.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GraphicsCore.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Math\\Frustum.cpp\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Camera.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ShadowCamera.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PipelineState.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"RootSignature.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SamplerManager.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CommandContext.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DescriptorHeap.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DDSTextureLoader.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"EngineTuning.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"EngineProfiling.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CommandListManager.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ColorBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PixelBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DepthBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ShadowBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GpuBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"LinearAllocator.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TextRenderer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TextureManager.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PostEffects.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"FXAA.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Utility.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SSAO.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"MotionBlur.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CommandSignature.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DynamicDescriptorHeap.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DepthOfField.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ParticleEffect.cpp\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ParticleEffectManager.cpp\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ParticleEmissionProperties.cpp\">\r\n      <Filter>Source Files\\ParticleEffects</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Math\\Random.cpp\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GraphRenderer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CommandAllocatorPool.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"BuddyAllocator.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Color.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DynamicUploadBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TemporalEffects.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GraphicsCommon.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"BitonicSort.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ReadbackBuffer.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\Animation\\AnimatedValue.cpp\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\GUICore.cpp\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui.cpp\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui_demo.cpp\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui_draw.cpp\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\imgui\\imgui_impl_dx11.cpp\">\r\n      <Filter>Source Files\\ART\\GUI\\imgui</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\Animation\\CameraAnimation.cpp\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\Animation\\SceneAnimation.cpp\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\Animation\\AnimationController.cpp\">\r\n      <Filter>Source Files\\ART\\Animation</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\AnimationWidget.cpp\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\Sequencer\\FrameSequencer.cpp\">\r\n      <Filter>Source Files\\ART\\Sequencer</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\GUI\\SequencerWidget.cpp\">\r\n      <Filter>Source Files\\ART\\GUI</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ART\\PerfStat\\PerfStat.cpp\">\r\n      <Filter>Source Files\\ART\\PerfStat</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GpuCounterManager.cpp\">\r\n      <Filter>Source Files\\Graphics</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{3e74f37f-1e1e-47ed-9c44-213389384278}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\">\r\n      <UniqueIdentifier>{1f1bcce9-78f0-4b80-b715-6c87fc6ab458}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\Graphics\">\r\n      <UniqueIdentifier>{654fa440-b708-422e-b398-76625052f65d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\Math\">\r\n      <UniqueIdentifier>{88832a4d-d1d7-417b-95dd-19e85e4e4925}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ParticleEffects\">\r\n      <UniqueIdentifier>{b3fb4ae8-ce74-4476-92e5-e474dbd0f52d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\SSAO\">\r\n      <UniqueIdentifier>{b12f874a-0281-4c0a-a1c5-b9f84bf1b4cc}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\Particles\">\r\n      <UniqueIdentifier>{139dc1ab-725f-432c-8813-f550c0c90a54}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\DoF\">\r\n      <UniqueIdentifier>{7a95a1be-f0d2-42d7-8787-47125d0d8dc7}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\FXAA\">\r\n      <UniqueIdentifier>{be1a569c-d662-49be-971b-40d0c8febec6}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\HDR\">\r\n      <UniqueIdentifier>{1b22d859-284b-450b-9ed2-a9c0aceb033e}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\Text\">\r\n      <UniqueIdentifier>{26bdd93c-f50c-4dec-8ecc-eb6d783a7071}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\PerfGraph\">\r\n      <UniqueIdentifier>{b5a8a76d-c035-42d6-a864-608af4f678e8}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\Present\">\r\n      <UniqueIdentifier>{a12c93f7-f6a6-4dd0-aac0-5cc5fa42b749}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\Misc\">\r\n      <UniqueIdentifier>{3de5d9a4-74c3-446a-8fb6-90873bf7321b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\GenerateMips\">\r\n      <UniqueIdentifier>{6bfe1a9c-fe27-4aa4-b232-2f6b673b1f75}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\Temporal\">\r\n      <UniqueIdentifier>{7f434daa-8c60-4590-ba57-173c6209d888}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\BitonicSort\">\r\n      <UniqueIdentifier>{29bbd948-3d9f-4b00-a170-52bc3e18d6ce}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ART\">\r\n      <UniqueIdentifier>{008df79f-930f-4d2e-b624-6b9019e26239}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ART\\Animation\">\r\n      <UniqueIdentifier>{2cfbbbd5-76db-4c0d-bee1-e33a92c1a10e}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ART\\GUI\">\r\n      <UniqueIdentifier>{1ba53fb4-4a01-418d-b68b-76ec1c4d4274}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ART\\GUI\\imgui\">\r\n      <UniqueIdentifier>{c6333170-9527-4882-bd3e-90b66ba4366d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ART\\Sequencer\">\r\n      <UniqueIdentifier>{0b55bbf1-f1fa-45e8-8a85-04e1a756cc62}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\ART\\PerfStat\">\r\n      <UniqueIdentifier>{e9c90eb3-912f-488e-8bb5-d90f8b9160c2}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsampleBlendOutCS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsampleCS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsamplePreMinBlendOutCS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoBlurUpsamplePreMinCS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoPrepareDepthBuffers1CS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoPrepareDepthBuffers2CS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoRender1CS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AoRender2CS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFCombineCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFCombineFastCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFDebugBlueCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFDebugGreenCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFDebugRedCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFMedianFilterCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFMedianFilterFixupCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFMedianFilterSepAlphaCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPass1CS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPass2CS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPass2DebugCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPass2FastCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPass2FixupCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPreFilterCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPreFilterFastCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFPreFilterFixupCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFTilePassCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFTilePassFixupCS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_Luma_CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_RGB_CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2HCS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2HDebugCS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2VCS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2VDebugCS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAResolveWorkQueueCS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleBinCullingCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleDepthBoundsCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleDispatchIndirectArgsCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleFinalDispatchIndirectArgsCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleLargeBinCullingCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticlePreSortCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticlePS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleSortIndirectArgsCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleSpawnCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileCullingCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastDynamicCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastLowResCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowDynamicCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowLowResCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleUpdateCS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleVS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AdaptExposureCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ApplyBloomCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\AverageLumaCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BloomExtractAndDownsampleHdrCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BloomExtractAndDownsampleLdrCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DebugDrawHistogramCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceLdrCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceHdrCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DownsampleBloomCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DownsampleBloomAllCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ExtractLumaCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateHistogramCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ToneMapCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ToneMap2CS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BlurCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CameraMotionBlurPrePassCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CameraMotionBlurPrePassLinearZCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CameraVelocityCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MotionBlurFinalPassCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MotionBlurPrePassCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DebugSSAOCS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\TemporalBlendCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\UpsampleAndBlurCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PerfGraphBackgroundVS.hlsl\">\r\n      <Filter>Shaders\\PerfGraph</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PerfGraphPS.hlsl\">\r\n      <Filter>Shaders\\PerfGraph</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PerfGraphVS.hlsl\">\r\n      <Filter>Shaders\\PerfGraph</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\TextAntialiasPS.hlsl\">\r\n      <Filter>Shaders\\Text</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\TextShadowPS.hlsl\">\r\n      <Filter>Shaders\\Text</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\TextVS.hlsl\">\r\n      <Filter>Shaders\\Text</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\LinearizeDepthCS.hlsl\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicUpsamplePS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BilinearUpsamplePS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BufferCopyPS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ScreenQuadVS.hlsl\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaOddCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaOddXCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsGammaOddYCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearOddCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearOddXCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\GenerateMipsLinearOddYCS.hlsl\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicUpsampleGammaPS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\SharpeningUpsamplePS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\SharpeningUpsampleGammaPS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicHorizontalUpsamplePS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BicubicVerticalUpsamplePS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MagnifyPixelsPS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ToneMapHDR2CS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ToneMapHDRCS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ApplyBloom2CS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceLdr2CS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DebugLuminanceHdr2CS.hlsl\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFCombine2CS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DoFCombineFast2CS.hlsl\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2H2CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2V2CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRender2CS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFast2CS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastDynamic2CS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderFastLowRes2CS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowDynamic2CS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleTileRenderSlowLowRes2CS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CopyBackPostBufferCS.hlsl\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MotionBlurFinalPassPS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_Luma2_CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass1_RGB2_CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BoundNeighborhoodCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ResolveTAACS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\SharpenTAACS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PresentHDRPS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\PresentSDRPS.hlsl\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic32InnerSortCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic32OuterSortCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic32PreSortCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic64InnerSortCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic64OuterSortCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\Bitonic64PreSortCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\BitonicIndirectArgsCS.hlsl\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ParticleNoSortVS.hlsl\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2HDebug2CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FXAAPass2VDebug2CS.hlsl\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\VarianceMapCS.hlsl\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </FxCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"Math\\Functions.inl\">\r\n      <Filter>Source Files\\Math</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\DoFCommon.hlsli\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ParticleUtility.hlsli\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ParticleUpdateCommon.hlsli\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\AoBlurAndUpsampleCS.hlsli\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\AoRenderCS.hlsli\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\FXAAPass1CS.hlsli\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\FXAAPass2CS.hlsli\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\FXAARootSignature.hlsli\">\r\n      <Filter>Shaders\\FXAA</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PostEffectsRS.hlsli\">\r\n      <Filter>Shaders\\HDR</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\TextRS.hlsli\">\r\n      <Filter>Shaders\\Text</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\SSAORS.hlsli\">\r\n      <Filter>Shaders\\SSAO</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\DoFRS.hlsli\">\r\n      <Filter>Shaders\\DoF</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\MotionBlurRS.hlsli\">\r\n      <Filter>Shaders\\Temporal</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ParticleRS.hlsli\">\r\n      <Filter>Shaders\\Particles</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PerfGraphRS.hlsli\">\r\n      <Filter>Shaders\\PerfGraph</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PresentRS.hlsli\">\r\n      <Filter>Shaders\\Present</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PixelPacking.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ShaderUtility.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\GenerateMipsCS.hlsli\">\r\n      <Filter>Shaders\\GenerateMips</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PixelPacking_LUV.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PixelPacking_RGBE.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PixelPacking_RGBM.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PixelPacking_R11G11B10.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ColorSpaceUtility.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\BitonicSortCommon.hlsli\">\r\n      <Filter>Shaders\\BitonicSort</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\PixelPacking_Velocity.hlsli\">\r\n      <Filter>Shaders\\Misc</Filter>\r\n    </None>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "MiniEngine/Core/DDSTextureLoader.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//--------------------------------------------------------------------------------------\r\n//\r\n// Functions for loading a DDS texture and creating a Direct3D runtime resource for it\r\n//\r\n// Note these functions are useful as a light-weight runtime loader for DDS files. For\r\n// a full-featured DDS file reader, writer, and texture processing pipeline see\r\n// the 'Texconv' sample and the 'DirectXTex' library.\r\n//\r\n// http://go.microsoft.com/fwlink/?LinkId=248926\r\n// http://go.microsoft.com/fwlink/?LinkId=248929\r\n//--------------------------------------------------------------------------------------\r\n\r\n#include \"pch.h\"\r\n\r\n#include \"DDSTextureLoader.h\"\r\n\r\n#include \"dds.h\"\r\n#include \"GpuResource.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"Utility.h\"\r\n\r\nstruct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };\r\ntypedef public std::unique_ptr<void, handle_closer> ScopedHandle;\r\ninline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\nstatic HRESULT LoadTextureDataFromFile( _In_z_ const wchar_t* fileName,\r\n                                        std::unique_ptr<uint8_t[]>& ddsData,\r\n                                        DDS_HEADER** header,\r\n                                        uint8_t** bitData,\r\n                                        size_t* bitSize\r\n                                      )\r\n{\r\n    if (!header || !bitData || !bitSize)\r\n    {\r\n        return E_POINTER;\r\n    }\r\n\r\n    // open the file\r\n#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)\r\n    ScopedHandle hFile( safe_handle( CreateFile2( fileName,\r\n                                                  GENERIC_READ,\r\n                                                  FILE_SHARE_READ,\r\n                                                  OPEN_EXISTING,\r\n                                                  nullptr ) ) );\r\n#else\r\n    ScopedHandle hFile( safe_handle( CreateFileW( fileName,\r\n                                                  GENERIC_READ,\r\n                                                  FILE_SHARE_READ,\r\n                                                  nullptr,\r\n                                                  OPEN_EXISTING,\r\n                                                  FILE_ATTRIBUTE_NORMAL,\r\n                                                  nullptr ) ) );\r\n#endif\r\n\r\n    if ( !hFile )\r\n    {\r\n        return HRESULT_FROM_WIN32( GetLastError() );\r\n    }\r\n\r\n    // Get the file size\r\n    LARGE_INTEGER FileSize = { 0 };\r\n\r\n#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)\r\n    FILE_STANDARD_INFO fileInfo;\r\n    if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )\r\n    {\r\n        return HRESULT_FROM_WIN32( GetLastError() );\r\n    }\r\n    FileSize = fileInfo.EndOfFile;\r\n#else\r\n    GetFileSizeEx( hFile.get(), &FileSize );\r\n#endif\r\n\r\n    // File is too big for 32-bit allocation, so reject read\r\n    if (FileSize.HighPart > 0)\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    // Need at least enough data to fill the header and magic number to be a valid DDS\r\n    if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) ) )\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    // create enough space for the file data\r\n    ddsData.reset( new (std::nothrow) uint8_t[ FileSize.LowPart ] );\r\n    if (!ddsData)\r\n    {\r\n        return E_OUTOFMEMORY;\r\n    }\r\n\r\n    // read the data in\r\n    DWORD BytesRead = 0;\r\n    if (!ReadFile( hFile.get(),\r\n                   ddsData.get(),\r\n                   FileSize.LowPart,\r\n                   &BytesRead,\r\n                   nullptr\r\n                 ))\r\n    {\r\n        return HRESULT_FROM_WIN32( GetLastError() );\r\n    }\r\n\r\n    if (BytesRead < FileSize.LowPart)\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    // DDS files always start with the same magic number (\"DDS \")\r\n    uint32_t dwMagicNumber = *( const uint32_t* )( ddsData.get() );\r\n    if (dwMagicNumber != DDS_MAGIC)\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    auto hdr = reinterpret_cast<DDS_HEADER*>( ddsData.get() + sizeof( uint32_t ) );\r\n\r\n    // Verify header to validate DDS file\r\n    if (hdr->size != sizeof(DDS_HEADER) ||\r\n        hdr->ddspf.size != sizeof(DDS_PIXELFORMAT))\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    size_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER );\r\n\r\n    // Check for extensions\r\n    if (hdr->ddspf.flags & DDS_FOURCC)\r\n    {\r\n        if (MAKEFOURCC( 'D', 'X', '1', '0' ) == hdr->ddspf.fourCC)\r\n            offset += sizeof(DDS_HEADER_DXT10);\r\n    }\r\n\r\n    // Must be long enough for all headers and magic value\r\n    if (FileSize.LowPart < offset)\r\n        return E_FAIL;\r\n\r\n    // setup the pointers in the process request\r\n    *header = hdr;\r\n    *bitData = ddsData.get() + offset;\r\n    *bitSize = FileSize.LowPart - offset;\r\n\r\n    return S_OK;\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Return the BPP for a particular format\r\n//--------------------------------------------------------------------------------------\r\nsize_t BitsPerPixel( _In_ DXGI_FORMAT fmt )\r\n{\r\n    switch( fmt )\r\n    {\r\n    case DXGI_FORMAT_R32G32B32A32_TYPELESS:\r\n    case DXGI_FORMAT_R32G32B32A32_FLOAT:\r\n    case DXGI_FORMAT_R32G32B32A32_UINT:\r\n    case DXGI_FORMAT_R32G32B32A32_SINT:\r\n        return 128;\r\n\r\n    case DXGI_FORMAT_R32G32B32_TYPELESS:\r\n    case DXGI_FORMAT_R32G32B32_FLOAT:\r\n    case DXGI_FORMAT_R32G32B32_UINT:\r\n    case DXGI_FORMAT_R32G32B32_SINT:\r\n        return 96;\r\n\r\n    case DXGI_FORMAT_R16G16B16A16_TYPELESS:\r\n    case DXGI_FORMAT_R16G16B16A16_FLOAT:\r\n    case DXGI_FORMAT_R16G16B16A16_UNORM:\r\n    case DXGI_FORMAT_R16G16B16A16_UINT:\r\n    case DXGI_FORMAT_R16G16B16A16_SNORM:\r\n    case DXGI_FORMAT_R16G16B16A16_SINT:\r\n    case DXGI_FORMAT_R32G32_TYPELESS:\r\n    case DXGI_FORMAT_R32G32_FLOAT:\r\n    case DXGI_FORMAT_R32G32_UINT:\r\n    case DXGI_FORMAT_R32G32_SINT:\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n    case DXGI_FORMAT_Y416:\r\n    case DXGI_FORMAT_Y210:\r\n    case DXGI_FORMAT_Y216:\r\n        return 64;\r\n\r\n    case DXGI_FORMAT_R10G10B10A2_TYPELESS:\r\n    case DXGI_FORMAT_R10G10B10A2_UNORM:\r\n    case DXGI_FORMAT_R10G10B10A2_UINT:\r\n    case DXGI_FORMAT_R11G11B10_FLOAT:\r\n    case DXGI_FORMAT_R8G8B8A8_TYPELESS:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:\r\n    case DXGI_FORMAT_R8G8B8A8_UINT:\r\n    case DXGI_FORMAT_R8G8B8A8_SNORM:\r\n    case DXGI_FORMAT_R8G8B8A8_SINT:\r\n    case DXGI_FORMAT_R16G16_TYPELESS:\r\n    case DXGI_FORMAT_R16G16_FLOAT:\r\n    case DXGI_FORMAT_R16G16_UNORM:\r\n    case DXGI_FORMAT_R16G16_UINT:\r\n    case DXGI_FORMAT_R16G16_SNORM:\r\n    case DXGI_FORMAT_R16G16_SINT:\r\n    case DXGI_FORMAT_R32_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT:\r\n    case DXGI_FORMAT_R32_FLOAT:\r\n    case DXGI_FORMAT_R32_UINT:\r\n    case DXGI_FORMAT_R32_SINT:\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n    case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:\r\n    case DXGI_FORMAT_R8G8_B8G8_UNORM:\r\n    case DXGI_FORMAT_G8R8_G8B8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM:\r\n    case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:\r\n    case DXGI_FORMAT_B8G8R8A8_TYPELESS:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:\r\n    case DXGI_FORMAT_B8G8R8X8_TYPELESS:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:\r\n    case DXGI_FORMAT_AYUV:\r\n    case DXGI_FORMAT_Y410:\r\n    case DXGI_FORMAT_YUY2:\r\n        return 32;\r\n\r\n    case DXGI_FORMAT_P010:\r\n    case DXGI_FORMAT_P016:\r\n        return 24;\r\n\r\n    case DXGI_FORMAT_R8G8_TYPELESS:\r\n    case DXGI_FORMAT_R8G8_UNORM:\r\n    case DXGI_FORMAT_R8G8_UINT:\r\n    case DXGI_FORMAT_R8G8_SNORM:\r\n    case DXGI_FORMAT_R8G8_SINT:\r\n    case DXGI_FORMAT_R16_TYPELESS:\r\n    case DXGI_FORMAT_R16_FLOAT:\r\n    case DXGI_FORMAT_D16_UNORM:\r\n    case DXGI_FORMAT_R16_UNORM:\r\n    case DXGI_FORMAT_R16_UINT:\r\n    case DXGI_FORMAT_R16_SNORM:\r\n    case DXGI_FORMAT_R16_SINT:\r\n    case DXGI_FORMAT_B5G6R5_UNORM:\r\n    case DXGI_FORMAT_B5G5R5A1_UNORM:\r\n    case DXGI_FORMAT_A8P8:\r\n    case DXGI_FORMAT_B4G4R4A4_UNORM:\r\n        return 16;\r\n\r\n    case DXGI_FORMAT_NV12:\r\n    case DXGI_FORMAT_420_OPAQUE:\r\n    case DXGI_FORMAT_NV11:\r\n        return 12;\r\n\r\n    case DXGI_FORMAT_R8_TYPELESS:\r\n    case DXGI_FORMAT_R8_UNORM:\r\n    case DXGI_FORMAT_R8_UINT:\r\n    case DXGI_FORMAT_R8_SNORM:\r\n    case DXGI_FORMAT_R8_SINT:\r\n    case DXGI_FORMAT_A8_UNORM:\r\n    case DXGI_FORMAT_AI44:\r\n    case DXGI_FORMAT_IA44:\r\n    case DXGI_FORMAT_P8:\r\n        return 8;\r\n\r\n    case DXGI_FORMAT_R1_UNORM:\r\n        return 1;\r\n\r\n    case DXGI_FORMAT_BC1_TYPELESS:\r\n    case DXGI_FORMAT_BC1_UNORM:\r\n    case DXGI_FORMAT_BC1_UNORM_SRGB:\r\n    case DXGI_FORMAT_BC4_TYPELESS:\r\n    case DXGI_FORMAT_BC4_UNORM:\r\n    case DXGI_FORMAT_BC4_SNORM:\r\n        return 4;\r\n\r\n    case DXGI_FORMAT_BC2_TYPELESS:\r\n    case DXGI_FORMAT_BC2_UNORM:\r\n    case DXGI_FORMAT_BC2_UNORM_SRGB:\r\n    case DXGI_FORMAT_BC3_TYPELESS:\r\n    case DXGI_FORMAT_BC3_UNORM:\r\n    case DXGI_FORMAT_BC3_UNORM_SRGB:\r\n    case DXGI_FORMAT_BC5_TYPELESS:\r\n    case DXGI_FORMAT_BC5_UNORM:\r\n    case DXGI_FORMAT_BC5_SNORM:\r\n    case DXGI_FORMAT_BC6H_TYPELESS:\r\n    case DXGI_FORMAT_BC6H_UF16:\r\n    case DXGI_FORMAT_BC6H_SF16:\r\n    case DXGI_FORMAT_BC7_TYPELESS:\r\n    case DXGI_FORMAT_BC7_UNORM:\r\n    case DXGI_FORMAT_BC7_UNORM_SRGB:\r\n        return 8;\r\n\r\n    default:\r\n        return 0;\r\n    }\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Get surface information for a particular format\r\n//--------------------------------------------------------------------------------------\r\nstatic void GetSurfaceInfo( _In_ size_t width,\r\n                            _In_ size_t height,\r\n                            _In_ DXGI_FORMAT fmt,\r\n                            _Out_opt_ size_t* outNumBytes,\r\n                            _Out_opt_ size_t* outRowBytes,\r\n                            _Out_opt_ size_t* outNumRows )\r\n{\r\n    size_t numBytes = 0;\r\n    size_t rowBytes = 0;\r\n    size_t numRows = 0;\r\n\r\n    bool bc = false;\r\n    bool packed = false;\r\n    bool planar = false;\r\n    size_t bpe = 0;\r\n    switch (fmt)\r\n    {\r\n    case DXGI_FORMAT_BC1_TYPELESS:\r\n    case DXGI_FORMAT_BC1_UNORM:\r\n    case DXGI_FORMAT_BC1_UNORM_SRGB:\r\n    case DXGI_FORMAT_BC4_TYPELESS:\r\n    case DXGI_FORMAT_BC4_UNORM:\r\n    case DXGI_FORMAT_BC4_SNORM:\r\n        bc=true;\r\n        bpe = 8;\r\n        break;\r\n\r\n    case DXGI_FORMAT_BC2_TYPELESS:\r\n    case DXGI_FORMAT_BC2_UNORM:\r\n    case DXGI_FORMAT_BC2_UNORM_SRGB:\r\n    case DXGI_FORMAT_BC3_TYPELESS:\r\n    case DXGI_FORMAT_BC3_UNORM:\r\n    case DXGI_FORMAT_BC3_UNORM_SRGB:\r\n    case DXGI_FORMAT_BC5_TYPELESS:\r\n    case DXGI_FORMAT_BC5_UNORM:\r\n    case DXGI_FORMAT_BC5_SNORM:\r\n    case DXGI_FORMAT_BC6H_TYPELESS:\r\n    case DXGI_FORMAT_BC6H_UF16:\r\n    case DXGI_FORMAT_BC6H_SF16:\r\n    case DXGI_FORMAT_BC7_TYPELESS:\r\n    case DXGI_FORMAT_BC7_UNORM:\r\n    case DXGI_FORMAT_BC7_UNORM_SRGB:\r\n        bc = true;\r\n        bpe = 16;\r\n        break;\r\n\r\n    case DXGI_FORMAT_R8G8_B8G8_UNORM:\r\n    case DXGI_FORMAT_G8R8_G8B8_UNORM:\r\n    case DXGI_FORMAT_YUY2:\r\n        packed = true;\r\n        bpe = 4;\r\n        break;\r\n\r\n    case DXGI_FORMAT_Y210:\r\n    case DXGI_FORMAT_Y216:\r\n        packed = true;\r\n        bpe = 8;\r\n        break;\r\n\r\n    case DXGI_FORMAT_NV12:\r\n    case DXGI_FORMAT_420_OPAQUE:\r\n        planar = true;\r\n        bpe = 2;\r\n        break;\r\n\r\n    case DXGI_FORMAT_P010:\r\n    case DXGI_FORMAT_P016:\r\n        planar = true;\r\n        bpe = 4;\r\n        break;\r\n\r\n    }\r\n\r\n    if (bc)\r\n    {\r\n        size_t numBlocksWide = 0;\r\n        if (width > 0)\r\n        {\r\n            numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 );\r\n        }\r\n        size_t numBlocksHigh = 0;\r\n        if (height > 0)\r\n        {\r\n            numBlocksHigh = std::max<size_t>( 1, (height + 3) / 4 );\r\n        }\r\n        rowBytes = numBlocksWide * bpe;\r\n        numRows = numBlocksHigh;\r\n        numBytes = rowBytes * numBlocksHigh;\r\n    }\r\n    else if (packed)\r\n    {\r\n        rowBytes = ( ( width + 1 ) >> 1 ) * bpe;\r\n        numRows = height;\r\n        numBytes = rowBytes * height;\r\n    }\r\n    else if ( fmt == DXGI_FORMAT_NV11 )\r\n    {\r\n        rowBytes = ( ( width + 3 ) >> 2 ) * 4;\r\n        numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data\r\n        numBytes = rowBytes * numRows;\r\n    }\r\n    else if (planar)\r\n    {\r\n        rowBytes = ( ( width + 1 ) >> 1 ) * bpe;\r\n        numBytes = ( rowBytes * height ) + ( ( rowBytes * height + 1 ) >> 1 );\r\n        numRows = height + ( ( height + 1 ) >> 1 );\r\n    }\r\n    else\r\n    {\r\n        size_t bpp = BitsPerPixel( fmt );\r\n        rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte\r\n        numRows = height;\r\n        numBytes = rowBytes * height;\r\n    }\r\n\r\n    if (outNumBytes)\r\n    {\r\n        *outNumBytes = numBytes;\r\n    }\r\n    if (outRowBytes)\r\n    {\r\n        *outRowBytes = rowBytes;\r\n    }\r\n    if (outNumRows)\r\n    {\r\n        *outNumRows = numRows;\r\n    }\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\n#define ISBITMASK( r,g,b,a ) ( ddpf.RBitMask == r && ddpf.GBitMask == g && ddpf.BBitMask == b && ddpf.ABitMask == a )\r\n\r\nstatic DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf )\r\n{\r\n    if (ddpf.flags & DDS_RGB)\r\n    {\r\n        // Note that sRGB formats are written using the \"DX10\" extended header\r\n\r\n        switch (ddpf.RGBBitCount)\r\n        {\r\n        case 32:\r\n            if (ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000))\r\n            {\r\n                return DXGI_FORMAT_R8G8B8A8_UNORM;\r\n            }\r\n\r\n            if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000))\r\n            {\r\n                return DXGI_FORMAT_B8G8R8A8_UNORM;\r\n            }\r\n\r\n            if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000))\r\n            {\r\n                return DXGI_FORMAT_B8G8R8X8_UNORM;\r\n            }\r\n\r\n            // No DXGI format maps to ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8\r\n\r\n            // Note that many common DDS reader/writers (including D3DX) swap the\r\n            // the RED/BLUE masks for 10:10:10:2 formats. We assumme\r\n            // below that the 'backwards' header mask is being used since it is most\r\n            // likely written by D3DX. The more robust solution is to use the 'DX10'\r\n            // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly\r\n\r\n            // For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data\r\n            if (ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000))\r\n            {\r\n                return DXGI_FORMAT_R10G10B10A2_UNORM;\r\n            }\r\n\r\n            // No DXGI format maps to ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10\r\n\r\n            if (ISBITMASK(0x0000ffff,0xffff0000,0x00000000,0x00000000))\r\n            {\r\n                return DXGI_FORMAT_R16G16_UNORM;\r\n            }\r\n\r\n            if (ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000))\r\n            {\r\n                // Only 32-bit color channel format in D3D9 was R32F\r\n                return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114\r\n            }\r\n            break;\r\n\r\n        case 24:\r\n            // No 24bpp DXGI formats aka D3DFMT_R8G8B8\r\n            break;\r\n\r\n        case 16:\r\n            if (ISBITMASK(0x7c00,0x03e0,0x001f,0x8000))\r\n            {\r\n                return DXGI_FORMAT_B5G5R5A1_UNORM;\r\n            }\r\n            if (ISBITMASK(0xf800,0x07e0,0x001f,0x0000))\r\n            {\r\n                return DXGI_FORMAT_B5G6R5_UNORM;\r\n            }\r\n\r\n            // No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5\r\n\r\n            if (ISBITMASK(0x0f00,0x00f0,0x000f,0xf000))\r\n            {\r\n                return DXGI_FORMAT_B4G4R4A4_UNORM;\r\n            }\r\n\r\n            // No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4\r\n\r\n            // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.\r\n            break;\r\n        }\r\n    }\r\n    else if (ddpf.flags & DDS_LUMINANCE)\r\n    {\r\n        if (8 == ddpf.RGBBitCount)\r\n        {\r\n            if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000))\r\n            {\r\n                return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension\r\n            }\r\n\r\n            // No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4\r\n        }\r\n\r\n        if (16 == ddpf.RGBBitCount)\r\n        {\r\n            if (ISBITMASK(0x0000ffff,0x00000000,0x00000000,0x00000000))\r\n            {\r\n                return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension\r\n            }\r\n            if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00))\r\n            {\r\n                return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension\r\n            }\r\n        }\r\n    }\r\n    else if (ddpf.flags & DDS_ALPHA)\r\n    {\r\n        if (8 == ddpf.RGBBitCount)\r\n        {\r\n            return DXGI_FORMAT_A8_UNORM;\r\n        }\r\n    }\r\n    else if (ddpf.flags & DDS_FOURCC)\r\n    {\r\n        if (MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC1_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC2_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC3_UNORM;\r\n        }\r\n\r\n        // While pre-mulitplied alpha isn't directly supported by the DXGI formats,\r\n        // they are basically the same as these BC formats so they can be mapped\r\n        if (MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC2_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC3_UNORM;\r\n        }\r\n\r\n        if (MAKEFOURCC( 'A', 'T', 'I', '1' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC4_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'B', 'C', '4', 'U' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC4_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'B', 'C', '4', 'S' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC4_SNORM;\r\n        }\r\n\r\n        if (MAKEFOURCC( 'A', 'T', 'I', '2' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC5_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'B', 'C', '5', 'U' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC5_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'B', 'C', '5', 'S' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_BC5_SNORM;\r\n        }\r\n\r\n        // BC6H and BC7 are written using the \"DX10\" extended header\r\n\r\n        if (MAKEFOURCC( 'R', 'G', 'B', 'G' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_R8G8_B8G8_UNORM;\r\n        }\r\n        if (MAKEFOURCC( 'G', 'R', 'G', 'B' ) == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_G8R8_G8B8_UNORM;\r\n        }\r\n\r\n        if (MAKEFOURCC('Y','U','Y','2') == ddpf.fourCC)\r\n        {\r\n            return DXGI_FORMAT_YUY2;\r\n        }\r\n\r\n        // Check for D3DFORMAT enums being set here\r\n        switch( ddpf.fourCC )\r\n        {\r\n        case 36: // D3DFMT_A16B16G16R16\r\n            return DXGI_FORMAT_R16G16B16A16_UNORM;\r\n\r\n        case 110: // D3DFMT_Q16W16V16U16\r\n            return DXGI_FORMAT_R16G16B16A16_SNORM;\r\n\r\n        case 111: // D3DFMT_R16F\r\n            return DXGI_FORMAT_R16_FLOAT;\r\n\r\n        case 112: // D3DFMT_G16R16F\r\n            return DXGI_FORMAT_R16G16_FLOAT;\r\n\r\n        case 113: // D3DFMT_A16B16G16R16F\r\n            return DXGI_FORMAT_R16G16B16A16_FLOAT;\r\n\r\n        case 114: // D3DFMT_R32F\r\n            return DXGI_FORMAT_R32_FLOAT;\r\n\r\n        case 115: // D3DFMT_G32R32F\r\n            return DXGI_FORMAT_R32G32_FLOAT;\r\n\r\n        case 116: // D3DFMT_A32B32G32R32F\r\n            return DXGI_FORMAT_R32G32B32A32_FLOAT;\r\n        }\r\n    }\r\n\r\n    return DXGI_FORMAT_UNKNOWN;\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\nstatic DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT format )\r\n{\r\n    switch( format )\r\n    {\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM:\r\n        return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;\r\n\r\n    case DXGI_FORMAT_BC1_UNORM:\r\n        return DXGI_FORMAT_BC1_UNORM_SRGB;\r\n\r\n    case DXGI_FORMAT_BC2_UNORM:\r\n        return DXGI_FORMAT_BC2_UNORM_SRGB;\r\n\r\n    case DXGI_FORMAT_BC3_UNORM:\r\n        return DXGI_FORMAT_BC3_UNORM_SRGB;\r\n\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM:\r\n        return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;\r\n\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM:\r\n        return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;\r\n\r\n    case DXGI_FORMAT_BC7_UNORM:\r\n        return DXGI_FORMAT_BC7_UNORM_SRGB;\r\n\r\n    default:\r\n        return format;\r\n    }\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\nstatic HRESULT FillInitData( _In_ size_t width,\r\n                             _In_ size_t height,\r\n                             _In_ size_t depth,\r\n                             _In_ size_t mipCount,\r\n                             _In_ size_t arraySize,\r\n                             _In_ DXGI_FORMAT format,\r\n                             _In_ size_t maxsize,\r\n                             _In_ size_t bitSize,\r\n                             _In_reads_bytes_(bitSize) const uint8_t* bitData,\r\n                             _Out_ size_t& twidth,\r\n                             _Out_ size_t& theight,\r\n                             _Out_ size_t& tdepth,\r\n                             _Out_ size_t& skipMip,\r\n                             _Out_writes_(mipCount*arraySize) D3D12_SUBRESOURCE_DATA* initData )\r\n{\r\n    if ( !bitData || !initData )\r\n    {\r\n        return E_POINTER;\r\n    }\r\n\r\n    skipMip = 0;\r\n    twidth = 0;\r\n    theight = 0;\r\n    tdepth = 0;\r\n\r\n    size_t NumBytes = 0;\r\n    size_t RowBytes = 0;\r\n    const uint8_t* pSrcBits = bitData;\r\n    const uint8_t* pEndBits = bitData + bitSize;\r\n\r\n    size_t index = 0;\r\n    for( size_t j = 0; j < arraySize; j++ )\r\n    {\r\n        size_t w = width;\r\n        size_t h = height;\r\n        size_t d = depth;\r\n        for( size_t i = 0; i < mipCount; i++ )\r\n        {\r\n            GetSurfaceInfo( w,\r\n                            h,\r\n                            format,\r\n                            &NumBytes,\r\n                            &RowBytes,\r\n                            nullptr\r\n                          );\r\n\r\n            if ( (mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize) )\r\n            {\r\n                if ( !twidth )\r\n                {\r\n                    twidth = w;\r\n                    theight = h;\r\n                    tdepth = d;\r\n                }\r\n\r\n                assert(index < mipCount * arraySize);\r\n                _Analysis_assume_(index < mipCount * arraySize);\r\n                initData[index].pData = ( const void* )pSrcBits;\r\n                initData[index].RowPitch = static_cast<UINT>( RowBytes );\r\n                initData[index].SlicePitch = static_cast<UINT>( NumBytes );\r\n                ++index;\r\n            }\r\n            else if ( !j )\r\n            {\r\n                // Count number of skipped mipmaps (first item only)\r\n                ++skipMip;\r\n            }\r\n\r\n            if (pSrcBits + (NumBytes*d) > pEndBits)\r\n            {\r\n                return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );\r\n            }\r\n  \r\n            pSrcBits += NumBytes * d;\r\n\r\n            w = w >> 1;\r\n            h = h >> 1;\r\n            d = d >> 1;\r\n            if (w == 0)\r\n            {\r\n                w = 1;\r\n            }\r\n            if (h == 0)\r\n            {\r\n                h = 1;\r\n            }\r\n            if (d == 0)\r\n            {\r\n                d = 1;\r\n            }\r\n        }\r\n    }\r\n\r\n    return (index > 0) ? S_OK : E_FAIL;\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\nstatic HRESULT CreateD3DResources( _In_ DX12_DEVICE* d3dDevice,\r\n                                   _In_ uint32_t resDim,\r\n                                   _In_ size_t width,\r\n                                   _In_ size_t height,\r\n                                   _In_ size_t depth,\r\n                                   _In_ size_t mipCount,\r\n                                   _In_ size_t arraySize,\r\n                                   _In_ DXGI_FORMAT format,\r\n                                   _In_ bool forceSRGB,\r\n                                   _In_ bool isCubeMap,\r\n                                   _Outptr_opt_ ID3D12Resource** texture,\r\n                                   _In_ D3D12_CPU_DESCRIPTOR_HANDLE textureView )\r\n{\r\n    if ( !d3dDevice )\r\n        return E_POINTER;\r\n\r\n    HRESULT hr = E_FAIL;\r\n\r\n    if ( forceSRGB )\r\n    {\r\n        format = MakeSRGB( format );\r\n    }\r\n\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    D3D12_RESOURCE_DESC ResourceDesc;\r\n    ResourceDesc.Alignment = 0;\r\n    ResourceDesc.Width = static_cast<UINT64>( width );\r\n    ResourceDesc.Height = static_cast<UINT>( height );\r\n    ResourceDesc.DepthOrArraySize = static_cast<UINT16>( arraySize );\r\n    ResourceDesc.MipLevels = static_cast<UINT16>( mipCount );\r\n    ResourceDesc.Format = format;\r\n    ResourceDesc.SampleDesc.Count = 1;\r\n    ResourceDesc.SampleDesc.Quality = 0;\r\n    ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;\r\n    ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;\r\n\r\n    switch ( resDim ) \r\n    {\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n            {\r\n                ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D;\r\n\r\n                ID3D12Resource* tex = nullptr;\r\n                hr = d3dDevice->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc,\r\n                    D3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&tex));\r\n\r\n                if (SUCCEEDED( hr ) && tex != nullptr)\r\n                {\r\n                    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n                    SRVDesc.Format = format;\r\n                    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n\r\n                    if (arraySize > 1)\r\n                    {\r\n                        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;\r\n                        SRVDesc.Texture1DArray.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n                        SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>( arraySize );\r\n                    }\r\n                    else\r\n                    {\r\n                        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;\r\n                        SRVDesc.Texture1D.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n                    }\r\n\r\n                    d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );\r\n\r\n                    if (texture != nullptr)\r\n                    {\r\n                        *texture = tex;\r\n                    }\r\n                    else\r\n                    {\r\n                        tex->SetName(L\"DDSTextureLoader\");\r\n                        tex->Release();\r\n                    }\r\n                }\r\n            }\r\n           break;\r\n\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n            {\r\n                ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\r\n\r\n                ID3D12Resource* tex = nullptr;\r\n                hr = d3dDevice->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc,\r\n                    D3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&tex));\r\n\r\n                if (SUCCEEDED( hr ) && tex != 0)\r\n                {\r\n                    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n                    SRVDesc.Format = format;\r\n                    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n\r\n                    if ( isCubeMap )\r\n                    {\r\n                        if (arraySize > 6)\r\n                        {\r\n                            SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;\r\n                            SRVDesc.TextureCubeArray.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n\r\n                            // Earlier we set arraySize to (NumCubes * 6)\r\n                            SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>( arraySize / 6 );\r\n                        }\r\n                        else\r\n                        {\r\n                            SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;\r\n                            SRVDesc.TextureCube.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n                        }\r\n                    }\r\n                    else if (arraySize > 1)\r\n                    {\r\n                        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;\r\n                        SRVDesc.Texture2DArray.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n                        SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>( arraySize );\r\n                    }\r\n                    else\r\n                    {\r\n                        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;\r\n                        SRVDesc.Texture2D.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n                        SRVDesc.Texture2D.MostDetailedMip = 0;\r\n                    }\r\n\r\n                    d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );\r\n\r\n                    if (texture != nullptr)\r\n                    {\r\n                        *texture = tex;\r\n                    }\r\n                    else\r\n                    {\r\n                        tex->SetName(L\"DDSTextureLoader\");\r\n                        tex->Release();\r\n                    }\r\n                }\r\n            }\r\n            break;\r\n\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n            {\r\n                ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;\r\n                ResourceDesc.DepthOrArraySize = static_cast<UINT16>( depth );\r\n\r\n                ID3D12Resource* tex = nullptr;\r\n                hr = d3dDevice->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc,\r\n                    D3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&tex));\r\n\r\n                if (SUCCEEDED( hr ) && tex != nullptr)\r\n                {\r\n                    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n                    SRVDesc.Format = format;\r\n                    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n\r\n                    SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;\r\n                    SRVDesc.Texture3D.MipLevels = (!mipCount) ? -1 : ResourceDesc.MipLevels;\r\n                    SRVDesc.Texture3D.MostDetailedMip = 0;\r\n\r\n                    d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );\r\n\r\n                    if (texture != nullptr)\r\n                    {\r\n                        *texture = tex;\r\n                    }\r\n                    else\r\n                    {\r\n                        tex->SetName(L\"DDS Texture (3D)\");\r\n                        tex->Release();\r\n                    }\r\n                }\r\n            }\r\n           break;\r\n    }\r\n\r\n    return hr;\r\n}\r\n\r\n//--------------------------------------------------------------------------------------\r\nstatic HRESULT CreateTextureFromDDS( _In_ DX12_DEVICE* d3dDevice,\r\n                                     _In_ const DDS_HEADER* header,\r\n                                     _In_reads_bytes_(bitSize) const uint8_t* bitData,\r\n                                     _In_ size_t bitSize,\r\n                                     _In_ size_t maxsize,\r\n                                     _In_ bool forceSRGB,\r\n                                     _Outptr_opt_ ID3D12Resource** texture,\r\n                                     _In_ D3D12_CPU_DESCRIPTOR_HANDLE textureView )\r\n{\r\n    HRESULT hr = S_OK;\r\n\r\n    UINT width = header->width;\r\n    UINT height = header->height;\r\n    UINT depth = header->depth;\r\n\r\n    uint32_t resDim = D3D12_RESOURCE_DIMENSION_UNKNOWN;\r\n    UINT arraySize = 1;\r\n    DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;\r\n    bool isCubeMap = false;\r\n\r\n    size_t mipCount = header->mipMapCount;\r\n    if (0 == mipCount)\r\n    {\r\n        mipCount = 1;\r\n    }\r\n\r\n    if ((header->ddspf.flags & DDS_FOURCC) && (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC ))\r\n    {\r\n        auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const char*)header + sizeof(DDS_HEADER) );\r\n\r\n        arraySize = d3d10ext->arraySize;\r\n        if (arraySize == 0)\r\n        {\r\n           return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );\r\n        }\r\n\r\n        switch( d3d10ext->dxgiFormat )\r\n        {\r\n        case DXGI_FORMAT_AI44:\r\n        case DXGI_FORMAT_IA44:\r\n        case DXGI_FORMAT_P8:\r\n        case DXGI_FORMAT_A8P8:\r\n            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n\r\n        default:\r\n            if ( BitsPerPixel( d3d10ext->dxgiFormat ) == 0 )\r\n            {\r\n                return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n            }\r\n        }\r\n           \r\n        format = d3d10ext->dxgiFormat;\r\n\r\n        switch ( d3d10ext->resourceDimension )\r\n        {\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n            // D3DX writes 1D textures with a fixed Height of 1\r\n            if ((header->flags & DDS_HEIGHT) && height != 1)\r\n            {\r\n                return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );\r\n            }\r\n            height = depth = 1;\r\n            break;\r\n\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n            if (d3d10ext->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE)\r\n            {\r\n                arraySize *= 6;\r\n                isCubeMap = true;\r\n            }\r\n            depth = 1;\r\n            break;\r\n\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n            if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))\r\n            {\r\n                return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );\r\n            }\r\n\r\n            if (arraySize > 1)\r\n            {\r\n                return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n            }\r\n            break;\r\n\r\n        default:\r\n            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n        }\r\n\r\n        resDim = d3d10ext->resourceDimension;\r\n    }\r\n    else\r\n    {\r\n        format = GetDXGIFormat( header->ddspf );\r\n\r\n        if (format == DXGI_FORMAT_UNKNOWN)\r\n        {\r\n           return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n        }\r\n\r\n        if (header->flags & DDS_HEADER_FLAGS_VOLUME)\r\n        {\r\n            resDim = D3D12_RESOURCE_DIMENSION_TEXTURE3D;\r\n        }\r\n        else \r\n        {\r\n            if (header->caps2 & DDS_CUBEMAP)\r\n            {\r\n                // We require all six faces to be defined\r\n                if ((header->caps2 & DDS_CUBEMAP_ALLFACES ) != DDS_CUBEMAP_ALLFACES)\r\n                {\r\n                    return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n                }\r\n\r\n                arraySize = 6;\r\n                isCubeMap = true;\r\n            }\r\n\r\n            depth = 1;\r\n            resDim = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\r\n\r\n            // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture\r\n        }\r\n\r\n        assert( BitsPerPixel( format ) != 0 );\r\n    }\r\n\r\n    // Bound sizes (for security purposes we don't trust DDS file metadata larger than the D3D 11.x hardware requirements)\r\n    if (mipCount > D3D12_REQ_MIP_LEVELS)\r\n    {\r\n        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n    }\r\n\r\n    switch ( resDim )\r\n    {\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n        if ((arraySize > D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||\r\n            (width > D3D12_REQ_TEXTURE1D_U_DIMENSION) )\r\n        {\r\n            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n        }\r\n        break;\r\n\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n        if ( isCubeMap )\r\n        {\r\n            // This is the right bound because we set arraySize to (NumCubes*6) above\r\n            if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||\r\n                (width > D3D12_REQ_TEXTURECUBE_DIMENSION) ||\r\n                (height > D3D12_REQ_TEXTURECUBE_DIMENSION))\r\n            {\r\n                return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n            }\r\n        }\r\n        else if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||\r\n                    (width > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||\r\n                    (height > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION))\r\n        {\r\n            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n        }\r\n        break;\r\n\r\n    case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n        if ((arraySize > 1) ||\r\n            (width > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||\r\n            (height > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||\r\n            (depth > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )\r\n        {\r\n            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n        }\r\n        break;\r\n\r\n    default:\r\n        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );\r\n    }\r\n\r\n    {\r\n        // Create the texture\r\n        UINT subresourceCount = static_cast<UINT>(mipCount) * arraySize;\r\n        std::unique_ptr<D3D12_SUBRESOURCE_DATA[]> initData( new (std::nothrow) D3D12_SUBRESOURCE_DATA[subresourceCount] );\r\n        if ( !initData )\r\n        {\r\n            return E_OUTOFMEMORY;\r\n        }\r\n\r\n        size_t skipMip = 0;\r\n        size_t twidth = 0;\r\n        size_t theight = 0;\r\n        size_t tdepth = 0;\r\n        hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,\r\n                           twidth, theight, tdepth, skipMip, initData.get() );\r\n\r\n        if ( SUCCEEDED(hr) )\r\n        {\r\n            hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,\r\n                                     format, forceSRGB,\r\n                                     isCubeMap, texture, textureView );\r\n\r\n            if ( FAILED(hr) && !maxsize && (mipCount > 1) )\r\n            {\r\n                // Retry with a maxsize determined by feature level\r\n                maxsize = (resDim == D3D12_RESOURCE_DIMENSION_TEXTURE3D)\r\n                            ? 2048 /*D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/\r\n                            : 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;\r\n\r\n                hr = FillInitData( width, height, depth, mipCount, arraySize, format, maxsize, bitSize, bitData,\r\n                                   twidth, theight, tdepth, skipMip, initData.get() );\r\n                if ( SUCCEEDED(hr) )\r\n                {\r\n                    hr = CreateD3DResources( d3dDevice, resDim, twidth, theight, tdepth, mipCount - skipMip, arraySize,\r\n                                             format, forceSRGB,\r\n                                             isCubeMap, texture, textureView );\r\n                }\r\n            }\r\n        }\r\n\r\n        if (SUCCEEDED(hr))\r\n        {\r\n            GpuResource DestTexture(*texture, D3D12_RESOURCE_STATE_COPY_DEST);\r\n            CommandContext::InitializeTexture(DestTexture, subresourceCount, initData.get());\r\n        }\r\n    }\r\n\r\n    return hr;\r\n}\r\n\r\n\r\n//--------------------------------------------------------------------------------------\r\nstatic DDS_ALPHA_MODE GetAlphaMode( _In_ const DDS_HEADER* header )\r\n{\r\n    if ( header->ddspf.flags & DDS_FOURCC )\r\n    {\r\n        if ( MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC )\r\n        {\r\n            auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const char*)header + sizeof(DDS_HEADER) );\r\n            auto mode = static_cast<DDS_ALPHA_MODE>( d3d10ext->miscFlags2 & DDS_MISC_FLAGS2_ALPHA_MODE_MASK );\r\n            switch( mode )\r\n            {\r\n            case DDS_ALPHA_MODE_STRAIGHT:\r\n            case DDS_ALPHA_MODE_PREMULTIPLIED:\r\n            case DDS_ALPHA_MODE_OPAQUE:\r\n            case DDS_ALPHA_MODE_CUSTOM:\r\n                return mode;\r\n            }\r\n        }\r\n        else if ( ( MAKEFOURCC( 'D', 'X', 'T', '2' ) == header->ddspf.fourCC )\r\n                  || ( MAKEFOURCC( 'D', 'X', 'T', '4' ) == header->ddspf.fourCC ) )\r\n        {\r\n            return DDS_ALPHA_MODE_PREMULTIPLIED;\r\n        }\r\n    }\r\n\r\n    return DDS_ALPHA_MODE_UNKNOWN;\r\n}\r\n\r\n\r\n_Use_decl_annotations_\r\nHRESULT CreateDDSTextureFromMemory(\r\n    DX12_DEVICE* d3dDevice,\r\n    const uint8_t* ddsData,\r\n    size_t ddsDataSize,\r\n    size_t maxsize,\r\n    bool forceSRGB,\r\n    ID3D12Resource** texture,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE textureView,\r\n    DDS_ALPHA_MODE* alphaMode )\r\n{\r\n    if ( texture )\r\n    {\r\n        *texture = nullptr;\r\n    }\r\n\r\n    if ( alphaMode )\r\n    {\r\n        *alphaMode = DDS_ALPHA_MODE_UNKNOWN;\r\n    }\r\n\r\n    if (!d3dDevice || !ddsData)\r\n    {\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    // Validate DDS file in memory\r\n    if (ddsDataSize < (sizeof(uint32_t) + sizeof(DDS_HEADER)))\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    uint32_t dwMagicNumber = *( const uint32_t* )( ddsData );\r\n    if (dwMagicNumber != DDS_MAGIC)\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    auto header = reinterpret_cast<const DDS_HEADER*>( ddsData + sizeof( uint32_t ) );\r\n\r\n    // Verify header to validate DDS file\r\n    if (header->size != sizeof(DDS_HEADER) ||\r\n        header->ddspf.size != sizeof(DDS_PIXELFORMAT))\r\n    {\r\n        return E_FAIL;\r\n    }\r\n\r\n    size_t offset = sizeof(DDS_HEADER) + sizeof(uint32_t);\r\n\r\n    // Check for extensions\r\n    if (header->ddspf.flags & DDS_FOURCC)\r\n    {\r\n        if (MAKEFOURCC( 'D', 'X', '1', '0' ) == header->ddspf.fourCC)\r\n            offset += sizeof(DDS_HEADER_DXT10);\r\n    }\r\n\r\n    // Must be long enough for all headers and magic value\r\n    if (ddsDataSize < offset)\r\n        return E_FAIL;\r\n\r\n    HRESULT hr = CreateTextureFromDDS( d3dDevice,\r\n                                       header, ddsData + offset, ddsDataSize - offset, maxsize,\r\n                                       forceSRGB, texture, textureView );\r\n    if ( SUCCEEDED(hr) )\r\n    {\r\n        if (texture != nullptr && *texture != nullptr)\r\n        {\r\n            (*texture)->SetName(L\"DDSTextureLoader\");\r\n        }\r\n\r\n        if ( alphaMode )\r\n            *alphaMode = GetAlphaMode( header );\r\n    }\r\n\r\n    return hr;\r\n}\r\n\r\n\r\n_Use_decl_annotations_\r\nHRESULT CreateDDSTextureFromFile(\r\n    DX12_DEVICE* d3dDevice,\r\n    const wchar_t* fileName,\r\n    size_t maxsize,\r\n    bool forceSRGB,\r\n    ID3D12Resource** texture,\r\n    D3D12_CPU_DESCRIPTOR_HANDLE textureView,\r\n    DDS_ALPHA_MODE* alphaMode )\r\n{\r\n    if ( texture )\r\n    {\r\n        *texture = nullptr;\r\n    }\r\n\r\n    if ( alphaMode )\r\n    {\r\n        *alphaMode = DDS_ALPHA_MODE_UNKNOWN;\r\n    }\r\n\r\n    if (!d3dDevice || !fileName)\r\n    {\r\n        return E_INVALIDARG;\r\n    }\r\n\r\n    DDS_HEADER* header = nullptr;\r\n    uint8_t* bitData = nullptr;\r\n    size_t bitSize = 0;\r\n\r\n    std::unique_ptr<uint8_t[]> ddsData;\r\n    HRESULT hr = LoadTextureDataFromFile( fileName, ddsData, &header, &bitData, &bitSize );\r\n    if (FAILED(hr))\r\n    {\r\n        return hr;\r\n    }\r\n\r\n    hr = CreateTextureFromDDS( d3dDevice,\r\n                               header, bitData, bitSize, maxsize,\r\n                               forceSRGB, texture, textureView );\r\n\r\n    if ( alphaMode )\r\n        *alphaMode = GetAlphaMode( header );\r\n\r\n    return hr;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DDSTextureLoader.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//--------------------------------------------------------------------------------------\r\n//\r\n// Functions for loading a DDS texture and creating a Direct3D runtime resource for it\r\n//\r\n// Note these functions are useful as a light-weight runtime loader for DDS files. For\r\n// a full-featured DDS file reader, writer, and texture processing pipeline see\r\n// the 'Texconv' sample and the 'DirectXTex' library.\r\n//\r\n// http://go.microsoft.com/fwlink/?LinkId=248926\r\n// http://go.microsoft.com/fwlink/?LinkId=248929\r\n//--------------------------------------------------------------------------------------\r\n\r\n#pragma once\r\n\r\n#include <d3d12.h>\r\n\r\n#pragma warning(push)\r\n#pragma warning(disable : 4005)\r\n#include <stdint.h>\r\n#pragma warning(pop)\r\n\r\nenum DDS_ALPHA_MODE\r\n{\r\n    DDS_ALPHA_MODE_UNKNOWN       = 0,\r\n    DDS_ALPHA_MODE_STRAIGHT      = 1,\r\n    DDS_ALPHA_MODE_PREMULTIPLIED = 2,\r\n    DDS_ALPHA_MODE_OPAQUE        = 3,\r\n    DDS_ALPHA_MODE_CUSTOM        = 4,\r\n};\r\n\r\nHRESULT __cdecl CreateDDSTextureFromMemory( _In_ DX12_DEVICE* d3dDevice,\r\n                                                _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,\r\n                                                _In_ size_t ddsDataSize,\r\n                                                _In_ size_t maxsize,\r\n                                                _In_ bool forceSRGB,\r\n                                                _Outptr_opt_ ID3D12Resource** texture,\r\n                                                _In_ D3D12_CPU_DESCRIPTOR_HANDLE textureView,\r\n                                                _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr\r\n                                            );\r\n\r\nHRESULT __cdecl CreateDDSTextureFromFile( _In_ DX12_DEVICE* d3dDevice,\r\n                                            _In_z_ const wchar_t* szFileName,\r\n                                            _In_ size_t maxsize,\r\n                                            _In_ bool forceSRGB,\r\n                                            _Outptr_opt_ ID3D12Resource** texture,\r\n                                            _In_ D3D12_CPU_DESCRIPTOR_HANDLE textureView,\r\n                                            _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr\r\n                                            );\r\n\r\nsize_t BitsPerPixel(_In_ DXGI_FORMAT fmt);\r\n"
  },
  {
    "path": "MiniEngine/Core/DepthBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"DepthBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"EsramAllocator.h\"\r\n#include \"DescriptorHeap.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nvoid DepthBuffer::Create( const std::wstring& Name, uint32_t Width, uint32_t Height, DXGI_FORMAT Format, D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr )\r\n{\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeTex2D(Width, Height, 1, 1, Format, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);\r\n\r\n    D3D12_CLEAR_VALUE ClearValue = {};\r\n    ClearValue.Format = Format;\r\n    CreateTextureResource(Graphics::g_Device, Name, ResourceDesc, ClearValue, VidMemPtr);\r\n    CreateDerivedViews(Graphics::g_Device, Format);\r\n}\r\n\r\nvoid DepthBuffer::Create( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t Samples, DXGI_FORMAT Format, D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr )\r\n{\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeTex2D(Width, Height, 1, 1, Format, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);\r\n    ResourceDesc.SampleDesc.Count = Samples;\r\n\r\n    D3D12_CLEAR_VALUE ClearValue = {};\r\n    ClearValue.Format = Format;\r\n    CreateTextureResource(Graphics::g_Device, Name, ResourceDesc, ClearValue, VidMemPtr);\r\n    CreateDerivedViews(Graphics::g_Device, Format);\r\n}\r\n\r\nvoid DepthBuffer::Create( const std::wstring& Name, uint32_t Width, uint32_t Height, DXGI_FORMAT Format, EsramAllocator& )\r\n{\r\n    Create(Name, Width, Height, Format);\r\n}\r\n\r\nvoid DepthBuffer::Create( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t Samples, DXGI_FORMAT Format, EsramAllocator& Allocator )\r\n{\r\n    Create(Name, Width, Height, Samples, Format);\r\n}\r\n\r\nvoid DepthBuffer::CreatePlaced( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t Samples, DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset )\r\n{\r\n    CreatePlacedResource(Name, Width, Height, Samples, Format, Heap, HeapOffset, true);\r\n}\r\n\r\nvoid DepthBuffer::RecreatePlaced( uint32_t Width, uint32_t Height, uint32_t Samples, DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset )\r\n{\r\n    CreatePlacedResource(L\"\", Width, Height, Samples, Format, Heap, HeapOffset, false);\r\n}\r\n\r\nvoid DepthBuffer::CreateDerivedViews( DX12_DEVICE* Device, DXGI_FORMAT Format )\r\n{\r\n    ID3D12Resource* Resource = m_pResource.Get();\r\n\r\n    D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;\r\n    dsvDesc.Format = GetDSVFormat(Format);\r\n    if (Resource->GetDesc().SampleDesc.Count == 1)\r\n    {\r\n        dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;\r\n        dsvDesc.Texture2D.MipSlice = 0;\r\n    }\r\n    else\r\n    {\r\n        dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;\r\n    }\r\n\r\n    if (m_hDSV[0].ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n    {\r\n        m_hDSV[0] = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\r\n        m_hDSV[1] = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\r\n    }\r\n\r\n    dsvDesc.Flags = D3D12_DSV_FLAG_NONE;\r\n    Device->CreateDepthStencilView(Resource, &dsvDesc, m_hDSV[0]);\r\n\r\n    dsvDesc.Flags = D3D12_DSV_FLAG_READ_ONLY_DEPTH;\r\n    Device->CreateDepthStencilView(Resource, &dsvDesc, m_hDSV[1]);\r\n\r\n    DXGI_FORMAT stencilReadFormat = GetStencilFormat(Format);\r\n    if (stencilReadFormat != DXGI_FORMAT_UNKNOWN)\r\n    {\r\n        if (m_hDSV[2].ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        {\r\n            m_hDSV[2] = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\r\n            m_hDSV[3] = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\r\n        }\r\n\r\n        dsvDesc.Flags = D3D12_DSV_FLAG_READ_ONLY_STENCIL;\r\n        Device->CreateDepthStencilView(Resource, &dsvDesc, m_hDSV[2]);\r\n\r\n        dsvDesc.Flags = D3D12_DSV_FLAG_READ_ONLY_DEPTH | D3D12_DSV_FLAG_READ_ONLY_STENCIL;\r\n        Device->CreateDepthStencilView(Resource, &dsvDesc, m_hDSV[3]);\r\n    }\r\n    else\r\n    {\r\n        m_hDSV[2] = m_hDSV[0];\r\n        m_hDSV[3] = m_hDSV[1];\r\n    }\r\n\r\n    if (m_hDepthSRV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_hDepthSRV = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n\r\n    // Create the shader resource view\r\n    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n    SRVDesc.Format = GetDepthFormat(Format);\r\n    if (dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2D)\r\n    {\r\n        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;\r\n        SRVDesc.Texture2D.MipLevels = 1;\r\n    }\r\n    else\r\n    {\r\n        SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;\r\n    }\r\n    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n    Device->CreateShaderResourceView( Resource, &SRVDesc, m_hDepthSRV );\r\n\r\n    if (stencilReadFormat != DXGI_FORMAT_UNKNOWN)\r\n    {\r\n        if (m_hStencilSRV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n            m_hStencilSRV = Graphics::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n\r\n        SRVDesc.Format = stencilReadFormat;\r\n        Device->CreateShaderResourceView( Resource, &SRVDesc, m_hStencilSRV );\r\n    }\r\n}\r\n\r\nvoid DepthBuffer::CreatePlacedResource(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t Samples, DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset, bool isNew)\r\n{\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeTex2D(Width, Height, 1, 1, Format, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);\r\n    ResourceDesc.SampleDesc.Count = Samples;\r\n\r\n    D3D12_CLEAR_VALUE ClearValue = {};\r\n    ClearValue.Format = Format;\r\n    \r\n    if (isNew)\r\n        PixelBuffer::CreatePlacedResource(Graphics::g_Device, Name, ResourceDesc, ClearValue, Heap, HeapOffset);\r\n    else\r\n        PixelBuffer::RecreatePlacedResource(Graphics::g_Device, ResourceDesc, ClearValue, Heap, HeapOffset);\r\n\r\n    CreateDerivedViews(Graphics::g_Device, Format);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DepthBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"PixelBuffer.h\"\r\n\r\nclass EsramAllocator;\r\n\r\nclass DepthBuffer : public PixelBuffer\r\n{\r\npublic:\r\n    DepthBuffer( float ClearDepth = 0.0f, uint8_t ClearStencil = 0 )\r\n        : m_ClearDepth(ClearDepth), m_ClearStencil(ClearStencil) \r\n    {\r\n        m_hDSV[0].ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_hDSV[1].ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_hDSV[2].ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_hDSV[3].ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_hDepthSRV.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_hStencilSRV.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n    }\r\n\r\n    // Create a depth buffer.  If an address is supplied, memory will not be allocated.\r\n    // The vmem address allows you to alias buffers (which can be especially useful for\r\n    // reusing ESRAM across a frame.)\r\n    void Create( const std::wstring& Name, uint32_t Width, uint32_t Height, DXGI_FORMAT Format,\r\n        D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN );\r\n\r\n    // Create a depth buffer.  Memory will be allocated in ESRAM (on Xbox One).  On Windows,\r\n    // this functions the same as Create() without a video address.\r\n    void Create( const std::wstring& Name, uint32_t Width, uint32_t Height, DXGI_FORMAT Format,\r\n        EsramAllocator& Allocator );\r\n\r\n    void Create(const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumSamples, DXGI_FORMAT Format,\r\n        D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN );\r\n    void Create( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumSamples, DXGI_FORMAT Format,\r\n        EsramAllocator& Allocator );\r\n\r\n    void CreatePlaced( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumSamples,\r\n        DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset );\r\n\r\n    void RecreatePlaced( uint32_t Width, uint32_t Height, uint32_t NumSamples, DXGI_FORMAT Format,\r\n        ID3D12Heap *Heap, UINT64 HeapOffset );\r\n\r\n    // Get pre-created CPU-visible descriptor handles\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetDSV() const { return m_hDSV[0]; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetDSV_DepthReadOnly() const { return m_hDSV[1]; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetDSV_StencilReadOnly() const { return m_hDSV[2]; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetDSV_ReadOnly() const { return m_hDSV[3]; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetDepthSRV() const { return m_hDepthSRV; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetStencilSRV() const { return m_hStencilSRV; }\r\n\r\n    float GetClearDepth() const { return m_ClearDepth; }\r\n    uint8_t GetClearStencil() const { return m_ClearStencil; }\r\n\r\nprivate:\r\n\r\n    void CreateDerivedViews( DX12_DEVICE* Device, DXGI_FORMAT Format );\r\n\r\n    void CreatePlacedResource( const std::wstring& Name, uint32_t Width, uint32_t Height, uint32_t NumSamples,\r\n        DXGI_FORMAT Format, ID3D12Heap *Heap, UINT64 HeapOffset, bool isNew );\r\n    \r\n    float m_ClearDepth;\r\n    uint8_t m_ClearStencil;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_hDSV[4];\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_hDepthSRV;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_hStencilSRV;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/DepthOfField.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"DepthOfField.h\"\r\n#include \"RootSignature.h\"\r\n#include \"PipelineState.h\"\r\n#include \"CommandContext.h\"\r\n#include \"BufferManager.h\"\r\n\r\n#include \"CompiledShaders/DoFPass1CS.h\"\r\n#include \"CompiledShaders/DoFTilePassCS.h\"\r\n#include \"CompiledShaders/DoFTilePassFixupCS.h\"\r\n#include \"CompiledShaders/DoFPreFilterCS.h\"\r\n#include \"CompiledShaders/DoFPreFilterFastCS.h\"\r\n#include \"CompiledShaders/DoFPreFilterFixupCS.h\"\r\n#include \"CompiledShaders/DoFPass2CS.h\"\r\n#include \"CompiledShaders/DoFPass2FastCS.h\"\r\n#include \"CompiledShaders/DoFPass2FixupCS.h\"\r\n#include \"CompiledShaders/DoFPass2DebugCS.h\"\r\n#include \"CompiledShaders/DoFMedianFilterCS.h\"\r\n#include \"CompiledShaders/DoFMedianFilterSepAlphaCS.h\"\r\n#include \"CompiledShaders/DoFMedianFilterFixupCS.h\"\r\n#include \"CompiledShaders/DoFCombineCS.h\"\r\n#include \"CompiledShaders/DoFCombine2CS.h\"\r\n#include \"CompiledShaders/DoFCombineFastCS.h\"\r\n#include \"CompiledShaders/DoFCombineFast2CS.h\"\r\n#include \"CompiledShaders/DoFDebugRedCS.h\"\r\n#include \"CompiledShaders/DoFDebugGreenCS.h\"\r\n#include \"CompiledShaders/DoFDebugBlueCS.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nnamespace DepthOfField\r\n{\r\n    BoolVar Enable(\"Graphics/Depth of Field/Enable\", false);\r\n    BoolVar EnablePreFilter(\"Graphics/Depth of Field/PreFilter\", true);\r\n    BoolVar MedianFilter(\"Graphics/Depth of Field/Median Filter\", true);\r\n    BoolVar MedianAlpha(\"Graphics/Depth of Field/Median Alpha\", false);\r\n    NumVar FocalDepth(\"Graphics/Depth of Field/Focal Center\", 0.1f, 0.0f, 1.0f, 0.01f);\r\n    NumVar FocalRange(\"Graphics/Depth of Field/Focal Radius\", 0.1f, 0.0f, 1.0f, 0.01f);\r\n    NumVar ForegroundRange(\"Graphics/Depth of Field/FG Range\", 100.0f, 10.0f, 1000.0f, 10.0f);\r\n    NumVar AntiSparkleWeight(\"Graphics/Depth of Field/AntiSparkle\", 1.0f, 0.0f, 10.0f, 1.0f);\r\n    const char* DebugLabels[] = { \"Off\", \"Foreground\", \"Background\", \"FG Alpha\", \"CoC\" };\r\n    EnumVar DebugMode(\"Graphics/Depth of Field/Debug Mode\", 0, _countof(DebugLabels), DebugLabels);\r\n    BoolVar DebugTiles(\"Graphics/Depth of Field/Debug Tiles\", false);\r\n    BoolVar ForceSlow(\"Graphics/Depth of Field/Force Slow Path\", false);\r\n    BoolVar ForceFast(\"Graphics/Depth of Field/Force Fast Path\", false);\r\n\r\n    RootSignature s_RootSignature;\r\n\r\n    ComputePSO s_DoFPass1CS;\t\t\t\t// Responsible for classifying tiles (1st pass)\r\n    ComputePSO s_DoFTilePassCS;\t\t\t\t// Disperses tile info to its neighbors (3x3)\r\n    ComputePSO s_DoFTilePassFixupCS;\t\t// Searches for straggler tiles to \"fixup\"\r\n\r\n    ComputePSO s_DoFPreFilterCS;\t\t\t// Full pre-filter with variable focus\r\n    ComputePSO s_DoFPreFilterFastCS;\t\t// Pre-filter assuming near-constant focus\r\n    ComputePSO s_DoFPreFilterFixupCS;\t\t// Pass through colors for completely in focus tile\r\n\r\n    ComputePSO s_DoFPass2CS;\t\t\t\t// Perform full CoC convolution pass\r\n    ComputePSO s_DoFPass2FastCS;\t\t\t// Perform color-only convolution for near-constant focus\r\n    ComputePSO s_DoFPass2FixupCS;\t\t\t// Pass through colors again\r\n    ComputePSO s_DoFPass2DebugCS;\t\t\t// Full pass 2 shader with options for debugging\r\n\r\n    ComputePSO s_DoFMedianFilterCS;\t\t\t// 3x3 median filter to reduce fireflies\r\n    ComputePSO s_DoFMedianFilterSepAlphaCS;\t// 3x3 median filter to reduce fireflies (separate filter on alpha)\r\n    ComputePSO s_DoFMedianFilterFixupCS;\t// Pass through without performing median\r\n\r\n    ComputePSO s_DoFCombineCS;\t\t\t\t// Combine DoF blurred buffer with focused color buffer\r\n    ComputePSO s_DoFCombineFastCS;\t\t\t// Upsample DoF blurred buffer\r\n    ComputePSO s_DoFDebugRedCS;\t\t\t\t// Output red to entire tile for debugging\r\n    ComputePSO s_DoFDebugGreenCS;\t\t\t// Output green to entire tile for debugging\r\n    ComputePSO s_DoFDebugBlueCS;\t\t\t// Output blue to entire tile for debugging\r\n\r\n    IndirectArgsBuffer s_IndirectParameters;\r\n}\r\n\r\nvoid DepthOfField::Initialize( void )\r\n{\r\n    s_RootSignature.Reset(4, 3);\r\n    s_RootSignature.InitStaticSampler(0, SamplerPointBorderDesc);\r\n    s_RootSignature.InitStaticSampler(1, SamplerPointClampDesc);\r\n    s_RootSignature.InitStaticSampler(2, SamplerLinearClampDesc);\r\n    s_RootSignature[0].InitAsConstantBuffer(0);\r\n    s_RootSignature[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 6);\r\n    s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 3);\r\n    s_RootSignature[3].InitAsConstants(1, 1);\r\n    s_RootSignature.Finalize(L\"Depth of Field\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(s_RootSignature); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO( s_DoFPass1CS, g_pDoFPass1CS);\r\n    CreatePSO( s_DoFTilePassCS, g_pDoFTilePassCS);\r\n    CreatePSO( s_DoFTilePassFixupCS, g_pDoFTilePassFixupCS);\r\n    CreatePSO( s_DoFPreFilterCS, g_pDoFPreFilterCS);\r\n    CreatePSO( s_DoFPreFilterFastCS, g_pDoFPreFilterFastCS);\r\n    CreatePSO( s_DoFPreFilterFixupCS, g_pDoFPreFilterFixupCS);\r\n    CreatePSO( s_DoFPass2CS, g_pDoFPass2CS);\r\n    CreatePSO( s_DoFPass2FastCS, g_pDoFPass2FastCS);\r\n    CreatePSO( s_DoFPass2FixupCS, g_pDoFPass2FixupCS);\r\n    CreatePSO( s_DoFPass2DebugCS, g_pDoFPass2DebugCS);\r\n    CreatePSO( s_DoFMedianFilterCS, g_pDoFMedianFilterCS );\r\n    CreatePSO( s_DoFMedianFilterSepAlphaCS, g_pDoFMedianFilterSepAlphaCS );\r\n    CreatePSO( s_DoFMedianFilterFixupCS, g_pDoFMedianFilterFixupCS );\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        CreatePSO(s_DoFCombineCS, g_pDoFCombine2CS);\r\n        CreatePSO(s_DoFCombineFastCS, g_pDoFCombineFast2CS);\r\n    }\r\n    else\r\n    {\r\n        CreatePSO(s_DoFCombineCS, g_pDoFCombineCS);\r\n        CreatePSO(s_DoFCombineFastCS, g_pDoFCombineFastCS);\r\n    }\r\n    CreatePSO( s_DoFDebugRedCS, g_pDoFDebugRedCS );\r\n    CreatePSO( s_DoFDebugGreenCS, g_pDoFDebugGreenCS );\r\n    CreatePSO( s_DoFDebugBlueCS, g_pDoFDebugBlueCS );\r\n\r\n#undef CreatePSO\r\n\r\n    __declspec(align(16)) const uint32_t initArgs[9] = { 0, 1, 1, 0, 1, 1, 0, 1, 1 };\r\n    s_IndirectParameters.Create(L\"DoF Indirect Parameters\", 3, sizeof(D3D12_DISPATCH_ARGUMENTS), initArgs);\r\n}\r\n\r\nvoid DepthOfField::Shutdown( void )\r\n{\r\n    s_IndirectParameters.Destroy();\r\n}\r\n\r\nvoid DepthOfField::Render( CommandContext& BaseContext, float /*NearClipDist*/, float FarClipDist )\r\n{\r\n    ScopedTimer _prof(L\"Depth of Field\", BaseContext);\r\n\r\n    if (!g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        WARN_ONCE_IF(!g_bTypedUAVLoadSupport_R11G11B10_FLOAT, \"Unable to perform final pass of DoF without support for R11G11B10F UAV loads\");\r\n        Enable = false;\r\n    }\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n    Context.SetRootSignature(s_RootSignature);\r\n\r\n    ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];\r\n\r\n    uint32_t BufferWidth = (uint32_t)LinearDepth.GetWidth();\r\n    uint32_t BufferHeight = (uint32_t)LinearDepth.GetHeight();\r\n    uint32_t TiledWidth = (uint32_t)g_DoFTileClass[0].GetWidth();\r\n    uint32_t TiledHeight = (uint32_t)g_DoFTileClass[0].GetHeight();\r\n\r\n    __declspec(align(16)) struct DoFConstantBuffer\r\n    {\r\n        float FocalCenter, FocalSpread;\r\n        float FocalMinZ, FocalMaxZ;\r\n        float RcpBufferWidth, RcpBufferHeight;\r\n        float RcpColorBufferWidth, RcpColorBufferHeight;\r\n        uint32_t BufferWidth, BufferHeight;\r\n        int32_t HalfWidth, HalfHeight;\r\n        uint32_t TiledWidth, TiledHeight;\r\n        float RcpTiledWidth, RcpTiledHeight;\r\n        uint32_t DebugState, DisablePreFilter;\r\n        float FGRange, RcpFGRange, AntiSparkleFilterStrength;\r\n    };\r\n    DoFConstantBuffer cbuffer =\r\n    {\r\n        (float)FocalDepth, 1.0f / (float)FocalRange,\r\n        (float)FocalDepth - (float)FocalRange, (float)FocalDepth + (float)FocalRange,\r\n        1.0f / BufferWidth, 1.0f / BufferHeight,\r\n        1.0f / g_pSceneColorBuffer->GetWidth(), 1.0f / g_pSceneColorBuffer->GetHeight(),\r\n        BufferWidth, BufferHeight,\r\n        (int32_t)Math::DivideByMultiple(BufferWidth, 2), (int32_t)Math::DivideByMultiple(BufferHeight, 2),\r\n        TiledWidth, TiledHeight,\r\n        1.0f / TiledWidth, 1.0f / TiledHeight,\r\n        (uint32_t)DebugMode, EnablePreFilter ? 0u : 1u,\r\n        ForegroundRange / FarClipDist, FarClipDist / ForegroundRange, (float)AntiSparkleWeight\r\n    };\r\n    Context.SetDynamicConstantBufferView(0, sizeof(cbuffer), &cbuffer);\r\n\r\n    {\r\n        ScopedTimer _prof2(L\"DoF Tiling\", Context);\r\n\r\n        // Initial pass to discover max CoC and closest depth in 16x16 tiles\r\n        Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_DoFTileClass[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.SetPipelineState(s_DoFPass1CS);\r\n        Context.SetDynamicDescriptor(1, 0, LinearDepth.GetSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_DoFTileClass[0].GetUAV());\r\n        Context.Dispatch2D(BufferWidth, BufferHeight, 16, 16);\r\n\r\n        Context.ResetCounter(g_DoFWorkQueue);\r\n        Context.ResetCounter(g_DoFFastQueue);\r\n        Context.ResetCounter(g_DoFFixupQueue);\r\n\r\n        // 3x3 filter to spread max CoC and closest depth to neighboring tiles\r\n        Context.TransitionResource(g_DoFTileClass[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_DoFTileClass[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DoFWorkQueue, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DoFFastQueue, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.SetPipelineState(s_DoFTilePassCS);\r\n        Context.SetDynamicDescriptor(1, 0, g_DoFTileClass[0].GetSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_DoFTileClass[1].GetUAV());\r\n        Context.SetDynamicDescriptor(2, 1, g_DoFWorkQueue.GetUAV());\r\n        Context.SetDynamicDescriptor(2, 2, g_DoFFastQueue.GetUAV());\r\n        Context.Dispatch2D(TiledWidth, TiledHeight);\r\n\r\n        Context.TransitionResource(g_DoFTileClass[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_DoFFixupQueue, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.SetPipelineState(s_DoFTilePassFixupCS);\r\n        Context.SetDynamicDescriptor(1, 0, g_DoFTileClass[1].GetSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_DoFFixupQueue.GetUAV());\r\n        Context.Dispatch2D(TiledWidth, TiledHeight);\r\n\r\n        Context.TransitionResource(g_DoFWorkQueue, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.CopyCounter(s_IndirectParameters, 0, g_DoFWorkQueue);\r\n\r\n        Context.TransitionResource(g_DoFFastQueue, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.CopyCounter(s_IndirectParameters, 12, g_DoFFastQueue);\r\n\r\n        Context.TransitionResource(g_DoFFixupQueue, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.CopyCounter(s_IndirectParameters, 24, g_DoFFixupQueue);\r\n\r\n        Context.TransitionResource(s_IndirectParameters, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n    }\r\n\r\n    {\r\n        ScopedTimer _prof2(L\"DoF PreFilter\", Context);\r\n\r\n        if (ForceFast && !DebugMode)\r\n            Context.SetPipelineState(s_DoFPreFilterFastCS);\r\n        else\r\n            Context.SetPipelineState(s_DoFPreFilterCS);\r\n        Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_DoFPresortBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DoFPrefilter, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.SetDynamicDescriptor(1, 0, LinearDepth.GetSRV());\r\n        Context.SetDynamicDescriptor(1, 1, g_DoFTileClass[1].GetSRV());\r\n        Context.SetDynamicDescriptor(1, 2, g_pSceneColorBuffer->GetSRV());\r\n        Context.SetDynamicDescriptor(1, 3, g_DoFWorkQueue.GetSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_DoFPresortBuffer.GetUAV());\r\n        Context.SetDynamicDescriptor(2, 1, g_DoFPrefilter.GetUAV());\r\n        Context.DispatchIndirect(s_IndirectParameters, 0);\r\n\r\n        if (!ForceSlow && !DebugMode)\r\n            Context.SetPipelineState(s_DoFPreFilterFastCS);\r\n        Context.SetDynamicDescriptor(1, 3, g_DoFFastQueue.GetSRV());\r\n        Context.DispatchIndirect(s_IndirectParameters, 12);\r\n\r\n        Context.SetPipelineState(s_DoFPreFilterFixupCS);\r\n        Context.SetDynamicDescriptor(1, 3, g_DoFFixupQueue.GetSRV());\r\n        Context.DispatchIndirect(s_IndirectParameters, 24);\r\n    }\r\n\r\n    {\r\n        ScopedTimer _prof2(L\"DoF Main Pass\", Context);\r\n\r\n        Context.TransitionResource(g_DoFPrefilter, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_DoFBlurColor[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DoFBlurAlpha[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        if (ForceFast && !DebugMode)\r\n            Context.SetPipelineState(s_DoFPass2FastCS);\r\n        else\r\n            Context.SetPipelineState(DebugMode > 0 ? s_DoFPass2DebugCS : s_DoFPass2CS);\r\n        Context.SetDynamicDescriptor(1, 0, g_DoFPrefilter.GetSRV());\r\n        Context.SetDynamicDescriptor(1, 1, g_DoFPresortBuffer.GetSRV());\r\n        Context.SetDynamicDescriptor(1, 2, g_DoFTileClass[1].GetSRV());\r\n        Context.SetDynamicDescriptor(1, 3, g_DoFWorkQueue.GetSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_DoFBlurColor[0].GetUAV());\r\n        Context.SetDynamicDescriptor(2, 1, g_DoFBlurAlpha[0].GetUAV());\r\n        Context.DispatchIndirect(s_IndirectParameters, 0);\r\n\r\n        if (!ForceSlow && !DebugMode)\r\n            Context.SetPipelineState(s_DoFPass2FastCS);\r\n        Context.SetDynamicDescriptor(1, 3, g_DoFFastQueue.GetSRV());\r\n        Context.DispatchIndirect(s_IndirectParameters, 12);\r\n\r\n        Context.SetPipelineState(s_DoFPass2FixupCS);\r\n        Context.SetDynamicDescriptor(1, 3, g_DoFFixupQueue.GetSRV());\r\n        Context.DispatchIndirect(s_IndirectParameters, 24);\r\n    }\r\n\r\n    {\r\n        ScopedTimer _prof2(L\"DoF Median Pass\", Context);\r\n        Context.TransitionResource(g_DoFBlurColor[0], D3D12_RESOURCE_STATE_GENERIC_READ);\r\n        Context.TransitionResource(g_DoFBlurAlpha[0], D3D12_RESOURCE_STATE_GENERIC_READ);\r\n\r\n        if (MedianFilter)\r\n        {\r\n            Context.TransitionResource(g_DoFBlurColor[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            Context.TransitionResource(g_DoFBlurAlpha[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            Context.SetPipelineState(MedianAlpha ? s_DoFMedianFilterSepAlphaCS : s_DoFMedianFilterCS);\r\n            Context.SetDynamicDescriptor(1, 0, g_DoFBlurColor[0].GetSRV());\r\n            Context.SetDynamicDescriptor(1, 1, g_DoFBlurAlpha[0].GetSRV());\r\n            Context.SetDynamicDescriptor(1, 2, g_DoFWorkQueue.GetSRV());\r\n            Context.SetDynamicDescriptor(2, 0, g_DoFBlurColor[1].GetUAV());\r\n            Context.SetDynamicDescriptor(2, 1, g_DoFBlurAlpha[1].GetUAV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 0);\r\n\r\n            Context.SetDynamicDescriptor(1, 2, g_DoFFastQueue.GetSRV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 12);\r\n\r\n            Context.SetPipelineState(s_DoFMedianFilterFixupCS);\r\n            Context.SetDynamicDescriptor(1, 2, g_DoFFixupQueue.GetSRV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 24);\r\n\r\n            Context.TransitionResource(g_DoFBlurColor[1], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n            Context.TransitionResource(g_DoFBlurAlpha[1], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        }\r\n    }\r\n\r\n    {\r\n        ScopedTimer _prof2(L\"DoF Final Combine\", Context);\r\n        Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n        if (DebugTiles)\r\n        {\r\n            Context.SetPipelineState(s_DoFDebugRedCS);\r\n            Context.SetDynamicDescriptor(1, 5, g_DoFWorkQueue.GetSRV());\r\n            Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 0);\r\n\r\n            Context.SetPipelineState(s_DoFDebugGreenCS);\r\n            Context.SetDynamicDescriptor(1, 5, g_DoFFastQueue.GetSRV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 12);\r\n\r\n            Context.SetPipelineState(s_DoFDebugBlueCS);\r\n            Context.SetDynamicDescriptor(1, 5, g_DoFFixupQueue.GetSRV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 24);\r\n        }\r\n        else\r\n        {\r\n            Context.SetPipelineState(s_DoFCombineCS);\r\n            Context.SetDynamicDescriptor(1, 0, g_DoFBlurColor[MedianFilter ? 1 : 0].GetSRV());\r\n            Context.SetDynamicDescriptor(1, 1, g_DoFBlurAlpha[MedianFilter ? 1 : 0].GetSRV());\r\n            Context.SetDynamicDescriptor(1, 2, g_DoFTileClass[1].GetSRV());\r\n            Context.SetDynamicDescriptor(1, 3, LinearDepth.GetSRV());\r\n            Context.SetDynamicDescriptor(1, 4, g_DoFWorkQueue.GetSRV());\r\n            Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 0);\r\n\r\n            Context.SetPipelineState(s_DoFCombineFastCS);\r\n            Context.SetDynamicDescriptor(1, 4, g_DoFFastQueue.GetSRV());\r\n            Context.DispatchIndirect(s_IndirectParameters, 12);\r\n        }\r\n\r\n        Context.InsertUAVBarrier(*g_pSceneColorBuffer);\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DepthOfField.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"EngineTuning.h\"\r\n\r\nnamespace DepthOfField\r\n{\r\n    extern BoolVar Enable;\r\n\r\n    void Initialize( void );\r\n    void Shutdown( void );\r\n\r\n    void Render( CommandContext& BaseContext, float NearClipDist, float FarClipDist );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DescriptorHeap.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"DescriptorHeap.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandListManager.h\"\r\n\r\nusing namespace Graphics;\r\n\r\n//\r\n// DescriptorAllocator implementation\r\n//\r\nstd::mutex DescriptorAllocator::sm_AllocationMutex;\r\nstd::vector<Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>> DescriptorAllocator::sm_DescriptorHeapPool;\r\n\r\nvoid DescriptorAllocator::DestroyAll(void)\r\n{\r\n    sm_DescriptorHeapPool.clear();\r\n}\r\n\r\nID3D12DescriptorHeap* DescriptorAllocator::RequestNewHeap(D3D12_DESCRIPTOR_HEAP_TYPE Type)\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(sm_AllocationMutex);\r\n\r\n    D3D12_DESCRIPTOR_HEAP_DESC Desc;\r\n    Desc.Type = Type;\r\n    Desc.NumDescriptors = sm_NumDescriptorsPerHeap;\r\n    Desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;\r\n    Desc.NodeMask = 1;\r\n\r\n    Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> pHeap;\r\n    ASSERT_SUCCEEDED(Graphics::g_Device->CreateDescriptorHeap(&Desc, MY_IID_PPV_ARGS(&pHeap)));\r\n    sm_DescriptorHeapPool.emplace_back(pHeap);\r\n    return pHeap.Get();\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE DescriptorAllocator::Allocate( uint32_t Count )\r\n{\r\n    if (m_CurrentHeap == nullptr || m_RemainingFreeHandles < Count)\r\n    {\r\n        m_CurrentHeap = RequestNewHeap(m_Type);\r\n        m_CurrentHandle = m_CurrentHeap->GetCPUDescriptorHandleForHeapStart();\r\n        m_RemainingFreeHandles = sm_NumDescriptorsPerHeap;\r\n\r\n        if (m_DescriptorSize == 0)\r\n            m_DescriptorSize = Graphics::g_Device->GetDescriptorHandleIncrementSize(m_Type);\r\n    }\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE ret = m_CurrentHandle;\r\n    m_CurrentHandle.ptr += Count * m_DescriptorSize;\r\n    m_RemainingFreeHandles -= Count;\r\n    return ret;\r\n}\r\n\r\n//\r\n// UserDescriptorHeap implementation\r\n//\r\n\r\nvoid UserDescriptorHeap::Create( const std::wstring& DebugHeapName )\r\n{\r\n    ASSERT_SUCCEEDED(Graphics::g_Device->CreateDescriptorHeap(&m_HeapDesc, MY_IID_PPV_ARGS(m_Heap.ReleaseAndGetAddressOf())));\r\n#ifdef RELEASE\r\n    (void)DebugHeapName;\r\n#else\r\n    m_Heap->SetName(DebugHeapName.c_str());\r\n#endif\r\n\r\n    m_DescriptorSize = Graphics::g_Device->GetDescriptorHandleIncrementSize(m_HeapDesc.Type);\r\n    m_NumFreeDescriptors = m_HeapDesc.NumDescriptors;\r\n    m_FirstHandle = DescriptorHandle( m_Heap->GetCPUDescriptorHandleForHeapStart(),  m_Heap->GetGPUDescriptorHandleForHeapStart() );\r\n    m_NextFreeHandle = m_FirstHandle;\r\n}\r\n\r\nDescriptorHandle UserDescriptorHeap::Alloc( uint32_t Count )\r\n{\r\n    ASSERT(HasAvailableSpace(Count), \"Descriptor Heap out of space.  Increase heap size.\");\r\n    DescriptorHandle ret = m_NextFreeHandle;\r\n    m_NextFreeHandle += Count * m_DescriptorSize;\r\n    return ret;\r\n}\r\n\r\nbool UserDescriptorHeap::ValidateHandle( const DescriptorHandle& DHandle ) const\r\n{\r\n    if (DHandle.GetCpuHandle().ptr < m_FirstHandle.GetCpuHandle().ptr ||\r\n        DHandle.GetCpuHandle().ptr >= m_FirstHandle.GetCpuHandle().ptr + m_HeapDesc.NumDescriptors * m_DescriptorSize)\r\n        return false;\r\n\r\n    if (DHandle.GetGpuHandle().ptr - m_FirstHandle.GetGpuHandle().ptr !=\r\n        DHandle.GetCpuHandle().ptr - m_FirstHandle.GetCpuHandle().ptr)\r\n        return false;\r\n\r\n    return true;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DescriptorHeap.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include <mutex>\r\n#include <vector>\r\n#include <queue>\r\n#include <string>\r\n\r\n\r\n// This is an unbounded resource descriptor allocator.  It is intended to provide space for CPU-visible resource descriptors\r\n// as resources are created.  For those that need to be made shader-visible, they will need to be copied to a UserDescriptorHeap\r\n// or a DynamicDescriptorHeap.\r\nclass DescriptorAllocator\r\n{\r\npublic:\r\n    DescriptorAllocator(D3D12_DESCRIPTOR_HEAP_TYPE Type) : m_Type(Type), m_CurrentHeap(nullptr) {}\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE Allocate( uint32_t Count );\r\n\r\n    static void DestroyAll(void);\r\n\r\nprotected:\r\n\r\n    static const uint32_t sm_NumDescriptorsPerHeap = 256;\r\n    static std::mutex sm_AllocationMutex;\r\n    static std::vector<Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>> sm_DescriptorHeapPool;\r\n    static ID3D12DescriptorHeap* RequestNewHeap( D3D12_DESCRIPTOR_HEAP_TYPE Type );\r\n\r\n    D3D12_DESCRIPTOR_HEAP_TYPE m_Type;\r\n    ID3D12DescriptorHeap* m_CurrentHeap;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_CurrentHandle;\r\n    uint32_t m_DescriptorSize;\r\n    uint32_t m_RemainingFreeHandles;\r\n};\r\n\r\n\r\nclass DescriptorHandle\r\n{\r\npublic:\r\n    DescriptorHandle()\r\n    {\r\n        m_CpuHandle.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_GpuHandle.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n    }\r\n\r\n    DescriptorHandle( D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle )\r\n        : m_CpuHandle(CpuHandle)\r\n    {\r\n        m_GpuHandle.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n    }\r\n\r\n    DescriptorHandle( D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle )\r\n        : m_CpuHandle(CpuHandle), m_GpuHandle(GpuHandle)\r\n    {\r\n    }\r\n\r\n    DescriptorHandle operator+ ( INT OffsetScaledByDescriptorSize ) const\r\n    {\r\n        DescriptorHandle ret = *this;\r\n        ret += OffsetScaledByDescriptorSize;\r\n        return ret;\r\n    }\r\n\r\n    void operator += ( INT OffsetScaledByDescriptorSize )\r\n    {\r\n         if (m_CpuHandle.ptr != D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n            m_CpuHandle.ptr += OffsetScaledByDescriptorSize;\r\n         if (m_GpuHandle.ptr != D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n            m_GpuHandle.ptr += OffsetScaledByDescriptorSize;\r\n    }\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle() const { return m_CpuHandle; }\r\n\r\n    D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle() const { return m_GpuHandle; }\r\n\r\n    bool IsNull() const { return m_CpuHandle.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN; }\r\n    bool IsShaderVisible() const { return m_GpuHandle.ptr != D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN; }\r\n\r\nprivate:\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_CpuHandle;\r\n    D3D12_GPU_DESCRIPTOR_HANDLE m_GpuHandle;\r\n};\r\n\r\nclass UserDescriptorHeap\r\n{\r\npublic:\r\n\r\n    UserDescriptorHeap( D3D12_DESCRIPTOR_HEAP_TYPE Type, uint32_t MaxCount )\r\n    {\r\n        m_HeapDesc.Type = Type;\r\n        m_HeapDesc.NumDescriptors = MaxCount;\r\n        m_HeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;\r\n        m_HeapDesc.NodeMask = 1;\r\n    }\r\n\r\n    void Create( const std::wstring& DebugHeapName );\r\n\r\n    bool HasAvailableSpace( uint32_t Count ) const { return Count <= m_NumFreeDescriptors; }\r\n    DescriptorHandle Alloc( uint32_t Count = 1 );\r\n\r\n    DescriptorHandle GetHandleAtOffset( uint32_t Offset ) const { return m_FirstHandle + Offset * m_DescriptorSize; }\r\n\r\n    bool ValidateHandle( const DescriptorHandle& DHandle ) const;\r\n\r\n    ID3D12DescriptorHeap* GetHeapPointer() const { return m_Heap.Get(); }\r\n\r\nprivate:\r\n\r\n    Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_Heap;\r\n    D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;\r\n    uint32_t m_DescriptorSize;\r\n    uint32_t m_NumFreeDescriptors;\r\n    DescriptorHandle m_FirstHandle;\r\n    DescriptorHandle m_NextFreeHandle;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/DynamicDescriptorHeap.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"DynamicDescriptorHeap.h\"\r\n#include \"CommandContext.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandListManager.h\"\r\n#include \"RootSignature.h\"\r\n\r\nusing namespace Graphics;\r\n\r\n//\r\n// DynamicDescriptorHeap Implementation\r\n//\r\n\r\nstd::mutex DynamicDescriptorHeap::sm_Mutex;\r\nstd::vector<Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>> DynamicDescriptorHeap::sm_DescriptorHeapPool[2];\r\nstd::queue<std::pair<uint64_t, ID3D12DescriptorHeap*>> DynamicDescriptorHeap::sm_RetiredDescriptorHeaps[2];\r\nstd::queue<ID3D12DescriptorHeap*> DynamicDescriptorHeap::sm_AvailableDescriptorHeaps[2];\r\n\r\nID3D12DescriptorHeap* DynamicDescriptorHeap::RequestDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE HeapType)\r\n{\r\n    std::lock_guard<std::mutex> LockGuard(sm_Mutex);\r\n\r\n    uint32_t idx = HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ? 1 : 0;\r\n\r\n    while (!sm_RetiredDescriptorHeaps[idx].empty() && g_CommandManager.IsFenceComplete(sm_RetiredDescriptorHeaps[idx].front().first))\r\n    {\r\n        sm_AvailableDescriptorHeaps[idx].push(sm_RetiredDescriptorHeaps[idx].front().second);\r\n        sm_RetiredDescriptorHeaps[idx].pop();\r\n    }\r\n\r\n    if (!sm_AvailableDescriptorHeaps[idx].empty())\r\n    {\r\n        ID3D12DescriptorHeap* HeapPtr = sm_AvailableDescriptorHeaps[idx].front();\r\n        sm_AvailableDescriptorHeaps[idx].pop();\r\n        return HeapPtr;\r\n    }\r\n    else\r\n    {\r\n        D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = {};\r\n        HeapDesc.Type = HeapType;\r\n        HeapDesc.NumDescriptors = kNumDescriptorsPerHeap;\r\n        HeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;\r\n        HeapDesc.NodeMask = 1;\r\n        Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> HeapPtr;\r\n        ASSERT_SUCCEEDED(g_Device->CreateDescriptorHeap(&HeapDesc, MY_IID_PPV_ARGS(&HeapPtr)));\r\n        sm_DescriptorHeapPool[idx].emplace_back(HeapPtr);\r\n        return HeapPtr.Get();\r\n    }\r\n}\r\n\r\nvoid DynamicDescriptorHeap::DiscardDescriptorHeaps( D3D12_DESCRIPTOR_HEAP_TYPE HeapType, uint64_t FenceValue, const std::vector<ID3D12DescriptorHeap*>& UsedHeaps )\r\n{\r\n    uint32_t idx = HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ? 1 : 0;\r\n    std::lock_guard<std::mutex> LockGuard(sm_Mutex);\r\n    for (auto iter = UsedHeaps.begin(); iter != UsedHeaps.end(); ++iter)\r\n        sm_RetiredDescriptorHeaps[idx].push(std::make_pair(FenceValue, *iter));\r\n}\r\n\r\nvoid DynamicDescriptorHeap::RetireCurrentHeap( void )\r\n{\r\n    // Don't retire unused heaps.\r\n    if (m_CurrentOffset == 0)\r\n    {\r\n        ASSERT(m_CurrentHeapPtr == nullptr);\r\n        return;\r\n    }\r\n\r\n    ASSERT(m_CurrentHeapPtr != nullptr);\r\n    m_RetiredHeaps.push_back(m_CurrentHeapPtr);\r\n    m_CurrentHeapPtr = nullptr;\r\n    m_CurrentOffset = 0;\r\n}\r\n\r\nvoid DynamicDescriptorHeap::RetireUsedHeaps( uint64_t fenceValue )\r\n{\r\n    DiscardDescriptorHeaps(m_DescriptorType, fenceValue, m_RetiredHeaps);\r\n    m_RetiredHeaps.clear();\r\n}\r\n\r\nDynamicDescriptorHeap::DynamicDescriptorHeap(CommandContext& OwningContext, D3D12_DESCRIPTOR_HEAP_TYPE HeapType)\r\n    : m_OwningContext(OwningContext), m_DescriptorType(HeapType)\r\n{\r\n    m_CurrentHeapPtr = nullptr;\r\n    m_CurrentOffset = 0;\r\n    m_DescriptorSize = Graphics::g_Device->GetDescriptorHandleIncrementSize(HeapType);\r\n}\r\n\r\nDynamicDescriptorHeap::~DynamicDescriptorHeap()\r\n{\r\n}\r\n\r\nvoid DynamicDescriptorHeap::CleanupUsedHeaps( uint64_t fenceValue )\r\n{\r\n    RetireCurrentHeap();\r\n    RetireUsedHeaps(fenceValue);\r\n    m_GraphicsHandleCache.ClearCache();\r\n    m_ComputeHandleCache.ClearCache();\r\n}\r\n\r\ninline ID3D12DescriptorHeap* DynamicDescriptorHeap::GetHeapPointer()\r\n{\r\n    if (m_CurrentHeapPtr == nullptr)\r\n    {\r\n        ASSERT(m_CurrentOffset == 0);\r\n        m_CurrentHeapPtr = RequestDescriptorHeap(m_DescriptorType);\r\n        m_FirstDescriptor = DescriptorHandle(\r\n            m_CurrentHeapPtr->GetCPUDescriptorHandleForHeapStart(),\r\n            m_CurrentHeapPtr->GetGPUDescriptorHandleForHeapStart());\r\n    }\r\n\r\n    return m_CurrentHeapPtr;\r\n}\r\n\r\nuint32_t DynamicDescriptorHeap::DescriptorHandleCache::ComputeStagedSize()\r\n{\r\n    // Sum the maximum assigned offsets of stale descriptor tables to determine total needed space.\r\n    uint32_t NeededSpace = 0;\r\n    uint32_t RootIndex;\r\n    uint32_t StaleParams = m_StaleRootParamsBitMap;\r\n    while (_BitScanForward((unsigned long*)&RootIndex, StaleParams))\r\n    {\r\n        StaleParams ^= (1 << RootIndex);\r\n\r\n        uint32_t MaxSetHandle;\r\n        ASSERT(TRUE == _BitScanReverse((unsigned long*)&MaxSetHandle, m_RootDescriptorTable[RootIndex].AssignedHandlesBitMap),\r\n            \"Root entry marked as stale but has no stale descriptors\");\r\n\r\n        NeededSpace += MaxSetHandle + 1;\r\n    }\r\n    return NeededSpace;\r\n}\r\n\r\nvoid DynamicDescriptorHeap::DescriptorHandleCache::CopyAndBindStaleTables(\r\n    D3D12_DESCRIPTOR_HEAP_TYPE Type, uint32_t DescriptorSize,\r\n    DescriptorHandle DestHandleStart, DX12_GRAPHICSCOMMANDLIST* CmdList,\r\n    void (STDMETHODCALLTYPE DX12_GRAPHICSCOMMANDLIST::*SetFunc)(UINT, D3D12_GPU_DESCRIPTOR_HANDLE))\r\n{\r\n    uint32_t StaleParamCount = 0;\r\n    uint32_t TableSize[DescriptorHandleCache::kMaxNumDescriptorTables];\r\n    uint32_t RootIndices[DescriptorHandleCache::kMaxNumDescriptorTables];\r\n    uint32_t NeededSpace = 0;\r\n    uint32_t RootIndex;\r\n\r\n    // Sum the maximum assigned offsets of stale descriptor tables to determine total needed space.\r\n    uint32_t StaleParams = m_StaleRootParamsBitMap;\r\n    while (_BitScanForward((unsigned long*)&RootIndex, StaleParams))\r\n    {\r\n        RootIndices[StaleParamCount] = RootIndex;\r\n        StaleParams ^= (1 << RootIndex);\r\n\r\n        uint32_t MaxSetHandle;\r\n        ASSERT(TRUE == _BitScanReverse((unsigned long*)&MaxSetHandle, m_RootDescriptorTable[RootIndex].AssignedHandlesBitMap),\r\n            \"Root entry marked as stale but has no stale descriptors\");\r\n\r\n        NeededSpace += MaxSetHandle + 1;\r\n        TableSize[StaleParamCount] = MaxSetHandle + 1;\r\n\r\n        ++StaleParamCount;\r\n    }\r\n\r\n    ASSERT(StaleParamCount <= DescriptorHandleCache::kMaxNumDescriptorTables,\r\n        \"We're only equipped to handle so many descriptor tables\");\r\n\r\n    m_StaleRootParamsBitMap = 0;\r\n\r\n    static const uint32_t kMaxDescriptorsPerCopy = 16;\r\n    UINT NumDestDescriptorRanges = 0;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE pDestDescriptorRangeStarts[kMaxDescriptorsPerCopy];\r\n    UINT pDestDescriptorRangeSizes[kMaxDescriptorsPerCopy];\r\n\r\n    UINT NumSrcDescriptorRanges = 0;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE pSrcDescriptorRangeStarts[kMaxDescriptorsPerCopy];\r\n    UINT pSrcDescriptorRangeSizes[kMaxDescriptorsPerCopy];\r\n\r\n    for (uint32_t i = 0; i < StaleParamCount; ++i)\r\n    {\r\n        RootIndex = RootIndices[i];\r\n        (CmdList->*SetFunc)(RootIndex, DestHandleStart.GetGpuHandle());\r\n\r\n        DescriptorTableCache& RootDescTable = m_RootDescriptorTable[RootIndex];\r\n\r\n        D3D12_CPU_DESCRIPTOR_HANDLE* SrcHandles = RootDescTable.TableStart;\r\n        uint64_t SetHandles = (uint64_t)RootDescTable.AssignedHandlesBitMap;\r\n        D3D12_CPU_DESCRIPTOR_HANDLE CurDest = DestHandleStart.GetCpuHandle();\r\n        DestHandleStart += TableSize[i] * DescriptorSize;\r\n\r\n        unsigned long SkipCount;\r\n        while (_BitScanForward64(&SkipCount, SetHandles))\r\n        {\r\n            // Skip over unset descriptor handles\r\n            SetHandles >>= SkipCount;\r\n            SrcHandles += SkipCount;\r\n            CurDest.ptr += SkipCount * DescriptorSize;\r\n\r\n            unsigned long DescriptorCount;\r\n            _BitScanForward64(&DescriptorCount, ~SetHandles);\r\n            SetHandles >>= DescriptorCount;\r\n\r\n            // If we run out of temp room, copy what we've got so far\r\n            if (NumSrcDescriptorRanges + DescriptorCount > kMaxDescriptorsPerCopy)\r\n            {\r\n                g_Device->CopyDescriptors(\r\n                    NumDestDescriptorRanges, pDestDescriptorRangeStarts, pDestDescriptorRangeSizes,\r\n                    NumSrcDescriptorRanges, pSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes,\r\n                    Type);\r\n\r\n                NumSrcDescriptorRanges = 0;\r\n                NumDestDescriptorRanges = 0;\r\n            }\r\n\r\n            // Setup destination range\r\n            pDestDescriptorRangeStarts[NumDestDescriptorRanges] = CurDest;\r\n            pDestDescriptorRangeSizes[NumDestDescriptorRanges] = DescriptorCount;\r\n            ++NumDestDescriptorRanges;\r\n\r\n            // Setup source ranges (one descriptor each because we don't assume they are contiguous)\r\n            for (uint32_t j = 0; j < DescriptorCount; ++j)\r\n            {\r\n                pSrcDescriptorRangeStarts[NumSrcDescriptorRanges] = SrcHandles[j];\r\n                pSrcDescriptorRangeSizes[NumSrcDescriptorRanges] = 1;\r\n                ++NumSrcDescriptorRanges;\r\n            }\r\n\r\n            // Move the destination pointer forward by the number of descriptors we will copy\r\n            SrcHandles += DescriptorCount;\r\n            CurDest.ptr += DescriptorCount * DescriptorSize;\r\n        }\r\n    }\r\n\r\n    g_Device->CopyDescriptors(\r\n        NumDestDescriptorRanges, pDestDescriptorRangeStarts, pDestDescriptorRangeSizes,\r\n        NumSrcDescriptorRanges, pSrcDescriptorRangeStarts, pSrcDescriptorRangeSizes,\r\n        Type);\r\n}\r\n    \r\nvoid DynamicDescriptorHeap::CopyAndBindStagedTables( DescriptorHandleCache& HandleCache, DX12_GRAPHICSCOMMANDLIST* CmdList,\r\n    void (STDMETHODCALLTYPE DX12_GRAPHICSCOMMANDLIST::*SetFunc)(UINT, D3D12_GPU_DESCRIPTOR_HANDLE))\r\n{\r\n    uint32_t NeededSize = HandleCache.ComputeStagedSize();\r\n    if (!HasSpace(NeededSize))\r\n    {\r\n        RetireCurrentHeap();\r\n        UnbindAllValid();\r\n        NeededSize = HandleCache.ComputeStagedSize();\r\n    }\r\n\r\n    // This can trigger the creation of a new heap\r\n    m_OwningContext.SetDescriptorHeap(m_DescriptorType, GetHeapPointer());\r\n    HandleCache.CopyAndBindStaleTables(m_DescriptorType, m_DescriptorSize, Allocate(NeededSize), CmdList, SetFunc);\r\n}\r\n\r\nvoid DynamicDescriptorHeap::UnbindAllValid( void )\r\n{\r\n    m_GraphicsHandleCache.UnbindAllValid();\r\n    m_ComputeHandleCache.UnbindAllValid();\r\n}\r\n\r\nD3D12_GPU_DESCRIPTOR_HANDLE DynamicDescriptorHeap::UploadDirect( D3D12_CPU_DESCRIPTOR_HANDLE Handle )\r\n{\r\n    if (!HasSpace(1))\r\n    {\r\n        RetireCurrentHeap();\r\n        UnbindAllValid();\r\n    }\r\n\r\n    m_OwningContext.SetDescriptorHeap(m_DescriptorType, GetHeapPointer());\r\n\r\n    DescriptorHandle DestHandle = m_FirstDescriptor + m_CurrentOffset * m_DescriptorSize;\r\n    m_CurrentOffset += 1;\r\n\r\n    g_Device->CopyDescriptorsSimple(1, DestHandle.GetCpuHandle(), Handle, m_DescriptorType);\r\n\r\n    return DestHandle.GetGpuHandle();\r\n}\r\n\r\nvoid DynamicDescriptorHeap::DescriptorHandleCache::UnbindAllValid()\r\n{\r\n    m_StaleRootParamsBitMap = 0;\r\n\r\n    unsigned long TableParams = m_RootDescriptorTablesBitMap;\r\n    unsigned long RootIndex;\r\n    while (_BitScanForward(&RootIndex, TableParams))\r\n    {\r\n        TableParams ^= (1 << RootIndex);\r\n        if (m_RootDescriptorTable[RootIndex].AssignedHandlesBitMap != 0)\r\n            m_StaleRootParamsBitMap |= (1 << RootIndex);\r\n    }\r\n}\r\n\r\nvoid DynamicDescriptorHeap::DescriptorHandleCache::StageDescriptorHandles( UINT RootIndex, UINT Offset, UINT NumHandles, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n{\r\n    ASSERT(((1 << RootIndex) & m_RootDescriptorTablesBitMap) != 0, \"Root parameter is not a CBV_SRV_UAV descriptor table\");\r\n    ASSERT(Offset + NumHandles <= m_RootDescriptorTable[RootIndex].TableSize);\r\n\r\n    DescriptorTableCache& TableCache = m_RootDescriptorTable[RootIndex];\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* CopyDest = TableCache.TableStart + Offset;\r\n    for (UINT i = 0; i < NumHandles; ++i)\r\n        CopyDest[i] = Handles[i];\r\n    TableCache.AssignedHandlesBitMap |= ((1 << NumHandles) - 1) << Offset;\r\n    m_StaleRootParamsBitMap |= (1 << RootIndex);\r\n}\r\n\r\nvoid DynamicDescriptorHeap::DescriptorHandleCache::ParseRootSignature( D3D12_DESCRIPTOR_HEAP_TYPE Type, const RootSignature& RootSig )\r\n{\r\n    UINT CurrentOffset = 0;\r\n\r\n    ASSERT(RootSig.m_NumParameters <= 16, \"Maybe we need to support something greater\");\r\n\r\n    m_StaleRootParamsBitMap = 0;\r\n    m_RootDescriptorTablesBitMap = (Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ?\r\n        RootSig.m_SamplerTableBitMap : RootSig.m_DescriptorTableBitMap);\r\n\r\n    unsigned long TableParams = m_RootDescriptorTablesBitMap;\r\n    unsigned long RootIndex;\r\n    while (_BitScanForward(&RootIndex, TableParams))\r\n    {\r\n        TableParams ^= (1 << RootIndex);\r\n\r\n        UINT TableSize = RootSig.m_DescriptorTableSize[RootIndex];\r\n        ASSERT(TableSize > 0);\r\n\r\n        DescriptorTableCache& RootDescriptorTable = m_RootDescriptorTable[RootIndex];\r\n        RootDescriptorTable.AssignedHandlesBitMap = 0;\r\n        RootDescriptorTable.TableStart = m_HandleCache + CurrentOffset;\r\n        RootDescriptorTable.TableSize = TableSize;\r\n\r\n        CurrentOffset += TableSize;\r\n    }\r\n\r\n    m_MaxCachedDescriptors = CurrentOffset;\r\n\r\n    ASSERT(m_MaxCachedDescriptors <= kMaxNumDescriptors, \"Exceeded user-supplied maximum cache size\");\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DynamicDescriptorHeap.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"DescriptorHeap.h\"\r\n#include \"RootSignature.h\"\r\n#include <vector>\r\n#include <queue>\r\n\r\nnamespace Graphics\r\n{\r\n    extern DX12_DEVICE* g_Device;\r\n}\r\n\r\n// This class is a linear allocation system for dynamically generated descriptor tables.  It internally caches\r\n// CPU descriptor handles so that when not enough space is available in the current heap, necessary descriptors\r\n// can be re-copied to the new heap.\r\nclass DynamicDescriptorHeap\r\n{\r\npublic:\r\n    DynamicDescriptorHeap(CommandContext& OwningContext, D3D12_DESCRIPTOR_HEAP_TYPE HeapType);\r\n    ~DynamicDescriptorHeap();\r\n\r\n    static void DestroyAll(void)\r\n    {\r\n        sm_DescriptorHeapPool[0].clear();\r\n        sm_DescriptorHeapPool[1].clear();\r\n    }\r\n\r\n    void CleanupUsedHeaps( uint64_t fenceValue );\r\n\r\n    // Copy multiple handles into the cache area reserved for the specified root parameter.\r\n    void SetGraphicsDescriptorHandles( UINT RootIndex, UINT Offset, UINT NumHandles, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n    {\r\n        m_GraphicsHandleCache.StageDescriptorHandles(RootIndex, Offset, NumHandles, Handles);\r\n    }\r\n\r\n    void SetComputeDescriptorHandles( UINT RootIndex, UINT Offset, UINT NumHandles, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] )\r\n    {\r\n        m_ComputeHandleCache.StageDescriptorHandles(RootIndex, Offset, NumHandles, Handles);\r\n    }\r\n\r\n    // Bypass the cache and upload directly to the shader-visible heap\r\n    D3D12_GPU_DESCRIPTOR_HANDLE UploadDirect( D3D12_CPU_DESCRIPTOR_HANDLE Handles );\r\n\r\n    // Deduce cache layout needed to support the descriptor tables needed by the root signature.\r\n    void ParseGraphicsRootSignature( const RootSignature& RootSig )\r\n    {\r\n        m_GraphicsHandleCache.ParseRootSignature(m_DescriptorType, RootSig);\r\n    }\r\n\r\n    void ParseComputeRootSignature( const RootSignature& RootSig )\r\n    {\r\n        m_ComputeHandleCache.ParseRootSignature(m_DescriptorType, RootSig);\r\n    }\r\n\r\n    // Upload any new descriptors in the cache to the shader-visible heap.\r\n    inline void CommitGraphicsRootDescriptorTables( DX12_GRAPHICSCOMMANDLIST* CmdList )\r\n    {\r\n        if (m_GraphicsHandleCache.m_StaleRootParamsBitMap != 0)\r\n            CopyAndBindStagedTables(m_GraphicsHandleCache, CmdList, &DX12_GRAPHICSCOMMANDLIST::SetGraphicsRootDescriptorTable);\r\n    }\r\n\r\n    inline void CommitComputeRootDescriptorTables( DX12_GRAPHICSCOMMANDLIST* CmdList )\r\n    {\r\n        if (m_ComputeHandleCache.m_StaleRootParamsBitMap != 0)\r\n            CopyAndBindStagedTables(m_ComputeHandleCache, CmdList, &DX12_GRAPHICSCOMMANDLIST::SetComputeRootDescriptorTable);\r\n    }\r\n\r\nprivate:\r\n\r\n    // Static members\r\n    static const uint32_t kNumDescriptorsPerHeap = 1024;\r\n    static std::mutex sm_Mutex;\r\n    static std::vector<Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>> sm_DescriptorHeapPool[2];\r\n    static std::queue<std::pair<uint64_t, ID3D12DescriptorHeap*>> sm_RetiredDescriptorHeaps[2];\r\n    static std::queue<ID3D12DescriptorHeap*> sm_AvailableDescriptorHeaps[2];\r\n\r\n    // Static methods\r\n    static ID3D12DescriptorHeap* RequestDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE HeapType);\r\n    static void DiscardDescriptorHeaps( D3D12_DESCRIPTOR_HEAP_TYPE HeapType, uint64_t FenceValueForReset, const std::vector<ID3D12DescriptorHeap*>& UsedHeaps );\r\n\r\n    // Non-static members\r\n    CommandContext& m_OwningContext;\r\n    ID3D12DescriptorHeap* m_CurrentHeapPtr;\r\n    const D3D12_DESCRIPTOR_HEAP_TYPE m_DescriptorType;\r\n    uint32_t m_DescriptorSize;\r\n    uint32_t m_CurrentOffset;\r\n    DescriptorHandle m_FirstDescriptor;\r\n    std::vector<ID3D12DescriptorHeap*> m_RetiredHeaps;\r\n\r\n    // Describes a descriptor table entry:  a region of the handle cache and which handles have been set\r\n    struct DescriptorTableCache\r\n    {\r\n        DescriptorTableCache() : AssignedHandlesBitMap(0) {}\r\n        uint32_t AssignedHandlesBitMap;\r\n        D3D12_CPU_DESCRIPTOR_HANDLE* TableStart;\r\n        uint32_t TableSize;\r\n    };\r\n\r\n    struct DescriptorHandleCache\r\n    {\r\n        DescriptorHandleCache()\r\n        {\r\n            ClearCache();\r\n        }\r\n\r\n        void ClearCache()\r\n        {\r\n            m_RootDescriptorTablesBitMap = 0;\r\n            m_MaxCachedDescriptors = 0;\r\n        }\r\n\r\n        uint32_t m_RootDescriptorTablesBitMap;\r\n        uint32_t m_StaleRootParamsBitMap;\r\n        uint32_t m_MaxCachedDescriptors;\r\n\r\n        static const uint32_t kMaxNumDescriptors = 256;\r\n        static const uint32_t kMaxNumDescriptorTables = 16;\r\n\r\n        uint32_t ComputeStagedSize();\r\n        void CopyAndBindStaleTables( D3D12_DESCRIPTOR_HEAP_TYPE Type, uint32_t DescriptorSize, DescriptorHandle DestHandleStart, DX12_GRAPHICSCOMMANDLIST* CmdList,\r\n            void (STDMETHODCALLTYPE DX12_GRAPHICSCOMMANDLIST::*SetFunc)(UINT, D3D12_GPU_DESCRIPTOR_HANDLE));\r\n\r\n        DescriptorTableCache m_RootDescriptorTable[kMaxNumDescriptorTables];\r\n        D3D12_CPU_DESCRIPTOR_HANDLE m_HandleCache[kMaxNumDescriptors];\r\n\r\n        void UnbindAllValid();\r\n        void StageDescriptorHandles( UINT RootIndex, UINT Offset, UINT NumHandles, const D3D12_CPU_DESCRIPTOR_HANDLE Handles[] );\r\n        void ParseRootSignature( D3D12_DESCRIPTOR_HEAP_TYPE Type, const RootSignature& RootSig );\r\n    };\r\n\r\n    DescriptorHandleCache m_GraphicsHandleCache;\r\n    DescriptorHandleCache m_ComputeHandleCache;\r\n\r\n    bool HasSpace( uint32_t Count )\r\n    {\r\n        return (m_CurrentHeapPtr != nullptr && m_CurrentOffset + Count <= kNumDescriptorsPerHeap);\r\n    }\r\n\r\n    void RetireCurrentHeap(void);\r\n    void RetireUsedHeaps( uint64_t fenceValue );\r\n    ID3D12DescriptorHeap* GetHeapPointer();\r\n\r\n    DescriptorHandle Allocate( UINT Count )\r\n    {\r\n        DescriptorHandle ret = m_FirstDescriptor + m_CurrentOffset * m_DescriptorSize;\r\n        m_CurrentOffset += Count;\r\n        return ret;\r\n    }\r\n\r\n    void CopyAndBindStagedTables( DescriptorHandleCache& HandleCache, DX12_GRAPHICSCOMMANDLIST* CmdList,\r\n        void (STDMETHODCALLTYPE DX12_GRAPHICSCOMMANDLIST::*SetFunc)(UINT, D3D12_GPU_DESCRIPTOR_HANDLE) );\r\n\r\n    // Mark all descriptors in the cache as stale and in need of re-uploading.\r\n    void UnbindAllValid( void );\r\n\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/DynamicUploadBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"DynamicUploadBuffer.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nvoid DynamicUploadBuffer::Create(const std::wstring& name, uint32_t NumElements, uint32_t ElementSize)\r\n{\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n    HeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;\r\n\r\n    D3D12_RESOURCE_DESC ResourceDesc;\r\n    ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;\r\n    ResourceDesc.Alignment = 0;\r\n    ResourceDesc.Height = 1;\r\n    ResourceDesc.DepthOrArraySize = 1;\r\n    ResourceDesc.MipLevels = 1;\r\n    ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;\r\n    ResourceDesc.SampleDesc.Count = 1;\r\n    ResourceDesc.SampleDesc.Quality = 0;\r\n    ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;\r\n    ResourceDesc.Width = NumElements * ElementSize;\r\n    ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;\r\n\r\n    ASSERT_SUCCEEDED( g_Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc,\r\n        D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, MY_IID_PPV_ARGS(&m_pResource)) );\r\n\r\n    m_pResource->SetName(name.c_str());\r\n\r\n    m_GpuVirtualAddress = m_pResource->GetGPUVirtualAddress();\r\n    m_CpuVirtualAddress = nullptr;\r\n}\r\n\r\nvoid DynamicUploadBuffer::Destroy( void )\r\n{\r\n    if (m_pResource.Get() != nullptr)\r\n    {\r\n        if (m_CpuVirtualAddress != nullptr)\r\n            Unmap();\r\n\r\n        m_pResource = nullptr;\r\n        m_GpuVirtualAddress = D3D12_GPU_VIRTUAL_ADDRESS_NULL;\r\n    }\r\n}\r\n\r\nvoid* DynamicUploadBuffer::Map( void )\r\n{\r\n    ASSERT(m_CpuVirtualAddress == nullptr, \"Buffer is already locked\");\r\n    ASSERT_SUCCEEDED(m_pResource->Map(0, nullptr, &m_CpuVirtualAddress));\r\n    return m_CpuVirtualAddress;\r\n}\r\n\r\nvoid DynamicUploadBuffer::Unmap( void )\r\n{\r\n    ASSERT(m_CpuVirtualAddress != nullptr, \"Buffer is not locked\");\r\n    m_pResource->Unmap(0, nullptr);\r\n    m_CpuVirtualAddress = nullptr;\r\n}\r\n\r\nD3D12_VERTEX_BUFFER_VIEW DynamicUploadBuffer::VertexBufferView(uint32_t NumVertices, uint32_t Stride, uint32_t Offset ) const\r\n{\r\n    D3D12_VERTEX_BUFFER_VIEW vbv;\r\n    vbv.BufferLocation = m_GpuVirtualAddress + Offset;\r\n    vbv.SizeInBytes = NumVertices * Stride;\r\n    vbv.StrideInBytes = Stride;\r\n    return vbv;\r\n}\r\n\r\nD3D12_INDEX_BUFFER_VIEW DynamicUploadBuffer::IndexBufferView(uint32_t NumIndices, bool _32bit, uint32_t Offset ) const\r\n{\r\n    D3D12_INDEX_BUFFER_VIEW ibv;\r\n    ibv.BufferLocation = m_GpuVirtualAddress + Offset;\r\n    ibv.Format = _32bit ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;\r\n    ibv.SizeInBytes = NumIndices * (_32bit ? 4 : 2);\r\n    return ibv;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/DynamicUploadBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\nclass DynamicUploadBuffer\r\n{\r\npublic:\r\n    DynamicUploadBuffer() : m_GpuVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS_NULL), m_CpuVirtualAddress(nullptr) {}\r\n    ~DynamicUploadBuffer() { Destroy(); }\r\n\r\n    void Create(const std::wstring& name, uint32_t NumElements, uint32_t ElementSize);\r\n    void Destroy(void);\r\n\r\n    // Map a CPU-visible pointer to the buffer memory.  You probably don't want to leave a lot of\r\n    // memory (100s of MB) mapped this way, so you have the option of unmapping it.\r\n    void* Map(void);\r\n    void Unmap(void);\r\n\r\n    D3D12_VERTEX_BUFFER_VIEW VertexBufferView(uint32_t NumVertices, uint32_t Stride, uint32_t Offset = 0) const;\r\n    D3D12_INDEX_BUFFER_VIEW IndexBufferView(uint32_t NumIndices, bool _32bit, uint32_t Offset = 0) const;\r\n    D3D12_GPU_VIRTUAL_ADDRESS GetGpuPointer(uint32_t Offset = 0) const\r\n    {\r\n        return m_GpuVirtualAddress + Offset;\r\n    }\r\n\r\nprivate:\r\n    Microsoft::WRL::ComPtr<ID3D12Resource> m_pResource;\r\n    D3D12_GPU_VIRTUAL_ADDRESS m_GpuVirtualAddress;\r\n    void* m_CpuVirtualAddress;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/EngineProfiling.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n\r\n#include \"SystemTime.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"TextRenderer.h\"\r\n#include \"GraphRenderer.h\"\r\n#include \"GameInput.h\"\r\n#include \"GpuCounterManager.h\"\r\n#include \"CommandContext.h\"\r\n#include <vector>\r\n#include <unordered_map>\r\n#include <array>\r\n\r\n#include \"document.h\"\r\n#include \"writer.h\"\r\n#include \"prettywriter.h\"\r\n#include \"stringbuffer.h\"\r\n\r\n#include <iostream>\r\n#include <fstream>\r\n#include <sstream>\r\n\r\nusing namespace Graphics;\r\nusing namespace GraphRenderer;\r\nusing namespace Math;\r\nusing namespace std;\r\n\r\n#define PERF_GRAPH_ERROR uint32_t(0xFFFFFFFF)\r\nnamespace EngineProfiling\r\n{\r\n    bool Paused = false;\r\n}\r\n\r\nclass StatHistory\r\n{\r\npublic:\r\n    StatHistory()\r\n    {\r\n        for (uint32_t i = 0; i < kHistorySize; ++i)\r\n            m_RecentHistory[i] = 0.0f;\r\n        for (uint32_t i = 0; i < kExtendedHistorySize; ++i)\r\n            m_ExtendedHistory[i] = 0.0f;\r\n        m_Average = 0.0f;\r\n        m_Minimum = 0.0f;\r\n        m_Maximum = 0.0f;\r\n    }\r\n\r\n    void RecordStat( uint32_t FrameIndex, float Value )\r\n    {\r\n        m_RecentHistory[FrameIndex % kHistorySize] = Value;\r\n        m_ExtendedHistory[FrameIndex % kExtendedHistorySize] = Value;\r\n        m_Recent = Value;\r\n\r\n        uint32_t ValidCount = 0;\r\n        m_Minimum = FLT_MAX;\r\n        m_Maximum = 0.0f;\r\n        m_Average = 0.0f;\r\n\r\n        for (float val : m_RecentHistory)\r\n        {\r\n            if (val > 0.0f)\r\n            {\r\n                ++ValidCount;\r\n                m_Average += val;\r\n                m_Minimum = min(val, m_Minimum);\r\n                m_Maximum = max(val, m_Maximum);\r\n            }\r\n        }\r\n\r\n        if (ValidCount > 0)\r\n            m_Average /= (float)ValidCount;\r\n        else\r\n            m_Minimum = 0.0f;\r\n    }\r\n\r\n    float GetLast(void) const { return m_Recent; }\r\n    float GetMax(void) const { return m_Maximum; }\r\n    float GetMin(void) const { return m_Minimum; }\r\n    float GetAvg(void) const { return m_Average; }\r\n\r\n    const float* GetHistory(void) const { return m_ExtendedHistory; }\r\n    uint32_t GetHistoryLength(void) const { return kExtendedHistorySize; }\r\n\r\nprivate:\r\n    static const uint32_t kHistorySize = 64;\r\n    static const uint32_t kExtendedHistorySize = 256;\r\n    float m_RecentHistory[kHistorySize];\r\n    float m_ExtendedHistory[kExtendedHistorySize];\r\n    float m_Recent;\r\n    float m_Average;\r\n    float m_Minimum;\r\n    float m_Maximum;\r\n};\r\n\r\nclass StatPlot\r\n{\r\npublic:\r\n    StatPlot(StatHistory& Data, Color Col = Color(1.0f, 1.0f, 1.0f))\r\n        : m_StatData(Data), m_PlotColor(Col)\r\n    {\r\n    }\r\n\r\n    void SetColor( Color Col )\r\n    {\r\n        m_PlotColor = Col;\r\n    }\r\n\r\nprivate:\r\n    StatHistory& m_StatData;\r\n    Color m_PlotColor;\r\n};\r\n\r\nclass StatGraph\r\n{\r\npublic:\r\n    StatGraph(const wstring& Label, D3D12_RECT Window)\r\n        : m_Label(Label), m_Window(Window), m_BGColor(0.0f, 0.0f, 0.0f, 0.2f)\r\n    {\r\n    }\r\n\r\n    void SetLabel(const wstring& Label)\r\n    {\r\n        m_Label = Label;\r\n    }\r\n\r\n    void SetWindow(D3D12_RECT Window)\r\n    {\r\n        m_Window = Window;\r\n    }\r\n\r\n    uint32_t AddPlot( const StatPlot& P )\r\n    {\r\n        uint32_t Idx = (uint32_t)m_Stats.size();\r\n        m_Stats.push_back(P);\r\n        return Idx;\r\n    }\r\n\r\n    StatPlot& GetPlot( uint32_t Handle );\r\n\r\n    void Draw( GraphicsContext& Context );\r\n\r\nprivate:\r\n    wstring m_Label;\r\n    D3D12_RECT m_Window;\r\n    vector<StatPlot> m_Stats;\r\n    Color m_BGColor;\r\n    float m_PeakValue;\r\n};\r\n\r\nclass GraphManager\r\n{\r\npublic:\r\n\r\nprivate:\r\n    vector<StatGraph> m_Graphs;\r\n};\r\n\r\nclass GpuTimer\r\n{\r\npublic:\r\n\r\n    GpuTimer::GpuTimer()\r\n    {\r\n        m_TimerIndex = GpuCounterManager::NewTimer();\r\n    }\r\n\r\n    void Start(CommandContext& Context)\r\n    {\r\n        GpuCounterManager::StartTimer(Context, m_TimerIndex);\r\n    }\r\n\r\n    void Stop(CommandContext& Context)\r\n    {\r\n        GpuCounterManager::StopTimer(Context, m_TimerIndex);\r\n    }\r\n\r\n    float GpuTimer::GetTime(void)\r\n    {\r\n        return GpuCounterManager::GetTime(m_TimerIndex);\r\n    }\r\n\r\n    uint32_t GetTimerIndex(void)\r\n    {\r\n        return m_TimerIndex;\r\n    }\r\nprivate:\r\n\r\n    uint32_t m_TimerIndex;\r\n};\r\n\r\nclass GraphicsPipelineQuery {\r\npublic:\r\n\tGraphicsPipelineQuery() {\r\n\t\tm_QueryIndex = GpuCounterManager::NewPipelineQuery();\r\n\t}\r\n\r\n\tvoid Begin(CommandContext& Context) {\r\n\t\tGpuCounterManager::BeginPipelineQuery(Context, m_QueryIndex);\r\n\t}\r\n\r\n\tvoid End(CommandContext& Context) {\r\n\t\tGpuCounterManager::EndPipelineQuery(Context, m_QueryIndex);\r\n\t}\r\n\r\n\tvoid GetPipelineStatistics(D3D12_QUERY_DATA_PIPELINE_STATISTICS& stats) {\r\n\t\tGpuCounterManager::GetPipelineStatistics(m_QueryIndex, stats);\r\n\t}\r\n\r\n\tuint32_t GetQueryIndex() {\r\n\t\treturn m_QueryIndex;\r\n\t}\r\n\r\nprivate:\r\n\tuint32_t m_QueryIndex;\r\n};\r\n\r\nclass NestedTimingTree\r\n{\r\npublic:\r\n    NestedTimingTree( const wstring& name, NestedTimingTree* parent = nullptr )\r\n        : m_Name(name), m_Parent(parent), m_IsExpanded(false), m_IsGraphed(false), m_GraphHandle(PERF_GRAPH_ERROR) {}\r\n\r\n    NestedTimingTree* GetChild( const wstring& name )\r\n    {\r\n        auto iter = m_LUT.find(name);\r\n        if (iter != m_LUT.end())\r\n            return iter->second;\r\n\r\n        NestedTimingTree* node = new NestedTimingTree(name, this);\r\n        m_Children.push_back(node);\r\n        m_LUT[name] = node;\r\n        return node;\r\n    }\r\n\r\n    NestedTimingTree* NextScope( void )\r\n    {\r\n        if (m_IsExpanded && m_Children.size() > 0)\r\n            return m_Children[0];\r\n\r\n        return m_Parent->NextChild(this);\r\n    }\r\n\r\n    NestedTimingTree* PrevScope( void )\r\n    {\r\n        NestedTimingTree* prev = m_Parent->PrevChild(this);\r\n        return prev == m_Parent ? prev : prev->LastChild();\r\n    }\r\n\r\n    NestedTimingTree* FirstChild( void )\r\n    {\r\n        return m_Children.size() == 0 ? nullptr : m_Children[0];\r\n    }\r\n\r\n    NestedTimingTree* LastChild( void )\r\n    {\r\n        if (!m_IsExpanded || m_Children.size() == 0)\r\n            return this;\r\n\r\n        return m_Children.back()->LastChild();\r\n    }\r\n\r\n    NestedTimingTree* NextChild( NestedTimingTree* curChild )\r\n    {\r\n        ASSERT(curChild->m_Parent == this);\r\n\r\n        for (auto iter = m_Children.begin(); iter != m_Children.end(); ++iter)\r\n        {\r\n            if (*iter == curChild)\r\n            {\r\n                auto nextChild = iter; ++nextChild;\r\n                if (nextChild != m_Children.end())\r\n                    return *nextChild;\r\n            }\r\n        }\r\n\r\n        if (m_Parent != nullptr)\r\n            return m_Parent->NextChild(this);\r\n        else\r\n            return &sm_RootScope;\r\n    }\r\n\r\n    NestedTimingTree* PrevChild( NestedTimingTree* curChild )\r\n    {\r\n        ASSERT(curChild->m_Parent == this);\r\n\r\n        if (*m_Children.begin() == curChild)\r\n        {\r\n            if (this == &sm_RootScope)\r\n                return sm_RootScope.LastChild();\r\n            else\r\n                return this;\r\n        }\r\n\r\n        for (auto iter = m_Children.begin(); iter != m_Children.end(); ++iter)\r\n        {\r\n            if (*iter == curChild)\r\n            {\r\n                auto prevChild = iter; --prevChild;\r\n                return *prevChild;\r\n            }\r\n        }\r\n\r\n        ERROR(\"All attempts to find a previous timing sample failed\");\r\n        return nullptr;\r\n    }\r\n\r\n    void StartTiming( CommandContext* Context )\r\n    {\r\n        m_StartTick = SystemTime::GetCurrentTick();\r\n        if (Context == nullptr)\r\n            return;\r\n\r\n        m_GpuTimer.Start(*Context);\r\n\r\n        Context->PIXBeginEvent(m_Name.c_str());\r\n    }\r\n\r\n    void StopTiming( CommandContext* Context )\r\n    {\r\n        m_EndTick = SystemTime::GetCurrentTick();\r\n        if (Context == nullptr)\r\n            return;\r\n\r\n        m_GpuTimer.Stop(*Context);\r\n\r\n        Context->PIXEndEvent();\r\n    }\r\n\r\n\tvoid BeginPipelineQueryInternal(const std::wstring& Name, CommandContext* Context) {\r\n\t\t\r\n\t\tif (Context == nullptr)\r\n\t\t\treturn;\r\n\r\n\t\tsize_t queryIdx = size_t(-1);\r\n\r\n\t\tauto iter = m_PipelineQueryLUT.find(Name);\r\n\t\tif (iter != m_PipelineQueryLUT.end())\r\n\t\t\tqueryIdx = iter->second;\r\n\r\n\t\tif (queryIdx == size_t(-1)) {\r\n\t\t\tm_PipelineQueryLUT[Name] = m_PipelineQueries.size();\r\n\t\t\tqueryIdx = m_PipelineQueries.size();\r\n\t\t\t\r\n\t\t\tm_PipelineQueries.push_back(GraphicsPipelineQuery());\r\n\t\t\tm_LastPipelineQueryData.push_back(D3D12_QUERY_DATA_PIPELINE_STATISTICS());\r\n\t\t}\r\n\r\n\t\tm_PipelineQueries[queryIdx].Begin(*Context);\r\n\t}\r\n\r\n\tvoid EndPipelineQueryInternal(const std::wstring& Name, CommandContext* Context) {\r\n\t\tif (Context == nullptr)\r\n\t\t\treturn;\r\n\r\n\t\tauto iter = m_PipelineQueryLUT.find(Name);\r\n\t\tASSERT(iter != m_PipelineQueryLUT.end());\r\n\t\tsize_t queryIdx = iter->second;\r\n\r\n\t\tm_PipelineQueries[queryIdx].End(*Context);\r\n\t}\r\n\r\n    void GatherTimes(uint32_t FrameIndex)\r\n    {\r\n        if (sm_SelectedScope == this)\r\n        {\r\n            GraphRenderer::SetSelectedIndex(m_GpuTimer.GetTimerIndex());\r\n        }\r\n        if (EngineProfiling::Paused)\r\n        {\r\n            for (auto node : m_Children)\r\n                node->GatherTimes(FrameIndex);\r\n            return;\r\n        }\r\n        m_CpuTime.RecordStat(FrameIndex, 1000.0f * (float)SystemTime::TimeBetweenTicks(m_StartTick, m_EndTick));\r\n        m_GpuTime.RecordStat(FrameIndex, 1000.0f * m_GpuTimer.GetTime());\r\n\r\n\t\t// get pipeline statistics for all counters\r\n\t\tfor (size_t iQuery = 0; iQuery < m_PipelineQueries.size(); iQuery++) {\r\n\t\t\tm_PipelineQueries[iQuery].GetPipelineStatistics(m_LastPipelineQueryData[iQuery]);\r\n\t\t}\r\n\r\n        for (auto node : m_Children)\r\n            node->GatherTimes(FrameIndex);\r\n\r\n        m_StartTick = 0;\r\n        m_EndTick = 0;\r\n    }\r\n\r\n    void SumInclusiveTimes(float& cpuTime, float& gpuTime)\r\n    {\r\n        cpuTime = 0.0f;\r\n        gpuTime = 0.0f;\r\n        for (auto iter = m_Children.begin(); iter != m_Children.end(); ++iter)\r\n        {\r\n            cpuTime += (*iter)->m_CpuTime.GetLast();\r\n            gpuTime += (*iter)->m_GpuTime.GetLast();\r\n        }\r\n    }\r\n\r\n    static void PushProfilingMarker( const wstring& name, CommandContext* Context );\r\n    static void PopProfilingMarker( CommandContext* Context );\r\n\t\r\n\tstatic void BeginPipelineQuery(const wstring& name, CommandContext* Context);\r\n\tstatic void EndPipelineQuery(const wstring& name, CommandContext* Context);\r\n\r\n    static void Update( void );\r\n    static void UpdateTimes( void )\r\n    {\r\n        uint32_t FrameIndex = (uint32_t)Graphics::GetFrameCount();\r\n\r\n        GpuCounterManager::BeginReadBack();\r\n        sm_RootScope.GatherTimes(FrameIndex);\r\n        s_FrameDelta.RecordStat(FrameIndex, GpuCounterManager::GetTime(0));\r\n        GpuCounterManager::EndReadBack();\r\n\r\n        float TotalCpuTime, TotalGpuTime;\r\n        sm_RootScope.SumInclusiveTimes(TotalCpuTime, TotalGpuTime);\r\n        s_TotalCpuTime.RecordStat(FrameIndex, TotalCpuTime);\r\n        s_TotalGpuTime.RecordStat(FrameIndex, TotalGpuTime);\r\n\r\n        GraphRenderer::Update(XMFLOAT2(TotalCpuTime, TotalGpuTime), 0, GraphType::Global);\r\n    }\r\n\r\n    static float GetTotalCpuTime(void) { return s_TotalCpuTime.GetAvg(); }\r\n    static float GetTotalGpuTime(void) { return s_TotalGpuTime.GetAvg(); }\r\n    static float GetFrameDelta(void) { return s_FrameDelta.GetAvg(); }\r\n\r\n    static void Display( TextContext& Text, float x )\r\n    {\r\n        float curX = Text.GetCursorX();\r\n        Text.DrawString(\"  \");\r\n        float indent = Text.GetCursorX() - curX;\r\n        Text.SetCursorX(curX);\r\n        sm_RootScope.DisplayNode( Text, x - indent, indent );\r\n        sm_RootScope.StoreToGraph();\r\n    }\r\n\r\n\tstatic void FillPerfData(ART::PerfCounterReport& report) {\r\n\t\tsm_RootScope.fillPerfDataRecursive(report);\r\n\t}\r\n\r\n\ttemplate<class TWriter>\r\n\tstatic void WriteJson(TWriter& writer) {\r\n\t\tsm_RootScope.writeJsonRecursive(writer);\r\n\t}\r\n\r\n    void Toggle()\r\n    { \r\n        //if (m_GraphHandle == PERF_GRAPH_ERROR)\r\n        //\tm_GraphHandle = GraphRenderer::InitGraph(GraphType::Profile);\r\n        //m_IsGraphed = GraphRenderer::ManageGraphs(m_GraphHandle, GraphType::Profile);\r\n    }\r\n    bool IsGraphed(){ return m_IsGraphed;}\r\n\r\nprivate:\r\n\r\n    void DisplayNode( TextContext& Text, float x, float indent );\r\n    void StoreToGraph(void);\r\n    void DeleteChildren( void )\r\n    {\r\n        for (auto node : m_Children)\r\n            delete node;\r\n        m_Children.clear();\r\n    }\r\n\r\n\ttemplate<class TWriter>\r\n\tvoid writeJsonRecursive(TWriter& writer) const {\r\n\t\twriter.StartObject();\r\n\r\n\t\t\twriter.Key(\"Name\");\r\n\t\t\twriter.String(std::string(m_Name.begin(), m_Name.end()).c_str());\r\n\r\n\t\t\twriter.Key(\"GPUTime\");\r\n\t\t\twriter.Double(m_GpuTime.GetLast());\r\n\r\n\t\t\tif (m_PipelineQueries.size() > 0) {\r\n\t\t\t\twriter.Key(\"PipelineQueries\");\r\n\t\t\t\twriter.StartArray();\r\n\t\t\t\tfor (auto& queryIt : m_PipelineQueryLUT) {\r\n\t\t\t\t\twriter.StartObject();\r\n\t\t\t\t\twriter.Key(\"Name\");\r\n\t\t\t\t\twriter.String(std::string(queryIt.first.begin(), queryIt.first.end()).c_str());\r\n\r\n\t\t\t\t\tsize_t idx = queryIt.second;\r\n\t\t\t\t\tauto& lastData = m_LastPipelineQueryData[idx];\r\n\t\t\t\t\t\r\n\t\t\t\t\twriter.Key(\"PSInvocations\");\r\n\t\t\t\t\twriter.Uint64(lastData.PSInvocations);\r\n\r\n\t\t\t\t\twriter.EndObject();\r\n\t\t\t\t}\r\n\t\t\t\twriter.EndArray();\r\n\t\t\t}\r\n\r\n\t\t\tif (m_Children.size() > 0) {\r\n\t\t\t\twriter.Key(\"SubEvents\");\r\n\t\t\t\twriter.StartArray();\r\n\r\n\t\t\t\tfor (auto& child : m_Children) {\r\n\t\t\t\t\tif (child)\r\n\t\t\t\t\t\tchild->writeJsonRecursive(writer);\r\n\t\t\t\t}\r\n\r\n\t\t\t\twriter.EndArray();\r\n\t\t\t}\r\n\r\n\t\twriter.EndObject();\r\n\t}\r\n\r\n\tvoid fillPerfDataRecursive(ART::PerfCounterReport& report) {\r\n\t\t\r\n        report.StoreCounterValue(\"Resolution Scale\", g_ResolutionScale);\r\n        \r\n        if(m_Name.length() > 0)\r\n\t\t\treport.StoreCounterValue(std::string(m_Name.begin(), m_Name.end()).c_str(), m_GpuTime.GetLast());\r\n\t\t\r\n\t\tif (m_LastPipelineQueryData.size() > 0) {\r\n\t\t\tfor (auto& query : m_PipelineQueryLUT) {\r\n\t\t\t\tstd::wstringstream ctrNameStrm;\r\n\t\t\t\tctrNameStrm << m_Name << L\".\" << query.first << \".PSInvocations\";\r\n\t\t\t\tstd::wstring ctrName = ctrNameStrm.str();\r\n\r\n\t\t\t\tfloat ctrValue = (float) m_LastPipelineQueryData[query.second].PSInvocations;\r\n\r\n\t\t\t\treport.StoreCounterValue(std::string(ctrName.begin(), ctrName.end()).c_str(), ctrValue);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tfor (auto& child : m_Children) {\r\n\t\t\tif (child)\r\n\t\t\t\tchild->fillPerfDataRecursive(report);\r\n\t\t}\r\n\t}\r\n\r\n    wstring m_Name;\r\n    NestedTimingTree* m_Parent;\r\n    vector<NestedTimingTree*> m_Children;\r\n    unordered_map<wstring, NestedTimingTree*> m_LUT;\r\n    int64_t m_StartTick;\r\n    int64_t m_EndTick;\r\n    StatHistory m_CpuTime;\r\n    StatHistory m_GpuTime;\r\n    bool m_IsExpanded;\r\n    GpuTimer m_GpuTimer;\r\n    bool m_IsGraphed;\r\n    GraphHandle m_GraphHandle;\r\n    static StatHistory s_TotalCpuTime;\r\n    static StatHistory s_TotalGpuTime;\r\n    static StatHistory s_FrameDelta;\r\n    static NestedTimingTree sm_RootScope;\r\n    static NestedTimingTree* sm_CurrentNode;\r\n    static NestedTimingTree* sm_SelectedScope;\r\n\r\n\tvector<GraphicsPipelineQuery> m_PipelineQueries;\r\n\tvector<D3D12_QUERY_DATA_PIPELINE_STATISTICS> m_LastPipelineQueryData;\r\n\tunordered_map<wstring, size_t> m_PipelineQueryLUT;\r\n\r\n    static bool sm_CursorOnGraph;\r\n\r\n};\r\n\r\nStatHistory NestedTimingTree::s_TotalCpuTime;\r\nStatHistory NestedTimingTree::s_TotalGpuTime;\r\nStatHistory NestedTimingTree::s_FrameDelta;\r\nNestedTimingTree NestedTimingTree::sm_RootScope(L\"\");\r\nNestedTimingTree* NestedTimingTree::sm_CurrentNode = &NestedTimingTree::sm_RootScope;\r\nNestedTimingTree* NestedTimingTree::sm_SelectedScope = &NestedTimingTree::sm_RootScope;\r\nbool NestedTimingTree::sm_CursorOnGraph = false;\r\nnamespace EngineProfiling\r\n{\r\n    BoolVar DrawFrameRate(\"Display Frame Rate\", true);\r\n    BoolVar DrawProfiler(\"Display Profiler\", false);\r\n    BoolVar DrawPerfGraph(\"Display Performance Graph\", false);\r\n    //const bool DrawPerfGraph = false;\r\n    \r\n    void Update( void )\r\n    {\r\n        if (GameInput::IsFirstPressed( GameInput::kStartButton ) \r\n            || GameInput::IsFirstPressed( GameInput::kKey_space ))\r\n        {\r\n            Paused = !Paused;\r\n        }\r\n        NestedTimingTree::UpdateTimes();\r\n    }\r\n\r\n    void BeginBlock(const wstring& name, CommandContext* Context)\r\n    {\r\n        NestedTimingTree::PushProfilingMarker(name, Context);\r\n    }\r\n\r\n    void EndBlock(CommandContext* Context)\r\n    {\r\n        NestedTimingTree::PopProfilingMarker(Context);\r\n    }\r\n\r\n\tvoid BeginPipelineQuery(const std::wstring& name, CommandContext* Context /* = nullptr */) {\r\n\t\tNestedTimingTree::BeginPipelineQuery(name, Context);\r\n\t}\r\n\r\n\tvoid EndPipelineQuery(const std::wstring& name, CommandContext* Context /* = nullptr */) {\r\n\t\tNestedTimingTree::EndPipelineQuery(name, Context);\r\n\t}\r\n\r\n    bool IsPaused()\r\n    {\r\n        return Paused;\r\n    }\r\n\r\n    void DisplayFrameRate( TextContext& Text )\r\n    {\r\n        if (!DrawFrameRate)\r\n            return;\r\n        \r\n        float cpuTime = NestedTimingTree::GetTotalCpuTime();\r\n        float gpuTime = NestedTimingTree::GetTotalGpuTime();\r\n        float frameRate = 1.0f / NestedTimingTree::GetFrameDelta();\r\n\r\n        Text.DrawFormattedString( \"CPU %7.3f ms, GPU %7.3f ms, %3u Hz, DRR Scale: %.2f\\n\",\r\n            cpuTime, gpuTime, (uint32_t)(frameRate + 0.5f), Graphics::g_ResolutionScale);\r\n    }\r\n\r\n    void DisplayPerfGraph( GraphicsContext& Context )\r\n    {\r\n        if (DrawPerfGraph)\r\n            GraphRenderer::RenderGraphs(Context, GraphType::Global );\r\n    }\r\n\r\n    void Display( TextContext& Text, float x, float y, float /*w*/, float /*h*/ )\r\n    {\r\n        Text.ResetCursor(x, y);\r\n\r\n        if (DrawProfiler)\r\n        {\r\n            //Text.GetCommandContext().SetScissor((uint32_t)Floor(x), (uint32_t)Floor(y), (uint32_t)Ceiling(w), (uint32_t)Ceiling(h));\r\n\r\n            NestedTimingTree::Update();\r\n\r\n            Text.SetColor( Color(0.5f, 1.0f, 1.0f) );\r\n            Text.DrawString(\"Engine Profiling\");\r\n            Text.SetColor(Color(0.8f, 0.8f, 0.8f));\r\n            Text.SetTextSize(20.0f);\r\n            Text.DrawString(\"           CPU    GPU\");\r\n            Text.SetTextSize(24.0f);\r\n            Text.NewLine();\r\n            Text.SetTextSize(20.0f);\r\n            Text.SetColor( Color(1.0f, 1.0f, 1.0f) );\r\n\r\n            NestedTimingTree::Display( Text, x );\r\n        }\r\n\r\n        Text.GetCommandContext().SetScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n    }\r\n\r\n\tvoid WriteLastFrameToJson(const std::string& path) {\r\n\t\trapidjson::StringBuffer buf;\r\n\t\trapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);\r\n\r\n\t\tNestedTimingTree::WriteJson(writer);\r\n\r\n\t\tstd::ofstream of(path.c_str());\r\n\t\tif (!of) {\r\n\t\t\tstd::cout << \"Unable to write file: \" << path.c_str() << std::endl;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tof << buf.GetString();\r\n\t\tof.close();\r\n\t}\r\n\r\n\tvoid FillPerfDataForLastFrame(ART::PerfCounterReport& report) {\r\n\t\tNestedTimingTree::FillPerfData(report);\r\n\t}\r\n\r\n    float GetFrameGPUTime( void )\r\n    {\r\n        return NestedTimingTree::GetTotalGpuTime();\r\n    }\r\n\r\n} // EngineProfiling\r\n\r\nvoid NestedTimingTree::PushProfilingMarker( const wstring& name, CommandContext* Context )\r\n{\r\n    sm_CurrentNode = sm_CurrentNode->GetChild(name);\r\n    sm_CurrentNode->StartTiming(Context);\r\n}\r\n\r\nvoid NestedTimingTree::PopProfilingMarker( CommandContext* Context )\r\n{\r\n    sm_CurrentNode->StopTiming(Context);\r\n    sm_CurrentNode = sm_CurrentNode->m_Parent;\r\n}\r\n\r\nvoid NestedTimingTree::BeginPipelineQuery(const wstring& name, CommandContext* Context) {\r\n\tsm_CurrentNode->BeginPipelineQueryInternal(name, Context);\r\n}\r\n\r\nvoid NestedTimingTree::EndPipelineQuery(const wstring& name, CommandContext* Context) {\r\n\tsm_CurrentNode->EndPipelineQueryInternal(name, Context);\r\n}\r\n\r\nvoid NestedTimingTree::Update( void )\r\n{\r\n    ASSERT(sm_SelectedScope != nullptr, \"Corrupted profiling data structure\");\r\n\r\n    if (sm_SelectedScope == &sm_RootScope)\r\n    {\r\n        sm_SelectedScope = sm_RootScope.FirstChild();\r\n        if (sm_SelectedScope == &sm_RootScope)\r\n            return;\r\n    }\r\n\r\n    if (GameInput::IsFirstPressed( GameInput::kDPadLeft )\r\n        || GameInput::IsFirstPressed( GameInput::kKey_left ))\r\n    {\r\n        //if still on graphs go back to text\r\n        if (sm_CursorOnGraph)\r\n            sm_CursorOnGraph = !sm_CursorOnGraph;\r\n        else\r\n            sm_SelectedScope->m_IsExpanded = false;\r\n    }\r\n    else if (GameInput::IsFirstPressed( GameInput::kDPadRight )\r\n        || GameInput::IsFirstPressed( GameInput::kKey_right ))\r\n    {\r\n        if (sm_SelectedScope->m_IsExpanded == true && !sm_CursorOnGraph)\r\n            sm_CursorOnGraph = true;\r\n        else\r\n            sm_SelectedScope->m_IsExpanded = true;\r\n        //if already expanded go over to graphs\r\n\r\n    }\r\n    else if (GameInput::IsFirstPressed( GameInput::kDPadDown )\r\n        || GameInput::IsFirstPressed( GameInput::kKey_down ))\r\n    {\r\n        sm_SelectedScope = sm_SelectedScope ? sm_SelectedScope->NextScope() : nullptr;\r\n    }\r\n    else if (GameInput::IsFirstPressed( GameInput::kDPadUp )\r\n        || GameInput::IsFirstPressed( GameInput::kKey_up ))\r\n    {\r\n        sm_SelectedScope = sm_SelectedScope ? sm_SelectedScope->PrevScope() : nullptr;\r\n    }\r\n    else if (GameInput::IsFirstPressed( GameInput::kAButton ) \r\n        || GameInput::IsFirstPressed( GameInput::kKey_return ))\r\n    {\r\n        sm_SelectedScope->Toggle();\r\n    }\r\n\r\n}\r\n\r\nvoid NestedTimingTree::DisplayNode( TextContext& Text, float leftMargin, float indent )\r\n{\r\n    if (this == &sm_RootScope)\r\n    {\r\n        m_IsExpanded = true;\r\n        sm_RootScope.FirstChild()->m_IsExpanded = true;\r\n    }\r\n    else\r\n    {\r\n        if (sm_SelectedScope == this && !sm_CursorOnGraph)\r\n            Text.SetColor( Color(1.0f, 1.0f, 0.5f) );\r\n        else\r\n            Text.SetColor( Color(1.0f, 1.0f, 1.0f) );\r\n    \r\n\r\n        Text.SetLeftMargin(leftMargin);\r\n        Text.SetCursorX(leftMargin);\r\n\r\n        if (m_Children.size() == 0)\r\n            Text.DrawString(\"  \");\r\n        else if (m_IsExpanded)\r\n            Text.DrawString(\"- \");\r\n        else\r\n            Text.DrawString(\"+ \");\r\n\r\n        Text.DrawString(m_Name.c_str());\r\n        Text.SetCursorX(leftMargin + 300.0f);\r\n        Text.DrawFormattedString(\"%6.3f %6.3f   \", m_CpuTime.GetAvg(), m_GpuTime.GetAvg());\r\n\r\n        if (IsGraphed())\r\n        {\r\n            Text.SetColor(GraphRenderer::GetGraphColor(m_GraphHandle, GraphType::Profile));\r\n            Text.DrawString(\"  []\\n\");\r\n        }\r\n        else\r\n            Text.DrawString(\"\\n\");\r\n    }\r\n\r\n    if (!m_IsExpanded)\r\n        return;\r\n\r\n\tif (m_PipelineQueries.size() > 0) {\r\n\t\tText.SetCursorX(leftMargin + 10);\r\n\t\tText.DrawString(\"Pipeline Stats \\n\");\r\n\t\tfor (auto& query : m_PipelineQueryLUT) {\r\n\t\t\tText.SetCursorX(leftMargin + 50);\r\n\t\t\tText.DrawString(query.first.c_str());\r\n\t\t\tText.DrawString(\"\\n\");\r\n\t\t\t\r\n\t\t\tsize_t queryIdx = query.second;\r\n\t\t\tauto& lastData = m_LastPipelineQueryData[queryIdx];\r\n\t\t\t\r\n\t\t\tText.DrawString(\"     - PSInvocations:\");\r\n\r\n\t\t\tText.SetCursorX(leftMargin + 300);\r\n\t\t\tText.DrawFormattedString(\"%d\", lastData.PSInvocations);\r\n\t\t\tText.DrawString(\"\\n\");\r\n\t\t}\r\n\t}\r\n\r\n    for (auto node : m_Children)\r\n        node->DisplayNode(Text, leftMargin + indent, indent);\r\n}\r\n\r\nvoid NestedTimingTree::StoreToGraph(void)\r\n{\r\n    if (m_GraphHandle != PERF_GRAPH_ERROR)\r\n        GraphRenderer::Update( XMFLOAT2(m_CpuTime.GetLast(), m_GpuTime.GetLast()), m_GraphHandle, GraphType::Profile);\r\n\r\n    for (auto node : m_Children)\r\n        node->StoreToGraph();\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/EngineProfiling.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include <string>\r\n#include \"TextRenderer.h\"\r\n\r\n#include \"ART/PerfStat/PerfStat.h\"\r\n\r\nclass CommandContext;\r\n\r\nnamespace EngineProfiling\r\n{\r\n    void Update();\r\n\r\n    void BeginBlock(const std::wstring& name, CommandContext* Context = nullptr);\r\n    void EndBlock(CommandContext* Context = nullptr);\r\n\r\n\tvoid BeginPipelineQuery(const std::wstring& name, CommandContext* Context = nullptr);\r\n\tvoid EndPipelineQuery(const std::wstring& name, CommandContext* Context = nullptr);\r\n\r\n    void DisplayFrameRate(TextContext& Text);\r\n    void DisplayPerfGraph(GraphicsContext& Text);\r\n    void Display(TextContext& Text, float x, float y, float w, float h);\r\n    bool IsPaused();\r\n\r\n\tvoid WriteLastFrameToJson(const std::string& path);\r\n\tvoid FillPerfDataForLastFrame(ART::PerfCounterReport& report);\r\n\r\n    float GetFrameGPUTime(void);\r\n}\r\n\r\n#ifdef RELEASE\r\nclass ScopedTimer\r\n{\r\npublic:\r\n    ScopedTimer(const std::wstring&) {}\r\n    ScopedTimer(const std::wstring&, CommandContext&) {}\r\n};\r\nclass ScopedPipelineQuery {\r\npublic:\r\n\tScopedPipelineQuery(const std::wstring&, CommandContext& ) {\r\n\t}\r\n\r\n\t~ScopedPipelineQuery() {\r\n\t}\r\n\r\nprivate:\r\n\tstd::wstring m_Name;\r\n\tCommandContext* m_Context;\r\n};\r\n#else\r\nclass ScopedTimer\r\n{\r\npublic:\r\n    ScopedTimer( const std::wstring& name ) : m_Context(nullptr)\r\n    {\r\n        EngineProfiling::BeginBlock(name);\r\n    }\r\n    ScopedTimer( const std::wstring& name, CommandContext& Context ) : m_Context(&Context)\r\n    {\r\n        EngineProfiling::BeginBlock(name, m_Context);\r\n    }\r\n    ~ScopedTimer()\r\n    {\r\n        EngineProfiling::EndBlock(m_Context);\r\n    }\r\n\r\nprivate:\r\n    CommandContext* m_Context;\r\n};\r\n\r\nclass ScopedPipelineQuery {\r\npublic:\r\n\tScopedPipelineQuery(const std::wstring& name, CommandContext& Context): \r\n\tm_Name(name), m_Context(&Context) {\r\n\t\tEngineProfiling::BeginPipelineQuery(name, &Context);\r\n\t}\r\n\r\n\t~ScopedPipelineQuery() {\r\n\t\tEngineProfiling::EndPipelineQuery(m_Name, m_Context);\r\n\t}\r\n\r\nprivate:\r\n\tstd::wstring m_Name;\r\n\tCommandContext* m_Context;\r\n};\r\n#endif\r\n"
  },
  {
    "path": "MiniEngine/Core/EngineTuning.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n\r\n#include \"pch.h\"\r\n#include \"TextRenderer.h\"\r\n#include \"GameInput.h\"\r\n#include \"Color.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"GraphRenderer.h\"\r\n\r\nusing namespace std;\r\nusing namespace Math;\r\nusing namespace Graphics;\r\n\r\nnamespace EngineTuning\r\n{\r\n    // For delayed registration.  Some objects are constructed before we can add them to the graph (due\r\n    // to unreliable order of initialization.)\r\n    enum { kMaxUnregisteredTweaks = 1024 };\r\n    char s_UnregisteredPath[kMaxUnregisteredTweaks][128];\r\n    EngineVar* s_UnregisteredVariable[kMaxUnregisteredTweaks] = { nullptr };\r\n    int32_t s_UnregisteredCount = 0;\r\n\r\n    float s_ScrollOffset = 0.0f;\r\n    float s_ScrollTopTrigger = 1080.0f * 0.2f;\r\n    float s_ScrollBottomTrigger = 1080.0f * 0.8f;\r\n\r\n    // Internal functions\r\n    void AddToVariableGraph( const string& path, EngineVar& var );\r\n    void RegisterVariable( const string& path, EngineVar& var );\r\n\r\n    EngineVar* sm_SelectedVariable = nullptr;\r\n    bool sm_IsVisible = false;\r\n}\r\n\r\n// Not open to the public.  Groups are auto-created when a tweaker's path includes the group name.\r\nclass VariableGroup : public EngineVar\r\n{\r\npublic:\r\n    VariableGroup() : m_IsExpanded(false) {}\r\n\r\n    EngineVar* FindChild( const string& name )\r\n    {\r\n        auto iter = m_Children.find(name);\r\n        return iter == m_Children.end() ? nullptr : iter->second;\r\n    }\r\n     \r\n    void AddChild( const string& name, EngineVar& child )\r\n    {\r\n        m_Children[name] = &child;\r\n        child.m_GroupPtr = this;\r\n    }\r\n\r\n    void Display( TextContext& Text, float leftMargin, EngineVar* highlightedTweak );\r\n\r\n    void SaveToFile( FILE* file, int fileMargin );\r\n    void LoadSettingsFromFile( FILE* file );\r\n\r\n    EngineVar* NextVariable( EngineVar* currentVariable );\r\n    EngineVar* PrevVariable( EngineVar* currentVariable );\r\n    EngineVar* FirstVariable( void );\r\n    EngineVar* LastVariable( void );\r\n\r\n    bool IsExpanded( void ) const { return m_IsExpanded; }\r\n\r\n    virtual void Increment( void ) override { m_IsExpanded = true; }\r\n    virtual void Decrement( void ) override { m_IsExpanded = false; }\r\n    virtual void Bang( void ) override { m_IsExpanded = !m_IsExpanded; }\r\n\r\n    virtual void SetValue( FILE*, const std::string& ) override {}\r\n    \r\n    static VariableGroup sm_RootGroup;\r\n\r\nprivate:\r\n    bool m_IsExpanded;\r\n    std::map<string, EngineVar*> m_Children;\r\n};\r\n\r\nVariableGroup VariableGroup::sm_RootGroup;\r\n\r\n//=====================================================================================================================\r\n// VariableGroup implementation\r\n\r\nvoid VariableGroup::Display( TextContext& Text, float leftMargin, EngineVar* highlightedTweak )\r\n{\r\n    Text.SetLeftMargin(leftMargin);\r\n    Text.SetCursorX(leftMargin);\r\n\r\n    for (auto iter = m_Children.begin(); iter != m_Children.end(); ++iter)\r\n    {\r\n        \r\n        if (iter->second == highlightedTweak)\r\n        {\r\n            Text.SetColor( Color(1.0f, 1.0f, 0.25f) );\r\n            float temp1 = Text.GetCursorY() - EngineTuning::s_ScrollBottomTrigger;\r\n            float temp2 = Text.GetCursorY() - EngineTuning::s_ScrollTopTrigger;\r\n            if (temp1 > 0.0f)\r\n            {\r\n                EngineTuning::s_ScrollOffset += 0.2f * temp1; \r\n            }\r\n            else if (temp2 < 0.0f)\r\n            {\r\n                EngineTuning::s_ScrollOffset = max(0.0f, EngineTuning::s_ScrollOffset + 0.2f * temp2);\r\n            }\r\n        }\r\n        else\r\n            Text.SetColor( Color(1.0f, 1.0f, 1.0f) );\r\n\r\n        VariableGroup* subGroup = dynamic_cast<VariableGroup*>(iter->second);\r\n        if (subGroup != nullptr)\r\n        {\r\n\r\n            if (subGroup->IsExpanded())\r\n            {\r\n                Text.DrawString(\"- \");\r\n            }\r\n            else\r\n            {\r\n                Text.DrawString(\"+ \");\t\t\t\t\r\n            }\r\n            Text.DrawString(iter->first);\r\n            Text.DrawString(\"/...\\n\");\r\n\r\n            if (subGroup->IsExpanded())\r\n            {\r\n                subGroup->Display(Text, leftMargin + 30.0f, highlightedTweak);\r\n                Text.SetLeftMargin(leftMargin);\r\n                Text.SetCursorX(leftMargin);\r\n            }\r\n            \r\n        }\r\n        else\r\n        {\r\n            \r\n            iter->second->DisplayValue(Text);\r\n            Text.SetCursorX(leftMargin + 200.0f);\r\n            Text.DrawString(iter->first);\r\n            Text.NewLine();\r\n        }\r\n        \r\n    }\r\n}\r\n\r\nvoid VariableGroup::SaveToFile( FILE* file, int fileMargin )\r\n{\r\n    for (auto iter = m_Children.begin(); iter != m_Children.end(); ++iter)\r\n    {\r\n        const char* buffer = (iter->first).c_str();\r\n\r\n        VariableGroup* subGroup = dynamic_cast<VariableGroup*>(iter->second);\r\n        if (subGroup != nullptr)\r\n        {\t\t\r\n            fprintf(file, \"%*c + %s ...\\r\\n\", fileMargin, ' ', buffer);\r\n            subGroup->SaveToFile(file, fileMargin + 5);\r\n        }\r\n        else if (dynamic_cast<CallbackTrigger*>(iter->second) == nullptr)\r\n        {\r\n            fprintf(file, \"%*c %s:  %s\\r\\n\", fileMargin, ' ', buffer, iter->second->ToString().c_str());\r\n        }\t\t\r\n    }\r\n}\r\n\r\nvoid VariableGroup::LoadSettingsFromFile( FILE* file )\r\n{\r\n    for (auto iter = m_Children.begin(); iter != m_Children.end(); ++iter)\r\n    {\r\n        VariableGroup* subGroup = dynamic_cast<VariableGroup*>(iter->second);\r\n        if (subGroup != nullptr)\r\n        {\r\n            char skippedLines[100];\r\n            fscanf_s(file, \"%*s %[^\\n]\", skippedLines, (int)_countof(skippedLines));\r\n            subGroup->LoadSettingsFromFile(file);\r\n        }\r\n        else\r\n        {\t\r\n            iter->second->SetValue(file, iter->first);\r\n        }\r\n    }\r\n}\r\n\r\nEngineVar* VariableGroup::FirstVariable( void )\r\n{\r\n    return m_Children.size() == 0 ? nullptr : m_Children.begin()->second;\r\n}\r\n\r\nEngineVar* VariableGroup::LastVariable( void )\r\n{\r\n    if (m_Children.size() == 0)\r\n        return this;\r\n\r\n    auto LastVariable = m_Children.end();\r\n    --LastVariable;\r\n\r\n    VariableGroup* isGroup = dynamic_cast<VariableGroup*>(LastVariable->second);\r\n    if (isGroup && isGroup->IsExpanded())\r\n        return isGroup->LastVariable();\r\n\r\n    return LastVariable->second;\r\n}\r\n\r\nEngineVar* VariableGroup::NextVariable( EngineVar* curVar )\r\n{\r\n    auto iter = m_Children.begin();\r\n    for (; iter != m_Children.end(); ++iter)\r\n    {\r\n        if (curVar == iter->second)\r\n            break;\r\n    }\r\n\r\n    ASSERT( iter != m_Children.end(), \"Did not find engine variable in its designated group\" );\r\n\r\n    auto nextIter = iter;\r\n    ++nextIter;\r\n\r\n    if (nextIter == m_Children.end())\r\n        return m_GroupPtr ? m_GroupPtr->NextVariable(this) : nullptr;\r\n    else\r\n        return nextIter->second;\r\n}\r\n\r\nEngineVar* VariableGroup::PrevVariable( EngineVar* curVar )\r\n{\r\n    auto iter = m_Children.begin();\r\n    for (; iter != m_Children.end(); ++iter)\r\n    {\r\n        if (curVar == iter->second)\r\n            break;\r\n    }\r\n\r\n    ASSERT( iter != m_Children.end(), \"Did not find engine variable in its designated group\" );\r\n\r\n    if (iter == m_Children.begin())\r\n        return this;\r\n\r\n    auto prevIter = iter;\r\n    --prevIter;\r\n\r\n    VariableGroup* isGroup = dynamic_cast<VariableGroup*>(prevIter->second);\r\n    if (isGroup && isGroup->IsExpanded())\r\n        return isGroup->LastVariable();\r\n\r\n    return prevIter->second;\r\n}\r\n\r\n//=====================================================================================================================\r\n// EngineVar implementations\r\n\r\nEngineVar::EngineVar( void ) : m_GroupPtr(nullptr)\r\n{\r\n}\r\n\r\nEngineVar::EngineVar( const std::string& path ) : m_GroupPtr(nullptr)\r\n{\r\n    EngineTuning::RegisterVariable(path, *this);\r\n}\r\n\r\n\r\nEngineVar* EngineVar::NextVar( void )\r\n{\r\n    EngineVar* next = nullptr;\r\n    VariableGroup* isGroup = dynamic_cast<VariableGroup*>(this);\r\n    if (isGroup != nullptr && isGroup->IsExpanded())\r\n        next = isGroup->FirstVariable();\r\n\r\n    if (next == nullptr)\r\n        next = m_GroupPtr->NextVariable(this);\r\n\r\n    return next != nullptr ? next : this;\r\n}\r\n\r\nEngineVar* EngineVar::PrevVar( void )\r\n{\r\n    EngineVar* prev = m_GroupPtr->PrevVariable(this);\r\n    if (prev != nullptr && prev != m_GroupPtr)\r\n    {\r\n        VariableGroup* isGroup = dynamic_cast<VariableGroup*>(prev);\r\n        if (isGroup != nullptr && isGroup->IsExpanded())\r\n            prev = isGroup->LastVariable();\r\n    }\r\n    return prev != nullptr ? prev : this;\r\n}\r\n\r\nBoolVar::BoolVar( const std::string& path, bool val )\r\n    : EngineVar(path)\r\n{\r\n    m_Flag = val;\r\n}\r\n\r\nvoid BoolVar::DisplayValue( TextContext& Text ) const\r\n{\r\n    Text.DrawFormattedString(\"[%c]\", m_Flag ? 'X' : '-');\r\n}\r\n\r\nstd::string BoolVar::ToString( void ) const\r\n{\r\n    return m_Flag ? \"on\" : \"off\";\r\n} \r\n\r\nvoid BoolVar::SetValue(FILE* file, const std::string& setting)\r\n{\t\r\n    std::string pattern = \"\\n \" + setting + \": %s\";\r\n    char valstr[6];\r\n\r\n    // Search through the file for an entry that matches this setting's name\r\n    fscanf_s(file, pattern.c_str(), valstr, _countof(valstr));\r\n\r\n    // Look for one of the many affirmations\r\n    m_Flag = (\r\n        0 == _stricmp(valstr, \"1\") ||\r\n        0 == _stricmp(valstr, \"on\") ||\r\n        0 == _stricmp(valstr, \"yes\") ||\r\n        0 == _stricmp(valstr, \"true\") );\r\n}\r\n\r\nNumVar::NumVar( const std::string& path, float val, float minVal, float maxVal, float stepSize )\r\n    : EngineVar(path)\r\n{\r\n    ASSERT(minVal <= maxVal);\r\n    m_MinValue = minVal;\r\n    m_MaxValue = maxVal;\r\n    m_Value = Clamp(val);\r\n    m_StepSize = stepSize;\r\n}\r\n\r\nvoid NumVar::DisplayValue( TextContext& Text ) const\r\n{\r\n    Text.DrawFormattedString(\"%-11f\", m_Value);\r\n}\r\n\r\nstd::string NumVar::ToString( void ) const\r\n{\r\n    char buf[128];\r\n    sprintf_s(buf, \"%f\", m_Value);\r\n    return buf;\r\n} \r\n\r\nvoid NumVar::SetValue(FILE* file, const std::string& setting) \r\n{\r\n    std::string scanString = \"\\n\" + setting + \": %f\";\r\n    float valueRead;\r\n    \r\n    //If we haven't read correctly, just keep m_Value at default value\r\n    if (fscanf_s(file, scanString.c_str(), &valueRead))\r\n        *this = valueRead; \r\n}\r\n\r\n#if _MSC_VER < 1800\r\n__forceinline float log2( float x ) { return log(x) / log(2.0f); }\r\n__forceinline float exp2( float x ) { return pow(2.0f, x); }\r\n#endif\r\n\r\nExpVar::ExpVar( const std::string& path, float val, float minExp, float maxExp, float expStepSize )\r\n    : NumVar(path, log2(val), minExp, maxExp, expStepSize)\r\n{\r\n}\r\n\r\nExpVar& ExpVar::operator=( float val )\r\n{\r\n    m_Value = Clamp(log2(val));\r\n    return *this;\r\n}\r\n\r\nExpVar::operator float() const\r\n{\r\n    return exp2(m_Value);\r\n}\r\n\r\nvoid ExpVar::DisplayValue( TextContext& Text ) const\r\n{\r\n    Text.DrawFormattedString(\"%-11f\", (float)*this);\r\n}\r\n\r\nstd::string ExpVar::ToString( void ) const\r\n{\r\n    char buf[128];\r\n    sprintf_s(buf, \"%f\", (float)*this);\r\n    return buf;\r\n} \r\n\r\nvoid ExpVar::SetValue(FILE* file, const std::string& setting) \r\n{\r\n    std::string scanString = \"\\n\" + setting + \": %f\";\r\n    float valueRead;\r\n    \r\n    //If we haven't read correctly, just keep m_Value at default value\r\n    if (fscanf_s(file, scanString.c_str(), &valueRead))\r\n        *this = valueRead;\r\n}\r\n\r\nIntVar::IntVar( const std::string& path, int32_t val, int32_t minVal, int32_t maxVal, int32_t stepSize )\r\n    : EngineVar(path)\r\n{\r\n    ASSERT(minVal <= maxVal);\r\n    m_MinValue = minVal;\r\n    m_MaxValue = maxVal;\r\n    m_Value = Clamp(val);\r\n    m_StepSize = stepSize;\r\n}\r\n\r\nvoid IntVar::DisplayValue( TextContext& Text ) const\r\n{\r\n    Text.DrawFormattedString(\"%-11d\", m_Value);\r\n}\r\n\r\nstd::string IntVar::ToString( void ) const\r\n{\r\n    char buf[128];\r\n    sprintf_s(buf, \"%d\", m_Value);\r\n    return buf;\r\n} \r\n\r\nvoid IntVar::SetValue(FILE* file, const std::string& setting) \r\n{\r\n    std::string scanString = \"\\n\" + setting + \": %d\";\r\n    int32_t valueRead;\r\n    \r\n    if (fscanf_s(file, scanString.c_str(), &valueRead))\r\n        *this = valueRead;\r\n}\r\n\r\n\r\nEnumVar::EnumVar( const std::string& path, int32_t initialVal, int32_t listLength, const char** listLabels )\r\n    : EngineVar(path)\r\n{\r\n    ASSERT(listLength > 0);\r\n    m_EnumLength = listLength;\r\n    m_EnumLabels = listLabels;\r\n    m_Value = Clamp(initialVal);\r\n}\r\n\r\nvoid EnumVar::DisplayValue( TextContext& Text ) const\r\n{\r\n    Text.DrawString(m_EnumLabels[m_Value]);\r\n}\r\n\r\nstd::string EnumVar::ToString( void ) const\r\n{\r\n    return m_EnumLabels[m_Value];\r\n} \r\n\r\nvoid EnumVar::SetValue(FILE* file, const std::string& setting) \r\n{\r\n    std::string scanString = \"\\n\" + setting + \": %[^\\n]\";\r\n    char valueRead[14];\r\n        \r\n    if (fscanf_s(file, scanString.c_str(), valueRead, _countof(valueRead)) == 1)\r\n    {\r\n        std::string valueReadStr = valueRead;\r\n        valueReadStr = valueReadStr.substr(0, valueReadStr.length() - 1);\r\n\r\n        //if we don't find the string, then leave m_EnumLabes[m_Value] as default\r\n        for(int32_t i = 0; i < m_EnumLength; ++i)\r\n        {\r\n            if (m_EnumLabels[i] == valueReadStr)\r\n            {\r\n                m_Value = i;\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n}\r\n\r\nCallbackTrigger::CallbackTrigger( const std::string& path, std::function<void (void*)> callback, void* args )\r\n    : EngineVar(path)\r\n{\r\n    m_Callback = callback;\r\n    m_Arguments = args;\r\n    m_BangDisplay = 0;\r\n}\r\n\r\nvoid CallbackTrigger::DisplayValue( TextContext& Text ) const\r\n{\r\n    static const char s_animation[] = { '-', '\\\\', '|', '/' };\r\n    Text.DrawFormattedString(\"[%c]\", s_animation[(m_BangDisplay >> 3) & 3]);\r\n\r\n    if (m_BangDisplay > 0)\r\n        --m_BangDisplay;\r\n}\r\n\r\nvoid CallbackTrigger::SetValue(FILE* file, const std::string& setting) \r\n{\r\n    //Skip over setting without reading anything\r\n    std::string scanString = \"\\n\" + setting + \": %[^\\n]\";\r\n    char skippedLines[100];\r\n    fscanf_s(file, scanString.c_str(), skippedLines, _countof(skippedLines));\r\n}\r\n\r\n//=====================================================================================================================\r\n// EngineTuning namespace methods\r\n\r\nvoid EngineTuning::Initialize( void )\r\n{\r\n\r\n    for (int32_t i = 0; i < s_UnregisteredCount; ++i)\r\n    {\r\n        ASSERT(strlen(s_UnregisteredPath[i]) > 0, \"Register = %d\\n\", i);\r\n        ASSERT(s_UnregisteredVariable[i] != nullptr);\r\n        AddToVariableGraph(s_UnregisteredPath[i], *s_UnregisteredVariable[i]);\r\n    }\r\n    s_UnregisteredCount = -1;\r\n\r\n}\r\n\r\nvoid HandleDigitalButtonPress( GameInput::DigitalInput button, float timeDelta, std::function<void ()> action )\r\n{\r\n    if (!GameInput::IsPressed(button))\r\n        return;\r\n\r\n    float durationHeld = GameInput::GetDurationPressed(button);\r\n\r\n    // Tick on the first press\r\n    if (durationHeld == 0.0f)\r\n    {\r\n        action();\r\n        return;\r\n    }\r\n\r\n    // After ward, tick at fixed intervals\r\n    float oldDuration = durationHeld - timeDelta;\r\n\r\n    // Before 2 seconds, use slow scale (200ms/tick), afterward use fast scale (50ms/tick).\r\n    float timeStretch = durationHeld < 2.0f ? 5.0f : 20.0f;\r\n\r\n    if (Floor(durationHeld * timeStretch) > Floor(oldDuration * timeStretch))\r\n        action();\r\n}\r\n\r\nvoid EngineTuning::Update( float frameTime )\r\n{\r\n    if (GameInput::IsFirstPressed( GameInput::kBackButton )\r\n        || GameInput::IsFirstPressed( GameInput::kKey_back ))\r\n        sm_IsVisible = !sm_IsVisible;\r\n\r\n    if (!sm_IsVisible)\r\n        return;\r\n\r\n    if (sm_SelectedVariable == nullptr || sm_SelectedVariable == &VariableGroup::sm_RootGroup)\r\n        sm_SelectedVariable = VariableGroup::sm_RootGroup.FirstVariable();\r\n\r\n    if (sm_SelectedVariable == nullptr)\r\n        return;\r\n\r\n    // Detect a DPad button press\r\n    HandleDigitalButtonPress(GameInput::kDPadRight, frameTime, []{ sm_SelectedVariable->Increment(); } );\r\n    HandleDigitalButtonPress(GameInput::kDPadLeft,\tframeTime, []{ sm_SelectedVariable->Decrement(); } );\r\n    HandleDigitalButtonPress(GameInput::kDPadDown,\tframeTime, []{ sm_SelectedVariable = sm_SelectedVariable->NextVar(); } );\r\n    HandleDigitalButtonPress(GameInput::kDPadUp,\tframeTime, []{ sm_SelectedVariable = sm_SelectedVariable->PrevVar(); } );\r\n\r\n    HandleDigitalButtonPress(GameInput::kKey_right, frameTime, []{ sm_SelectedVariable->Increment(); } );\r\n    HandleDigitalButtonPress(GameInput::kKey_left,\tframeTime, []{ sm_SelectedVariable->Decrement(); } );\r\n    HandleDigitalButtonPress(GameInput::kKey_down,\tframeTime, []{ sm_SelectedVariable = sm_SelectedVariable->NextVar(); } );\r\n    HandleDigitalButtonPress(GameInput::kKey_up,\tframeTime, []{ sm_SelectedVariable = sm_SelectedVariable->PrevVar(); } );\r\n\r\n    if (GameInput::IsFirstPressed( GameInput::kAButton )\r\n        || GameInput::IsFirstPressed( GameInput::kKey_return ))\r\n    {\r\n        sm_SelectedVariable->Bang();\r\n    }\r\n}\r\n\r\nvoid StartSave(void*)\r\n{\r\n    FILE* settingsFile;\r\n    fopen_s(&settingsFile, \"engineTuning.txt\", \"wb\");\r\n    if (settingsFile != nullptr)\r\n    {\r\n        VariableGroup::sm_RootGroup.SaveToFile(settingsFile, 2 );\r\n        fclose(settingsFile);\r\n    }\r\n}\r\nstd::function<void(void*)> StartSaveFunc = StartSave;\r\nstatic CallbackTrigger Save(\"Save Settings\", StartSaveFunc, nullptr); \r\n\r\nvoid StartLoad(void*)\r\n{\r\n    FILE* settingsFile;\r\n    fopen_s(&settingsFile, \"engineTuning.txt\", \"rb\");\r\n    if (settingsFile != nullptr)\r\n    {\r\n        VariableGroup::sm_RootGroup.LoadSettingsFromFile(settingsFile);\r\n        fclose(settingsFile);\r\n    }\r\n}\r\nstd::function<void(void*)> StartLoadFunc = StartLoad;\r\nstatic CallbackTrigger Load(\"Load Settings\", StartLoadFunc, nullptr); \r\n\r\n\r\nvoid EngineTuning::Display( GraphicsContext& Context, float x, float y, float w, float h )\r\n{\r\n    GraphRenderer::RenderGraphs(Context, GraphRenderer::GraphType::Profile);\r\n\r\n    TextContext Text(Context);\r\n    Text.Begin();\r\n\r\n    EngineProfiling::DisplayFrameRate(Text);\r\n\r\n    Text.ResetCursor( x, y );\r\n\r\n    if (!sm_IsVisible)\r\n    {\r\n        EngineProfiling::Display(Text, x, y, w, h);\r\n        return;\r\n    }\r\n\r\n    s_ScrollTopTrigger = y + h * 0.2f;\r\n    s_ScrollBottomTrigger = y + h * 0.8f;\r\n\r\n    float hScale = g_DisplayWidth / 1920.0f;\r\n    float vScale = g_DisplayHeight / 1080.0f;\r\n\r\n    Context.SetScissor((uint32_t)Floor(x * hScale), (uint32_t)Floor(y * vScale), \r\n        (uint32_t)Ceiling((x + w) * hScale), (uint32_t)Ceiling((y + h) * vScale));\r\n\r\n    Text.ResetCursor(x, y - s_ScrollOffset );\r\n    Text.SetColor( Color(0.5f, 1.0f, 1.0f) );\r\n    Text.DrawString(\"Engine Tuning\\n\");\r\n    Text.SetTextSize(20.0f);\r\n\r\n    VariableGroup::sm_RootGroup.Display( Text, x, sm_SelectedVariable );\r\n    \r\n    EngineProfiling::DisplayPerfGraph(Context);\r\n\r\n    Text.End();\r\n    Context.SetScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n}\r\n\r\nvoid EngineTuning::AddToVariableGraph( const string& path, EngineVar& var )\r\n{\r\n    vector<string> separatedPath;\r\n    string leafName;\r\n    size_t start = 0, end = 0;\r\n\r\n    while (1)\r\n    {\r\n        end = path.find('/', start);\r\n        if (end == string::npos)\r\n        {\r\n            leafName = path.substr(start);\r\n            break;\r\n        }\r\n        else\r\n        {\r\n            separatedPath.push_back(path.substr(start, end - start));\r\n            start = end + 1;\r\n        }\r\n    }\r\n\r\n    VariableGroup* group = &VariableGroup::sm_RootGroup;\r\n\r\n    for (auto iter = separatedPath.begin(); iter != separatedPath.end(); ++iter )\r\n    {\r\n        VariableGroup* nextGroup;\r\n        EngineVar* node = group->FindChild(*iter);\r\n        if (node == nullptr)\r\n        {\r\n            nextGroup = new VariableGroup();\r\n            group->AddChild(*iter, *nextGroup);\r\n            group = nextGroup;\r\n        }\r\n        else\r\n        {\r\n            nextGroup = dynamic_cast<VariableGroup*>(node);\r\n            ASSERT(nextGroup != nullptr, \"Attempted to trash the tweak graph\");\r\n            group = nextGroup;\r\n        }\r\n    }\r\n\r\n    group->AddChild(leafName, var);\r\n}\r\n\r\nvoid EngineTuning::RegisterVariable( const std::string& path, EngineVar& var )\r\n{\r\n    if (s_UnregisteredCount >= 0)\r\n    {\r\n        int32_t Idx = s_UnregisteredCount++;\r\n        strcpy_s(s_UnregisteredPath[Idx], path.c_str());\r\n        s_UnregisteredVariable[Idx] = &var;\r\n    }\r\n    else\r\n    {\r\n        AddToVariableGraph( path, var );\r\n    }\r\n}\r\n\r\nbool EngineTuning::IsFocused( void )\r\n{\r\n    return sm_IsVisible;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/EngineTuning.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include <string>\r\n#include <stdint.h>\r\n#include <float.h>\r\n#include <map>\r\n#include <set>\r\n\r\nclass VariableGroup;\r\nclass TextContext;\r\n\r\nclass EngineVar\r\n{\r\npublic:\r\n\r\n    virtual ~EngineVar() {}\r\n\r\n    virtual void Increment( void ) {}\t// DPad Right\r\n    virtual void Decrement( void ) {}\t// DPad Left\r\n    virtual void Bang( void ) {}\t\t// A Button\r\n\r\n    virtual void DisplayValue( TextContext& ) const {}\r\n    virtual std::string ToString( void ) const { return \"\"; }\r\n    virtual void SetValue( FILE* file, const std::string& setting) = 0; //set value read from file\r\n\r\n    EngineVar* NextVar( void );\r\n    EngineVar* PrevVar( void );\r\n\r\nprotected:\r\n    EngineVar( void );\r\n    EngineVar( const std::string& path );\r\n\r\nprivate:\r\n    friend class VariableGroup;\r\n    VariableGroup* m_GroupPtr;\r\n};\r\n\r\nclass BoolVar : public EngineVar\r\n{\r\npublic:\r\n    BoolVar( const std::string& path, bool val );\r\n    BoolVar& operator=( bool val ) { m_Flag = val; return *this; }\r\n    operator bool() const { return m_Flag; }\r\n\r\n    virtual void Increment( void ) override { m_Flag = true; }\r\n    virtual void Decrement( void ) override { m_Flag = false; }\r\n    virtual void Bang( void ) override { m_Flag = !m_Flag; }\r\n\r\n    virtual void DisplayValue( TextContext& Text ) const override;\r\n    virtual std::string ToString( void ) const override;\r\n    virtual void SetValue( FILE* file, const std::string& setting) override;\r\n\r\nprivate:\r\n    bool m_Flag;\r\n};\r\n\r\nclass NumVar : public EngineVar\r\n{\r\npublic:\r\n    NumVar( const std::string& path, float val, float minValue = -FLT_MAX, float maxValue = FLT_MAX, float stepSize = 1.0f );\r\n    NumVar& operator=( float val ) { m_Value = Clamp(val); return *this; }\r\n    operator float() const { return m_Value; }\r\n\r\n    virtual void Increment( void ) override { m_Value = Clamp(m_Value + m_StepSize); }\r\n    virtual void Decrement( void ) override { m_Value = Clamp(m_Value - m_StepSize); }\r\n\r\n    virtual void DisplayValue( TextContext& Text ) const override;\r\n    virtual std::string ToString( void ) const override;\r\n    virtual void SetValue( FILE* file, const std::string& setting)  override;\r\n\r\nprotected:\r\n    float Clamp( float val ) { return val > m_MaxValue ? m_MaxValue : val < m_MinValue ? m_MinValue : val; }\r\n\r\n    float m_Value;\r\n    float m_MinValue;\r\n    float m_MaxValue;\r\n    float m_StepSize;\r\n};\r\n\r\nclass ExpVar : public NumVar\r\n{\r\npublic:\r\n    ExpVar( const std::string& path, float val, float minExp = -FLT_MAX, float maxExp = FLT_MAX, float expStepSize = 1.0f );\r\n    ExpVar& operator=( float val );\t// m_Value = log2(val)\r\n    operator float() const;\t\t\t// returns exp2(m_Value)\r\n\r\n    virtual void DisplayValue( TextContext& Text ) const override;\r\n    virtual std::string ToString( void ) const override;\r\n    virtual void SetValue( FILE* file, const std::string& setting ) override;\r\n\r\n};\r\n\r\nclass IntVar : public EngineVar\r\n{\r\npublic:\r\n    IntVar( const std::string& path, int32_t val, int32_t minValue = 0, int32_t maxValue = (1 << 24) - 1, int32_t stepSize = 1 );\r\n    IntVar& operator=( int32_t val ) { m_Value = Clamp(val); return *this; }\r\n    operator int32_t() const { return m_Value; }\r\n\r\n    virtual void Increment( void ) override { m_Value = Clamp(m_Value + m_StepSize); }\r\n    virtual void Decrement( void ) override { m_Value = Clamp(m_Value - m_StepSize); }\r\n\r\n    virtual void DisplayValue( TextContext& Text ) const override;\r\n    virtual std::string ToString( void ) const override;\r\n    virtual void SetValue( FILE* file, const std::string& setting ) override;\r\n\r\nprotected:\r\n    int32_t Clamp( int32_t val ) { return val > m_MaxValue ? m_MaxValue : val < m_MinValue ? m_MinValue : val; }\r\n\r\n    int32_t m_Value;\r\n    int32_t m_MinValue;\r\n    int32_t m_MaxValue;\r\n    int32_t m_StepSize;\r\n};\r\n\r\nclass EnumVar : public EngineVar\r\n{\r\npublic:\r\n    EnumVar( const std::string& path, int32_t initialVal, int32_t listLength, const char** listLabels );\r\n    EnumVar& operator=( int32_t val ) { m_Value = Clamp(val); return *this; }\r\n    operator int32_t() const { return m_Value; }\r\n\r\n    virtual void Increment( void ) override { m_Value = (m_Value + 1) % m_EnumLength; }\r\n    virtual void Decrement( void ) override { m_Value = (m_Value + m_EnumLength - 1) % m_EnumLength; }\r\n\r\n    virtual void DisplayValue( TextContext& Text ) const override;\r\n    virtual std::string ToString( void ) const override;\r\n    virtual void SetValue( FILE* file, const std::string& setting ) override;\r\n\r\n    void SetListLength(int32_t listLength) { m_EnumLength = listLength; m_Value = Clamp(m_Value); }\r\n\r\nprivate:\r\n    int32_t Clamp( int32_t val ) { return val < 0 ? 0 : val >= m_EnumLength ? m_EnumLength - 1 : val; }\r\n\r\n    int32_t m_Value;\r\n    int32_t m_EnumLength;\r\n    const char** m_EnumLabels;\r\n};\r\n\r\nclass CallbackTrigger : public EngineVar\r\n{\r\npublic:\r\n    CallbackTrigger( const std::string& path, std::function<void (void*)> callback, void* args = nullptr );\r\n\r\n    virtual void Bang( void ) override { m_Callback(m_Arguments); m_BangDisplay = 64; }\r\n\r\n    virtual void DisplayValue( TextContext& Text ) const override;\r\n    virtual void SetValue( FILE* file, const std::string& setting ) override;\r\n\r\nprivate:\r\n    std::function<void (void*)> m_Callback;\r\n    void* m_Arguments;\r\n    mutable uint32_t m_BangDisplay;\r\n};\r\n\r\nclass GraphicsContext;\r\n\r\nnamespace EngineTuning\r\n{\r\n    void Initialize( void );\r\n    void Update( float frameTime );\r\n    void Display( GraphicsContext& Context, float x, float y, float w, float h );\r\n    bool IsFocused( void );\r\n\r\n} // namespace EngineTuning\r\n"
  },
  {
    "path": "MiniEngine/Core/EsramAllocator.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\nclass EsramAllocator\r\n{\r\npublic:\r\n    EsramAllocator() {}\r\n\r\n    void PushStack() {}\r\n    void PopStack() {}\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS Alloc( size_t size, size_t align, const std::wstring& bufferName )\r\n    {\r\n        (size); (align); (bufferName);\r\n        return D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n    }\r\n\r\n    intptr_t SizeOfFreeSpace( void ) const\r\n    {\r\n        return 0;\r\n    }\r\n\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/FXAA.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"FXAA.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"BufferManager.h\"\r\n#include \"CommandContext.h\"\r\n\r\n#include \"CompiledShaders/FXAAPass1_RGB_CS.h\"\r\n#include \"CompiledShaders/FXAAPass1_Luma_CS.h\"\r\n#include \"CompiledShaders/FXAAPass2HCS.h\"\r\n#include \"CompiledShaders/FXAAPass2VCS.h\"\r\n#include \"CompiledShaders/FXAAPass2HDebugCS.h\"\r\n#include \"CompiledShaders/FXAAPass2VDebugCS.h\"\r\n\r\n// These shaders are when typed UAV loads of complex formats is available\r\n#include \"CompiledShaders/FXAAPass1_RGB2_CS.h\"\r\n#include \"CompiledShaders/FXAAPass1_Luma2_CS.h\"\r\n#include \"CompiledShaders/FXAAPass2H2CS.h\"\r\n#include \"CompiledShaders/FXAAPass2V2CS.h\"\r\n#include \"CompiledShaders/FXAAPass2HDebug2CS.h\"\r\n#include \"CompiledShaders/FXAAPass2VDebug2CS.h\"\r\n\r\n#include \"CompiledShaders/FXAAResolveWorkQueueCS.h\"\r\n\r\n\r\nusing namespace Graphics;\r\n\r\nnamespace FXAA\r\n{\r\n    RootSignature RootSig;\r\n    ComputePSO Pass1HdrCS;\r\n    ComputePSO Pass1LdrCS;\r\n    ComputePSO ResolveWorkCS;\r\n    ComputePSO Pass2HCS;\r\n    ComputePSO Pass2VCS;\r\n    ComputePSO Pass2HDebugCS;\r\n    ComputePSO Pass2VDebugCS;\r\n    IndirectArgsBuffer IndirectParameters;\r\n\r\n    BoolVar Enable(\"Graphics/AA/FXAA/Enable\", true);\r\n    BoolVar DebugDraw(\"Graphics/AA/FXAA/Debug\", false);\r\n\r\n    // With a properly encoded luma buffer, [0.25 = \"low\", 0.2 = \"medium\", 0.15 = \"high\", 0.1 = \"ultra\"]\r\n    NumVar ContrastThreshold(\"Graphics/AA/FXAA/Contrast Threshold\", 0.175f, 0.05f, 0.5f, 0.025f);\r\n\r\n    // Controls how much to blur isolated pixels that have little-to-no edge length.\r\n    NumVar SubpixelRemoval(\"Graphics/AA/FXAA/Subpixel Removal\", 0.50f, 0.0f, 1.0f, 0.25f);\r\n\r\n    // This is for testing the performance of computing luma on the fly rather than reusing\r\n    // the luma buffer output of tone mapping.\r\n    BoolVar ForceOffPreComputedLuma(\"Graphics/AA/FXAA/Always Recompute Log-Luma\", false);\r\n}\r\n\r\nvoid FXAA::Initialize( void )\r\n{\r\n    RootSig.Reset(3, 1);\r\n    RootSig.InitStaticSampler(0, SamplerLinearClampDesc);\r\n    RootSig[0].InitAsConstants(0, 7);\r\n    RootSig[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 5);\r\n    RootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 6);\r\n    RootSig.Finalize(L\"FXAA\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(RootSig); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO(ResolveWorkCS, g_pFXAAResolveWorkQueueCS);\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        CreatePSO(Pass1LdrCS, g_pFXAAPass1_RGB2_CS);    // Use RGB and recompute log-luma; pre-computed luma is unavailable\r\n        CreatePSO(Pass1HdrCS, g_pFXAAPass1_Luma2_CS);   // Use pre-computed luma\r\n        CreatePSO(Pass2HCS, g_pFXAAPass2H2CS);\r\n        CreatePSO(Pass2VCS, g_pFXAAPass2V2CS);\r\n        CreatePSO(Pass2HDebugCS, g_pFXAAPass2HDebug2CS);\r\n        CreatePSO(Pass2VDebugCS, g_pFXAAPass2VDebug2CS);\r\n    }\r\n    else\r\n    {\r\n        CreatePSO(Pass1LdrCS, g_pFXAAPass1_RGB_CS);     // Use RGB and recompute log-luma; pre-computed luma is unavailable\r\n        CreatePSO(Pass1HdrCS, g_pFXAAPass1_Luma_CS);    // Use pre-computed luma\r\n        CreatePSO(Pass2HCS, g_pFXAAPass2HCS);\r\n        CreatePSO(Pass2VCS, g_pFXAAPass2VCS);\r\n        CreatePSO(Pass2HDebugCS, g_pFXAAPass2HDebugCS);\r\n        CreatePSO(Pass2VDebugCS, g_pFXAAPass2VDebugCS);\r\n    }\r\n#undef CreatePSO\r\n\r\n    __declspec(align(16)) const uint32_t initArgs[6] = { 0, 1, 1, 0, 1, 1 };\r\n    IndirectParameters.Create(L\"FXAA Indirect Parameters\", 2, sizeof(D3D12_DISPATCH_ARGUMENTS), initArgs);\r\n}\r\n\r\nvoid FXAA::Shutdown(void)\r\n{\r\n    IndirectParameters.Destroy();\r\n}\r\n\r\nvoid FXAA::Render( ComputeContext& Context, bool bUsePreComputedLuma )\r\n{\r\n    ScopedTimer _prof(L\"FXAA\", Context);\r\n\r\n    if (ForceOffPreComputedLuma)\r\n        bUsePreComputedLuma = false;\r\n\r\n    ColorBuffer& Target = g_bTypedUAVLoadSupport_R11G11B10_FLOAT ? *g_pSceneColorBuffer : g_PostEffectsBuffer;\r\n\r\n    Context.SetRootSignature(RootSig);\r\n    Context.SetConstants(0, 1.0f / Target.GetWidth(), 1.0f / Target.GetHeight(), (float)ContrastThreshold, (float)SubpixelRemoval);\r\n    Context.SetConstant(0, g_FXAAWorkQueue.GetElementCount() - 1, 4);\r\n\r\n    // Apply algorithm to each quarter of the screen separately to reduce maximum size of work buffers.\r\n    uint32_t BlockWidth = Target.GetWidth() / 2;\r\n    uint32_t BlockHeight = Target.GetHeight() / 2;\r\n\r\n    for (uint32_t x = 0; x < Target.GetWidth(); x += BlockWidth)\r\n    {\r\n        for (uint32_t y = 0; y < Target.GetHeight(); y += BlockHeight)\r\n        {\r\n            // Pass 1\r\n            Context.SetConstant(0, x, 5);\r\n            Context.SetConstant(0, y, 6);\r\n\r\n            // Begin by analysing the luminance buffer and setting aside high-contrast pixels in\r\n            // work queues to be processed later.  There are horizontal edge and vertical edge work\r\n            // queues so that the shader logic is simpler for each type of edge.\r\n            // Counter values do not need to be reset because they are read and cleared at once.\r\n\r\n            Context.TransitionResource(Target, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.TransitionResource(g_FXAAWorkQueue, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            Context.TransitionResource(g_FXAAColorQueue, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n            D3D12_CPU_DESCRIPTOR_HANDLE Pass1UAVs[] =\r\n            {\r\n                g_FXAAWorkCounters.GetUAV(),\r\n                g_FXAAWorkQueue.GetUAV(),\r\n                g_FXAAColorQueue.GetUAV(),\r\n                g_LumaBuffer.GetUAV()\r\n            };\r\n\r\n            D3D12_CPU_DESCRIPTOR_HANDLE Pass1SRVs[] =\r\n            {\r\n                Target.GetSRV(),\r\n                g_LumaBuffer.GetSRV()\r\n            };\r\n\r\n            if (bUsePreComputedLuma)\r\n            {\r\n                Context.SetPipelineState(Pass1HdrCS);\r\n                Context.TransitionResource(g_LumaBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                Context.SetDynamicDescriptors(1, 0, _countof(Pass1UAVs) - 1, Pass1UAVs);\r\n                Context.SetDynamicDescriptors(2, 0, _countof(Pass1SRVs), Pass1SRVs);\r\n            }\r\n            else\r\n            {\r\n                Context.SetPipelineState(Pass1LdrCS);\r\n                Context.TransitionResource(g_LumaBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n                Context.SetDynamicDescriptors(1, 0, _countof(Pass1UAVs), Pass1UAVs);\r\n                Context.SetDynamicDescriptors(2, 0, _countof(Pass1SRVs) - 1, Pass1SRVs);\r\n            }\r\n\r\n            Context.Dispatch2D(BlockWidth, BlockHeight);\r\n\r\n            // Pass 2\r\n\r\n            // The next phase involves converting the work queues to DispatchIndirect parameters.\r\n            // The queues are also padded out to 64 elements to simplify the final consume logic.\r\n            Context.SetPipelineState(ResolveWorkCS);\r\n            Context.TransitionResource(IndirectParameters, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            Context.InsertUAVBarrier(g_FXAAWorkCounters);\r\n\r\n            Context.SetDynamicDescriptor(1, 0, IndirectParameters.GetUAV());\r\n            Context.SetDynamicDescriptor(1, 1, g_FXAAWorkQueue.GetUAV());\r\n            Context.SetDynamicDescriptor(1, 2, g_FXAAWorkCounters.GetUAV());\r\n\r\n            Context.Dispatch(1, 1, 1);\r\n\r\n            Context.InsertUAVBarrier(g_FXAAWorkCounters);\r\n            Context.TransitionResource(IndirectParameters, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n            Context.TransitionResource(g_FXAAWorkQueue, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.TransitionResource(g_FXAAColorQueue, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.TransitionResource(Target, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n            Context.SetDynamicDescriptor(1, 0, Target.GetUAV());\r\n            Context.SetDynamicDescriptor(2, 0, g_LumaBuffer.GetSRV());\r\n            Context.SetDynamicDescriptor(2, 1, g_FXAAWorkQueue.GetSRV());\r\n            Context.SetDynamicDescriptor(2, 2, g_FXAAColorQueue.GetSRV());\r\n\r\n            // The final phase involves processing pixels on the work queues and writing them\r\n            // back into the color buffer.  Because the two source pixels required for linearly\r\n            // blending are held in the work queue, this does not require also sampling from\r\n            // the target color buffer (i.e. no read/modify/write, just write.)\r\n\r\n            Context.SetPipelineState(DebugDraw ? Pass2HDebugCS : Pass2HCS);\r\n            Context.DispatchIndirect(IndirectParameters, 0);\r\n            Context.SetPipelineState(DebugDraw ? Pass2VDebugCS : Pass2VCS);\r\n            Context.DispatchIndirect(IndirectParameters, 12);\r\n\r\n            Context.InsertUAVBarrier(Target);\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/FXAA.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\nclass ColorBuffer;\r\nclass BoolVar;\r\nclass NumVar;\r\nclass ComputeContext;\r\n\r\nnamespace FXAA\r\n{\r\n    extern BoolVar Enable;\r\n    extern NumVar ContrastThreshold;\t// Default = 0.20\r\n    extern NumVar SubpixelRemoval;\t\t// Default = 0.75\r\n\r\n    void Initialize( void );\r\n    void Shutdown( void );\r\n    void Render( ComputeContext& Context, bool bUsePreComputedLuma );\r\n\r\n} // namespace FXAA\r\n"
  },
  {
    "path": "MiniEngine/Core/FileUtility.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"FileUtility.h\"\r\n#include <fstream>\r\n#include <mutex>\r\n#include <zlib.h> // From NuGet package \r\n\r\n\r\nusing namespace std;\r\nusing namespace Utility;\r\n\r\nnamespace Utility\r\n{\r\n    ByteArray NullFile = make_shared<vector<byte> > (vector<byte>() );\r\n}\r\n\r\nByteArray DecompressZippedFile( wstring& fileName );\r\n\r\nByteArray ReadFileHelper(const wstring& fileName)\r\n{\r\n    struct _stat64 fileStat;\r\n    int fileExists = _wstat64(fileName.c_str(), &fileStat);\r\n    if (fileExists == -1)\r\n        return NullFile;\r\n\r\n    ifstream file( fileName, ios::in | ios::binary );\r\n    if (!file)\r\n        return NullFile;\r\n\r\n    Utility::ByteArray byteArray = make_shared<vector<byte> >( file.seekg(0, ios::end).tellg() );\r\n    file.seekg(0, ios::beg).read( (char*)byteArray->data(), byteArray->size() );\r\n    file.close();\r\n\r\n    ASSERT(byteArray->size() == (size_t)fileStat.st_size);\r\n\r\n    return byteArray;\r\n}\r\n\r\nByteArray ReadFileHelperEx( shared_ptr<wstring> fileName)\r\n{\r\n    std::wstring zippedFileName = *fileName + L\".gz\";\r\n    ByteArray firstTry = DecompressZippedFile(zippedFileName);\r\n    if (firstTry != NullFile)\r\n        return firstTry;\r\n\r\n    return ReadFileHelper(*fileName);\r\n}\r\n\r\nByteArray Inflate(ByteArray CompressedSource, int& err, uint32_t ChunkSize = 0x100000 ) \r\n{\r\n    // Create a dynamic buffer to hold compressed blocks\r\n    vector<unique_ptr<byte> > blocks;\r\n\r\n    z_stream strm  = {};\r\n    strm.data_type = Z_BINARY;\r\n    strm.total_in  = strm.avail_in  = (uInt)CompressedSource->size();\r\n    strm.next_in   = CompressedSource->data();\r\n\r\n    err = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib\r\n\r\n    while (err == Z_OK || err == Z_BUF_ERROR)\r\n    {\r\n        strm.avail_out = ChunkSize;\r\n        strm.next_out = (byte*)malloc(ChunkSize);\r\n        blocks.emplace_back(strm.next_out);\r\n        err = inflate(&strm, Z_NO_FLUSH);\r\n    }\r\n\r\n    if (err != Z_STREAM_END) \r\n    {\r\n        inflateEnd(&strm);\r\n        return NullFile;\r\n    }\r\n\r\n    ASSERT(strm.total_out > 0, \"Nothing to decompress\");\r\n\r\n    Utility::ByteArray byteArray = make_shared<vector<byte> >( strm.total_out );\r\n\r\n    // Allocate actual memory for this.\r\n    // copy the bits into that RAM.\r\n    // Free everything else up!!\r\n    void* curDest = byteArray->data();\r\n    size_t remaining = byteArray->size();\r\n\r\n    for (size_t i = 0; i < blocks.size(); ++i)\r\n    {\r\n        ASSERT(remaining > 0);\r\n\r\n        size_t CopySize = min(remaining, (size_t)ChunkSize);\r\n\r\n        memcpy(curDest, blocks[i].get(), CopySize);\r\n        curDest = (byte*)curDest + CopySize;\r\n        remaining -= CopySize;\r\n    }\r\n\r\n    inflateEnd(&strm);\r\n\r\n    return byteArray;\r\n}\r\n\r\nByteArray DecompressZippedFile( wstring& fileName )\r\n{\r\n    ByteArray CompressedFile = ReadFileHelper(fileName);\r\n    if (CompressedFile == NullFile)\r\n        return NullFile;\r\n\r\n    int error;\r\n    ByteArray DecompressedFile = Inflate(CompressedFile, error);\r\n    if (DecompressedFile->size() == 0)\r\n    {\r\n        Utility::Printf(L\"Couldn't unzip file %s:  Error = %d\\n\", fileName.c_str(), error);\r\n        return NullFile;\r\n    }\r\n\r\n    return DecompressedFile;\r\n}\r\n\r\nByteArray Utility::ReadFileSync( const wstring& fileName)\r\n{\r\n    return ReadFileHelperEx(make_shared<wstring>(fileName));\r\n}\r\n\r\ntask<ByteArray> Utility::ReadFileAsync(const wstring& fileName)\r\n{\r\n    shared_ptr<wstring> SharedPtr = make_shared<wstring>(fileName);\r\n    return create_task( [=] { return ReadFileHelperEx(SharedPtr); } );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/FileUtility.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n#include <vector>\r\n#include <string>\r\n#include <ppl.h>\r\n\r\nnamespace Utility\r\n{\r\n    using namespace std;\r\n    using namespace concurrency;\r\n\r\n    typedef shared_ptr<vector<byte> > ByteArray;\r\n    extern ByteArray NullFile;\r\n\r\n    // Reads the entire contents of a binary file.  If the file with the same name except with an additional\r\n    // \".gz\" suffix exists, it will be loaded and decompressed instead.\r\n    // This operation blocks until the entire file is read.\r\n    ByteArray ReadFileSync(const wstring& fileName);\r\n\r\n    // Same as previous except that it does not block but instead returns a task.\r\n    task<ByteArray> ReadFileAsync(const wstring& fileName);\r\n\r\n} // namespace Utility\r\n"
  },
  {
    "path": "MiniEngine/Core/Fonts/consola24.h",
    "content": "unsigned char g_pconsola24[113408] =\r\n{\r\n\t0x53,0x44,0x46,0x46,0x4f,0x4e,0x54,0x00,0x01,0x00,0x03,0x00,0x00,0x02,0xd9,0x00,\r\n\t0x81,0x01,0xc2,0x01,0xbe,0x00,0x30,0x00,0x20,0x00,0x21,0x00,0x22,0x00,0x23,0x00,\r\n\t0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x2b,0x00,\r\n\t0x2c,0x00,0x2d,0x00,0x2e,0x00,0x2f,0x00,0x30,0x00,0x31,0x00,0x32,0x00,0x33,0x00,\r\n\t0x34,0x00,0x35,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,\r\n\t0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x40,0x00,0x41,0x00,0x42,0x00,0x43,0x00,\r\n\t0x44,0x00,0x45,0x00,0x46,0x00,0x47,0x00,0x48,0x00,0x49,0x00,0x4a,0x00,0x4b,0x00,\r\n\t0x4c,0x00,0x4d,0x00,0x4e,0x00,0x4f,0x00,0x50,0x00,0x51,0x00,0x52,0x00,0x53,0x00,\r\n\t0x54,0x00,0x55,0x00,0x56,0x00,0x57,0x00,0x58,0x00,0x59,0x00,0x5a,0x00,0x5b,0x00,\r\n\t0x5c,0x00,0x5d,0x00,0x5e,0x00,0x5f,0x00,0x60,0x00,0x61,0x00,0x62,0x00,0x63,0x00,\r\n\t0x64,0x00,0x65,0x00,0x66,0x00,0x67,0x00,0x68,0x00,0x69,0x00,0x6a,0x00,0x6b,0x00,\r\n\t0x6c,0x00,0x6d,0x00,0x6e,0x00,0x6f,0x00,0x70,0x00,0x71,0x00,0x72,0x00,0x73,0x00,\r\n\t0x74,0x00,0x75,0x00,0x76,0x00,0x77,0x00,0x78,0x00,0x79,0x00,0x7a,0x00,0x7b,0x00,\r\n\t0x7c,0x00,0x7d,0x00,0x7e,0x00,0xa0,0x00,0xa1,0x00,0xa2,0x00,0xa3,0x00,0xa4,0x00,\r\n\t0xa5,0x00,0xa6,0x00,0xa7,0x00,0xa8,0x00,0xa9,0x00,0xaa,0x00,0xab,0x00,0xac,0x00,\r\n\t0xad,0x00,0xae,0x00,0xaf,0x00,0xb0,0x00,0xb1,0x00,0xb2,0x00,0xb3,0x00,0xb4,0x00,\r\n\t0xb5,0x00,0xb6,0x00,0xb7,0x00,0xb8,0x00,0xb9,0x00,0xba,0x00,0xbb,0x00,0xbc,0x00,\r\n\t0xbd,0x00,0xbe,0x00,0xbf,0x00,0xc0,0x00,0xc1,0x00,0xc2,0x00,0xc3,0x00,0xc4,0x00,\r\n\t0xc5,0x00,0xc6,0x00,0xc7,0x00,0xc8,0x00,0xc9,0x00,0xca,0x00,0xcb,0x00,0xcc,0x00,\r\n\t0xcd,0x00,0xce,0x00,0xcf,0x00,0xd0,0x00,0xd1,0x00,0xd2,0x00,0xd3,0x00,0xd4,0x00,\r\n\t0xd5,0x00,0xd6,0x00,0xd7,0x00,0xd8,0x00,0xd9,0x00,0xda,0x00,0xdb,0x00,0xdc,0x00,\r\n\t0xdd,0x00,0xde,0x00,0xdf,0x00,0xe0,0x00,0xe1,0x00,0xe2,0x00,0xe3,0x00,0xe4,0x00,\r\n\t0xe5,0x00,0xe6,0x00,0xe7,0x00,0xe8,0x00,0xe9,0x00,0xea,0x00,0xeb,0x00,0xec,0x00,\r\n\t0xed,0x00,0xee,0x00,0xef,0x00,0xf0,0x00,0xf1,0x00,0xf2,0x00,0xf3,0x00,0xf4,0x00,\r\n\t0xf5,0x00,0xf6,0x00,0xf7,0x00,0xf8,0x00,0xf9,0x00,0xfa,0x00,0xfb,0x00,0xfc,0x00,\r\n\t0xfd,0x00,0xfe,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0xd3,0x00,0x90,0x00,\r\n\t0x30,0x00,0x32,0x00,0x50,0x00,0xd3,0x00,0x30,0x01,0x30,0x00,0x6d,0x00,0x33,0x00,\r\n\t0xd3,0x00,0x00,0x02,0x30,0x00,0xc3,0x00,0x08,0x00,0xd3,0x00,0x30,0x03,0x30,0x00,\r\n\t0xa8,0x00,0x15,0x00,0xd3,0x00,0x40,0x04,0x30,0x00,0xcd,0x00,0x03,0x00,0xd3,0x00,\r\n\t0x70,0x05,0x30,0x00,0xc9,0x00,0x0b,0x00,0xd3,0x00,0xa0,0x06,0x30,0x00,0x26,0x00,\r\n\t0x57,0x00,0xd3,0x00,0x30,0x07,0x30,0x00,0x6a,0x00,0x38,0x00,0xd3,0x00,0x00,0x08,\r\n\t0x30,0x00,0x6a,0x00,0x30,0x00,0xd3,0x00,0xd0,0x08,0x30,0x00,0x97,0x00,0x1e,0x00,\r\n\t0xd3,0x00,0xd0,0x09,0x30,0x00,0xb4,0x00,0x10,0x00,0xd3,0x00,0xf0,0x0a,0x30,0x00,\r\n\t0x5b,0x00,0x2d,0x00,0xd3,0x00,0xb0,0x0b,0x30,0x00,0x70,0x00,0x31,0x00,0xd3,0x00,\r\n\t0x80,0x0c,0x30,0x00,0x3e,0x00,0x49,0x00,0xd3,0x00,0x20,0x0d,0x30,0x00,0xa1,0x00,\r\n\t0x15,0x00,0xd3,0x00,0x30,0x0e,0x30,0x00,0xb2,0x00,0x10,0x00,0xd3,0x00,0x50,0x0f,\r\n\t0x30,0x00,0xa2,0x00,0x19,0x00,0xd3,0x00,0x60,0x10,0x30,0x00,0xa1,0x00,0x1c,0x00,\r\n\t0xd3,0x00,0x70,0x11,0x30,0x00,0x9a,0x00,0x1e,0x00,0xd3,0x00,0x70,0x12,0x30,0x00,\r\n\t0xc1,0x00,0x08,0x00,0xd3,0x00,0xa0,0x13,0x30,0x00,0x96,0x00,0x21,0x00,0xd3,0x00,\r\n\t0xa0,0x14,0x30,0x00,0xa9,0x00,0x17,0x00,0xd3,0x00,0xb0,0x15,0x30,0x00,0xa6,0x00,\r\n\t0x16,0x00,0xd3,0x00,0xc0,0x16,0x30,0x00,0xa6,0x00,0x16,0x00,0xd3,0x00,0xd0,0x17,\r\n\t0x30,0x00,0xa9,0x00,0x13,0x00,0xd3,0x00,0xe0,0x18,0x30,0x00,0x3a,0x00,0x4d,0x00,\r\n\t0xd3,0x00,0x80,0x19,0x30,0x00,0x5b,0x00,0x2f,0x00,0xd3,0x00,0x40,0x1a,0x30,0x00,\r\n\t0x94,0x00,0x19,0x00,0xd3,0x00,0x40,0x1b,0x30,0x00,0xa1,0x00,0x19,0x00,0xd3,0x00,\r\n\t0x50,0x1c,0x30,0x00,0x93,0x00,0x27,0x00,0xd3,0x00,0x50,0x1d,0x30,0x00,0x74,0x00,\r\n\t0x39,0x00,0xd3,0x00,0x30,0x1e,0x30,0x00,0xce,0x00,0x02,0x00,0xd3,0x00,0x30,0x00,\r\n\t0x20,0x02,0xd1,0x00,0x01,0x00,0xd3,0x00,0x70,0x01,0x20,0x02,0xa1,0x00,0x1e,0x00,\r\n\t0xd3,0x00,0x80,0x02,0x20,0x02,0xaa,0x00,0x11,0x00,0xd3,0x00,0x90,0x03,0x20,0x02,\r\n\t0xb1,0x00,0x14,0x00,0xd3,0x00,0xb0,0x04,0x20,0x02,0x8c,0x00,0x26,0x00,0xd3,0x00,\r\n\t0xa0,0x05,0x20,0x02,0x8a,0x00,0x26,0x00,0xd3,0x00,0x90,0x06,0x20,0x02,0xb1,0x00,\r\n\t0x0c,0x00,0xd3,0x00,0xb0,0x07,0x20,0x02,0xaa,0x00,0x15,0x00,0xd3,0x00,0xc0,0x08,\r\n\t0x20,0x02,0x93,0x00,0x20,0x00,0xd3,0x00,0xc0,0x09,0x20,0x02,0x83,0x00,0x22,0x00,\r\n\t0xd3,0x00,0xb0,0x0a,0x20,0x02,0xa7,0x00,0x1d,0x00,0xd3,0x00,0xc0,0x0b,0x20,0x02,\r\n\t0x8d,0x00,0x2c,0x00,0xd3,0x00,0xb0,0x0c,0x20,0x02,0xb5,0x00,0x0f,0x00,0xd3,0x00,\r\n\t0xd0,0x0d,0x20,0x02,0xa7,0x00,0x16,0x00,0xd3,0x00,0xe0,0x0e,0x20,0x02,0xbe,0x00,\r\n\t0x0b,0x00,0xd3,0x00,0x00,0x10,0x20,0x02,0xa1,0x00,0x1e,0x00,0xd3,0x00,0x10,0x11,\r\n\t0x20,0x02,0xc9,0x00,0x0b,0x00,0xd3,0x00,0x40,0x12,0x20,0x02,0xa6,0x00,0x20,0x00,\r\n\t0xd3,0x00,0x50,0x13,0x20,0x02,0xa6,0x00,0x15,0x00,0xd3,0x00,0x60,0x14,0x20,0x02,\r\n\t0xb3,0x00,0x10,0x00,0xd3,0x00,0x80,0x15,0x20,0x02,0xaa,0x00,0x14,0x00,0xd3,0x00,\r\n\t0x90,0x16,0x20,0x02,0xd3,0x00,0x00,0x00,0xd3,0x00,0xd0,0x17,0x20,0x02,0xb2,0x00,\r\n\t0x11,0x00,0xd3,0x00,0xf0,0x18,0x20,0x02,0xcc,0x00,0x03,0x00,0xd3,0x00,0x20,0x1a,\r\n\t0x20,0x02,0xd4,0x00,0x00,0x00,0xd3,0x00,0x60,0x1b,0x20,0x02,0xa9,0x00,0x15,0x00,\r\n\t0xd3,0x00,0x70,0x1c,0x20,0x02,0x5d,0x00,0x41,0x00,0xd3,0x00,0x30,0x1d,0x20,0x02,\r\n\t0xa0,0x00,0x1e,0x00,0xd3,0x00,0x30,0x1e,0x20,0x02,0x5d,0x00,0x36,0x00,0xd3,0x00,\r\n\t0xf0,0x1e,0x20,0x02,0xa9,0x00,0x16,0x00,0xd3,0x00,0x30,0x00,0x10,0x04,0xd3,0x00,\r\n\t0x00,0x00,0xd3,0x00,0x70,0x01,0x10,0x04,0x7e,0x00,0x00,0x00,0xd3,0x00,0x50,0x02,\r\n\t0x10,0x04,0x9b,0x00,0x19,0x00,0xd3,0x00,0x50,0x03,0x10,0x04,0xa1,0x00,0x1e,0x00,\r\n\t0xd3,0x00,0x60,0x04,0x10,0x04,0x93,0x00,0x1e,0x00,0xd3,0x00,0x60,0x05,0x10,0x04,\r\n\t0xa0,0x00,0x14,0x00,0xd3,0x00,0x60,0x06,0x10,0x04,0xa7,0x00,0x16,0x00,0xd3,0x00,\r\n\t0x70,0x07,0x10,0x04,0xc5,0x00,0x00,0x00,0xd3,0x00,0xa0,0x08,0x10,0x04,0xb2,0x00,\r\n\t0x12,0x00,0xd3,0x00,0xc0,0x09,0x10,0x04,0x97,0x00,0x1e,0x00,0xd3,0x00,0xc0,0x0a,\r\n\t0x10,0x04,0x97,0x00,0x20,0x00,0xd3,0x00,0xc0,0x0b,0x10,0x04,0x8b,0x00,0x18,0x00,\r\n\t0xd3,0x00,0xb0,0x0c,0x10,0x04,0xa6,0x00,0x22,0x00,0xd3,0x00,0xc0,0x0d,0x10,0x04,\r\n\t0x97,0x00,0x20,0x00,0xd3,0x00,0xc0,0x0e,0x10,0x04,0xb1,0x00,0x11,0x00,0xd3,0x00,\r\n\t0xe0,0x0f,0x10,0x04,0x97,0x00,0x1e,0x00,0xd3,0x00,0xe0,0x10,0x10,0x04,0xb0,0x00,\r\n\t0x11,0x00,0xd3,0x00,0xf0,0x11,0x10,0x04,0xa1,0x00,0x1e,0x00,0xd3,0x00,0x00,0x13,\r\n\t0x10,0x04,0xa0,0x00,0x14,0x00,0xd3,0x00,0x00,0x14,0x10,0x04,0x9b,0x00,0x26,0x00,\r\n\t0xd3,0x00,0x00,0x15,0x10,0x04,0x92,0x00,0x22,0x00,0xd3,0x00,0x00,0x16,0x10,0x04,\r\n\t0xaa,0x00,0x0c,0x00,0xd3,0x00,0x10,0x17,0x10,0x04,0x97,0x00,0x1e,0x00,0xd3,0x00,\r\n\t0x10,0x18,0x10,0x04,0xba,0x00,0x0c,0x00,0xd3,0x00,0x30,0x19,0x10,0x04,0xc7,0x00,\r\n\t0x06,0x00,0xd3,0x00,0x60,0x1a,0x10,0x04,0xbb,0x00,0x0d,0x00,0xd3,0x00,0x80,0x1b,\r\n\t0x10,0x04,0xbb,0x00,0x0b,0x00,0xd3,0x00,0xa0,0x1c,0x10,0x04,0x98,0x00,0x1f,0x00,\r\n\t0xd3,0x00,0xa0,0x1d,0x10,0x04,0x8b,0x00,0x1e,0x00,0xd3,0x00,0x90,0x1e,0x10,0x04,\r\n\t0x1f,0x00,0x5a,0x00,0xd3,0x00,0x10,0x1f,0x10,0x04,0x8a,0x00,0x2b,0x00,0xd3,0x00,\r\n\t0x30,0x00,0x00,0x06,0xbb,0x00,0x0c,0x00,0xd3,0x00,0x50,0x01,0x00,0x06,0x00,0x00,\r\n\t0x00,0x00,0xd3,0x00,0xb0,0x01,0x00,0x06,0x32,0x00,0x51,0x00,0xd3,0x00,0x50,0x02,\r\n\t0x00,0x06,0x93,0x00,0x17,0x00,0xd3,0x00,0x50,0x03,0x00,0x06,0xac,0x00,0x11,0x00,\r\n\t0xd3,0x00,0x60,0x04,0x00,0x06,0xb3,0x00,0x10,0x00,0xd3,0x00,0x80,0x05,0x00,0x06,\r\n\t0xc0,0x00,0x0a,0x00,0xd3,0x00,0xa0,0x06,0x00,0x06,0x1f,0x00,0x5a,0x00,0xd3,0x00,\r\n\t0x20,0x07,0x00,0x06,0x9f,0x00,0x1a,0x00,0xd3,0x00,0x20,0x08,0x00,0x06,0xa8,0x00,\r\n\t0xff,0xff,0xd3,0x00,0x30,0x09,0x00,0x06,0xcf,0x00,0x02,0x00,0xd3,0x00,0x60,0x0a,\r\n\t0x00,0x06,0x7f,0x00,0x2a,0x00,0xd3,0x00,0x40,0x0b,0x00,0x06,0x9d,0x00,0x1a,0x00,\r\n\t0xd3,0x00,0x40,0x0c,0x00,0x06,0xa0,0x00,0x16,0x00,0xd3,0x00,0x40,0x0d,0x00,0x06,\r\n\t0x70,0x00,0x31,0x00,0xd3,0x00,0x10,0x0e,0x00,0x06,0xac,0x00,0x14,0x00,0xd3,0x00,\r\n\t0x20,0x0f,0x00,0x06,0x9b,0x00,0xff,0xff,0xd3,0x00,0x20,0x10,0x00,0x06,0x83,0x00,\r\n\t0x28,0x00,0xd3,0x00,0x10,0x11,0x00,0x06,0xac,0x00,0x13,0x00,0xd3,0x00,0x20,0x12,\r\n\t0x00,0x06,0x77,0x00,0x2e,0x00,0xd3,0x00,0x00,0x13,0x00,0x06,0x6f,0x00,0x33,0x00,\r\n\t0xd3,0x00,0xd0,0x13,0x00,0x06,0xb3,0x00,0x00,0x00,0xd3,0x00,0xf0,0x14,0x00,0x06,\r\n\t0xac,0x00,0x1e,0x00,0xd3,0x00,0x00,0x16,0x00,0x06,0xa7,0x00,0x14,0x00,0xd3,0x00,\r\n\t0x10,0x17,0x00,0x06,0x3e,0x00,0x4a,0x00,0xd3,0x00,0xb0,0x17,0x00,0x06,0x2e,0x00,\r\n\t0x51,0x00,0xd3,0x00,0x40,0x18,0x00,0x06,0x7b,0x00,0x2a,0x00,0xd3,0x00,0x20,0x19,\r\n\t0x00,0x06,0x80,0x00,0x29,0x00,0xd3,0x00,0x00,0x1a,0x00,0x06,0x9c,0x00,0x1d,0x00,\r\n\t0xd3,0x00,0x00,0x1b,0x00,0x06,0xcd,0x00,0x03,0x00,0xd3,0x00,0x30,0x1c,0x00,0x06,\r\n\t0xcd,0x00,0x03,0x00,0xd3,0x00,0x60,0x1d,0x00,0x06,0xcd,0x00,0x03,0x00,0xd3,0x00,\r\n\t0x90,0x1e,0x00,0x06,0x74,0x00,0x26,0x00,0xd3,0x00,0x30,0x00,0xf0,0x07,0xd2,0x00,\r\n\t0x00,0x00,0xd3,0x00,0x70,0x01,0xf0,0x07,0xd2,0x00,0x00,0x00,0xd3,0x00,0xb0,0x02,\r\n\t0xf0,0x07,0xd2,0x00,0x00,0x00,0xd3,0x00,0xf0,0x03,0xf0,0x07,0xd2,0x00,0x00,0x00,\r\n\t0xd3,0x00,0x30,0x05,0xf0,0x07,0xd2,0x00,0x00,0x00,0xd3,0x00,0x70,0x06,0xf0,0x07,\r\n\t0xd1,0x00,0x00,0x00,0xd3,0x00,0xb0,0x07,0xf0,0x07,0xd4,0x00,0xf7,0xff,0xd3,0x00,\r\n\t0xf0,0x08,0xf0,0x07,0xaa,0x00,0x11,0x00,0xd3,0x00,0x00,0x0a,0xf0,0x07,0xb2,0x00,\r\n\t0x00,0x00,0xd3,0x00,0x20,0x0b,0xf0,0x07,0xb2,0x00,0x00,0x00,0xd3,0x00,0x40,0x0c,\r\n\t0xf0,0x07,0xb2,0x00,0x00,0x00,0xd3,0x00,0x60,0x0d,0xf0,0x07,0xb2,0x00,0x00,0x00,\r\n\t0xd3,0x00,0x80,0x0e,0xf0,0x07,0xb4,0x00,0xff,0xff,0xd3,0x00,0xa0,0x0f,0xf0,0x07,\r\n\t0xb4,0x00,0xff,0xff,0xd3,0x00,0xc0,0x10,0xf0,0x07,0xb4,0x00,0xff,0xff,0xd3,0x00,\r\n\t0xe0,0x11,0xf0,0x07,0xb4,0x00,0xff,0xff,0xd3,0x00,0x00,0x13,0xf0,0x07,0xc5,0x00,\r\n\t0x00,0x00,0xd3,0x00,0x30,0x14,0xf0,0x07,0xbe,0x00,0xff,0xff,0xd3,0x00,0x50,0x15,\r\n\t0xf0,0x07,0xc9,0x00,0x00,0x00,0xd3,0x00,0x80,0x16,0xf0,0x07,0xc9,0x00,0x00,0x00,\r\n\t0xd3,0x00,0xb0,0x17,0xf0,0x07,0xc9,0x00,0x00,0x00,0xd3,0x00,0xe0,0x18,0xf0,0x07,\r\n\t0xc9,0x00,0x00,0x00,0xd3,0x00,0x10,0x1a,0xf0,0x07,0xc9,0x00,0x00,0x00,0xd3,0x00,\r\n\t0x40,0x1b,0xf0,0x07,0x9d,0x00,0x1b,0x00,0xd3,0x00,0x40,0x1c,0xf0,0x07,0xbe,0x00,\r\n\t0x0b,0x00,0xd3,0x00,0x60,0x1d,0xf0,0x07,0xbf,0x00,0xff,0xff,0xd3,0x00,0x80,0x1e,\r\n\t0xf0,0x07,0xbf,0x00,0xff,0xff,0xd3,0x00,0x30,0x00,0xe0,0x09,0xbf,0x00,0xff,0xff,\r\n\t0xd3,0x00,0x50,0x01,0xe0,0x09,0xbf,0x00,0xff,0xff,0xd3,0x00,0x70,0x02,0xe0,0x09,\r\n\t0xd4,0x00,0x00,0x00,0xd3,0x00,0xb0,0x03,0xe0,0x09,0xa1,0x00,0x1e,0x00,0xd3,0x00,\r\n\t0xc0,0x04,0xe0,0x09,0xa4,0x00,0x1c,0x00,0xd3,0x00,0xd0,0x05,0xe0,0x09,0xb4,0x00,\r\n\t0x00,0x00,0xd3,0x00,0xf0,0x06,0xe0,0x09,0xb4,0x00,0x00,0x00,0xd3,0x00,0x10,0x08,\r\n\t0xe0,0x09,0xb4,0x00,0x00,0x00,0xd3,0x00,0x30,0x09,0xe0,0x09,0xb4,0x00,0x00,0x00,\r\n\t0xd3,0x00,0x50,0x0a,0xe0,0x09,0xb4,0x00,0x00,0x00,0xd3,0x00,0x70,0x0b,0xe0,0x09,\r\n\t0xb4,0x00,0x00,0x00,0xd3,0x00,0x90,0x0c,0xe0,0x09,0xc6,0x00,0x06,0x00,0xd3,0x00,\r\n\t0xc0,0x0d,0xe0,0x09,0x93,0x00,0x1e,0x00,0xd3,0x00,0xc0,0x0e,0xe0,0x09,0xbd,0x00,\r\n\t0x00,0x00,0xd3,0x00,0xe0,0x0f,0xe0,0x09,0xbd,0x00,0x00,0x00,0xd3,0x00,0x00,0x11,\r\n\t0xe0,0x09,0xbd,0x00,0x00,0x00,0xd3,0x00,0x20,0x12,0xe0,0x09,0xbd,0x00,0x00,0x00,\r\n\t0xd3,0x00,0x40,0x13,0xe0,0x09,0xb8,0x00,0xff,0xff,0xd3,0x00,0x60,0x14,0xe0,0x09,\r\n\t0xb8,0x00,0xff,0xff,0xd3,0x00,0x80,0x15,0xe0,0x09,0xb8,0x00,0xff,0xff,0xd3,0x00,\r\n\t0xa0,0x16,0xe0,0x09,0xb8,0x00,0xff,0xff,0xd3,0x00,0xc0,0x17,0xe0,0x09,0xaa,0x00,\r\n\t0x13,0x00,0xd3,0x00,0xd0,0x18,0xe0,0x09,0xb5,0x00,0x00,0x00,0xd3,0x00,0xf0,0x19,\r\n\t0xe0,0x09,0xc2,0x00,0xff,0xff,0xd3,0x00,0x20,0x1b,0xe0,0x09,0xc2,0x00,0xff,0xff,\r\n\t0xd3,0x00,0x50,0x1c,0xe0,0x09,0xc2,0x00,0xff,0xff,0xd3,0x00,0x80,0x1d,0xe0,0x09,\r\n\t0xc2,0x00,0xff,0xff,0xd3,0x00,0xb0,0x1e,0xe0,0x09,0xc2,0x00,0xff,0xff,0xd3,0x00,\r\n\t0x30,0x00,0xd0,0x0b,0xb4,0x00,0x10,0x00,0xd3,0x00,0x50,0x01,0xd0,0x0b,0xb1,0x00,\r\n\t0x11,0x00,0xd3,0x00,0x70,0x02,0xd0,0x0b,0xb5,0x00,0x00,0x00,0xd3,0x00,0x90,0x03,\r\n\t0xd0,0x0b,0xb5,0x00,0x00,0x00,0xd3,0x00,0xb0,0x04,0xd0,0x0b,0xb5,0x00,0x00,0x00,\r\n\t0xd3,0x00,0xd0,0x05,0xd0,0x0b,0xb5,0x00,0x00,0x00,0xd3,0x00,0xf0,0x06,0xd0,0x0b,\r\n\t0xc7,0x00,0xff,0xff,0xd3,0x00,0x20,0x08,0xd0,0x0b,0xa1,0x00,0x1e,0x00,0xd3,0x00,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x88,0x88,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x8b,0x8b,0x8b,0x85,0x81,0x81,0x81,\r\n\t0x81,0x81,0x86,0x88,0x88,0x88,0x81,0x88,0x88,0x88,0x84,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa3,0xb2,0xb2,0xb2,0xa4,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x84,0x8e,0x90,0x8d,0x84,0x81,0x81,0x81,0x81,0x87,0x88,\r\n\t0x88,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xa6,0xad,0xa2,0x89,0x81,0x81,0x81,0x81,0x92,\r\n\t0xa8,0xad,0x9e,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0x88,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x89,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x89,0x8b,0x8a,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x8f,0x90,0x8e,0x87,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xa9,0xb5,0xb5,0xb5,0xac,0x92,0x81,0x81,\r\n\t0x81,0x9b,0xaf,0xb2,0xb2,0xb2,0xa6,0xb2,0xb2,0xb2,0xad,0x96,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xc2,0xdc,0xdd,0xdc,0xc4,0x9e,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x99,0xac,0xb7,0xba,0xb7,0xac,0x99,0x81,0x83,0xa0,0xb1,0xb2,\r\n\t0xb2,0xac,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0x99,0xa1,0xa3,0xa0,0x98,0x89,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xb2,0xa4,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8e,0xac,0xca,0xd7,0xc5,0xa7,0x89,0x81,0x81,0x92,0xb0,\r\n\t0xcd,0xd6,0xc1,0xa3,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,\r\n\t0xaf,0xb2,0xb2,0xa8,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,0xb5,0xb2,0x9d,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x83,0x83,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x88,0x88,0x85,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,\r\n\t0x88,0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x82,0x88,0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9d,0xb2,0xb5,0xb4,0xae,0xa4,0x97,0x86,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa0,0xaf,0xb8,0xba,0xb8,0xb0,0xa1,0x8d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xca,0xdf,0xdf,0xdf,0xce,0xa9,0x81,0x81,\r\n\t0x90,0xb6,0xd6,0xdd,0xdd,0xdb,0xc6,0xdd,0xdd,0xdd,0xd2,0xaf,0x88,0x81,0x81,0x81,\r\n\t0x81,0x83,0x9e,0xaa,0xab,0xaa,0x9e,0xa2,0xab,0xab,0xa8,0x96,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0x97,0xa6,0xd0,0xfa,0x09,0xfa,0xd0,0xa5,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9d,0xbb,0xd2,0xe1,0xe5,0xe1,0xd2,0xbb,0x9d,0x9b,0xbe,0xda,0xdd,\r\n\t0xdd,0xd0,0xad,0x85,0x81,0x81,0x81,0x83,0x9e,0xb3,0xc3,0xcb,0xcd,0xca,0xc0,0xaf,\r\n\t0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xdc,0xc4,0x9e,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8b,0xaa,0xca,0xe8,0xff,0xe3,0xc5,0xa3,0x81,0x89,0xaf,0xce,\r\n\t0xec,0xfb,0xdf,0xbf,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x8f,0x90,0xb6,\r\n\t0xd6,0xdd,0xdd,0xca,0xa6,0x93,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xb5,0xd7,0xdf,0xdf,0xd9,0xb8,0x90,0x81,\r\n\t0x81,0x81,0x81,0x81,0x85,0x99,0xa7,0xb0,0xb2,0xb2,0xaa,0x9d,0x8c,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x9b,0xab,0xad,0xad,0xa6,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x9b,0xa8,0xb0,0xb2,0xb2,0xab,0x9d,0x8c,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x93,0x9f,0xa9,0xb0,0xb2,0xb2,0xaf,0xa6,0x9a,0x87,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa0,0xab,0xab,0xab,\r\n\t0xaa,0x9f,0x85,0x81,0x81,0x81,0x81,0x81,0x8a,0xa1,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa8,0x9f,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x9a,0xa4,\r\n\t0xa8,0xab,0xab,0xaa,0x9e,0x83,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xa2,0xad,\r\n\t0xb2,0xb2,0xb0,0xaa,0x9e,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x9f,\r\n\t0xab,0xb2,0xb2,0xb0,0xa7,0x99,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x90,0xb8,0xd9,0xdf,0xdd,0xd7,0xcd,0xbe,0xab,0x95,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x98,0xb1,0xc7,0xd7,0xe2,0xe5,0xe2,0xd8,0xc7,0xb0,0x94,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x0b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x95,0xc0,0xea,0x09,0x09,0xf5,0xd2,0xfc,0x09,0x09,0xe2,0xb8,0x8d,0x81,0x81,0x81,\r\n\t0x81,0x9b,0xbf,0xd4,0xd5,0xd4,0xbf,0xc6,0xd5,0xd5,0xd1,0xb5,0x8f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x99,0xae,0xbf,0xcc,0xd5,0xff,0x1e,0xf4,0xca,0xc3,0xb3,0x94,0x81,\r\n\t0x81,0x81,0x94,0xb9,0xd9,0xf6,0x0a,0x11,0x0a,0xf5,0xd9,0xb7,0xb2,0xd5,0xf9,0x09,\r\n\t0x07,0xdf,0xb5,0x8b,0x81,0x81,0x81,0xa1,0xbf,0xd8,0xeb,0xf5,0xf7,0xf4,0xe7,0xd3,\r\n\t0xb8,0x99,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,0x09,0xfa,0xd0,0xa5,0x81,\r\n\t0x81,0x81,0x81,0x84,0xa6,0xc7,0xe6,0x06,0x1f,0xff,0xda,0xb0,0x85,0x93,0xbd,0xe7,\r\n\t0x0b,0x1c,0xfb,0xdc,0xbb,0x9b,0x81,0x81,0x81,0x81,0x81,0x88,0xa6,0xb9,0xb6,0xc0,\r\n\t0xea,0x09,0x04,0xd7,0xaf,0xbd,0xb3,0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc7,0xee,0x0b,0x0b,0xe9,0xbf,0x95,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xa9,0xbf,0xcf,0xda,0xdd,0xdc,0xd3,0xc5,0xb0,0x96,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0x99,0xac,0xc0,0xd4,0xd7,0xd7,0xca,0xa8,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x96,0xae,0xc1,0xd1,0xda,0xdd,0xdc,0xd3,0xc5,0xaf,0x96,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9a,0xb8,0xc8,0xd2,0xda,0xdd,0xdd,0xd8,0xcf,0xc0,0xab,\r\n\t0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc3,0xd5,0xd5,0xd5,\r\n\t0xd5,0xc1,0x9e,0x81,0x81,0x81,0x81,0x81,0xa6,0xc6,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xd2,0xc3,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa2,0xb5,0xc3,0xcd,\r\n\t0xd2,0xd5,0xd5,0xd4,0xbf,0x9b,0x81,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xbd,0x9a,0x81,0x81,0x81,0x85,0xa1,0xb8,0xca,0xd6,\r\n\t0xdd,0xdd,0xda,0xd3,0xc6,0xb2,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xb3,0xc6,\r\n\t0xd4,0xdc,0xdd,0xda,0xcf,0xbf,0xa8,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x0b,0x09,0xff,0xf5,0xe5,0xd0,0xb6,0x9a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9a,0xb8,0xd4,0xec,0xff,0x0b,0x11,0x0b,0xff,0xeb,0xd0,0xb2,\r\n\t0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x21,0xf5,0xd2,0xfc,0x29,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,\r\n\t0x81,0xa5,0xd0,0xfa,0xff,0xfa,0xd0,0xdd,0xff,0xff,0xed,0xc2,0x98,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9f,0xbb,0xd4,0xe7,0xf5,0xfa,0x06,0x19,0xfa,0xf5,0xec,0xce,0xa6,0x81,\r\n\t0x81,0x81,0xa6,0xcd,0xf3,0x16,0x11,0x06,0x14,0x14,0xf1,0xc9,0xc9,0xec,0x10,0x12,\r\n\t0xef,0xcc,0xa8,0x82,0x81,0x81,0x95,0xba,0xdd,0xfb,0x12,0x1f,0x23,0x1e,0x0d,0xf3,\r\n\t0xd4,0xaf,0x8a,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x26,0xfa,0xd0,0xa5,0x81,\r\n\t0x81,0x81,0x81,0x9c,0xbf,0xe1,0x04,0x23,0x09,0xe8,0xca,0xa7,0x81,0x8d,0xb4,0xd6,\r\n\t0xf5,0x15,0x18,0xf7,0xd5,0xb4,0x91,0x81,0x81,0x81,0x81,0x9e,0xc2,0xe1,0xdb,0xc3,\r\n\t0xea,0x16,0xff,0xd5,0xd2,0xe7,0xd3,0xae,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xb0,0xd7,0xfc,0x25,0xff,0xd9,0xb2,0x8b,0x81,\r\n\t0x81,0x81,0x8d,0xac,0xca,0xe3,0xf6,0x04,0x09,0x06,0xfb,0xeb,0xd2,0xb6,0x96,0x81,\r\n\t0x81,0x81,0x81,0x82,0x97,0xab,0xbe,0xd2,0xe6,0xf9,0x04,0x04,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9a,0xb7,0xd1,0xe7,0xf9,0x04,0x09,0x06,0xfb,0xea,0xd2,0xb4,\r\n\t0x93,0x81,0x81,0x81,0x82,0xab,0xd4,0xf1,0xfb,0x04,0x09,0x09,0x04,0xf7,0xe6,0xcd,\r\n\t0xaf,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xb7,0xdb,0xff,0xff,0xff,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xd7,0xad,0x83,0x81,0x81,0x81,0x81,0x94,0xb0,0xc8,0xdb,0xec,0xf6,\r\n\t0xfc,0xff,0xff,0xfa,0xd0,0xa5,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xfc,0xfc,0xf9,0xcf,0xa5,0x81,0x81,0x81,0xa3,0xc1,0xdc,0xf1,0xff,\r\n\t0x06,0x09,0x06,0xfb,0xec,0xd5,0xb8,0x97,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd7,0xed,\r\n\t0xfc,0x06,0x09,0x04,0xf6,0xe3,0xc8,0xaa,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x99,0x98,0x86,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x82,0x95,0x9a,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0x24,0x1d,0x0a,0xf1,0xd5,0xb6,0x94,0x81,0x81,\r\n\t0x81,0x81,0x81,0x93,0xb5,0xd5,0xf3,0x0f,0x19,0x09,0x04,0x09,0x1a,0x0d,0xee,0xcb,\r\n\t0xa7,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x21,0xf5,0xd2,0xfc,0x29,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,\r\n\t0x83,0xaa,0xd5,0xfc,0x21,0xf5,0xcb,0xdf,0x0b,0x14,0xea,0xc0,0x96,0x81,0x81,0x81,\r\n\t0x81,0x97,0xba,0xdb,0xf6,0x0d,0x1d,0x24,0x27,0x26,0x24,0x1e,0xfc,0xd2,0xa8,0x81,\r\n\t0x81,0x88,0xb2,0xdb,0x04,0x1c,0xf5,0xdc,0xfa,0x23,0xfc,0xd5,0xe0,0x04,0x1f,0xfb,\r\n\t0xd9,0xb5,0x91,0x81,0x81,0x81,0xa5,0xcd,0xf4,0x18,0x1c,0xff,0xfa,0x07,0x25,0x0f,\r\n\t0xe8,0xc1,0x98,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x26,0xfa,0xd0,0xa5,0x81,\r\n\t0x81,0x81,0x8e,0xb3,0xd7,0xfa,0x1c,0x0f,0xed,0xcc,0xac,0x8e,0x81,0x81,0x9b,0xb9,\r\n\t0xd9,0xfa,0x1c,0x11,0xee,0xcb,0xa7,0x82,0x81,0x81,0x8e,0xb4,0xd8,0xfc,0xfc,0xe6,\r\n\t0xea,0x16,0xfc,0xdd,0xf5,0x0d,0xe8,0xc3,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8f,0x9a,0x9b,0x9b,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9a,0xc1,0xe7,0x0f,0x17,0xef,0xc8,0xa1,0x81,0x81,\r\n\t0x81,0x81,0xa5,0xc8,0xe8,0x05,0x1d,0x1f,0x19,0x1d,0x23,0x0f,0xf1,0xd1,0xae,0x8a,\r\n\t0x81,0x81,0x81,0xa3,0xbc,0xcf,0xe3,0xf7,0x0b,0x1f,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x8d,0xb4,0xd5,0xf3,0x0c,0x20,0x1e,0x1b,0x20,0x23,0x0d,0xf0,0xce,\r\n\t0xaa,0x84,0x81,0x81,0x83,0xad,0xd7,0x04,0x24,0x1c,0x19,0x19,0x22,0x1f,0x09,0xea,\r\n\t0xc8,0xa2,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xaa,0xce,0xf1,0x15,0x2b,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x29,0x23,0x23,0x23,0x23,\r\n\t0x23,0x23,0x04,0xd7,0xad,0x83,0x81,0x81,0x81,0x90,0xb1,0xd0,0xeb,0xff,0x13,0x20,\r\n\t0x23,0x21,0x21,0xfa,0xd0,0xa5,0x81,0x81,0x95,0xc0,0xea,0x16,0x29,0x29,0x29,0x29,\r\n\t0x29,0x29,0x29,0x29,0x26,0xfa,0xd0,0xa5,0x81,0x81,0x97,0xbc,0xdf,0xfc,0x17,0x20,\r\n\t0x17,0x16,0x1b,0x24,0x10,0xf3,0xd2,0xad,0x86,0x81,0x81,0x94,0xb8,0xd9,0xf7,0x12,\r\n\t0x24,0x18,0x16,0x1e,0x1d,0x05,0xe6,0xc5,0xa1,0x81,0x81,0x81,0x81,0x82,0x93,0x9b,\r\n\t0x99,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x94,0x9b,0x98,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xac,0xc3,0xc0,0xa7,0x89,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x83,0xa1,0xbc,0xc4,0xb2,0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x94,0xbd,0xe3,0xed,0xf2,0xfb,0x0d,0x25,0x12,0xf1,0xcf,0xab,0x85,0x81,\r\n\t0x81,0x81,0x86,0xab,0xce,0xf0,0x12,0x12,0xf5,0xe1,0xd7,0xe1,0xf9,0x1a,0x06,0xe1,\r\n\t0xba,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x21,0xf5,0xd2,0xfc,0x29,0x0e,0xe2,0xb8,0x8d,0x81,0x85,0xa0,\r\n\t0xad,0xaf,0xd7,0x04,0x1b,0xf1,0xc7,0xe5,0x0f,0x11,0xe5,0xbb,0xac,0x9c,0x81,0x81,\r\n\t0x82,0xaa,0xd1,0xf5,0x16,0x1d,0x06,0xfa,0x11,0x0e,0xfa,0x04,0xfc,0xd2,0xa8,0x81,\r\n\t0x81,0x8b,0xb5,0xdf,0x0b,0x16,0xea,0xc8,0xf2,0x1e,0x04,0xd7,0xf7,0x1a,0x09,0xe5,\r\n\t0xc1,0x9e,0x81,0x81,0x81,0x86,0xb0,0xda,0x04,0x2b,0x04,0xdf,0xd1,0xe9,0x11,0x1e,\r\n\t0xf3,0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x26,0xfa,0xd0,0xa5,0x81,\r\n\t0x81,0x81,0xa2,0xc8,0xed,0x11,0x1a,0xf5,0xd3,0xb2,0x91,0x81,0x81,0x81,0x81,0x9e,\r\n\t0xbf,0xe1,0x05,0x28,0x05,0xe0,0xbb,0x95,0x81,0x81,0x95,0xc0,0xea,0x09,0x1b,0x09,\r\n\t0xf0,0x16,0xfa,0xff,0x18,0x12,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0x94,\r\n\t0xb3,0xc5,0xc5,0xc5,0xba,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x83,0xaa,0xd1,0xf7,0x1f,0x06,0xdf,0xb8,0x91,0x81,0x81,\r\n\t0x81,0x94,0xba,0xdf,0x04,0x25,0x0f,0xf6,0xed,0xf5,0x0b,0x29,0x0c,0xe8,0xc2,0x9c,\r\n\t0x81,0x81,0x90,0xb9,0xdf,0xf5,0x0a,0x1d,0x1e,0x0f,0x30,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x92,0xbd,0xe7,0x0b,0x1d,0x05,0xf5,0xef,0xf7,0x10,0x2b,0x09,0xe2,\r\n\t0xbb,0x93,0x81,0x81,0x83,0xad,0xd7,0x04,0xfa,0xf2,0xed,0xef,0xfa,0x12,0x26,0xff,\r\n\t0xda,0xb2,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xc1,0xe5,0x09,0x20,0x07,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf7,0xf7,0xf7,0xf7,\r\n\t0xf7,0xf7,0xf7,0xd6,0xad,0x82,0x81,0x81,0x82,0xa8,0xcb,0xec,0x0b,0x25,0x11,0xff,\r\n\t0xf7,0xf5,0xf5,0xf3,0xce,0xa4,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0x0b,0x20,0xfa,0xd0,0xa5,0x81,0x81,0xa6,0xce,0xf5,0x1a,0x14,0xf9,\r\n\t0xed,0xea,0xf2,0x07,0x27,0x0b,0xe4,0xbb,0x92,0x81,0x81,0xa8,0xce,0xf3,0x15,0x1a,\r\n\t0xfc,0xee,0xeb,0xf6,0x0f,0x22,0xff,0xda,0xb4,0x8d,0x81,0x81,0x89,0xa6,0xbb,0xc5,\r\n\t0xc3,0xb3,0x9b,0x81,0x81,0x81,0x81,0x81,0x8c,0xa9,0xbd,0xc5,0xc1,0xb1,0x98,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xb2,0xcd,0xe8,0xe3,0xc5,0xa7,0x87,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9f,0xbf,0xdd,0xed,0xd2,0xb7,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0xa7,0xbe,0xc2,0xc8,0xd4,0xea,0x07,0x2b,0x09,0xe3,0xbc,0x94,0x81,\r\n\t0x81,0x81,0x99,0xbf,0xe5,0x09,0x18,0xf5,0xd5,0xbb,0xad,0xbd,0xdf,0x05,0x19,0xf1,\r\n\t0xc9,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x21,0xf5,0xd2,0xfc,0x29,0x0e,0xe2,0xb8,0x8d,0x81,0x9c,0xc1,\r\n\t0xd7,0xd7,0xdd,0x07,0x19,0xed,0xd7,0xe9,0x13,0x0b,0xe1,0xd7,0xd5,0xba,0x95,0x81,\r\n\t0x8d,0xb6,0xdf,0x09,0x29,0xff,0xe1,0xed,0x16,0x09,0xdd,0xd9,0xdf,0xc8,0xa2,0x81,\r\n\t0x81,0x8a,0xb5,0xde,0x09,0x19,0xef,0xd1,0xf7,0x21,0xff,0xeb,0x0f,0x14,0xf1,0xcd,\r\n\t0xaa,0x86,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x29,0xfc,0xd2,0xba,0xe4,0x0e,0x1f,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x26,0xfa,0xd0,0xa5,0x81,\r\n\t0x81,0x8e,0xb4,0xdb,0xff,0x27,0x05,0xe0,0xbc,0x99,0x81,0x81,0x81,0x81,0x81,0x84,\r\n\t0xa7,0xca,0xee,0x13,0x1a,0xf4,0xce,0xa7,0x81,0x81,0x8d,0xb2,0xcf,0xe2,0xf5,0x09,\r\n\t0x12,0x18,0x0c,0x12,0xff,0xec,0xd9,0xc3,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,\r\n\t0xcd,0xee,0xef,0xef,0xd6,0xae,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x94,0xba,0xe1,0x09,0x1d,0xf5,0xce,0xa8,0x81,0x81,0x81,\r\n\t0x81,0xa3,0xcb,0xf2,0x19,0x15,0xf1,0xd2,0xc3,0xcf,0xed,0x11,0x21,0xfa,0xd2,0xaa,\r\n\t0x82,0x81,0x92,0xbb,0xe4,0x0b,0x21,0x0d,0xf9,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x88,0xad,0xce,0xee,0xfc,0xe1,0xcd,0xc5,0xd4,0xf5,0x1d,0x19,0xef,\r\n\t0xc6,0x9d,0x81,0x81,0x81,0xa6,0xca,0xdd,0xd2,0xc8,0xc3,0xc5,0xd6,0xfb,0x24,0x0e,\r\n\t0xe4,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x91,0xb4,0xd8,0xfb,0x1f,0x09,0x06,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,0xcd,0xcd,0xcd,\r\n\t0xcd,0xcd,0xcd,0xbf,0x9e,0x81,0x81,0x81,0x95,0xbb,0xe1,0x06,0x25,0x05,0xec,0xd9,\r\n\t0xcf,0xca,0xca,0xca,0xb7,0x96,0x81,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xf6,0x1d,0x0f,0xe8,0xc1,0x9b,0x81,0x85,0xaf,0xd9,0x04,0x29,0xff,0xd8,\r\n\t0xc3,0xc1,0xcb,0xee,0x18,0x16,0xed,0xc2,0x98,0x81,0x8d,0xb6,0xde,0x06,0x28,0xff,\r\n\t0xde,0xc5,0xc2,0xd3,0xf5,0x1b,0x12,0xeb,0xc3,0x9a,0x81,0x81,0xa5,0xc5,0xe0,0xef,\r\n\t0xec,0xd7,0xb9,0x97,0x81,0x81,0x81,0x85,0xa9,0xc8,0xe3,0xef,0xe9,0xd4,0xb5,0x93,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xb7,0xd2,0xee,0x09,0xff,0xe3,0xc1,0x99,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8f,0xb8,0xdb,0xfb,0x0f,0xf3,0xd7,0xbd,0xa1,0x86,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x86,0x96,0x98,0x9f,0xaf,0xcc,0xf1,0x19,0x19,0xef,0xc7,0x9d,0x81,\r\n\t0x81,0x84,0xab,0xd2,0xf7,0x1e,0xff,0xde,0xba,0xbf,0xc0,0xb8,0xcd,0xf5,0x1e,0xfc,\r\n\t0xd4,0xab,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x95,0xc0,0xea,0x0e,0x0e,0xf5,0xd2,0xfc,0x0e,0x0e,0xe2,0xb8,0x8d,0x81,0xa5,0xd0,\r\n\t0xfa,0x04,0x04,0x0c,0x14,0x04,0x04,0x04,0x19,0x0a,0x04,0x04,0xf2,0xc8,0x9d,0x81,\r\n\t0x90,0xba,0xe5,0x11,0x23,0xf7,0xce,0xf2,0x1c,0x04,0xd7,0xb0,0xb5,0xa8,0x8c,0x81,\r\n\t0x81,0x84,0xad,0xd5,0xfc,0x22,0x05,0xf7,0x0d,0x18,0xf1,0xff,0x21,0xfc,0xda,0xb6,\r\n\t0x93,0x81,0x81,0x81,0x81,0x86,0xb0,0xda,0x04,0x2c,0x06,0xe0,0xd6,0xf5,0x19,0x13,\r\n\t0xec,0xc4,0x9b,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x0e,0x0e,0xfa,0xd0,0xa5,0x81,\r\n\t0x81,0x9c,0xc4,0xec,0x13,0x19,0xf1,0xcc,0xa6,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x90,0xb5,0xda,0xff,0x28,0x06,0xde,0xb6,0x8f,0x81,0x81,0xa3,0xbb,0xce,0xe1,0xf3,\r\n\t0x06,0x27,0x12,0xfb,0xe8,0xd6,0xc4,0xaf,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x1b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa4,0xcb,0xf1,0x19,0x0c,0xe5,0xbe,0x98,0x81,0x81,0x81,\r\n\t0x86,0xaf,0xd8,0xff,0x29,0x04,0xdc,0xb7,0xa9,0xc3,0xdc,0xff,0x29,0x09,0xdf,0xb6,\r\n\t0x8d,0x81,0x86,0xad,0xd3,0xfa,0xfb,0xe7,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x93,0xb3,0xd3,0xda,0xc1,0xa7,0x9c,0xc0,0xea,0x13,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x8e,0xa8,0xb2,0xa9,0x9f,0x99,0xa1,0xca,0xf5,0x21,0x11,\r\n\t0xe5,0xba,0x90,0x81,0x81,0x81,0x81,0x83,0xa7,0xcb,0xee,0x12,0x15,0xf1,0x06,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,0xca,0xa5,0xa3,\r\n\t0xa3,0xa3,0xa3,0x9a,0x83,0x81,0x81,0x81,0xa4,0xcd,0xf4,0x1a,0x0f,0xea,0xca,0xb2,\r\n\t0xad,0xa8,0xa0,0xa0,0x94,0x81,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xbe,0xe3,0x0a,0x22,0xfb,0xd5,0xaf,0x8a,0x81,0x85,0xb0,0xda,0x06,0x29,0xff,0xd8,\r\n\t0xb8,0xa9,0xc6,0xed,0x16,0x16,0xec,0xc2,0x98,0x81,0x95,0xbf,0xe7,0x12,0x1d,0xf3,\r\n\t0xca,0xa3,0x98,0xbd,0xe6,0x0e,0x1f,0xf6,0xcd,0xa4,0x81,0x90,0xb8,0xdf,0xff,0x19,\r\n\t0x12,0xf5,0xd1,0xa9,0x81,0x81,0x81,0x95,0xbd,0xe3,0x05,0x19,0x0f,0xf1,0xcc,0xa4,\r\n\t0x81,0x81,0x81,0x81,0x81,0x86,0xa1,0xbd,0xd7,0xf3,0x0f,0x23,0x09,0xee,0xc6,0x9d,\r\n\t0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa6,0x94,\r\n\t0x81,0x81,0x92,0xbc,0xe5,0x04,0x1e,0x13,0xf7,0xdd,0xc2,0xa7,0x8c,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x82,0x95,0x9b,0x9b,0xbe,0xe7,0x13,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x92,0xba,0xe1,0x0a,0x15,0xef,0xc8,0xdc,0xe9,0xea,0xe0,0xe9,0xeb,0x15,0x06,\r\n\t0xdd,0xb2,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x91,0xb9,0xdb,0xe2,0xe2,0xe0,0xc9,0xe2,0xe2,0xe2,0xd5,0xb2,0x89,0x81,0xa5,0xd0,\r\n\t0xfa,0x13,0x13,0x1c,0x18,0x13,0x13,0x13,0x24,0x13,0x13,0x13,0xf2,0xc8,0x9d,0x81,\r\n\t0x8f,0xb8,0xe2,0x0b,0x2b,0x05,0xe7,0xf7,0x22,0xfc,0xd2,0xa9,0x8b,0x82,0x81,0x81,\r\n\t0x81,0x81,0x9e,0xc4,0xe7,0x05,0x19,0x1e,0x13,0xfb,0xf5,0x19,0x0a,0xe6,0xc2,0x9f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa6,0xce,0xf5,0x1b,0x1a,0xf7,0xf9,0x12,0x1c,0xfc,\r\n\t0xda,0xb4,0x9a,0x8e,0x81,0x81,0x81,0x91,0xb9,0xdb,0xe2,0xe2,0xe1,0xc7,0xa0,0x81,\r\n\t0x81,0xa9,0xd2,0xfa,0x22,0x0a,0xe1,0xba,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa2,0xca,0xf1,0x19,0x14,0xec,0xc3,0x9b,0x81,0x90,0xb9,0xdf,0xf4,0x07,0x19,\r\n\t0x04,0x16,0xfc,0x10,0x0f,0xfc,0xe9,0xcb,0xa2,0x81,0x81,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8d,0xb4,0xdb,0x04,0x23,0xfc,0xd5,0xae,0x87,0x81,0x81,0x81,\r\n\t0x8e,0xb7,0xe1,0x0b,0x21,0xf7,0xcf,0xb2,0xcc,0xe4,0xfc,0x17,0x33,0x11,0xe7,0xbe,\r\n\t0x94,0x81,0x81,0x9c,0xc2,0xdd,0xd6,0xc2,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x98,0xae,0xb1,0xa0,0x85,0x96,0xc0,0xea,0x13,0x1e,0xf4,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x83,0xa3,0xb8,0xba,0xba,0xc0,0xd9,0xfc,0x26,0x06,\r\n\t0xde,0xb5,0x8c,0x81,0x81,0x81,0x81,0x9a,0xbe,0xe1,0x05,0x22,0xfc,0xdb,0x06,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,0xd0,0xcf,0xca,\r\n\t0xc2,0xb5,0xa2,0x8b,0x81,0x81,0x81,0x86,0xb0,0xd9,0xff,0x26,0xfc,0xd6,0xd4,0xd7,\r\n\t0xd7,0xd2,0xc5,0xb3,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xaa,\r\n\t0xd1,0xf6,0x1d,0x0f,0xe9,0xc4,0x9d,0x81,0x81,0x81,0xaa,0xd3,0xfb,0x22,0x12,0xf3,\r\n\t0xdb,0xcc,0xe3,0xff,0x25,0x0a,0xe2,0xba,0x91,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,\r\n\t0xc5,0x9c,0x8b,0xb3,0xdd,0x07,0x29,0xfc,0xd4,0xaa,0x81,0x95,0xc0,0xea,0x15,0x3d,\r\n\t0x2e,0x06,0xda,0xb0,0x85,0x81,0x81,0x9b,0xc5,0xef,0x1a,0x41,0x29,0xff,0xd5,0xab,\r\n\t0x81,0x81,0x81,0x81,0x8c,0xa7,0xc2,0xdd,0xf7,0x14,0x1d,0x04,0xe8,0xcd,0xb2,0x8f,\r\n\t0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xce,0xb3,\r\n\t0x8e,0x81,0x86,0xaa,0xc8,0xe3,0xfc,0x19,0x18,0xfc,0xe3,0xc7,0xac,0x91,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa0,0xbc,0xc5,0xc5,0xcc,0xed,0x16,0x1c,0xf2,0xc8,0x9e,0x81,\r\n\t0x81,0x9f,0xc7,0xef,0x18,0x07,0xdf,0xe6,0xff,0x13,0x13,0x09,0x11,0xe6,0x11,0x0b,\r\n\t0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x81,0x9f,0xb4,0xb8,0xb8,0xb7,0xaa,0xb8,0xb8,0xb8,0xb2,0x9a,0x81,0x81,0xa2,0xc9,\r\n\t0xe7,0xe7,0xea,0x13,0x0b,0xe7,0xe7,0xf5,0x21,0xfc,0xe7,0xe7,0xe3,0xc2,0x9a,0x81,\r\n\t0x85,0xae,0xd4,0xf9,0x1a,0x23,0x0b,0xfc,0x21,0xf7,0xcd,0xb9,0xa5,0x8d,0x81,0x81,\r\n\t0x81,0x81,0x8a,0xac,0xca,0xe1,0xef,0xf2,0xec,0xe8,0x0d,0x16,0xf3,0xcf,0xac,0x89,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xbc,0xe1,0x05,0x26,0x13,0x1d,0x12,0xfb,0xdf,\r\n\t0xc5,0xc5,0xc4,0xb2,0x91,0x81,0x81,0x81,0x9f,0xb4,0xb8,0xb8,0xb7,0xa9,0x8c,0x81,\r\n\t0x8a,0xb3,0xdc,0x06,0x26,0xfc,0xd4,0xac,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x94,0xbc,0xe5,0x0e,0x20,0xf7,0xcd,0xa4,0x81,0x92,0xbb,0xe3,0x09,0x0f,0xf7,\r\n\t0xea,0x16,0xfc,0xee,0x06,0x18,0xf3,0xcd,0xa4,0x81,0x81,0x91,0xa2,0xa5,0xa5,0xa5,\r\n\t0xd0,0xfa,0x26,0x06,0xda,0xb0,0xa5,0xa5,0xa4,0x96,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xa8,0xab,0xab,0xab,0xab,0xab,\r\n\t0xab,0xab,0xa8,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9e,0xc5,0xec,0x13,0x13,0xec,0xc5,0x9e,0x81,0x81,0x81,0x81,\r\n\t0x93,0xbd,0xe7,0x11,0x1b,0xf1,0xc7,0xd4,0xee,0x07,0x20,0x13,0x18,0x18,0xed,0xc2,\r\n\t0x98,0x81,0x81,0x86,0xa4,0xb4,0xb0,0xad,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x87,0x81,0x89,0xaa,0xce,0xf4,0x1c,0x14,0xec,\r\n\t0xc3,0x99,0x81,0x81,0x81,0x81,0x94,0xbc,0xde,0xe5,0xe5,0xe9,0xf9,0x14,0x12,0xf1,\r\n\t0xce,0xa8,0x81,0x81,0x81,0x81,0x8e,0xb1,0xd5,0xf9,0x1c,0x0b,0xe7,0xda,0x06,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xfa,0xfa,0xf9,0xf5,\r\n\t0xeb,0xdb,0xc6,0xac,0x8e,0x81,0x81,0x8e,0xb8,0xe2,0x0b,0x1e,0xf5,0xf4,0xfc,0x04,\r\n\t0x04,0xfa,0xec,0xd6,0xb9,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xbc,\r\n\t0xe2,0x09,0x24,0xfc,0xd7,0xb1,0x8b,0x81,0x81,0x81,0x9d,0xc4,0xe8,0x09,0x25,0x15,\r\n\t0xff,0xf1,0x07,0x1f,0x10,0xf1,0xd0,0xab,0x84,0x81,0x93,0xbd,0xe7,0x11,0x20,0xf7,\r\n\t0xd0,0xb6,0xb5,0xbe,0xd8,0x04,0x2c,0x04,0xd7,0xad,0x83,0x93,0xbc,0xe5,0x0b,0x25,\r\n\t0x1d,0xfc,0xd6,0xad,0x83,0x81,0x81,0x98,0xc1,0xe9,0x0f,0x27,0x1a,0xf7,0xd1,0xa8,\r\n\t0x81,0x81,0x81,0x91,0xac,0xc7,0xe3,0xfc,0x18,0x18,0xfc,0xe3,0xc8,0xac,0x92,0x81,\r\n\t0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xec,0xc2,\r\n\t0x98,0x81,0x81,0x8c,0xa7,0xc2,0xdd,0xf7,0x14,0x1d,0x04,0xe7,0xcc,0xb1,0x96,0x81,\r\n\t0x81,0x81,0x81,0x8a,0xb3,0xdb,0xef,0xef,0xf4,0x07,0x26,0x0f,0xe7,0xbf,0x97,0x81,\r\n\t0x81,0xa9,0xd2,0xfa,0x23,0xfa,0xde,0xff,0x21,0x05,0x04,0x20,0x09,0xe2,0x0b,0x0f,\r\n\t0xe5,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x81,0x81,0x8b,0x8d,0x8d,0x8d,0x84,0x8d,0x8d,0x8d,0x89,0x81,0x81,0x81,0x8f,0xad,\r\n\t0xbd,0xc4,0xed,0x19,0x06,0xdd,0xd0,0xfa,0x24,0xfa,0xd0,0xbd,0xbb,0xa8,0x89,0x81,\r\n\t0x81,0x9b,0xbe,0xdd,0xfa,0x12,0x24,0x23,0x1f,0xff,0xf1,0xde,0xc8,0xae,0x90,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xa8,0xbb,0xc6,0xc8,0xdc,0xff,0x22,0xff,0xdb,0xbd,0xba,0xaf,\r\n\t0x9c,0x83,0x81,0x81,0x81,0x8b,0xae,0xcc,0xe9,0x04,0x1f,0x32,0x0e,0xee,0xd9,0xdb,\r\n\t0xef,0xef,0xed,0xca,0xa1,0x81,0x81,0x81,0x81,0x8b,0x8d,0x8d,0x8d,0x83,0x81,0x81,\r\n\t0x90,0xba,0xe4,0x0e,0x1e,0xf5,0xcc,0xa2,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x89,0xb2,0xdc,0x06,0x29,0xff,0xd5,0xab,0x81,0x85,0xaa,0xcf,0xf4,0xec,0xd4,\r\n\t0xea,0x16,0xfc,0xd2,0xe3,0xfb,0xde,0xb9,0x94,0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,\r\n\t0xd0,0xfa,0x26,0x06,0xda,0xd0,0xd0,0xd0,0xce,0xb7,0x94,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xb2,0xcf,0xd5,0xd5,0xd5,0xd5,0xd5,\r\n\t0xd5,0xd5,0xcf,0xb2,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x87,0xae,0xd5,0xfc,0x23,0x04,0xdb,0xb4,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x19,0xed,0xdd,0xf6,0x0f,0x23,0x0b,0xf1,0x13,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x8a,0x88,0xad,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc5,0xe6,0x09,0x26,0x04,0xdc,\r\n\t0xb5,0x8e,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x11,0x11,0x13,0x1f,0x07,0xf1,0xd5,\r\n\t0xbb,0x9d,0x81,0x81,0x81,0x81,0xa4,0xc8,0xec,0x0f,0x17,0xf3,0xd0,0xda,0x06,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x26,0x26,0x26,0x23,0x1e,\r\n\t0x13,0xff,0xe8,0xc9,0xa7,0x83,0x81,0x93,0xbd,0xe7,0x11,0x1c,0x0c,0x1d,0x1b,0x19,\r\n\t0x1c,0x23,0x11,0xf5,0xd6,0xb3,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xaa,0xcf,\r\n\t0xf5,0x1b,0x12,0xeb,0xc5,0x9f,0x81,0x81,0x81,0x81,0x8a,0xad,0xcc,0xea,0x04,0x18,\r\n\t0x26,0x19,0x24,0x07,0xf0,0xd4,0xb6,0x95,0x81,0x81,0x8b,0xb4,0xdc,0x04,0x29,0x0b,\r\n\t0xee,0xdf,0xdf,0xe7,0xf5,0x0a,0x2e,0x04,0xd7,0xad,0x83,0x86,0xac,0xd0,0xec,0xfc,\r\n\t0xf7,0xe1,0xc2,0x9e,0x81,0x81,0x81,0x8b,0xb1,0xd4,0xef,0xfc,0xf6,0xdd,0xbe,0x99,\r\n\t0x81,0x81,0x96,0xb1,0xcc,0xe8,0x04,0x1d,0x12,0xf7,0xdd,0xc2,0xa7,0x8c,0x81,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x19,0xed,0xc2,\r\n\t0x98,0x81,0x81,0x81,0x87,0xa1,0xbd,0xd7,0xf3,0x0f,0x23,0x09,0xec,0xd2,0xb7,0x9b,\r\n\t0x81,0x81,0x81,0x8b,0xb5,0xdf,0x0b,0x1b,0x1e,0x20,0x0f,0xf5,0xd4,0xaf,0x89,0x81,\r\n\t0x87,0xb1,0xda,0x04,0x19,0xf1,0xef,0x16,0x0c,0xe6,0xf5,0x1f,0x04,0xdf,0x0b,0x11,\r\n\t0xe5,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xa3,0xb9,\r\n\t0xbd,0xc8,0xf2,0x1c,0x04,0xd7,0xd4,0xfc,0x21,0xf5,0xcc,0xbd,0xb2,0x95,0x81,0x81,\r\n\t0x81,0x83,0xa1,0xbf,0xd8,0xec,0xfc,0x10,0x2a,0x28,0x17,0x04,0xea,0xcc,0xac,0x89,\r\n\t0x81,0x81,0x81,0x81,0x82,0x93,0xac,0xd0,0xf3,0x17,0x0b,0xe8,0xe3,0xe7,0xe4,0xd5,\r\n\t0xbf,0xa1,0x81,0x81,0x81,0xa1,0xc6,0xe8,0x09,0x25,0x0b,0x12,0x25,0x04,0xe3,0xdf,\r\n\t0x0b,0x1b,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xbf,0xe7,0x13,0x1a,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x82,0xab,0xd5,0xff,0x2b,0x04,0xda,0xb0,0x85,0x81,0x96,0xb9,0xd1,0xc9,0xc0,\r\n\t0xea,0x16,0xfc,0xd2,0xc0,0xd2,0xc4,0xa4,0x81,0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xfa,\r\n\t0xfa,0xfa,0x26,0x06,0xfa,0xfa,0xfa,0xfa,0xf3,0xca,0xa0,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0xff,0xff,0xff,0xff,0xff,\r\n\t0xff,0xff,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xbe,0xe6,0x0c,0x19,0xf1,0xcb,0xa4,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x19,0xed,0xff,0x18,0x1a,0xff,0xe8,0xe7,0x13,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa3,0xc3,0xe1,0xff,0x21,0x0f,0xec,0xc8,\r\n\t0xa4,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x0e,0x0e,0x0f,0x16,0x1e,0x0f,0xf7,\r\n\t0xd9,0xb8,0x94,0x81,0x81,0x97,0xbb,0xdf,0x04,0x23,0xff,0xdc,0xb9,0xda,0x06,0x29,\r\n\t0xfc,0xd2,0xa8,0x9e,0x8e,0x81,0x81,0x88,0xb2,0xdc,0xfa,0xfa,0xfa,0xfa,0xfc,0x09,\r\n\t0x1a,0x23,0x05,0xe1,0xbc,0x95,0x81,0x95,0xc0,0xea,0x16,0x25,0x0f,0xfc,0xf2,0xed,\r\n\t0xf3,0x06,0x23,0x11,0xec,0xc6,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xbc,0xe2,\r\n\t0x09,0x25,0xff,0xd9,0xb3,0x8c,0x81,0x81,0x81,0x81,0x91,0xb2,0xd0,0xec,0x05,0x1a,\r\n\t0x19,0x17,0x2a,0x14,0xfc,0xe3,0xc4,0xa2,0x81,0x81,0x81,0xa5,0xcb,0xee,0x0f,0x28,\r\n\t0x14,0x09,0x09,0x0f,0x1d,0x16,0x2b,0xff,0xd7,0xad,0x83,0x81,0x94,0xb1,0xc7,0xd2,\r\n\t0xcf,0xc0,0xa5,0x87,0x81,0x81,0x81,0x81,0x98,0xb4,0xc9,0xd2,0xce,0xbd,0xa1,0x83,\r\n\t0x81,0x8b,0xb2,0xd2,0xec,0x09,0x23,0x0d,0xf1,0xd7,0xbc,0xa1,0x86,0x81,0x81,0x81,\r\n\t0x81,0x95,0xbf,0xe7,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xe9,0xc1,\r\n\t0x97,0x81,0x81,0x81,0x81,0x81,0x9c,0xb7,0xd2,0xed,0x09,0x23,0x0d,0xf1,0xd7,0xb8,\r\n\t0x93,0x81,0x81,0x8b,0xb5,0xdf,0x0b,0x1b,0xfc,0xf7,0xeb,0xd5,0xb9,0x99,0x81,0x81,\r\n\t0x8d,0xb8,0xe2,0x0b,0x13,0xe8,0xfc,0x24,0xfc,0xd5,0xfb,0x26,0xfc,0xdf,0x0b,0x11,\r\n\t0xe5,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbb,0xdf,\r\n\t0xe7,0xe7,0xf6,0x21,0xfc,0xe7,0xe7,0x04,0x1c,0xf2,0xe7,0xe7,0xd0,0xa9,0x81,0x81,\r\n\t0x81,0x81,0x83,0x9d,0xb3,0xc6,0xe4,0x0e,0x0f,0x06,0x19,0x25,0x09,0xe7,0xc2,0x9b,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa0,0xc4,0xe7,0x0b,0x18,0xf4,0xf7,0x0b,0x13,0x0d,0xf9,\r\n\t0xdd,0xba,0x95,0x81,0x89,0xb2,0xd9,0xff,0x24,0x0b,0xea,0xf7,0x1a,0x1e,0xfc,0xe5,\r\n\t0x0e,0x1e,0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x99,0xa7,0xa3,0xbf,\r\n\t0xe7,0xf5,0xf4,0xd1,0xa7,0xa8,0xa0,0x89,0x81,0x81,0x95,0xc0,0xea,0x16,0x26,0x26,\r\n\t0x26,0x26,0x36,0x26,0x26,0x26,0x26,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8e,0x93,0x90,0x82,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x29,0x29,0x29,0x29,\r\n\t0x29,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x85,0x8d,0x8d,0x84,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa8,0xcf,0xf5,0x1d,0x09,0xe1,0xba,0x93,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xbf,0xe8,0x13,0x19,0x09,0x21,0x12,0xf9,0xdf,0xc6,0xea,0x16,0x19,0xed,0xc3,\r\n\t0x9a,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc3,0xdf,0xff,0x1d,0x12,0xf3,0xd3,0xb1,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x94,0xbb,0xdc,0xe2,0xe2,0xe5,0xee,0xff,0x1c,0x16,\r\n\t0xf1,0xcd,0xa5,0x81,0x8a,0xae,0xd2,0xf5,0x19,0x0d,0xe9,0xca,0xca,0xda,0x06,0x29,\r\n\t0xfc,0xd2,0xca,0xc7,0xae,0x8b,0x81,0x81,0xa4,0xc4,0xd0,0xd0,0xd0,0xd0,0xd5,0xe1,\r\n\t0xf9,0x1d,0x1a,0xf2,0xc9,0xa0,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xd6,0xc9,0xc2,\r\n\t0xcc,0xe8,0x0f,0x24,0xfa,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x84,0xaa,0xcf,0xf5,\r\n\t0x1b,0x13,0xed,0xc7,0xa0,0x81,0x81,0x81,0x81,0x81,0xa6,0xcb,0xee,0x0d,0x25,0x0b,\r\n\t0xf3,0xf1,0x05,0x1d,0x1d,0xff,0xdd,0xb8,0x92,0x81,0x81,0x91,0xb3,0xd2,0xee,0x04,\r\n\t0x0e,0x13,0x11,0x0a,0xfc,0x06,0x26,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x8e,0x9f,0xa8,\r\n\t0xa6,0x9a,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xa1,0xa8,0xa5,0x98,0x82,0x81,\r\n\t0x81,0x93,0xbd,0xe7,0x0c,0x27,0x0e,0xee,0xd4,0xb9,0x9d,0x83,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8a,0xae,0xc8,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xc9,0xb0,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xb2,0xcd,0xe8,0x06,0x2c,0x11,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x8b,0xb5,0xdf,0x0b,0x1b,0xef,0xcd,0xc3,0xb2,0x99,0x81,0x81,0x81,\r\n\t0x92,0xbd,0xe7,0x11,0x0e,0xe2,0x06,0x1e,0xf5,0xd7,0x04,0x20,0xf5,0xe2,0x0e,0x0e,\r\n\t0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x23,0x06,0xda,0xb0,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x13,0x13,0x13,0x28,0x13,0x13,0x13,0x14,0x22,0x13,0x13,0x04,0xd7,0xad,0x83,0x81,\r\n\t0x81,0x81,0x83,0x84,0x96,0xc0,0xea,0x13,0x0b,0xdf,0xf5,0x16,0x20,0xf9,0xd1,0xa7,\r\n\t0x81,0x81,0x81,0x81,0x94,0xb7,0xdb,0xfc,0x22,0xff,0xf3,0x16,0x10,0x04,0x11,0x18,\r\n\t0xf4,0xcd,0xa5,0x81,0x92,0xbc,0xe6,0x0f,0x1f,0xf7,0xd1,0xde,0xff,0x20,0x18,0xf6,\r\n\t0x15,0x16,0xed,0xc4,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x14,0x19,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xaa,0xd5,0xfc,0x29,0x04,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x88,0xac,\r\n\t0xc6,0xca,0xca,0xb9,0x99,0x81,0x81,0x81,0x81,0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xfa,\r\n\t0xfa,0xfa,0x26,0x06,0xfa,0xfa,0xfa,0xfa,0xf3,0xca,0xa0,0x81,0x81,0x81,0x81,0x89,\r\n\t0xa4,0xb7,0xbd,0xb9,0xa8,0x90,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xea,0xc0,0x95,0x81,0x81,0x99,0xad,0xb8,0xb7,0xab,0x96,0x81,0x81,0x81,\r\n\t0x81,0x81,0x91,0xb8,0xdf,0x06,0x1f,0xf7,0xd1,0xaa,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x91,0xba,0xe5,0x0f,0x33,0x22,0x09,0xf0,0xd7,0xbd,0xc6,0xef,0x19,0x13,0xe9,0xbf,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc3,0xe1,0xff,0x1c,0x14,0xf5,0xd6,0xb8,0x97,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb5,0xb8,0xb8,0xbb,0xc6,0xe1,0x06,0x2b,\r\n\t0x04,0xd8,0xaf,0x85,0x95,0xbf,0xe8,0x0d,0x1a,0xf5,0xf5,0xf5,0xf5,0xf5,0x06,0x29,\r\n\t0xfc,0xf5,0xf5,0xe9,0xc1,0x97,0x81,0x81,0x88,0x9e,0xa5,0xa5,0xa5,0xa5,0xab,0xbf,\r\n\t0xe6,0x0f,0x24,0xfa,0xd0,0xa5,0x81,0x95,0xbf,0xe8,0x13,0x1e,0xf2,0xc8,0xa0,0x98,\r\n\t0xb1,0xda,0x05,0x2c,0x04,0xd7,0xad,0x83,0x81,0x81,0x81,0x81,0x97,0xbc,0xe2,0x09,\r\n\t0x27,0xff,0xda,0xb4,0x8e,0x81,0x81,0x81,0x81,0x8d,0xb6,0xde,0x05,0x29,0x09,0xe8,\r\n\t0xcf,0xcb,0xe3,0xff,0x20,0x17,0xef,0xc8,0x9f,0x81,0x81,0x81,0x96,0xb3,0xc9,0xdb,\r\n\t0xe5,0xe7,0xe7,0xe1,0xe2,0x0b,0x1e,0xf5,0xcc,0xa2,0x81,0x81,0x81,0x90,0xa2,0xab,\r\n\t0xa9,0x9b,0x87,0x81,0x81,0x81,0x81,0x81,0x89,0xa4,0xb7,0xbd,0xb8,0xa8,0x90,0x81,\r\n\t0x81,0x8a,0xb0,0xd0,0xeb,0x07,0x21,0x0f,0xf3,0xd9,0xbe,0xa3,0x88,0x81,0x81,0x81,\r\n\t0x81,0x95,0xbf,0xe8,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xeb,0xc2,\r\n\t0x98,0x81,0x81,0x81,0x81,0x82,0x9d,0xb8,0xd3,0xee,0x09,0x23,0x0c,0xf0,0xd5,0xb7,\r\n\t0x92,0x81,0x81,0x8b,0xb5,0xdf,0x0b,0x1b,0xef,0xc5,0x9b,0x8c,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x13,0x0a,0xdf,0x0b,0x19,0xef,0xde,0x09,0x19,0xef,0xe7,0x11,0x09,\r\n\t0xdf,0xb5,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xaa,0xd4,0xf7,0xf7,0xf7,0xd9,0xaf,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x04,0x04,0x04,0x21,0x04,0x04,0x04,0x0c,0x14,0x04,0x04,0x04,0xd7,0xad,0x83,0x81,\r\n\t0x81,0x99,0xad,0xad,0xa1,0xc5,0xef,0x19,0x05,0xda,0xdf,0x09,0x2b,0xff,0xd5,0xab,\r\n\t0x81,0x81,0x81,0x87,0xab,0xce,0xf1,0x15,0x0d,0xe9,0x04,0x1e,0xf5,0xd8,0xf7,0x1f,\r\n\t0xff,0xd7,0xad,0x84,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0xc3,0xe4,0x06,0x27,0x12,\r\n\t0x21,0x0b,0xe2,0xba,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x92,0xbc,0xe6,0x11,0x1e,0xf4,0xca,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0xaf,0xd9,0x04,0x29,0xff,0xd5,0xab,0x82,0x81,0x81,0x81,0x81,0x81,0x8c,\r\n\t0x9d,0xa0,0xa0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,\r\n\t0xd0,0xfa,0x26,0x06,0xda,0xd0,0xd0,0xd0,0xce,0xb7,0x94,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xc5,0xdf,0xe7,0xe1,0xcc,0xae,0x8c,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xcd,0xb1,0x8c,0x81,0x9b,0xb9,0xd3,0xe2,0xe0,0xd1,0xb6,0x97,0x81,0x81,\r\n\t0x81,0x81,0xa1,0xc8,0xef,0x17,0x0f,0xe7,0xc1,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xb5,0xde,0x07,0x2b,0xff,0xe7,0xce,0xb5,0xab,0xd2,0xfa,0x23,0x0b,0xe1,0xb8,\r\n\t0x8e,0x81,0x81,0x81,0x8d,0x95,0x95,0xad,0xd7,0x04,0x2e,0x09,0xdd,0xb2,0x95,0x94,\r\n\t0x86,0x81,0x81,0x81,0x87,0xa5,0xc3,0xe1,0xff,0x1d,0x14,0xf5,0xd7,0xb9,0x9b,0x98,\r\n\t0x96,0x87,0x81,0x81,0x81,0x81,0x90,0x92,0x8d,0x8d,0x8d,0x91,0xac,0xd5,0xff,0x2b,\r\n\t0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x16,0x29,0x21,0x21,0x21,0x21,0x21,0x21,0x34,\r\n\t0x21,0x21,0x19,0xed,0xc2,0x98,0x81,0x81,0x83,0x93,0x94,0x8d,0x89,0x8a,0x96,0xbb,\r\n\t0xe4,0x0e,0x23,0xfa,0xd0,0xa5,0x81,0x90,0xba,0xe4,0x0e,0x21,0xf7,0xcf,0xa6,0x87,\r\n\t0xb0,0xda,0x04,0x2c,0x04,0xd7,0xad,0x83,0x81,0x81,0x81,0x84,0xaa,0xcf,0xf5,0x1b,\r\n\t0x14,0xee,0xc8,0xa2,0x81,0x81,0x81,0x81,0x81,0x95,0xbf,0xe8,0x13,0x1f,0xf5,0xce,\r\n\t0xad,0xa7,0xc3,0xe7,0x11,0x23,0xfa,0xd0,0xa5,0x81,0x81,0x81,0x81,0x90,0xa4,0xb2,\r\n\t0xba,0xbd,0xbd,0xce,0xf1,0x18,0x11,0xe9,0xc1,0x98,0x81,0x81,0x94,0xb2,0xc9,0xd5,\r\n\t0xd2,0xc1,0xa7,0x88,0x81,0x81,0x81,0x81,0xa5,0xc5,0xde,0xe7,0xe1,0xcc,0xae,0x8b,\r\n\t0x81,0x81,0x94,0xb0,0xcb,0xe6,0xff,0x1c,0x14,0xf9,0xdf,0xc3,0xa8,0x8d,0x81,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x19,0xed,0xc2,\r\n\t0x98,0x81,0x81,0x81,0x88,0xa3,0xbd,0xd9,0xf3,0x0f,0x21,0x07,0xec,0xd0,0xb5,0x9a,\r\n\t0x81,0x81,0x81,0x8b,0xb5,0xdf,0xfa,0xfa,0xee,0xc5,0x9a,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x09,0xe2,0x0e,0x19,0xed,0xe5,0x0e,0x13,0xea,0xee,0x18,0xff,\r\n\t0xd7,0xaf,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa6,0xc7,0xe0,0xea,0xe2,0xca,0xaa,0x86,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb4,0xd2,\r\n\t0xd7,0xd9,0x04,0x1b,0xf2,0xd7,0xe5,0x11,0x11,0xe5,0xd7,0xd7,0xc7,0xa4,0x81,0x81,\r\n\t0x8f,0xb5,0xd4,0xd6,0xca,0xca,0xf5,0x1f,0xff,0xd5,0xe6,0x0d,0x25,0xfc,0xd2,0xa9,\r\n\t0x81,0x81,0x81,0x9e,0xc2,0xe5,0x09,0x19,0xf5,0xdd,0x09,0x19,0xed,0xc5,0xef,0x1b,\r\n\t0x06,0xda,0xb0,0x85,0x95,0xbf,0xe9,0x13,0x1f,0xf6,0xd0,0xb6,0xca,0xec,0x0d,0x2d,\r\n\t0x20,0xfb,0xd4,0xad,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8c,0xb6,0xdf,0x09,0x25,0xfc,0xd3,0xaa,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x90,0xb9,0xe1,0x0b,0x21,0xf7,0xcf,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xa2,0xa5,0xa5,0xa5,\r\n\t0xd0,0xfa,0x26,0x06,0xda,0xb0,0xa5,0xa5,0xa4,0x96,0x81,0x81,0x81,0x81,0x90,0xb9,\r\n\t0xdf,0xff,0x13,0x07,0xea,0xc6,0x9f,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa5,0x93,0x81,0x8a,0xb1,0xd6,0xf5,0x0b,0x0a,0xf1,0xd2,0xac,0x85,0x81,\r\n\t0x81,0x8b,0xb2,0xd9,0xff,0x25,0xfc,0xd7,0xb0,0x89,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x82,0xab,0xd3,0xfb,0x23,0x0e,0xe8,0xc5,0xb3,0xc3,0xe4,0x0a,0x25,0xfc,0xd6,0xad,\r\n\t0x85,0x81,0x81,0x95,0xb2,0xc0,0xc0,0xc0,0xd7,0x04,0x2e,0x09,0xdd,0xc0,0xc0,0xbd,\r\n\t0xa8,0x88,0x81,0x83,0xa5,0xc3,0xe1,0xff,0x1d,0x12,0xf3,0xd7,0xc2,0xc2,0xc2,0xc2,\r\n\t0xbf,0xa9,0x87,0x81,0x82,0xa3,0xb9,0xbc,0xb7,0xb3,0xb2,0xb7,0xc5,0xe2,0x09,0x26,\r\n\t0xfc,0xd4,0xab,0x82,0x95,0xc0,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x06,0x29,\r\n\t0xff,0xff,0xff,0xed,0xc2,0x98,0x81,0x83,0xa5,0xbc,0xbd,0xb7,0xb3,0xb4,0xbc,0xd1,\r\n\t0xf1,0x18,0x18,0xf1,0xc8,0x9f,0x81,0x89,0xb3,0xdc,0x05,0x2b,0x04,0xdc,0xba,0xb1,\r\n\t0xc1,0xe5,0x0c,0x22,0xfa,0xd1,0xa8,0x81,0x81,0x81,0x81,0x97,0xbc,0xe2,0x09,0x28,\r\n\t0x04,0xdc,0xb6,0x8f,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf5,0xcd,\r\n\t0xb6,0xb4,0xc0,0xe4,0x0e,0x23,0xfa,0xd0,0xa5,0x81,0x81,0x83,0xa3,0xb8,0xba,0xba,\r\n\t0xbd,0xc5,0xd4,0xeb,0x09,0x22,0xfc,0xd9,0xb2,0x8b,0x81,0x87,0xad,0xd0,0xee,0xff,\r\n\t0xfa,0xe3,0xc3,0x9f,0x81,0x81,0x81,0x90,0xb9,0xdf,0xff,0x13,0x07,0xe9,0xc5,0x9f,\r\n\t0x81,0x81,0x81,0x8f,0xaa,0xc5,0xe1,0xfb,0x17,0x1a,0xff,0xe4,0xc8,0xae,0x93,0x81,\r\n\t0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xec,0xc2,\r\n\t0x98,0x81,0x81,0x8d,0xa8,0xc3,0xde,0xf9,0x14,0x1c,0xff,0xe6,0xcb,0xb0,0x94,0x81,\r\n\t0x81,0x81,0x81,0x8f,0xb3,0xd2,0xe7,0xea,0xda,0xbd,0x9b,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x09,0xe2,0x0b,0x19,0xef,0xf3,0x18,0x13,0xe7,0xfa,0x1f,0xf6,\r\n\t0xce,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb9,0xe0,0x04,0x16,0x07,0xe5,0xbe,0x96,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xaa,\r\n\t0xb3,0xdd,0x09,0x19,0xed,0xc3,0xea,0x13,0x0b,0xe1,0xb7,0xad,0xa4,0x8b,0x81,0x81,\r\n\t0x95,0xc0,0xea,0xfc,0xf3,0xed,0xfa,0x23,0xfa,0xf2,0x04,0x21,0x13,0xee,0xc8,0x9f,\r\n\t0x81,0x81,0x92,0xb5,0xd9,0xfc,0x20,0x04,0xdf,0xdb,0x06,0x1c,0xf2,0xd3,0xf6,0x1f,\r\n\t0xff,0xd7,0xad,0x84,0x8e,0xb8,0xe0,0x07,0x2d,0x0b,0xee,0xdf,0xdf,0xed,0x05,0x28,\r\n\t0x24,0x04,0xe2,0xc1,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x84,0xad,0xd6,0xfc,0x26,0x09,0xe0,0xb9,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9e,0xc5,0xed,0x15,0x16,0xed,0xc5,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x15,0x3c,0x24,0xfc,0xd5,0xac,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xbf,0xe7,0x0f,0x32,0x2e,0x0b,0xe2,0xb9,0x8f,0x81,\r\n\t0x81,0x9b,0xc2,0xe9,0x11,0x14,0xee,0xc7,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9d,0xc5,0xeb,0x11,0x22,0xff,0xe8,0xdd,0xe6,0xff,0x1f,0x10,0xec,0xc6,0x9f,\r\n\t0x81,0x81,0x81,0xa8,0xcf,0xea,0xea,0xea,0xea,0x04,0x2e,0x09,0xea,0xea,0xea,0xe4,\r\n\t0xc1,0x98,0x81,0x93,0xbc,0xe1,0xff,0x1d,0x12,0xf3,0xed,0xed,0xed,0xed,0xed,0xed,\r\n\t0xe4,0xbf,0x96,0x81,0x92,0xbb,0xdf,0xe6,0xe1,0xdd,0xdd,0xe1,0xec,0xff,0x1d,0x12,\r\n\t0xed,0xc7,0xa0,0x81,0x8d,0xb2,0xcf,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xda,0x06,0x29,\r\n\t0xfc,0xd5,0xd5,0xd1,0xb5,0x8f,0x81,0x93,0xbc,0xe1,0xe7,0xe0,0xdd,0xdd,0xe4,0xf4,\r\n\t0x0d,0x25,0x04,0xe0,0xba,0x93,0x81,0x81,0xa7,0xce,0xf5,0x1b,0x16,0xf5,0xe0,0xda,\r\n\t0xe5,0xfc,0x1e,0x10,0xeb,0xc4,0x9d,0x81,0x81,0x81,0x84,0xaa,0xcf,0xf5,0x1b,0x17,\r\n\t0xef,0xc9,0xa4,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xbb,0xe4,0x0c,0x2b,0x09,0xed,\r\n\t0xdf,0xdd,0xe6,0xfb,0x1d,0x17,0xef,0xc8,0x9f,0x81,0x81,0x94,0xbc,0xde,0xe5,0xe5,\r\n\t0xe7,0xee,0xfa,0x0d,0x25,0x09,0xe7,0xc5,0xa0,0x81,0x81,0x94,0xbd,0xe5,0x0c,0x28,\r\n\t0x1f,0xfc,0xd6,0xad,0x83,0x81,0x81,0x95,0xc0,0xea,0x16,0x3c,0x24,0xfc,0xd5,0xac,\r\n\t0x82,0x81,0x81,0x81,0x8a,0xa5,0xc0,0xdb,0xf6,0x12,0x1f,0x05,0xe9,0xce,0xb2,0x8f,\r\n\t0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xcc,0xb1,\r\n\t0x8d,0x81,0x88,0xac,0xc8,0xe3,0xff,0x1a,0x18,0xfb,0xe1,0xc5,0xaa,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa0,0xc8,0xee,0x0d,0x13,0xf9,0xd4,0xad,0x84,0x81,0x81,0x81,0x81,\r\n\t0x94,0xbd,0xe7,0x13,0x0b,0xdf,0x05,0x21,0xfc,0x0b,0xff,0x19,0xfa,0x0f,0x0d,0xe7,\r\n\t0xc0,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x3e,0x1b,0xef,0xc5,0x9b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,\r\n\t0xb8,0xe2,0x0b,0x13,0xe9,0xc4,0xed,0x19,0x07,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x1d,0x18,0x16,0x2a,0x16,0x1c,0x25,0x12,0xf7,0xd9,0xb5,0x8f,\r\n\t0x81,0x85,0xa9,0xcd,0xf0,0x13,0x0f,0xec,0xc8,0xd2,0xf9,0x1d,0x0b,0xfc,0x0f,0x17,\r\n\t0xf1,0xcc,0xa4,0x81,0x82,0xa9,0xcf,0xf3,0x14,0x29,0x14,0x09,0x09,0x14,0x24,0x0c,\r\n\t0x1a,0x1d,0xfc,0xdb,0xbb,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa1,0xc8,0xf1,0x18,0x17,0xef,0xc9,0xa4,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xaf,0xd5,0xfc,0x24,0x07,0xe0,0xb9,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x1e,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbc,\r\n\t0xe5,0x0a,0x2b,0x30,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x13,0x39,0x35,0x0e,0xe5,0xba,0x90,0x81,\r\n\t0x85,0xac,0xd3,0xfa,0x21,0x05,0xde,0xb6,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8c,0xb2,0xd6,0xf7,0x17,0x22,0x0f,0x09,0x0e,0x20,0x16,0xf7,0xd5,0xb2,0x8d,\r\n\t0x81,0x81,0x81,0xab,0xd5,0xff,0x16,0x16,0x16,0x16,0x33,0x18,0x16,0x16,0x16,0xef,\r\n\t0xc5,0x9b,0x81,0x95,0xc0,0xea,0x16,0x39,0x1a,0x19,0x19,0x19,0x19,0x19,0x19,0x19,\r\n\t0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x11,0x0b,0x09,0x09,0x0b,0x14,0x24,0x11,0xf5,\r\n\t0xd6,0xb4,0x8e,0x81,0x81,0x95,0xa8,0xab,0xab,0xab,0xab,0xab,0xb0,0xda,0x06,0x29,\r\n\t0xfc,0xd2,0xab,0xa8,0x96,0x81,0x81,0x95,0xc0,0xea,0x11,0x0b,0x09,0x09,0x0e,0x1a,\r\n\t0x1d,0x05,0xe8,0xc8,0xa6,0x81,0x81,0x81,0x97,0xbc,0xe1,0x04,0x21,0x18,0x09,0x06,\r\n\t0x0c,0x1e,0x14,0xf6,0xd5,0xb2,0x8c,0x81,0x81,0x81,0x97,0xbc,0xe2,0x09,0x2a,0x04,\r\n\t0xde,0xb8,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xad,0xd3,0xf7,0x16,0x27,0x14,\r\n\t0x0b,0x09,0x0e,0x1e,0x1a,0xfc,0xdc,0xb8,0x92,0x81,0x81,0x98,0xc2,0xed,0x11,0x11,\r\n\t0x13,0x18,0x23,0x18,0x04,0xea,0xcc,0xac,0x8a,0x81,0x81,0x95,0xc0,0xea,0x14,0x3c,\r\n\t0x2e,0x06,0xda,0xb0,0x85,0x81,0x81,0x93,0xbc,0xe5,0x0a,0x2b,0x30,0x06,0xda,0xb1,\r\n\t0x87,0x81,0x81,0x81,0x81,0x85,0x9f,0xbb,0xd5,0xf1,0x0d,0x25,0x0b,0xee,0xc6,0x9d,\r\n\t0x81,0x81,0x91,0xa2,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa3,0x92,\r\n\t0x81,0x81,0x95,0xbf,0xe7,0x05,0x1f,0x12,0xf6,0xdb,0xc0,0xa5,0x8a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa5,0xd0,0xfa,0x26,0x32,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,\r\n\t0x90,0xba,0xe5,0x0e,0x0f,0xe5,0xf3,0x11,0x1b,0x0b,0xf1,0x12,0x1b,0x0f,0xf3,0xd3,\r\n\t0xae,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xe1,0x05,0x19,0x09,0xe6,0xbf,0x97,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,\r\n\t0xbb,0xe5,0x11,0x0f,0xe5,0xc8,0xf2,0x11,0x04,0xd7,0xaf,0x85,0x81,0x81,0x81,0x81,\r\n\t0x95,0xbf,0xe8,0xfc,0x06,0x0b,0x11,0x1c,0x0e,0x09,0xfc,0xed,0xd7,0xbb,0x9d,0x81,\r\n\t0x81,0x92,0xbb,0xe3,0x07,0x11,0xf7,0xd4,0xb1,0xc0,0xe3,0xff,0x13,0x19,0x0f,0xf9,\r\n\t0xdb,0xb9,0x93,0x81,0x81,0x95,0xb7,0xd7,0xf1,0x07,0x13,0x19,0x16,0x0e,0xff,0xe9,\r\n\t0xff,0x11,0x11,0xf5,0xd2,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x93,0xb9,0xe0,0x06,0x28,0x04,0xdd,0xb8,0x95,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa0,0xc4,0xe8,0x0f,0x1d,0xf6,0xd0,0xa9,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,\r\n\t0xcd,0xf1,0xf2,0xf2,0xd7,0xaf,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xac,\r\n\t0xce,0xf1,0x17,0x2f,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8e,0xb5,0xdb,0xfc,0x15,0x13,0xf9,0xd6,0xb1,0x89,0x81,\r\n\t0x95,0xbc,0xe3,0x0a,0x1b,0xf4,0xcd,0xa6,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9b,0xbd,0xdb,0xf5,0x09,0x14,0x19,0x14,0x09,0xf3,0xd9,0xbb,0x9b,0x81,\r\n\t0x81,0x81,0x81,0xab,0xd5,0xff,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,\r\n\t0xc5,0x9b,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x11,0x16,0x19,0x19,0x14,0x0c,0xff,0xed,0xd5,\r\n\t0xb9,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x13,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x13,0x16,0x19,0x19,0x12,0x07,\r\n\t0xf7,0xe3,0xca,0xac,0x8d,0x81,0x81,0x81,0x83,0xa7,0xc7,0xe4,0xfc,0x0e,0x16,0x19,\r\n\t0x12,0x05,0xf1,0xd8,0xbb,0x9a,0x81,0x81,0x81,0x81,0xa4,0xce,0xf5,0x11,0x11,0xf1,\r\n\t0xcc,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xbb,0xd9,0xf3,0x06,0x12,\r\n\t0x18,0x19,0x13,0x09,0xf6,0xdf,0xc3,0xa1,0x81,0x81,0x81,0x98,0xc2,0xed,0x11,0x11,\r\n\t0x0e,0x09,0xff,0xf1,0xdf,0xc8,0xae,0x90,0x81,0x81,0x81,0x8f,0xb8,0xde,0xff,0x16,\r\n\t0x10,0xf3,0xcf,0xa9,0x81,0x81,0x81,0x86,0xac,0xcf,0xf1,0x16,0x2f,0x06,0xda,0xb0,\r\n\t0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb6,0xd0,0xec,0x07,0xff,0xe1,0xc0,0x99,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x91,0xb9,0xdb,0xf9,0x0d,0xf1,0xd5,0xbb,0x9f,0x85,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa1,0xc9,0xf0,0x0f,0x15,0xfb,0xd6,0xae,0x85,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xb5,0xde,0x09,0x17,0xed,0xd5,0xeb,0xef,0xe6,0xd7,0xeb,0xef,0xe8,0xd4,0xb8,\r\n\t0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xa8,0xc8,0xe2,0xed,0xe5,0xcc,0xac,0x87,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,\r\n\t0xb8,0xdb,0xe5,0xe5,0xd7,0xc1,0xe1,0xe5,0xe5,0xcd,0xa8,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8a,0xae,0xc9,0xd4,0xdc,0xe2,0x0b,0x13,0xe9,0xde,0xd5,0xc7,0xb4,0x9c,0x81,0x81,\r\n\t0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xde,0xbd,0x99,0xa7,0xc5,0xdb,0xea,0xed,0xe7,0xd6,\r\n\t0xbd,0x9f,0x81,0x81,0x81,0x81,0x9b,0xb7,0xce,0xdf,0xea,0xed,0xec,0xe4,0xd8,0xc5,\r\n\t0xe2,0xe5,0xe5,0xe5,0xcd,0xa6,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa8,0xcd,0xf3,0x18,0x17,0xf3,0xd0,0xae,0x8c,0x81,0x81,0x81,0x81,0x97,\r\n\t0xb9,0xdb,0xff,0x22,0x09,0xe3,0xbe,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xb5,0xc7,0xc8,0xc8,0xbc,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb5,\r\n\t0xc3,0xe7,0x13,0x24,0xfb,0xd3,0xaa,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xc1,0xdc,0xec,0xeb,0xda,0xbd,0x9d,0x81,0x81,\r\n\t0xa6,0xcd,0xf3,0x1a,0x0b,0xe3,0xbc,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9f,0xba,0xd1,0xe1,0xea,0xed,0xea,0xe0,0xcf,0xb9,0x9d,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa6,0xcd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,\r\n\t0xbf,0x97,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xde,0xbc,0x94,0x81,0x92,0xba,0xdd,0xe7,0xea,0xed,0xed,0xea,0xe3,0xd7,0xc7,0xb3,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xac,0xd3,0xe7,0xe7,\r\n\t0xe7,0xcc,0xa4,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe7,0xed,0xed,0xed,0xe8,0xdf,\r\n\t0xd2,0xbf,0xa8,0x8e,0x81,0x81,0x81,0x81,0x81,0x8b,0xa9,0xc3,0xd8,0xe5,0xec,0xed,\r\n\t0xe8,0xde,0xcd,0xb7,0x9d,0x81,0x81,0x81,0x81,0x81,0xa1,0xc8,0xe4,0xe5,0xe5,0xdb,\r\n\t0xb9,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xb9,0xce,0xde,0xe7,\r\n\t0xed,0xed,0xe9,0xe0,0xd1,0xbd,0xa4,0x87,0x81,0x81,0x81,0x94,0xbc,0xde,0xe5,0xe5,\r\n\t0xe2,0xdf,0xd6,0xca,0xba,0xa5,0x8d,0x81,0x81,0x81,0x81,0x81,0xa4,0xc5,0xdf,0xed,\r\n\t0xe9,0xd5,0xb8,0x96,0x81,0x81,0x9b,0xaf,0xb5,0xc3,0xe7,0x11,0x24,0xfc,0xd3,0xaa,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xb0,0xcb,0xe6,0xe1,0xc3,0xa5,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9f,0xbd,0xdb,0xeb,0xd0,0xb6,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x92,0xb5,0xd4,0xe9,0xed,0xdc,0xbf,0x9d,0x81,0x81,0x81,0x81,0x81,\r\n\t0x83,0xac,0xd5,0xfc,0x22,0xfa,0xd3,0xc2,0xc5,0xbf,0xb3,0xc2,0xc5,0xc0,0xaf,0x99,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xa8,0xbc,0xc2,0xbd,0xac,0x90,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9f,0xb6,0xba,0xba,0xb4,0xa6,0xb9,0xba,0xba,0xae,0x92,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8f,0xa2,0xab,0xbd,0xe7,0x11,0x0e,0xe2,0xb9,0xac,0x9f,0x8e,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9f,0xb6,0xba,0xba,0xb8,0xa3,0x83,0x89,0xa2,0xb5,0xc0,0xc2,0xbf,0xb1,\r\n\t0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xa8,0xb7,0xc0,0xc2,0xc2,0xbb,0xb0,0xa8,\r\n\t0xb9,0xba,0xba,0xba,0xae,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x94,0xb9,0xdd,0xff,0x23,0x0b,0xe8,0xc8,0xa9,0x89,0x81,0x81,0x94,0xb2,\r\n\t0xd3,0xf3,0x16,0x14,0xf1,0xce,0xaa,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x92,0x9d,0x9d,0x9d,0x96,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdf,\r\n\t0xe8,0xff,0x20,0x0f,0xeb,0xc5,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xa2,0xb6,0xc2,0xc2,0xb4,0x9f,0x81,0x81,0x8e,\r\n\t0xb6,0xdc,0x04,0x21,0xfa,0xd3,0xac,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x97,0xab,0xb9,0xc1,0xc2,0xc0,0xb8,0xaa,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x92,0xae,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xb8,\r\n\t0xa5,0x85,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xb8,0xa3,0x83,0x81,0x81,0xa1,0xb7,0xbd,0xc1,0xc2,0xc2,0xc0,0xba,0xaf,0xa1,0x8e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xb3,0xbd,0xbd,\r\n\t0xbd,0xaf,0x91,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xbe,0xc2,0xc2,0xc2,0xbf,0xb6,\r\n\t0xa9,0x99,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0x9f,0xb0,0xbc,0xc2,0xc2,\r\n\t0xbf,0xb6,0xa7,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xab,0xba,0xba,0xba,0xb6,\r\n\t0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xa8,0xb6,0xbf,\r\n\t0xc2,0xc2,0xbf,0xb7,0xaa,0x98,0x82,0x81,0x81,0x81,0x81,0x83,0xa3,0xb8,0xba,0xba,\r\n\t0xb9,0xb5,0xad,0xa2,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xa4,0xb9,0xc2,\r\n\t0xc0,0xb2,0x9a,0x81,0x81,0x90,0xb6,0xd6,0xdf,0xe8,0xff,0x1f,0x0f,0xeb,0xc5,0x9e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xaa,0xc0,0xbd,0xa5,0x87,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9f,0xba,0xc2,0xb0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x98,0xb1,0xc0,0xc2,0xb6,0xa1,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa0,0xc8,0xef,0x17,0x0d,0xe9,0xca,0xb6,0xb4,0xbb,0xc8,0xd9,0xd0,0xae,0x87,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x93,0x98,0x94,0x86,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8d,0x90,0x90,0x8c,0x82,0x8f,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xc2,0xed,0x06,0x06,0xdd,0xb4,0x8a,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8d,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x8d,0x97,0x98,0x95,0x8a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x95,0x98,0x98,0x92,0x88,0x84,\r\n\t0x8f,0x90,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa2,0xc5,0xe8,0x09,0x25,0x05,0xe4,0xc5,0xa2,0x81,0x8c,0xb1,0xd0,\r\n\t0xee,0x0f,0x1c,0xfb,0xd9,0xb7,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,\r\n\t0x11,0x21,0x0f,0xf3,0xd4,0xb2,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0x98,0x98,0x8e,0x81,0x81,0x81,0x92,\r\n\t0xbd,0xe7,0xfa,0xfa,0xe9,0xc3,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x83,0x90,0x97,0x98,0x96,0x8f,0x82,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x8e,0x93,0x97,0x98,0x98,0x95,0x90,0x87,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0x93,0x93,\r\n\t0x93,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x94,0x98,0x98,0x98,0x95,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x92,0x98,0x98,\r\n\t0x95,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x90,0x90,0x90,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x95,\r\n\t0x98,0x98,0x95,0x8e,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,\r\n\t0x8f,0x8b,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0x98,\r\n\t0x97,0x8b,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,0x11,0x21,0x0f,0xf3,0xd4,0xb2,0x8c,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x97,0x95,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x93,0x98,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8b,0x97,0x98,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x92,0xb8,0xde,0x04,0x25,0x05,0xed,0xdf,0xdd,0xe4,0xef,0xff,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x91,0xb7,0xd5,0xda,0xda,0xcc,0xaa,0x82,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8b,0xac,0xce,0xee,0x0d,0x21,0xff,0xd7,0xad,0x83,0x95,0xc0,0xea,\r\n\t0x0d,0x1f,0xff,0xe1,0xc0,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,\r\n\t0x0b,0xfc,0xec,0xd4,0xb8,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,\r\n\t0xad,0xc9,0xd0,0xd0,0xcb,0xaf,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x0b,0xfc,0xec,0xd4,0xb8,0x99,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa4,0xc8,0xe8,0x07,0x1f,0x13,0x09,0x09,0x0e,0x18,0x0e,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9b,0xad,0xb0,0xb0,0xa8,0x90,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x92,0xb2,0xd2,0xf0,0x05,0xe6,0xc8,0xa5,0x81,0x8f,0xb5,0xd5,\r\n\t0xf3,0xff,0xe3,0xc5,0xa5,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,\r\n\t0xe0,0xd6,0xc6,0xb2,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8f,0xa2,0xa5,0xa5,0xa2,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe0,0xd6,0xc6,0xb2,0x99,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0xac,0xca,0xe5,0xf7,0x06,0x0b,0x0b,0x05,0xfa,0xec,0xd7,0xb3,0x8a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x84,0x85,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x96,0xb4,0xd2,0xdf,0xc8,0xaa,0x8c,0x81,0x81,0x9a,0xb8,\r\n\t0xd5,0xe0,0xc5,0xa7,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,\r\n\t0xb7,0xae,0xa0,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xb7,0xae,0xa0,0x8d,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xaa,0xc0,0xd1,0xdc,0xdf,0xdf,0xda,0xd2,0xc5,0xb5,0x9b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xad,0xb5,0xa8,0x8c,0x81,0x81,0x81,0x81,0x9a,\r\n\t0xb2,0xb7,0xa6,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,\r\n\t0x8d,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x8d,0x85,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x86,0x9a,0xa9,0xb2,0xb5,0xb5,0xb1,0xa9,0x9d,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x8b,0x82,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x89,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x87,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x88,0x98,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x96,0x83,0x81,\r\n\t0x81,0x81,0x89,0x8b,0x8b,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0x98,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x96,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x85,0x85,\r\n\t0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x88,\r\n\t0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x83,0x88,0x88,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x85,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x85,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x86,0xa8,0xc1,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xbe,0xa2,0x81,\r\n\t0x81,0x9d,0xb2,0xb5,0xb5,0xb1,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0xa8,0xc1,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xbe,0xa2,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xa6,0xab,0xab,0xab,0xa8,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa7,0xa2,0x99,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x99,0xa5,0xad,0xb0,0xb0,\r\n\t0xad,0xa5,0x9a,0x8c,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa5,0x9f,\r\n\t0x95,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa8,0xa8,0xa2,0x8c,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa8,0xa0,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x97,0xa4,0xad,0xb2,\r\n\t0xb2,0xb0,0xab,0xa1,0x94,0x81,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa6,0x94,0x81,\r\n\t0x81,0x83,0x9c,0xa8,0xa8,0xa8,0xa0,0x89,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa8,0xa8,0xa8,0xa7,0x97,0x81,0x81,0x81,0x8c,0xa2,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa8,0xa8,0xa8,0xa7,0x97,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa6,0x94,0x81,\r\n\t0x81,0x9b,0xa8,0xa8,0xa8,0xa6,0x96,0x81,0x81,0x81,0x95,0xa8,0xab,0xab,0xa9,0x98,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa4,0x8f,\r\n\t0x81,0x89,0xa0,0xa8,0xa8,0xa8,0xa7,0x9a,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,\r\n\t0xa1,0x8a,0x81,0x85,0x9e,0xa8,0xa8,0xa8,0x9c,0x83,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x93,0xa2,0xad,0xb2,0xb2,0xaf,0xa5,0x95,0x82,0x81,0x81,0x81,0x81,0x81,0x95,0xa8,\r\n\t0xab,0xab,0xab,0xab,0xab,0xa8,0xa3,0x99,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x91,0x9f,0xaa,0xb0,0xb0,0xac,0xa2,0x94,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa5,0x9f,0x93,0x82,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x9e,0xa9,0xb0,0xb2,0xb2,0xaf,0xa9,0xa1,0x94,\r\n\t0x81,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0xa7,0x97,0x81,0x81,0x81,0x95,0xa8,0xab,0xab,0xa8,0x96,0x81,0x81,0x85,0x9f,\r\n\t0xaa,0xab,0xab,0xa2,0x8b,0x81,0x81,0x93,0xa7,0xab,0xab,0xaa,0x9e,0x83,0x81,0x81,\r\n\t0x81,0x81,0x96,0xa8,0xab,0xab,0xa9,0x98,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa3,\r\n\t0x8e,0x81,0x81,0x81,0x87,0x9f,0xa8,0xa8,0xa6,0x96,0x81,0x81,0x81,0x87,0x9f,0xa8,\r\n\t0xa8,0xa8,0xa4,0x91,0x81,0x81,0x81,0x94,0xa6,0xa8,0xa8,0xa7,0x9a,0x81,0x81,0x81,\r\n\t0x95,0xa8,0xab,0xab,0xab,0xa1,0x89,0x81,0x81,0x81,0x81,0x99,0xa9,0xab,0xab,0xaa,\r\n\t0x9b,0x81,0x81,0x81,0x8e,0xa3,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,\r\n\t0xa8,0x9c,0x83,0x81,0x94,0xbd,0xe4,0xef,0xef,0xef,0xef,0xef,0xef,0xde,0xb6,0x8c,\r\n\t0x90,0xb8,0xd9,0xdf,0xdf,0xd7,0xb6,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0xbd,0xe4,0xef,0xef,0xef,0xef,0xef,0xef,0xde,0xb6,0x8c,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8c,0xa3,0xab,0xab,0xa8,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x88,0xae,0xcd,0xd5,0xd5,0xd5,0xcf,0xb2,0x8d,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd1,0xcc,0xc1,0xb1,\r\n\t0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xad,0xc0,0xce,0xd7,0xda,0xda,\r\n\t0xd6,0xcf,0xc3,0xb2,0x96,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xcf,0xc8,\r\n\t0xbd,0xad,0x9a,0x82,0x81,0x81,0x81,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xd2,0xd2,0xc8,0xa8,0x82,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xd2,0xc4,0xa3,0x81,0x81,0x81,0x81,0x81,0x94,0xab,0xbe,0xcd,0xd7,0xdd,\r\n\t0xdd,0xda,0xd4,0xc9,0xba,0xa3,0x82,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xce,0xb3,0x8e,\r\n\t0x81,0x9c,0xbf,0xd2,0xd2,0xd2,0xc4,0xa3,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xd2,0xd2,0xd2,0xd0,0xb7,0x93,0x81,0x82,0xa8,0xc8,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd2,0xd2,0xd2,0xd0,0xb7,0x93,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xce,0xb3,0x8e,\r\n\t0x9c,0xbd,0xd2,0xd2,0xd2,0xcf,0xb5,0x91,0x81,0x8d,0xb2,0xcf,0xd5,0xd5,0xd2,0xb7,\r\n\t0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xcb,0xac,\r\n\t0x87,0xa3,0xc4,0xd2,0xd2,0xd2,0xd1,0xbb,0x98,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,\r\n\t0xc6,0xa7,0x81,0x9f,0xc1,0xd2,0xd2,0xd2,0xbf,0x9c,0x81,0x81,0x81,0x81,0x88,0xa2,\r\n\t0xb9,0xca,0xd6,0xdd,0xdd,0xd7,0xcd,0xbb,0xa6,0x8b,0x81,0x81,0x81,0x8d,0xb2,0xcf,\r\n\t0xd5,0xd5,0xd5,0xd5,0xd5,0xd2,0xcc,0xc1,0xb1,0x9c,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x85,0xa0,0xb6,0xc8,0xd4,0xda,0xda,0xd5,0xcb,0xba,0xa4,0x8a,0x81,0x81,0x81,\r\n\t0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd0,0xc8,0xba,0xa8,0x90,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x83,0x9e,0xb4,0xc6,0xd2,0xda,0xdd,0xdd,0xd9,0xd2,0xcb,0xb7,\r\n\t0x96,0x81,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xd0,0xb7,0x93,0x81,0x8d,0xb2,0xcf,0xd5,0xd5,0xd1,0xb5,0x8f,0x81,0x9e,0xc1,\r\n\t0xd5,0xd5,0xd5,0xc6,0xa5,0x81,0x8a,0xb0,0xce,0xd5,0xd5,0xd4,0xbf,0x9c,0x81,0x81,\r\n\t0x81,0x91,0xb5,0xd1,0xd5,0xd5,0xd2,0xb7,0x92,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xc9,\r\n\t0xaa,0x84,0x81,0x81,0xa1,0xc3,0xd2,0xd2,0xcf,0xb5,0x91,0x81,0x81,0xa1,0xc3,0xd2,\r\n\t0xd2,0xd2,0xcc,0xaf,0x8b,0x81,0x91,0xb4,0xce,0xd2,0xd2,0xd1,0xbb,0x98,0x81,0x8d,\r\n\t0xb2,0xcf,0xd5,0xd5,0xd5,0xc5,0xa2,0x81,0x81,0x81,0x94,0xb9,0xd2,0xd5,0xd5,0xd3,\r\n\t0xbb,0x97,0x81,0x84,0xaa,0xc9,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,\r\n\t0xd2,0xbf,0x9c,0x81,0x95,0xc0,0xea,0x16,0x1b,0x1b,0x1b,0x1b,0x0e,0xe2,0xb8,0x8d,\r\n\t0x95,0xbf,0xe8,0x0b,0x0b,0xee,0xc8,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x1b,0x1b,0x1b,0x1b,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x83,0xa8,0xc8,0xd5,0xd5,0xcf,0xb3,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x96,0xbe,0xe7,0xff,0xff,0xff,0xec,0xc3,0x9b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfa,0xf5,0xe9,0xd6,\r\n\t0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb8,0xd1,0xe6,0xf6,0xff,0x06,0x06,\r\n\t0xff,0xf7,0xea,0xd1,0xab,0x82,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xf9,0xf1,\r\n\t0xe5,0xd3,0xbd,0xa3,0x85,0x81,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xfc,0xdf,0xb5,0x8b,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xda,0xb0,0x85,0x81,0x81,0x81,0x98,0xb6,0xcf,0xe3,0xf5,0xff,0x06,\r\n\t0x09,0x06,0xfc,0xf1,0xdf,0xbb,0x92,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xec,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfb,0xfc,0xfc,0xda,0xb0,0x85,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xfc,0xfc,0xf1,0xc7,0x9d,0x81,0x8b,0xb5,0xdf,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xfc,0xf1,0xc7,0x9d,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xec,0xc2,0x98,\r\n\t0xb6,0xd7,0xf9,0xfc,0xfc,0xef,0xc5,0x9b,0x81,0x95,0xc0,0xea,0xff,0xff,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xe6,0xbd,\r\n\t0x96,0xb4,0xdb,0xfc,0xfc,0xfc,0xf6,0xcd,0xa2,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,\r\n\t0xe0,0xb9,0x93,0xaa,0xd5,0xfc,0xfc,0xfb,0xd2,0xa8,0x81,0x81,0x81,0x87,0xa7,0xc3,\r\n\t0xdd,0xf1,0xff,0x07,0x09,0xff,0xf4,0xe0,0xc7,0xaa,0x8a,0x81,0x81,0x95,0xc0,0xea,\r\n\t0xff,0xff,0xff,0xff,0xff,0xfc,0xf5,0xe9,0xd6,0xbe,0xa1,0x81,0x81,0x81,0x81,0x81,\r\n\t0x85,0xa3,0xc1,0xdb,0xef,0xfc,0x05,0x06,0xff,0xf2,0xde,0xc5,0xa9,0x88,0x81,0x81,\r\n\t0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfa,0xf1,0xe1,0xcc,0xb0,0x91,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa1,0xbf,0xd9,0xed,0xfb,0x04,0x09,0x09,0x04,0xfc,0xf3,0xce,\r\n\t0xa4,0x81,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xf1,0xc7,0x9d,0x81,0x95,0xc0,0xea,0xff,0xff,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0xff,0xff,0xda,0xb0,0x85,0x93,0xbd,0xe7,0xff,0xff,0xfb,0xd3,0xab,0x83,0x81,\r\n\t0x81,0x9e,0xc7,0xef,0xff,0xff,0xef,0xc5,0x9b,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xe2,\r\n\t0xb8,0x8d,0x81,0x83,0xad,0xd7,0xfc,0xfc,0xef,0xc5,0x9b,0x81,0x83,0xad,0xd7,0xfc,\r\n\t0xfc,0xfc,0xe9,0xc5,0xa1,0x83,0xa7,0xcb,0xef,0xfc,0xfc,0xf6,0xcd,0xa2,0x81,0x95,\r\n\t0xc0,0xea,0xff,0xff,0xff,0xdb,0xb6,0x92,0x81,0x82,0xa8,0xcd,0xf3,0xff,0xff,0xf5,\r\n\t0xca,0xa0,0x81,0x8d,0xb8,0xe2,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfb,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x13,0xff,0xff,0xff,0xff,0xe2,0xb8,0x8d,\r\n\t0x8a,0xb1,0xd8,0xff,0x26,0xff,0xd8,0xb1,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0xff,0xff,0xff,0xff,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x98,0xbd,0xe1,0xff,0xff,0xee,0xc9,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa4,0xcc,0xf4,0x1c,0x2b,0x21,0xf9,0xd1,0xa9,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x29,0x23,0x23,0x23,0x26,0x1e,0x0f,0xf9,\r\n\t0xdb,0xb8,0x92,0x81,0x81,0x81,0x81,0x97,0xb8,0xd7,0xf3,0x0b,0x1e,0x24,0x1e,0x1e,\r\n\t0x23,0x20,0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x16,0x29,0x23,0x23,0x23,0x23,0x1a,\r\n\t0x0c,0xf7,0xde,0xc1,0xa0,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x29,0x23,0x23,0x23,\r\n\t0x23,0x23,0x23,0x0b,0xdf,0xb5,0x8b,0x95,0xc0,0xea,0x16,0x29,0x23,0x23,0x23,0x23,\r\n\t0x23,0x23,0x06,0xda,0xb0,0x85,0x81,0x81,0x95,0xb6,0xd4,0xf1,0x0a,0x1d,0x27,0x1f,\r\n\t0x1e,0x21,0x26,0x16,0xea,0xc0,0x95,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x16,0x23,0x23,0x23,\r\n\t0x29,0x24,0x23,0x23,0x1e,0xf2,0xc8,0x9d,0x81,0x8b,0xb5,0xdf,0x0b,0x26,0x26,0x26,\r\n\t0x26,0x26,0x29,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xaf,\r\n\t0xd0,0xf1,0x12,0x1d,0xfb,0xdb,0xba,0x94,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x29,0x1b,0xf4,0xcc,\r\n\t0xa4,0xc2,0xea,0x11,0x29,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x29,0x18,\r\n\t0xf1,0xcc,0xa5,0xab,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,0xa0,0xc2,0xe3,\r\n\t0xff,0x17,0x25,0x1b,0x1c,0x26,0x1a,0x04,0xe6,0xc5,0xa2,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x29,0x21,0x21,0x21,0x24,0x1f,0x0f,0xf9,0xdd,0xbd,0x9a,0x81,0x81,0x81,0x81,\r\n\t0x9e,0xc0,0xdf,0xfc,0x14,0x25,0x1e,0x1e,0x28,0x19,0xff,0xe4,0xc4,0xa1,0x81,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x29,0x23,0x23,0x23,0x23,0x19,0x06,0xec,0xcc,0xa8,0x82,\r\n\t0x81,0x81,0x81,0x98,0xbc,0xdd,0xfb,0x13,0x24,0x1e,0x1b,0x1b,0x1f,0x26,0xfa,0xd0,\r\n\t0xa5,0x81,0x81,0x95,0xc0,0xea,0x16,0x23,0x23,0x23,0x23,0x29,0x24,0x23,0x23,0x23,\r\n\t0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x8d,0xb5,0xdd,0x06,0x2b,0x09,0xe1,0xb8,0x90,0x81,\r\n\t0x83,0xab,0xd3,0xfb,0x24,0x0d,0xe5,0xbd,0x95,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xb8,0x8d,0x81,0x83,0xad,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0xa5,0xc9,0xed,\r\n\t0x11,0x23,0xff,0xdb,0xb7,0x99,0xbd,0xe1,0x05,0x29,0x09,0xe5,0xc2,0x9c,0x81,0x8e,\r\n\t0xb4,0xd9,0xfc,0x22,0x15,0xf0,0xcb,0xa6,0x81,0x97,0xbb,0xe1,0x07,0x2b,0x07,0xe2,\r\n\t0xbd,0x98,0x81,0x8d,0xb8,0xe2,0x0e,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xd5,0xd5,0xd5,0xcb,0xac,0x85,\r\n\t0x81,0xa1,0xc8,0xee,0x15,0x0f,0xe8,0xc1,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8d,0xb2,0xcf,0xd5,0xd5,0xd5,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x88,\r\n\t0xad,0xd2,0xf6,0x1b,0x20,0x04,0xdf,0xbb,0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x89,0xb1,0xd9,0xff,0x27,0xff,0x28,0x06,0xde,0xb6,0x8e,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xf7,0xf7,0xf7,0xfc,0x0c,0x27,0x16,\r\n\t0xf1,0xca,0xa2,0x81,0x81,0x81,0x88,0xae,0xd2,0xf3,0x14,0x25,0x0c,0xfb,0xf2,0xf3,\r\n\t0xfa,0x06,0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x16,0x19,0xf7,0xf7,0xf7,0xff,0x0b,\r\n\t0x20,0x1a,0xfc,0xdb,0xb7,0x92,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xf7,0xf7,0xf7,\r\n\t0xf7,0xf7,0xf7,0xf7,0xde,0xb5,0x8a,0x95,0xc0,0xea,0x16,0x1b,0xf7,0xf7,0xf7,0xf7,\r\n\t0xf7,0xf7,0xf7,0xd9,0xaf,0x85,0x81,0x87,0xac,0xd0,0xf1,0x10,0x29,0x11,0xff,0xf5,\r\n\t0xf2,0xf7,0xff,0x0f,0xea,0xc0,0x95,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x95,0xbf,0xe8,0xf7,0xf7,0xf7,0xff,\r\n\t0x2b,0x06,0xf7,0xf7,0xf7,0xef,0xc7,0x9d,0x81,0x8b,0xb5,0xdf,0xfa,0xfa,0xfa,0xfa,\r\n\t0xfa,0xfa,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xca,\r\n\t0xea,0x0c,0x22,0xff,0xe1,0xc1,0x9f,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x10,0x20,0x04,0xda,\r\n\t0xb3,0xd2,0xf9,0x20,0x0c,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x28,0x2a,\r\n\t0x04,0xde,0xb7,0xab,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x8f,0xb5,0xda,0xfc,\r\n\t0x1d,0x18,0xfc,0xf1,0xf2,0xff,0x18,0x21,0xff,0xdc,0xb6,0x91,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xf5,0xf5,0xf5,0xfb,0x0a,0x22,0x1a,0xf7,0xd3,0xad,0x86,0x81,0x81,0x8d,\r\n\t0xb3,0xd9,0xfb,0x1c,0x19,0xff,0xf4,0xf5,0xff,0x1a,0x20,0xff,0xdb,0xb5,0x8f,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xf7,0xf7,0xf7,0xff,0x16,0x28,0x07,0xe1,0xba,0x92,\r\n\t0x81,0x81,0x81,0xa9,0xd1,0xf6,0x19,0x1c,0x04,0xf5,0xef,0xf1,0xf5,0xfc,0xfa,0xd0,\r\n\t0xa5,0x81,0x81,0x95,0xbf,0xe8,0xf7,0xf7,0xf7,0xf7,0xff,0x2b,0x06,0xf7,0xf7,0xf7,\r\n\t0xf7,0xef,0xc7,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0xa8,0xd0,0xf7,0x20,0x15,0xed,0xc5,0x9d,0x81,\r\n\t0x90,0xb8,0xe0,0x09,0x28,0xff,0xd7,0xaf,0x87,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xb8,0x8d,0x81,0x83,0xad,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x8f,0xb3,0xd7,\r\n\t0xfb,0x1f,0x15,0xf1,0xcd,0xaf,0xd3,0xf7,0x1b,0x16,0xf1,0xce,0xab,0x87,0x81,0x81,\r\n\t0x9f,0xc4,0xe8,0x0d,0x2a,0x04,0xdf,0xba,0x94,0xab,0xcf,0xf5,0x1a,0x17,0xf1,0xcd,\r\n\t0xa8,0x84,0x81,0x8d,0xb8,0xe2,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0x1e,0x1a,\r\n\t0xf6,0xd1,0xa7,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0xab,0xab,0xa5,0x90,0x81,\r\n\t0x81,0x90,0xb8,0xde,0x06,0x20,0xf9,0xd2,0xab,0x84,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x95,0xa8,0xab,0xab,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x9e,\r\n\t0xc2,0xe7,0x0c,0x0f,0x07,0x19,0xf5,0xd1,0xad,0x89,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xbd,0xe7,0x0f,0x1a,0xf3,0x1b,0x14,0xec,0xc3,0x9a,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xcd,0xcd,0xd4,0xea,0x0f,0x27,\r\n\t0xfc,0xd3,0xaa,0x81,0x81,0x81,0x9b,0xc1,0xe7,0x0c,0x27,0x07,0xe8,0xd3,0xc9,0xca,\r\n\t0xd1,0xde,0xef,0xd5,0xad,0x84,0x95,0xc0,0xea,0x16,0x19,0xed,0xcd,0xcf,0xd6,0xe6,\r\n\t0xff,0x20,0x15,0xf1,0xcb,0xa4,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xcd,0xcd,\r\n\t0xcd,0xcd,0xcd,0xcd,0xc3,0xa5,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xcd,0xcd,0xcd,\r\n\t0xcd,0xcd,0xcd,0xc0,0xa1,0x81,0x81,0x9a,0xc0,0xe6,0x0b,0x2b,0x0b,0xee,0xd8,0xcb,\r\n\t0xc8,0xcd,0xd9,0xe9,0xe4,0xbd,0x94,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x8a,0xae,0xc8,0xcd,0xcd,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xcd,0xcd,0xcb,0xb4,0x91,0x81,0x81,0xa7,0xc5,0xd0,0xd0,0xd0,0xd0,\r\n\t0xd0,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc3,0xe3,\r\n\t0x05,0x26,0x07,0xe6,0xc6,0xa5,0x85,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0x14,0x11,0xe8,\r\n\t0xc1,0xe0,0x09,0x19,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0x12,\r\n\t0x15,0xef,0xc9,0xab,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x81,0xa0,0xc7,0xee,0x14,\r\n\t0x1e,0xfa,0xdb,0xc8,0xc8,0xdd,0xfb,0x20,0x15,0xef,0xc8,0x9f,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xca,0xcb,0xd2,0xe6,0x06,0x2b,0x0c,0xe4,0xbb,0x92,0x81,0x81,0x9e,\r\n\t0xc6,0xec,0x12,0x1f,0xfb,0xdd,0xca,0xcb,0xdf,0xfc,0x21,0x14,0xee,0xc7,0x9f,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xcd,0xcf,0xdb,0xf7,0x1f,0x17,0xee,0xc5,0x9a,\r\n\t0x81,0x81,0x8b,0xb5,0xde,0x07,0x2a,0x04,0xdf,0xcc,0xc5,0xc7,0xcc,0xd4,0xda,0xc2,\r\n\t0x9d,0x81,0x81,0x8a,0xae,0xc8,0xcd,0xcd,0xcd,0xd5,0xff,0x2b,0x06,0xda,0xcd,0xcd,\r\n\t0xcd,0xcb,0xb4,0x91,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x9a,0xc3,0xeb,0x13,0x22,0xfa,0xd2,0xa9,0x81,\r\n\t0x9d,0xc5,0xed,0x15,0x19,0xf1,0xc9,0xa2,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xb8,0x9f,0xa0,0x9f,0xad,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x9c,0xc0,\r\n\t0xe4,0x09,0x2b,0x07,0xe3,0xc5,0xe9,0x0d,0x22,0xff,0xdb,0xb8,0x94,0x81,0x81,0x81,\r\n\t0x8b,0xaf,0xd4,0xf9,0x1e,0x18,0xf3,0xce,0xa9,0xbe,0xe3,0x09,0x27,0x04,0xde,0xb9,\r\n\t0x94,0x81,0x81,0x84,0xaa,0xc9,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xe8,0x0c,0x25,0x04,\r\n\t0xdf,0xbc,0x99,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa7,0xce,0xf5,0x1c,0x09,0xe2,0xbb,0x94,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x8e,0xb2,\r\n\t0xd7,0xfb,0x1f,0xfa,0xf1,0x17,0x0b,0xe7,0xc2,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa3,0xcb,0xf3,0x1b,0x0e,0xe6,0x0f,0x20,0xf7,0xd0,0xa8,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xa3,0xb3,0xdd,0x09,0x2b,\r\n\t0xff,0xd5,0xab,0x81,0x81,0x81,0xa9,0xd2,0xf9,0x20,0x12,0xed,0xca,0xae,0x9f,0xa0,\r\n\t0xa8,0xb7,0xc5,0xb8,0x9b,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xa5,0xad,0xc3,\r\n\t0xe6,0x0b,0x2a,0xff,0xd9,0xb1,0x88,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xa3,\r\n\t0xa3,0xa3,0xa3,0xa3,0x9d,0x88,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0xa3,0xa3,\r\n\t0xa3,0xa3,0xa3,0x9b,0x85,0x81,0x81,0xa9,0xd1,0xf7,0x1f,0x15,0xf1,0xce,0xb3,0xa2,\r\n\t0x9d,0xa4,0xb2,0xc3,0xc1,0xa8,0x86,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x95,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x8e,0xa0,0xa3,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0xa3,0xa1,0x93,0x81,0x81,0x81,0x8a,0x9f,0xa5,0xa5,0xa5,0xa5,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xdd,0xfc,\r\n\t0x1f,0x0d,0xec,0xcb,0xaa,0x8a,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0x06,0x1f,0xf6,\r\n\t0xcf,0xef,0x17,0x0b,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xff,\r\n\t0x28,0xff,0xdb,0xb5,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x84,0xad,0xd6,0xfc,0x26,\r\n\t0x0c,0xe5,0xc0,0xa0,0xa1,0xc2,0xe7,0x0f,0x25,0xfc,0xd4,0xab,0x82,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0xa1,0xac,0xcc,0xf5,0x1e,0x16,0xec,0xc2,0x98,0x81,0x83,0xac,\r\n\t0xd4,0xfc,0x24,0x0c,0xe5,0xc1,0xa2,0xa4,0xc2,0xe8,0x0f,0x24,0xfc,0xd4,0xab,0x82,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xa5,0xc2,0xeb,0x16,0x1e,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x8d,0xb8,0xe2,0x0e,0x26,0xfa,0xd1,0xb0,0x9c,0x9d,0xa2,0xab,0xb0,0xa2,\r\n\t0x87,0x81,0x81,0x81,0x8e,0xa0,0xa3,0xa3,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0xa3,\r\n\t0xa3,0xa1,0x93,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x8d,0xb5,0xdd,0x06,0x2e,0x07,0xdf,0xb6,0x8e,\r\n\t0xa9,0xd2,0xfa,0x23,0x0c,0xe4,0xbc,0x94,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xb8,0xc9,0xca,0xc9,0xb4,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x86,0xaa,\r\n\t0xce,0xf1,0x15,0x1d,0xf9,0xdb,0xff,0x23,0x0c,0xe8,0xc5,0xa1,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9a,0xbf,0xe3,0x09,0x2d,0x07,0xe2,0xbd,0xd2,0xf7,0x1d,0x12,0xee,0xc8,0xa4,\r\n\t0x81,0x81,0x81,0x81,0x8e,0xa3,0xa8,0xa8,0xa8,0xa8,0xba,0xdd,0xff,0x23,0x0f,0xeb,\r\n\t0xc8,0xa4,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x97,0xbe,0xe5,0x0b,0x19,0xf2,0xcc,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0xa2,0xc7,\r\n\t0xec,0x11,0x0b,0xe6,0xdd,0xff,0x21,0xfc,0xd9,0xb4,0x90,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x88,0xb0,0xd8,0xff,0x29,0xff,0xd9,0xff,0x2a,0x06,0xdd,0xb5,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xbf,0xc8,0xe7,0x0e,0x21,\r\n\t0xf9,0xd0,0xa7,0x81,0x81,0x8b,0xb4,0xdd,0x06,0x2b,0x04,0xdb,0xb4,0x8f,0x81,0x81,\r\n\t0x81,0x92,0x9b,0x93,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x88,0xac,\r\n\t0xd4,0xfc,0x26,0x0e,0xe4,0xba,0x90,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xbd,\r\n\t0xbd,0xbd,0xbd,0xbd,0xaf,0x91,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0xb2,0xb2,\r\n\t0xb2,0xb2,0xb2,0xa3,0x86,0x81,0x8b,0xb4,0xdd,0x06,0x2d,0x05,0xdd,0xb6,0xb1,0xb2,\r\n\t0xb2,0xb2,0xb2,0xb2,0xb0,0x9d,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xc0,\r\n\t0xc0,0xc0,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xf7,0x18,\r\n\t0x12,0xf1,0xd0,0xb0,0x90,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xf7,0x20,0x05,\r\n\t0xdd,0xfc,0x23,0xfb,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xf1,\r\n\t0x18,0x14,0xed,0xc7,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x8d,0xb7,0xe0,0x0a,0x29,\r\n\t0xff,0xd6,0xae,0x86,0x89,0xb1,0xda,0x04,0x2c,0x06,0xdd,0xb3,0x8a,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x9c,0xc5,0xef,0x1b,0x19,0xed,0xc2,0x98,0x81,0x8c,0xb6,\r\n\t0xdf,0x09,0x29,0xff,0xd6,0xae,0x87,0x8a,0xb2,0xda,0x04,0x2d,0x06,0xdd,0xb3,0x8a,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb4,0xca,0xef,0x19,0x19,0xef,0xc5,0x9c,\r\n\t0x81,0x81,0x8c,0xb5,0xdf,0x09,0x2f,0x0b,0xec,0xd4,0xc2,0xb3,0xa2,0x91,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0xa8,0xd0,0xf7,0x20,0x14,0xec,0xc3,0x9b,\r\n\t0xb6,0xdf,0x07,0x27,0xff,0xd6,0xaf,0x86,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xc9,0xf0,0xf5,0xf0,0xcb,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x94,\r\n\t0xb7,0xdb,0xff,0x23,0x0f,0xf1,0x15,0x19,0xf5,0xd2,0xae,0x8b,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0xab,0xcf,0xf4,0x19,0x1b,0xf6,0xd2,0xe6,0x0b,0x22,0xfc,0xd9,0xb4,0x8f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xae,0xd1,0xf4,0x18,0x1a,0xf6,0xd3,\r\n\t0xb0,0x8d,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x86,0xad,0xd4,0xfb,0x22,0x04,0xdc,0xb5,0x8e,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x93,0xb8,0xdc,\r\n\t0xff,0x1c,0xf6,0xd2,0xc8,0xed,0x12,0x12,0xee,0xca,0xa6,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xbd,0xe6,0x0e,0x1c,0xf4,0xcd,0xf5,0x1d,0x13,0xeb,0xc2,0x9a,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe7,0xe7,0xef,0x04,0x22,0x0b,\r\n\t0xe8,0xc2,0x9b,0x81,0x81,0x92,0xbb,0xe5,0x0f,0x23,0xf7,0xcf,0xa6,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa1,\r\n\t0xca,0xf5,0x1e,0x14,0xea,0xc0,0x95,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe7,0xe7,\r\n\t0xe7,0xe7,0xe7,0xe7,0xcc,0xa4,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xdd,0xdd,0xdd,\r\n\t0xdd,0xdd,0xdc,0xc2,0x9c,0x81,0x92,0xbb,0xe5,0x0f,0x23,0xfa,0xd1,0xbb,0xd9,0xdd,\r\n\t0xdd,0xdd,0xdd,0xdd,0xd8,0xb9,0x92,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xea,0xea,\r\n\t0xea,0xea,0xea,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xf0,0x11,0x18,\r\n\t0xf7,0xd5,0xb6,0x95,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xe9,0x11,0x14,\r\n\t0xec,0x0d,0x13,0xec,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0x07,0x26,0xff,0xd9,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x93,0xbd,0xe7,0x11,0x21,\r\n\t0xf7,0xcd,0xa4,0x81,0x81,0xa8,0xd2,0xfc,0x26,0x0d,0xe2,0xb8,0x8d,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0xa7,0xb2,0xd0,0xf7,0x20,0x11,0xe7,0xbe,0x94,0x81,0x92,0xbc,\r\n\t0xe6,0x11,0x21,0xf7,0xcd,0xa4,0x81,0x81,0xa9,0xd2,0xfc,0x26,0x0d,0xe2,0xb8,0x8d,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xda,0xdd,0xeb,0x05,0x27,0x0a,0xe3,0xbc,0x93,\r\n\t0x81,0x81,0x82,0xaa,0xd2,0xf6,0x19,0x27,0x0f,0xfa,0xe9,0xda,0xc9,0xb8,0xa3,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x9a,0xc3,0xeb,0x13,0x21,0xf7,0xd0,0xa8,\r\n\t0xc3,0xec,0x14,0x19,0xf1,0xc9,0xa1,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xd8,0xff,0x21,0x04,0xdb,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa1,0xc5,0xe8,0x0d,0x25,0x0a,0x26,0x04,0xdf,0xbb,0x97,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xba,0xdf,0x04,0x29,0x0b,0xe5,0xf9,0x1f,0x0f,0xe9,0xc4,0x9f,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xc5,0xe8,0x0c,0x25,0x04,0xdf,0xbc,\r\n\t0x99,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9c,0xc4,0xeb,0x12,0x13,0xec,0xc5,0x9e,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x82,0xa8,0xcd,0xf1,\r\n\t0x16,0x09,0xe2,0xbe,0xb3,0xd8,0xfc,0x21,0x04,0xe0,0xbb,0x97,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa3,0xcb,0xf3,0x1b,0x0f,0xe7,0xc0,0xe8,0x11,0x1f,0xf7,0xcf,0xa7,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x20,0x13,0x13,0x13,0x19,0x1a,0xff,0xeb,\r\n\t0xce,0xae,0x8f,0x81,0x81,0x95,0xc0,0xea,0x14,0x1e,0xf2,0xc9,0x9f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x9d,\r\n\t0xc6,0xef,0x1b,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x20,0x13,0x13,0x13,\r\n\t0x13,0x13,0x13,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x1d,0x09,0x09,0x09,0x09,\r\n\t0x09,0x09,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x14,0x1e,0xf4,0xca,0xc5,0xef,0x09,\r\n\t0x09,0x09,0x09,0x09,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x21,0x16,0x16,0x16,\r\n\t0x16,0x16,0x16,0x16,0x2e,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0x0b,0x1e,0xfc,\r\n\t0xdb,0xbb,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xff,0x21,\r\n\t0xf9,0x1a,0x04,0xdc,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xf5,0x1b,0x12,0xec,0xd5,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x1e,\r\n\t0xf2,0xc8,0x9f,0x81,0x81,0xa4,0xce,0xf7,0x23,0x11,0xe5,0xba,0x90,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xd0,0xd1,0xd9,0xec,0x0b,0x25,0xff,0xda,0xb3,0x8b,0x81,0x95,0xc0,\r\n\t0xea,0x14,0x1e,0xf2,0xc8,0x9f,0x81,0x81,0xa5,0xcf,0xf7,0x23,0x11,0xe5,0xba,0x90,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0x06,0x06,0x09,0x11,0x24,0x0d,0xf0,0xcf,0xab,0x85,\r\n\t0x81,0x81,0x81,0x99,0xbc,0xdd,0xf9,0x12,0x25,0x20,0x11,0xff,0xef,0xdc,0xc6,0xaa,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x8d,0xb5,0xdd,0x06,0x2e,0x06,0xdd,0xb4,\r\n\t0xd0,0xf7,0x21,0x0b,0xe3,0xbb,0x93,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xe7,0x0f,0x36,0x11,0xea,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xaf,0xd3,0xf5,0x1a,0x33,0x0f,0xec,0xc8,0xa4,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa6,0xcb,0xef,0x14,0x1e,0xf7,0x0c,0x1e,0xf9,0xd4,0xaf,0x8b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xb9,0xdc,0xff,0x23,0x0f,0xeb,0xc8,0xa4,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8c,0xb4,0xda,0xff,0x24,0xfc,0xd5,0xaf,0x88,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x91,0xba,0xe1,0x06,\r\n\t0x16,0xf3,0xce,0xaa,0x9e,0xc2,0xe7,0x0c,0x16,0xf5,0xd1,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x88,0xb0,0xd8,0xff,0x29,0x04,0xdb,0xb3,0xdc,0x04,0x2c,0x05,0xdc,0xb4,\r\n\t0x8c,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1d,0x0e,0x0e,0x0e,0x12,0x1e,0x1a,0x07,\r\n\t0xea,0xcb,0xa6,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc8,0x9d,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x1d,0x0e,0x0e,0x0e,\r\n\t0x0e,0x0e,0x0e,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x25,0x19,0x19,0x19,0x19,\r\n\t0x19,0x19,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc8,0xc5,0xef,0x16,\r\n\t0x16,0x16,0x1f,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x1d,0x0e,0x0e,0x0e,\r\n\t0x0e,0x0e,0x0e,0x0e,0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0x0b,0x25,0x05,\r\n\t0xe3,0xc2,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xf1,0x19,\r\n\t0x0c,0x1b,0xf4,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xe3,0x0a,0x24,0xfc,0xd7,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x1e,\r\n\t0xf2,0xc8,0x9d,0x81,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xba,0x90,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xfa,0xfa,0xfa,0xff,0x11,0x26,0x0b,0xea,0xc8,0xa2,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x16,0x1e,0xf2,0xc8,0x9d,0x81,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xba,0x90,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x23,0x19,0x19,0x23,0x14,0xfc,0xea,0xd2,0xb4,0x94,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa1,0xbe,0xd8,0xed,0xff,0x0f,0x1f,0x28,0x15,0xff,0xe6,0xc8,\r\n\t0xa7,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0xa8,0xd0,0xf7,0x21,0x12,0xea,0xc2,\r\n\t0xdd,0x06,0x26,0xfc,0xd6,0xae,0x85,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0xf5,0x1e,0x0b,0x21,0xfa,0xd7,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8a,0xae,0xd1,0xf4,0x18,0x35,0x12,0xee,0xcb,0xa7,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x91,0xb5,0xda,0xff,0x24,0x0b,0x20,0x0a,0xe5,0xc0,0x9b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0xad,0xd0,0xf3,0x17,0x1a,0xf6,0xd3,0xb0,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa3,0xca,0xf1,0x18,0x0d,0xe6,0xbf,0x98,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x90,0xb9,0xdf,0xea,\r\n\t0xea,0xdf,0xba,0x95,0x89,0xad,0xd2,0xea,0xea,0xea,0xcf,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xbd,0xe6,0x0e,0x1f,0xf6,0xd0,0xd0,0xd0,0xf7,0x1f,0x12,0xea,0xc2,\r\n\t0x99,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe2,0xe2,0xe8,0xf6,0x10,0x27,\r\n\t0x05,0xdf,0xb7,0x8f,0x81,0x95,0xbf,0xe9,0x13,0x21,0xf5,0xcc,0xa2,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa0,\r\n\t0xca,0xf3,0x1e,0x14,0xea,0xc0,0x96,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe2,0xe2,\r\n\t0xe2,0xe2,0xe2,0xe2,0xc9,0xa3,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xed,0xed,0xed,\r\n\t0xed,0xed,0xeb,0xc9,0xa0,0x81,0x95,0xbf,0xe8,0x13,0x21,0xf5,0xcb,0xc1,0xe4,0xea,\r\n\t0xea,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe2,0xe2,\r\n\t0xe2,0xe2,0xe2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xf1,0x13,0x1e,\r\n\t0xfc,0xdb,0xba,0x99,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xe2,0x0a,\r\n\t0x31,0x0b,0xe4,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xd1,0xf7,0x1e,0x0f,0xe9,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xbf,0xe8,0x13,0x21,\r\n\t0xf5,0xca,0xa1,0x81,0x81,0xa7,0xd1,0xfa,0x26,0x0e,0xe2,0xb8,0x8e,0x95,0xc0,0xea,\r\n\t0x16,0x2d,0x26,0x26,0x25,0x1f,0x14,0x04,0xeb,0xce,0xaf,0x8d,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x13,0x21,0xf5,0xca,0xa1,0x81,0x81,0xa7,0xd0,0xfa,0x26,0x0e,0xe2,0xb8,0x8f,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xef,0xfc,0x1a,0x14,0xf1,0xcf,0xaa,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x83,0x9d,0xb3,0xc7,0xd8,0xe8,0xf7,0x0a,0x1f,0x23,0x05,0xe2,\r\n\t0xbc,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x9b,0xc3,0xec,0x14,0x1f,0xf6,0xce,\r\n\t0xea,0x12,0x19,0xf1,0xc8,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xe2,\r\n\t0x05,0x1d,0xf7,0x20,0x09,0xe1,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa1,0xc5,0xe8,0x0c,0x24,0x0c,0x28,0x05,0xe1,0xbd,0x9a,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa1,0xc6,0xeb,0x0f,0x31,0x1a,0xf4,0xd0,0xab,0x86,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xc5,0xe8,0x0b,0x25,0x04,0xdf,0xbc,0x99,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x93,0xb9,0xe1,0x07,0x1e,0xf6,0xcf,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0xa3,0xbb,0xc0,\r\n\t0xc0,0xbb,0xa3,0x81,0x81,0x97,0xb4,0xc0,0xc0,0xc0,0xb2,0x95,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa3,0xcb,0xf3,0x1b,0x13,0xfa,0xfa,0xfa,0xfa,0xfa,0x13,0x1f,0xf6,0xce,\r\n\t0xa6,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb8,0xc0,0xd4,0xf7,0x1f,\r\n\t0x14,0xea,0xc1,0x97,0x81,0x91,0xba,0xe5,0x0e,0x26,0xfc,0xd4,0xab,0x84,0x81,0x81,\r\n\t0x81,0x81,0x88,0x82,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x85,0xab,\r\n\t0xd2,0xfb,0x24,0x0e,0xe4,0xba,0x91,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb8,\r\n\t0xb8,0xb8,0xb8,0xb8,0xaa,0x8e,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0xc2,0xc2,\r\n\t0xc2,0xc2,0xc2,0xb0,0x90,0x81,0x90,0xba,0xe4,0x0e,0x26,0xfc,0xd3,0xaa,0xbd,0xc0,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb8,\r\n\t0xb8,0xb8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x8e,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xf9,0x1b,\r\n\t0x18,0xf5,0xd5,0xb3,0x92,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xd3,0xfa,\r\n\t0x11,0xfc,0xd5,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xbf,0xe6,0x0c,0x21,0xfa,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x91,0xba,0xe5,0x0f,0x24,\r\n\t0xfa,0xd1,0xa8,0x81,0x86,0xaf,0xd7,0xff,0x2b,0x09,0xdd,0xb4,0x8a,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xfa,0xfa,0xfa,0xf5,0xec,0xdc,0xc8,0xb0,0x92,0x81,0x81,0x81,0x92,0xbb,\r\n\t0xe5,0x11,0x24,0xfa,0xd1,0xa8,0x81,0x85,0xae,0xd7,0xff,0x2a,0x09,0xdd,0xb4,0x8a,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc5,0xdf,0x04,0x28,0x09,0xe3,0xbd,0x97,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xa0,0xb1,0xc1,0xd1,0xe4,0xfc,0x1e,0x1b,0xf4,\r\n\t0xcb,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,0x8e,0xb6,0xde,0x06,0x2c,0x04,0xdc,\r\n\t0xf7,0x1f,0x0b,0xe2,0xbb,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xec,\r\n\t0x14,0x11,0xec,0x14,0x19,0xf1,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x95,\r\n\t0xb8,0xdc,0xff,0x22,0x0d,0xf3,0x18,0x1b,0xf7,0xd4,0xb1,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8c,0xb1,0xd5,0xfc,0x29,0x09,0xe0,0xbb,0x96,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xb8,0xdc,0xff,0x22,0x0f,0xeb,0xc8,0xa4,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x82,0xa9,0xd0,0xf7,0x1e,0x07,0xe0,0xb9,0x92,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x82,0x92,0x95,\r\n\t0x95,0x92,0x82,0x81,0x81,0x81,0x8e,0x95,0x95,0x95,0x8d,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb0,0xd8,0xff,0x29,0x2b,0x26,0x26,0x26,0x26,0x26,0x2b,0x2c,0x04,0xdc,\r\n\t0xb4,0x8b,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x9c,0xc6,0xef,0x1b,\r\n\t0x19,0xed,0xc2,0x98,0x81,0x8a,0xb3,0xdc,0x06,0x2e,0x09,0xe2,0xbd,0x9e,0x90,0x90,\r\n\t0x98,0xa7,0xb2,0xaa,0x90,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0xa4,0xc0,\r\n\t0xe3,0x09,0x2a,0x04,0xda,0xb1,0x88,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x90,0x90,0x90,0x90,0x8b,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0x9b,0x98,\r\n\t0x98,0x98,0x98,0x8c,0x81,0x81,0x89,0xb2,0xdb,0x04,0x2c,0x09,0xe1,0xbc,0x9c,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x8d,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x8e,0x90,0xab,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xb0,0x90,0x8f,0x82,0x81,0x81,0x81,0xa1,0xb7,0xb8,0xa5,0x92,0x94,\r\n\t0xbe,0xe7,0x13,0x1e,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe0,0xff,\r\n\t0x23,0x10,0xee,0xce,0xac,0x8b,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0x9b,0x90,0x90,0x90,0x90,0x8c,0x81,0x81,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xc4,0xe2,\r\n\t0xe5,0xe2,0xc5,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xbd,0xd3,0xfa,0x20,0x0b,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x8b,0xb4,0xdd,0x06,0x2d,\r\n\t0x05,0xdc,0xb5,0x91,0x99,0xbc,0xe3,0x0b,0x26,0xfc,0xd5,0xac,0x82,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xd0,0xd0,0xcc,0xc3,0xb6,0xa4,0x8e,0x81,0x81,0x81,0x81,0x8c,0xb5,\r\n\t0xdf,0x09,0x2d,0x04,0xdc,0xb4,0x90,0x97,0xbb,0xe2,0x0b,0x26,0xfc,0xd5,0xac,0x83,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xc9,0xef,0x17,0x1b,0xf5,0xcf,0xaa,0x83,\r\n\t0x81,0x81,0x81,0x93,0xa5,0xa6,0x9a,0x92,0x8d,0x9a,0xab,0xc1,0xe5,0x0e,0x26,0xfa,\r\n\t0xd0,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x14,0x19,0xef,0xc5,0x9c,0x8a,0xad,0xd6,\r\n\t0xff,0x2a,0x04,0xd8,0xaf,0x85,0x81,0x81,0x81,0x81,0xa9,0xd1,0xf9,0x21,0x11,0xe7,\r\n\t0x04,0x25,0xfc,0xd5,0xad,0x85,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0xfa,\r\n\t0x22,0x04,0xde,0x06,0x28,0xff,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x89,0xac,\r\n\t0xd0,0xf3,0x16,0x1c,0xf7,0xde,0xff,0x26,0x0f,0xec,0xc8,0xa4,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x89,0xac,0xd0,0xf3,0x17,0x1a,0xf6,0xd3,0xb0,0x98,0x98,0x98,\r\n\t0x98,0x90,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x99,0xc0,0xe7,0x0e,0x17,0xf1,0xc9,0xa2,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x95,0xbd,0xe6,0x0e,0x20,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x21,0x11,0xe9,\r\n\t0xc1,0x99,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xba,0xc1,0xd4,0xf9,0x21,\r\n\t0x11,0xe7,0xbf,0x95,0x81,0x81,0xa8,0xd0,0xf7,0x1e,0x1b,0xf7,0xd9,0xc3,0xba,0xba,\r\n\t0xc1,0xcd,0xdd,0xcc,0xa8,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xc0,0xcb,0xdf,\r\n\t0xfb,0x1d,0x17,0xf1,0xcc,0xa4,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xba,\r\n\t0xba,0xba,0xba,0xba,0xb3,0x9a,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0x9b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa6,0xce,0xf5,0x1b,0x1a,0xf7,0xd7,0xc1,0xb7,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0xa1,0xb7,0xba,0xba,0xd5,0xff,\r\n\t0x2b,0x06,0xda,0xba,0xba,0xb9,0xa6,0x87,0x81,0x92,0xba,0xdd,0xdf,0xc9,0xbb,0xb6,\r\n\t0xca,0xf1,0x19,0x17,0xed,0xc4,0x9a,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc6,0xe8,\r\n\t0x0a,0x2b,0x09,0xe8,0xc6,0xa5,0x84,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,\r\n\t0xba,0xba,0xba,0xba,0xba,0xb4,0x9b,0x81,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xb5,0xb9,\r\n\t0xba,0xb9,0xad,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xbd,0xc1,0xe7,0x0f,0x1d,0xff,0x29,0xfc,0xd2,0xa8,0x81,0x81,0xaa,0xd2,0xfa,0x21,\r\n\t0x14,0xee,0xcc,0xb8,0xba,0xd4,0xf6,0x1b,0x16,0xef,0xc8,0xa0,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0xa5,0xa2,0x9b,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xab,\r\n\t0xd4,0xfb,0x24,0x13,0xee,0xcb,0xb6,0xb8,0xd2,0xf5,0x1a,0x17,0xef,0xc8,0xa0,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb8,0xde,0x04,0x2b,0x09,0xe1,0xbb,0x95,\r\n\t0x81,0x81,0x8c,0xb1,0xcd,0xcf,0xc3,0xbb,0xb7,0xb5,0xb9,0xc5,0xe7,0x11,0x21,0xf7,\r\n\t0xce,0xa4,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x91,0xbb,0xe4,0x0e,0x21,0xf7,0xd2,0xb7,0xb3,0xc1,0xe2,\r\n\t0x0a,0x23,0xfa,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x9b,0xc3,0xec,0x14,0x1d,0xf5,\r\n\t0x11,0x18,0xef,0xc8,0x9f,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0x09,\r\n\t0x1f,0xf6,0xd0,0xf7,0x20,0x11,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0xa0,0xc3,\r\n\t0xe6,0x0a,0x2b,0x06,0xe2,0xc8,0xec,0x10,0x25,0x04,0xde,0xbb,0x97,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa1,0xc4,0xe7,0x0b,0x25,0x04,0xdf,0xc2,0xc2,0xc2,0xc2,0xc2,\r\n\t0xc2,0xb6,0x99,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x88,0xaf,0xd6,0xfc,0x24,0xff,0xda,0xb3,0x8c,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa3,0xcb,0xf3,0x1b,0x14,0xeb,0xd5,0xd5,0xd5,0xd5,0xd5,0xec,0x14,0x1e,0xf5,\r\n\t0xcd,0xa5,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe5,0xe5,0xea,0xf6,0x10,0x22,\r\n\t0xff,0xda,0xb3,0x8b,0x81,0x81,0x99,0xbf,0xe5,0x09,0x2a,0x16,0xfb,0xeb,0xe3,0xe3,\r\n\t0xea,0xf5,0x05,0xda,0xb0,0x85,0x95,0xc0,0xea,0x16,0x19,0xed,0xe7,0xea,0xf2,0x04,\r\n\t0x1a,0x1f,0xff,0xdd,0xb9,0x93,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xd5,0xb0,0x88,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0x9b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xbc,0xe2,0x05,0x27,0x14,0xfa,0xe9,0xe1,\r\n\t0xe1,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xff,\r\n\t0x2b,0x06,0xe5,0xe5,0xe5,0xe1,0xc1,0x99,0x81,0x95,0xc0,0xea,0x04,0xf1,0xe4,0xdf,\r\n\t0xea,0x05,0x28,0x0a,0xe2,0xba,0x91,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xce,\r\n\t0xf0,0x12,0x23,0xff,0xe1,0xbf,0x9e,0x81,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xd7,0xb3,0x8a,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xb5,0x8f,\r\n\t0x90,0x8f,0xad,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xbd,0xaf,0xd5,0xfc,0x22,0x13,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x9c,0xc3,0xe9,0x0f,\r\n\t0x29,0x09,0xee,0xe2,0xe2,0xf3,0x10,0x24,0xff,0xdd,0xb8,0x91,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9e,\r\n\t0xc5,0xeb,0x10,0x28,0x07,0xed,0xdf,0xe1,0xf1,0x0f,0x25,0x04,0xde,0xb8,0x92,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xa6,0xcc,0xf1,0x19,0x1a,0xf4,0xce,0xa8,\r\n\t0x81,0x81,0x95,0xc0,0xea,0xf7,0xed,0xe5,0xe1,0xdf,0xe2,0xec,0xff,0x20,0x12,0xec,\r\n\t0xc5,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x89,0xb1,0xda,0xff,0x27,0x0d,0xf0,0xe1,0xdd,0xe6,0xfb,\r\n\t0x1d,0x12,0xec,0xc5,0x9d,0x81,0x81,0x81,0x81,0x81,0x8e,0xb6,0xde,0x06,0x2a,0xff,\r\n\t0x1e,0x0b,0xe2,0xba,0x92,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0e,0x17,\r\n\t0x11,0xe9,0xc2,0xea,0x12,0x1f,0x04,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x94,0xb7,0xda,\r\n\t0xfc,0x21,0x14,0xf0,0xcc,0xb2,0xd6,0xfa,0x1f,0x19,0xf5,0xd2,0xae,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x90,0xb8,0xdb,0xff,0x22,0x0f,0xed,0xed,0xed,0xed,0xed,0xed,0xed,\r\n\t0xed,0xd3,0xab,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xc6,0xed,0x14,0x11,0xea,0xc3,0x9c,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x87,0xb0,0xd8,0xff,0x29,0x06,0xde,0xb6,0xab,0xab,0xab,0xb7,0xdf,0x09,0x2b,0x04,\r\n\t0xdb,0xb3,0x8b,0x81,0x95,0xc0,0xea,0x16,0x1e,0x11,0x11,0x11,0x13,0x1e,0x1b,0x04,\r\n\t0xe6,0xc5,0xa1,0x81,0x81,0x81,0x86,0xab,0xcd,0xee,0x0b,0x22,0x21,0x14,0x0e,0x0e,\r\n\t0x13,0x1e,0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x16,0x20,0x13,0x13,0x14,0x1c,0x25,\r\n\t0x14,0xfc,0xe3,0xc3,0xa2,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x0b,0xdf,0xb5,0x8b,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc5,0x9b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xa8,0xca,0xea,0x09,0x20,0x20,0x12,0x0b,\r\n\t0x0b,0x11,0x21,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,\r\n\t0x2e,0x12,0x11,0x11,0x11,0xf2,0xc8,0x9d,0x81,0x95,0xc0,0xea,0x16,0x18,0x0e,0x0b,\r\n\t0x11,0x25,0x14,0xf3,0xd0,0xab,0x84,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb5,\r\n\t0xd6,0xf7,0x1a,0x1c,0xfb,0xd9,0xb8,0x96,0x81,0x95,0xc0,0xea,0x16,0x20,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x0e,0xe2,0xb8,0x8d,0x95,0xc0,0xea,0x16,0x0b,0xdf,0xb5,0x8b,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,\r\n\t0xbd,0x9e,0xc4,0xe9,0x11,0x37,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x8b,0xb0,0xd4,0xf5,\r\n\t0x14,0x29,0x15,0x0b,0x0c,0x19,0x22,0x07,0xe8,0xc7,0xa3,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,\r\n\t0xb2,0xd5,0xf7,0x16,0x27,0x13,0x0b,0x0b,0x17,0x24,0x09,0xea,0xc8,0xa5,0x81,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0xba,0xe0,0x06,0x2d,0x06,0xe0,0xba,\r\n\t0x94,0x81,0x95,0xc0,0xea,0x16,0x16,0x0f,0x0b,0x0b,0x0e,0x14,0x24,0x15,0xf9,0xd8,\r\n\t0xb4,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa2,0xc8,0xec,0x0d,0x27,0x15,0x0b,0x09,0x0e,0x1e,\r\n\t0x17,0xf9,0xd7,0xb3,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0xa9,0xd1,0xf9,0x21,0x1c,\r\n\t0x24,0xfc,0xd4,0xad,0x85,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x24,0x2b,\r\n\t0x04,0xdc,0xb4,0xdc,0x04,0x2c,0x21,0x1b,0xef,0xc5,0x9b,0x81,0x86,0xaa,0xcd,0xf1,\r\n\t0x14,0x22,0xff,0xda,0xb6,0x9c,0xc0,0xe5,0x09,0x2d,0x0d,0xe8,0xc5,0xa1,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x37,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,\r\n\t0x04,0xd7,0xad,0x83,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xb5,0xdc,0x04,0x21,0xfa,0xd3,0xad,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x92,0xbc,0xe5,0x0d,0x11,0xfa,0xd1,0xa9,0x81,0x81,0x82,0xaa,0xd2,0xfa,0x11,0x11,\r\n\t0xe8,0xbf,0x95,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,0x0b,0x04,0xf5,0xe1,\r\n\t0xc8,0xaa,0x8a,0x81,0x81,0x81,0x81,0x92,0xb2,0xd0,0xe8,0xfc,0x0b,0x14,0x19,0x16,\r\n\t0x11,0x07,0xfa,0xd9,0xaf,0x85,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x0e,0x09,0xfc,\r\n\t0xee,0xdb,0xc3,0xa7,0x88,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x0b,0xdf,0xb5,0x8b,0x95,0xc0,0xea,0x13,0x13,0xef,0xc5,0x9b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xae,0xcc,0xe6,0xfb,0x0b,0x13,0x19,\r\n\t0x16,0x11,0x09,0xfb,0xe8,0xc1,0x97,0x81,0x95,0xc0,0xea,0x11,0x11,0xed,0xc2,0x98,\r\n\t0x81,0xa8,0xd2,0xfc,0x11,0x06,0xda,0xb0,0x85,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x11,0xf2,0xc8,0x9d,0x81,0x94,0xbe,0xe6,0xff,0x0d,0x16,0x19,\r\n\t0x13,0x07,0xf1,0xd7,0xb8,0x96,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0xed,0xc2,0x9b,\r\n\t0xbd,0xde,0xff,0x11,0x11,0xf3,0xce,0xa4,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x0e,0xe2,0xb8,0x8d,0x95,0xc0,0xea,0x11,0x0b,0xdf,0xb5,0x8b,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x11,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x11,0x11,0xe7,\r\n\t0xbd,0x93,0xb2,0xd8,0xfc,0x11,0x11,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x99,0xb9,0xd7,\r\n\t0xf1,0x06,0x13,0x19,0x16,0x0d,0xfc,0xe6,0xca,0xac,0x8c,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x11,0x11,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9b,0xbb,0xd9,0xf4,0x09,0x16,0x27,0x1b,0x11,0xff,0xe8,0xcc,0xae,0xa0,0x89,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x13,0x13,0xed,0xc2,0x98,0xa8,0xce,0xf4,0x13,0x13,0xf3,0xcd,\r\n\t0xa4,0x81,0x95,0xc0,0xea,0x07,0x0e,0x13,0x18,0x19,0x16,0x0f,0x04,0xf1,0xd9,0xbd,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x11,0x06,0xda,0xb0,0x85,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb1,0xd0,0xed,0x04,0x11,0x16,0x19,0x13,0x07,\r\n\t0xf4,0xdb,0xbd,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc3,0xec,0x11,0x11,\r\n\t0x11,0xef,0xc7,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,\r\n\t0xf6,0xce,0xa6,0xce,0xf5,0x11,0x11,0x11,0xef,0xc5,0x9b,0x81,0x92,0xbc,0xe5,0x09,\r\n\t0x11,0x0d,0xe8,0xc5,0xa0,0x86,0xab,0xce,0xf3,0x11,0x11,0xff,0xdb,0xb2,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x11,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x04,0xd7,0xad,0x83,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa5,0xcc,0xf3,0x1a,0x0b,0xe3,0xbd,0x96,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8f,0xb8,0xdb,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x9d,0xc4,0xe2,0xe5,0xe5,\r\n\t0xdd,0xba,0x92,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe2,0xda,0xcd,0xbc,\r\n\t0xa7,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xae,0xc5,0xd6,0xe3,0xea,0xed,0xed,\r\n\t0xe7,0xdf,0xd2,0xc0,0xa1,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe2,0xde,0xd5,\r\n\t0xc8,0xb5,0xa0,0x87,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xd5,0xb0,0x88,0x92,0xbb,0xdf,0xe7,0xe7,0xe2,0xc0,0x98,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xab,0xc2,0xd4,0xe1,0xea,0xed,\r\n\t0xed,0xe7,0xdf,0xd3,0xc5,0xac,0x8a,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xde,0xbc,0x94,\r\n\t0x81,0xa4,0xcb,0xe4,0xe5,0xe5,0xd1,0xab,0x82,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe1,0xc1,0x99,0x81,0x87,0xaa,0xc6,0xd8,0xe4,0xea,0xed,\r\n\t0xea,0xe0,0xce,0xb7,0x9b,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xde,0xbc,0x94,\r\n\t0xa3,0xc5,0xe2,0xe5,0xe5,0xe4,0xc8,0xa1,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xd7,0xb3,0x8a,0x92,0xba,0xdd,0xe5,0xe5,0xd5,0xb0,0x88,\r\n\t0x81,0x81,0xa9,0xcf,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xdb,\r\n\t0xb8,0x8f,0xa0,0xc6,0xe3,0xe5,0xe5,0xe4,0xcb,0xa4,0x81,0x81,0x81,0x81,0x9b,0xb7,\r\n\t0xcd,0xde,0xe9,0xed,0xec,0xe4,0xd6,0xc4,0xac,0x8e,0x81,0x81,0x81,0x92,0xba,0xdd,\r\n\t0xe5,0xe5,0xde,0xbc,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9d,0xba,0xd0,0xe1,0xef,0x1b,0x0e,0xe7,0xd9,0xc6,0xc1,0xd2,0xc4,0xa4,0x81,\r\n\t0x81,0x92,0xbb,0xdf,0xe7,0xe7,0xe0,0xbd,0x95,0x96,0xbc,0xdf,0xe7,0xe7,0xe7,0xc9,\r\n\t0xa2,0x81,0x8e,0xb4,0xd2,0xdd,0xe5,0xea,0xed,0xed,0xea,0xe5,0xdb,0xcc,0xb7,0x9e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa6,0xcd,0xe5,0xe5,0xe5,0xd1,0xab,0x82,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xb2,0xc9,0xdb,0xe7,0xed,0xed,0xea,0xe0,\r\n\t0xcf,0xba,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb5,0xd9,0xe5,0xe5,\r\n\t0xe5,0xdb,0xb9,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,\r\n\t0xe0,0xc0,0x99,0xbf,0xe0,0xe5,0xe5,0xe5,0xe0,0xbf,0x97,0x81,0x8f,0xb8,0xdb,0xe5,\r\n\t0xe5,0xe5,0xd2,0xaf,0x8b,0x81,0x94,0xb9,0xdb,0xe5,0xe5,0xe5,0xd3,0xae,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa4,0xcb,0xe4,0xe5,0xe5,0xd3,0xae,0x85,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xcf,0xa9,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x93,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xbc,0xe2,0x0a,0x1b,0xf4,0xcd,0xa6,0x81,\r\n\t0x81,0x81,0x90,0x93,0x9d,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9f,0xb6,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x89,0xa8,0xb9,0xba,0xba,\r\n\t0xb7,0xa1,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xba,0xb8,0xb1,0xa5,0x97,\r\n\t0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x9f,0xaf,0xba,0xc0,0xc2,0xc2,\r\n\t0xbd,0xb6,0xaa,0x9b,0x85,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xb9,0xb5,0xac,\r\n\t0x9f,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xb3,0x9a,0x81,0x82,0xa3,0xb9,0xbd,0xbd,0xbb,0xa7,0x86,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x9c,0xad,0xb9,0xc0,0xc2,\r\n\t0xc2,0xbe,0xb6,0xab,0x9d,0x8b,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb8,0xa3,0x83,\r\n\t0x81,0x8f,0xac,0xba,0xba,0xba,0xb1,0x96,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xb9,0xa6,0x87,0x81,0x81,0x8b,0xa0,0xb0,0xbb,0xc1,0xc2,\r\n\t0xc0,0xb8,0xa8,0x94,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb8,0xa3,0x83,\r\n\t0x89,0xa8,0xb9,0xba,0xba,0xba,0xab,0x8d,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xb4,0x9b,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb3,0x9a,0x81,\r\n\t0x81,0x81,0x94,0xaf,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb6,\r\n\t0x9f,0x81,0x8b,0xa9,0xba,0xba,0xba,0xba,0xac,0x8f,0x81,0x81,0x81,0x81,0x81,0x94,\r\n\t0xa7,0xb6,0xbf,0xc2,0xc2,0xbb,0xaf,0x9e,0x89,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,\r\n\t0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x96,0xab,0xc1,0xea,0x12,0x1e,0xfb,0xe1,0xda,0xe6,0xfb,0xde,0xbb,0x98,\r\n\t0x81,0x82,0xa3,0xb9,0xbd,0xbd,0xba,0xa5,0x84,0x83,0xa3,0xb9,0xbd,0xbd,0xbd,0xad,\r\n\t0x8f,0x81,0x81,0x97,0xaa,0xb4,0xba,0xc0,0xc2,0xc2,0xc1,0xbc,0xb3,0xa5,0x93,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xae,0xba,0xba,0xba,0xb1,0x96,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xa4,0xb4,0xbd,0xc2,0xc2,0xc0,0xb7,\r\n\t0xa9,0x96,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xb5,0xba,0xba,\r\n\t0xba,0xb6,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,\r\n\t0xb8,0xa5,0x85,0xa5,0xb8,0xba,0xba,0xba,0xb8,0xa5,0x85,0x81,0x81,0x9f,0xb6,0xba,\r\n\t0xba,0xba,0xb1,0x96,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xb2,0x98,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8f,0xac,0xba,0xba,0xba,0xb2,0x98,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xaf,0x94,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0xbd,0xbd,0xb6,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xac,0xd2,0xf9,0x20,0x05,0xde,0xb6,0x90,\r\n\t0x82,0xa3,0xb9,0xbd,0xbd,0xc8,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x84,0x8f,0x90,0x90,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x90,0x8d,0x88,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x90,0x96,0x98,0x98,\r\n\t0x94,0x8d,0x82,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x8f,0x8a,0x83,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x8b,0x81,0x81,0x81,0x81,0x90,0x93,0x93,0x91,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x8f,0x96,0x98,\r\n\t0x98,0x94,0x8d,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x87,0x90,0x90,0x90,0x8a,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x8f,0x82,0x81,0x81,0x81,0x81,0x81,0x88,0x91,0x97,0x98,\r\n\t0x96,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x81,0x81,\r\n\t0x81,0x84,0x8f,0x90,0x90,0x90,0x86,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x8c,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x89,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8d,\r\n\t0x81,0x81,0x81,0x85,0x90,0x90,0x90,0x90,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8d,0x95,0x98,0x98,0x92,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,\r\n\t0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8c,0xb3,0xd9,0xfc,0x1d,0x1a,0x0a,0x06,0x0d,0x19,0xf5,0xd2,0xa9,\r\n\t0x81,0x81,0x81,0x90,0x93,0x93,0x91,0x82,0x81,0x81,0x81,0x90,0x93,0x93,0x92,0x88,\r\n\t0x81,0x81,0x81,0x81,0x82,0x8a,0x90,0x95,0x98,0x98,0x97,0x92,0x89,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x90,0x90,0x90,0x8a,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x94,0x98,0x98,0x95,0x8e,\r\n\t0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,\r\n\t0x90,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,\r\n\t0x8f,0x81,0x81,0x81,0x8f,0x90,0x90,0x90,0x8f,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,\r\n\t0x90,0x90,0x8a,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x8b,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x90,0x90,0x90,0x8b,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x89,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xe7,0xe7,0xe7,0xd9,0xb4,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc2,0xe9,0xfa,0xfa,0xe9,0xbf,0x95,\r\n\t0x92,0xbb,0xdf,0xe7,0xe7,0xe7,0xf2,0x1e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa0,0xc2,0xe1,0xfc,0x0f,0x19,0x1b,0x14,0x05,0xef,0xcf,0xa8,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1c,0x13,0x13,0x13,0x0e,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xcb,0xaf,0x8b,\r\n\t0x95,0xc0,0xea,0x13,0x13,0x13,0x13,0x24,0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x87,0xa5,0xc2,0xd8,0xe7,0xef,0xef,0xea,0xde,0xcc,0xb4,0x95,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,0x09,0x09,0x09,0x09,0x09,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xa2,0xa5,0xa5,0xa2,0x91,0x81,\r\n\t0x95,0xc0,0xea,0x09,0x09,0x09,0x09,0x09,0x09,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x86,0x9e,0xb1,0xbd,0xc5,0xc5,0xc1,0xb7,0xa6,0x91,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xd2,0xaf,0x88,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x90,0xb6,0xd6,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xd2,0xaf,0x88,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0x94,0x9b,0x9b,0x97,0x8e,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xad,0x96,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9b,0xaf,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xad,0x96,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x88,0x88,0x88,0x88,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x86,0x88,0x88,0x88,0x88,0x88,0x88,0x84,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xc9,0xad,0x88,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x8b,0x89,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x89,0x8b,0x8b,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0x8b,0x8b,\r\n\t0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0x8f,\r\n\t0x90,0x90,0x8c,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x86,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,\r\n\t0x8d,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x82,0x8d,0x8d,0x85,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x86,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x8b,0x8b,0x8b,0x8b,\r\n\t0x8b,0x8b,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x91,\r\n\t0x98,0x9b,0x9b,0x95,0x81,0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xe7,0xbd,0x92,0x81,0x88,\r\n\t0x98,0x9b,0x9b,0x96,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,0xb5,0xb5,0xb2,0x9d,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9d,0xb2,0xb5,0xb5,0xb2,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xb3,0xb5,0xb5,\r\n\t0xb2,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xa5,0xb2,0xb8,\r\n\t0xba,0xba,0xb6,0xaf,0xa1,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xaf,0x9b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x9f,0xb1,\r\n\t0xb8,0xb4,0xa3,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x93,0xaa,0xb7,0xb8,0xad,0x97,0x81,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xb0,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xac,0xb5,0xb5,0xb5,0xb5,\r\n\t0xb5,0xb5,0xb1,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x82,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xab,0xba,\r\n\t0xc2,0xc5,0xc5,0xbb,0x9e,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x86,0xa8,\r\n\t0xc1,0xc5,0xc5,0xc0,0xb5,0xa4,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb5,0xd7,0xdf,0xdf,0xdf,0xd9,0xbb,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x90,0xb8,0xd9,0xdf,0xdf,0xd9,0xb8,0x90,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xba,0xda,0xdf,0xdf,\r\n\t0xd9,0xb8,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xb8,0xcc,0xdb,0xe2,\r\n\t0xe5,0xe4,0xdf,0xd9,0xc0,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xd6,0xb6,\r\n\t0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xc1,0xd9,\r\n\t0xe2,0xdc,0xc6,0xa7,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,\r\n\t0xb2,0xce,0xe0,0xe2,0xd3,0xb8,0x96,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xd8,0xb9,0x92,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa9,0xce,0xdf,0xdf,0xdf,0xdf,\r\n\t0xdf,0xdf,0xd7,0xb5,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x82,0x95,0xa1,0xab,0xaf,0xa1,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb9,0xd1,0xe2,\r\n\t0xed,0xef,0xef,0xd9,0xb1,0x87,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x94,0xbd,\r\n\t0xe4,0xef,0xef,0xea,0xdc,0xc9,0xae,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbc,0xe6,0x05,0x0b,0x0b,0xf7,0xd9,0xbb,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x0b,0x0b,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x0b,0x0b,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xbb,0xd9,0xf1,0x04,0x0d,\r\n\t0x11,0x0e,0x0a,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,0x09,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb6,0xdc,0xfc,\r\n\t0x0e,0xff,0xe2,0xbd,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa2,\r\n\t0xc9,0xed,0x09,0x0b,0xf3,0xd0,0xa9,0x81,0x95,0xc0,0xea,0x09,0x09,0xed,0xc2,0x98,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x0b,0x0b,0x0b,\r\n\t0x0b,0x0b,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa0,0xbc,0xca,0xd4,0xd9,0xc0,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xb6,0xd7,0xf4,0x0a,\r\n\t0x16,0x1b,0x09,0xdd,0xb2,0x88,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x95,0xc0,\r\n\t0xea,0x16,0x19,0x13,0x04,0xea,0xcb,0xa8,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xac,0xc9,0xe3,0xfc,0x16,0x16,0xf7,0xd9,0xbb,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0xae,0xd4,0xf7,0x15,0x22,0x13,\r\n\t0x0e,0x11,0x15,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x14,\r\n\t0x37,0x1b,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,\r\n\t0xd5,0xff,0x28,0x2e,0x07,0xdd,0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x13,0x13,0x13,\r\n\t0x22,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8a,0xb3,0xdb,0xf3,0xfc,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa2,0xc9,0xef,0x13,0x21,\r\n\t0x0b,0xff,0xff,0xdd,0xb2,0x88,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x95,0xc0,\r\n\t0xea,0xff,0x04,0x12,0x26,0x06,0xe1,0xba,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xa8,0xc1,0xdb,0xf3,0x0f,0x16,0xf7,0xd9,\r\n\t0xb4,0x8b,0x81,0x81,0x81,0x81,0x88,0x91,0x97,0x9b,0x9b,0x98,0x90,0x84,0x81,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,0x96,0x9b,0x9b,0x94,0x88,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0x95,0x98,0x98,0x95,0x8e,0x84,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x8e,0x95,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x87,0x93,0x9a,0x9b,0x98,0x91,0x84,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xbd,0xe6,0x0d,0x23,0xff,0xea,\r\n\t0xe2,0xe5,0xeb,0xed,0xca,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x94,0x9a,0x9b,\r\n\t0x98,0x90,0x90,0x90,0x90,0x8f,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,\r\n\t0x97,0x9b,0x9a,0x93,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0x94,0xbd,0xe6,0x0d,\r\n\t0x25,0x12,0xed,0xc5,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x93,0x93,0x93,0xa9,\r\n\t0xd2,0xfa,0x1d,0x21,0xff,0xd9,0xb1,0x87,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x81,0x8b,0x90,0x90,0x90,0x8e,0x81,0x81,0x81,0x83,0xac,0xd3,0xe7,0xe7,0xe7,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x99,\r\n\t0x9b,0x95,0x86,0x94,0x9b,0x9a,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,\r\n\t0x8d,0x8d,0x97,0x9b,0x9a,0x93,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x85,0x91,0x99,0x9b,0x9a,0x94,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,\r\n\t0x90,0x8d,0x8b,0x96,0x9b,0x9b,0x94,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x82,0x8e,0x95,0x98,0x98,0x92,0x90,0x9a,0x98,0x88,0x81,0x81,0x81,0x8e,\r\n\t0x90,0x90,0x8d,0x87,0x94,0x9b,0x9b,0x95,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x83,0x90,0x98,0x9b,0x9b,0x98,0x95,0x8e,0x83,0x81,0x81,0x81,0x81,0x81,0x8e,\r\n\t0x90,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x90,0x90,0x90,0x8a,0x81,0x81,0x81,0x81,\r\n\t0x90,0x93,0x93,0x91,0x82,0x81,0x81,0x8c,0x93,0x93,0x93,0x89,0x81,0x81,0x81,0x81,\r\n\t0x90,0x93,0x93,0x92,0x88,0x81,0x81,0x81,0x81,0x8c,0x93,0x93,0x93,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x8d,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x90,0x90,0x90,\r\n\t0x86,0x81,0x81,0x81,0x81,0x8b,0x90,0x90,0x90,0x8d,0x81,0x81,0x81,0x81,0x8e,0x90,\r\n\t0x90,0x90,0x87,0x81,0x81,0x81,0x81,0x90,0x93,0x93,0x92,0x88,0x81,0x81,0x81,0x81,\r\n\t0x8b,0x93,0x93,0x93,0x8c,0x81,0x81,0x81,0x81,0x8c,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd6,0xff,0x28,0x06,\r\n\t0xe6,0xd7,0xd5,0xc8,0xa7,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x8d,0xb2,\r\n\t0xcf,0xd5,0xda,0xf0,0x14,0x19,0xef,0xc7,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x9f,0xb9,0xd3,0xec,0xef,0xef,0xde,\r\n\t0xb6,0x8c,0x81,0x81,0x91,0xa4,0xb1,0xba,0xc1,0xc5,0xc5,0xc2,0xb9,0xab,0x96,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,0xbf,0xc5,0xc5,0xbd,0xae,0x99,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xa6,0xb4,0xbf,0xc2,0xc2,0xbf,0xb8,0xac,\r\n\t0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xa9,0xb7,0xc0,0xc2,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x83,0x9b,0xae,0xbc,0xc4,0xc5,0xc2,0xba,0xab,0x97,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xc7,0xf1,0x1a,0x13,0xeb,0xc5,\r\n\t0xb8,0xbb,0xc2,0xc4,0xb2,0x91,0x81,0x81,0x81,0x81,0x85,0x9c,0xaf,0xbd,0xc4,0xc5,\r\n\t0xc2,0xba,0xba,0xba,0xba,0xb8,0xa5,0x85,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,\r\n\t0xc0,0xc5,0xc4,0xbc,0xac,0x96,0x81,0x81,0x81,0x81,0x97,0xb3,0xbd,0xbd,0xd1,0xee,\r\n\t0xfa,0xf1,0xd7,0xb5,0x8f,0x81,0x81,0x81,0x81,0x81,0x93,0xb0,0xbd,0xbd,0xbd,0xbd,\r\n\t0xc0,0xe1,0xf6,0xf9,0xe6,0xc6,0xa2,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x98,0xb2,0xba,0xba,0xba,0xb7,0xa1,0x81,0x81,0x81,0x97,0xb3,0xbd,0xbd,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb4,0xc3,\r\n\t0xc5,0xbd,0xaa,0xbb,0xc5,0xc4,0xb6,0xa1,0x83,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,\r\n\t0xb5,0xb4,0xc1,0xc5,0xc4,0xbc,0xac,0x96,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x99,\r\n\t0xad,0xba,0xc2,0xc5,0xc4,0xbd,0xb1,0x9f,0x89,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,\r\n\t0xba,0xb5,0xb3,0xbf,0xc5,0xc5,0xbd,0xad,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x97,0xaa,0xb8,0xc0,0xc2,0xc2,0xbc,0xb9,0xc3,0xc1,0xa8,0x86,0x81,0xa1,0xb7,\r\n\t0xba,0xba,0xb5,0xae,0xbd,0xc5,0xc5,0xbe,0xaf,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x97,0xaa,0xb9,0xc2,0xc5,0xc5,0xc2,0xbf,0xb8,0xa9,0x8c,0x81,0x81,0x81,0xa1,0xb7,\r\n\t0xba,0xba,0xdf,0x0b,0x23,0xf7,0xcd,0xba,0xba,0xba,0xba,0xb1,0x96,0x81,0x82,0xa3,\r\n\t0xb9,0xbd,0xbd,0xba,0xa5,0x84,0x97,0xb3,0xbd,0xbd,0xbd,0xaf,0x91,0x81,0x82,0xa3,\r\n\t0xb9,0xbd,0xbd,0xbd,0xad,0x8f,0x81,0x81,0x98,0xb3,0xbd,0xbd,0xbd,0xb2,0x95,0x81,\r\n\t0x81,0x9f,0xb6,0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0x81,0x96,0xb1,0xba,0xba,0xba,\r\n\t0xab,0x8d,0x81,0x81,0x9a,0xb3,0xba,0xba,0xba,0xb5,0x9d,0x81,0x83,0xa3,0xb8,0xba,\r\n\t0xba,0xba,0xac,0x8f,0x81,0x81,0xa1,0xb9,0xbd,0xbd,0xbd,0xad,0x8f,0x81,0x81,0x96,\r\n\t0xb2,0xbd,0xbd,0xbd,0xb3,0x97,0x81,0x81,0x9b,0xb4,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xb8,0xa5,0x85,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x07,0x21,0xf7,\r\n\t0xce,0xad,0xab,0xa3,0x8c,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x95,\r\n\t0xa8,0xab,0xb5,0xde,0x09,0x21,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xb1,0xc4,0xc5,0xc5,0xbe,\r\n\t0xa2,0x81,0x81,0x8b,0xaf,0xcb,0xd9,0xe4,0xea,0xef,0xef,0xec,0xe1,0xd1,0xb9,0x9b,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xd9,0xe7,0xef,0xef,0xe6,0xd3,0xb9,0x9b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xb7,0xcc,0xdc,0xe7,0xed,0xed,0xe9,0xe1,0xd3,\r\n\t0xb9,0x94,0x81,0x81,0x81,0x83,0xa1,0xba,0xcf,0xdf,0xea,0xed,0xed,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x87,0xa4,0xbe,0xd4,0xe5,0xed,0xef,0xed,0xe2,0xd1,0xba,\r\n\t0x9f,0x81,0x81,0x81,0x81,0x81,0x8b,0x9b,0x9d,0xa0,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0x9d,0x9d,0x9d,0x9a,0x8e,0x81,0x81,0x81,0x81,0x87,0xa5,0xc0,0xd5,0xe5,0xed,0xef,\r\n\t0xeb,0xe5,0xe5,0xe5,0xe5,0xe0,0xbf,0x97,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xda,\r\n\t0xea,0xef,0xed,0xe4,0xd0,0xb6,0x97,0x81,0x81,0x83,0xac,0xd3,0xe7,0xe7,0xe7,0xe7,\r\n\t0xe7,0xe7,0xdd,0xb9,0x90,0x81,0x81,0x81,0x81,0x81,0xa7,0xce,0xe7,0xe7,0xe7,0xe7,\r\n\t0xe7,0xe7,0xe7,0xe7,0xe6,0xc7,0x9f,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0xb6,0xd4,0xe5,0xe5,0xe5,0xdd,0xba,0x92,0x81,0x81,0x81,0x8c,0x93,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xd9,0xec,\r\n\t0xef,0xe5,0xca,0xe1,0xef,0xed,0xdc,0xbf,0x9d,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,\r\n\t0xd9,0xdb,0xea,0xef,0xed,0xe4,0xd1,0xb6,0x98,0x81,0x81,0x81,0x81,0x85,0xa3,0xbd,\r\n\t0xd3,0xe3,0xed,0xef,0xed,0xe7,0xd8,0xc3,0xaa,0x8c,0x81,0x81,0x92,0xba,0xdd,0xe5,\r\n\t0xe5,0xd9,0xda,0xe8,0xef,0xef,0xe6,0xd3,0xb9,0x9b,0x81,0x81,0x81,0x81,0x81,0x83,\r\n\t0xa1,0xbb,0xcf,0xe0,0xea,0xed,0xec,0xe6,0xe2,0xec,0xe4,0xbd,0x94,0x92,0xba,0xdd,\r\n\t0xe5,0xe5,0xd9,0xd4,0xe6,0xef,0xef,0xe7,0xd5,0xbb,0x9d,0x81,0x81,0x81,0x81,0x9f,\r\n\t0xba,0xd1,0xe1,0xeb,0xef,0xef,0xed,0xe7,0xe1,0xc7,0xa0,0x81,0x81,0x92,0xba,0xdd,\r\n\t0xe5,0xe5,0xe5,0x0b,0x23,0xf7,0xe5,0xe5,0xe5,0xe5,0xe5,0xd1,0xab,0x82,0x92,0xbb,\r\n\t0xdf,0xe7,0xe7,0xe0,0xbd,0x95,0xac,0xd3,0xe7,0xe7,0xe7,0xcc,0xa4,0x81,0x92,0xbb,\r\n\t0xdf,0xe7,0xe7,0xe7,0xc9,0xa2,0x81,0x86,0xae,0xd3,0xe7,0xe7,0xe7,0xd0,0xa9,0x81,\r\n\t0x8f,0xb8,0xdb,0xe5,0xe5,0xde,0xbc,0x94,0x81,0x81,0x82,0xab,0xd1,0xe5,0xe5,0xe4,\r\n\t0xc8,0xa1,0x81,0x88,0xb0,0xd5,0xe5,0xe5,0xe5,0xd9,0xb7,0x94,0x9b,0xbe,0xde,0xe5,\r\n\t0xe5,0xe4,0xcb,0xa4,0x81,0x90,0xb9,0xdd,0xe7,0xe7,0xe7,0xcb,0xa4,0x81,0x84,0xac,\r\n\t0xd1,0xe7,0xe7,0xe7,0xd3,0xac,0x83,0x8a,0xb3,0xd7,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe0,0xbf,0x97,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x9a,0x9b,0x9b,0x96,\r\n\t0x83,0x81,0x81,0x95,0xbf,0xe9,0xff,0x0d,0x15,0x1a,0x1b,0x15,0x0a,0xf4,0xd7,0xb7,\r\n\t0x93,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xfc,0x0f,0x19,0x19,0x0d,0xf5,0xd7,0xb5,\r\n\t0x91,0x81,0x81,0x81,0x81,0x9c,0xbb,0xd9,0xf1,0x05,0x11,0x19,0x19,0x13,0x0a,0xf2,\r\n\t0xc8,0x9d,0x81,0x81,0x81,0xa0,0xbf,0xdd,0xf5,0x07,0x13,0x19,0x16,0x0f,0x1b,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0xa1,0xc2,0xdf,0xf9,0x0c,0x18,0x1b,0x16,0x0a,0xf5,0xdb,\r\n\t0xbc,0x9a,0x81,0x81,0x81,0x8a,0xac,0xc4,0xc8,0xc8,0xca,0xf5,0x21,0x0e,0xe2,0xc8,\r\n\t0xc8,0xc8,0xc8,0xc2,0xa8,0x85,0x81,0x81,0x81,0xa0,0xc2,0xe1,0xfb,0x0d,0x19,0x1b,\r\n\t0x14,0x11,0x11,0x11,0x11,0xef,0xc5,0x9b,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xff,\r\n\t0x12,0x1b,0x19,0x0b,0xf1,0xd3,0xaf,0x8a,0x81,0x85,0xb0,0xda,0x06,0x13,0x13,0x13,\r\n\t0x13,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x13,0x13,0x13,\r\n\t0x13,0x13,0x13,0x13,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb6,\r\n\t0xd4,0xf1,0x10,0x11,0x05,0xe6,0xbe,0x94,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x06,0xf7,0x13,\r\n\t0x19,0x07,0xe4,0x05,0x19,0x15,0xfb,0xd6,0xb0,0x88,0x81,0x95,0xc0,0xea,0x11,0x11,\r\n\t0xe6,0xff,0x13,0x1b,0x19,0x0b,0xf1,0xd3,0xaf,0x8a,0x81,0x81,0x81,0xa1,0xc1,0xdf,\r\n\t0xf7,0x0b,0x16,0x1b,0x19,0x0f,0xfc,0xe6,0xc8,0xa8,0x86,0x81,0x95,0xc0,0xea,0x11,\r\n\t0x11,0xe6,0xff,0x11,0x19,0x19,0x0c,0xf4,0xd6,0xb5,0x91,0x81,0x81,0x81,0x81,0xa0,\r\n\t0xbf,0xdd,0xf5,0x09,0x13,0x19,0x16,0x0f,0x0b,0x15,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x11,0x11,0xe5,0xf9,0x0d,0x19,0x19,0x0f,0xf7,0xd9,0xb5,0x8f,0x81,0x81,0x99,0xbb,\r\n\t0xdb,0xf5,0x09,0x15,0x1b,0x1b,0x19,0x13,0xfa,0xd0,0xa5,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x11,0x11,0x11,0x14,0x27,0x11,0x11,0x11,0x11,0x11,0x06,0xda,0xb0,0x85,0x95,0xc0,\r\n\t0xea,0x13,0x13,0xed,0xc2,0x98,0xb0,0xda,0x06,0x13,0xfc,0xd2,0xa8,0x81,0x94,0xbd,\r\n\t0xe5,0x0d,0x13,0xff,0xd8,0xb1,0x89,0x95,0xbd,0xe4,0x0c,0x13,0xfc,0xd6,0xac,0x82,\r\n\t0x92,0xbd,0xe7,0x11,0x11,0xef,0xc5,0x9b,0x93,0x93,0x90,0xb2,0xdd,0x07,0x11,0xfa,\r\n\t0xd0,0xa5,0x81,0x8a,0xb4,0xdc,0xff,0x11,0x11,0xf1,0xcf,0xac,0xb2,0xd5,0xf9,0x11,\r\n\t0x11,0xf5,0xd1,0xa7,0x81,0x91,0xbb,0xe2,0x0a,0x13,0x04,0xdb,0xb4,0x8c,0x92,0xba,\r\n\t0xe1,0x0a,0x13,0xff,0xd8,0xaf,0x85,0x8d,0xb8,0xe2,0x0e,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0x0b,0x06,0x06,0x11,0x27,0x14,0xf1,0xcb,\r\n\t0xa4,0x81,0x95,0xc0,0xea,0x16,0x16,0x04,0x20,0x0f,0x06,0x0d,0x25,0x12,0xef,0xcb,\r\n\t0xa4,0x81,0x81,0x81,0x91,0xb5,0xd7,0xf7,0x14,0x26,0x13,0x09,0x09,0x0e,0x19,0xf2,\r\n\t0xc8,0x9d,0x81,0x81,0x93,0xb8,0xdb,0xfb,0x18,0x1a,0x0b,0x06,0x09,0x11,0x23,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x94,0xba,0xdd,0xfc,0x1c,0x14,0x04,0xff,0x09,0x1d,0x18,0xf7,\r\n\t0xd5,0xaf,0x8a,0x81,0x81,0x97,0xc1,0xe8,0xf2,0xf2,0xf2,0xf5,0x21,0x0e,0xf2,0xf2,\r\n\t0xf2,0xf2,0xf2,0xe3,0xbb,0x92,0x81,0x81,0x8e,0xb4,0xda,0xfc,0x1d,0x14,0xff,0xfa,\r\n\t0x05,0x1c,0x23,0x0b,0x0b,0xef,0xc5,0x9b,0x81,0x95,0xc0,0xea,0x16,0x16,0x04,0x20,\r\n\t0x0c,0x06,0x0f,0x2b,0x0d,0xe8,0xc1,0x99,0x81,0x85,0xb0,0xda,0x06,0x0b,0x0b,0x0b,\r\n\t0x1e,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x0b,0x0b,0x0b,\r\n\t0x0b,0x0b,0x10,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xd2,\r\n\t0xf1,0x10,0x23,0x05,0xe6,0xc8,0xaa,0x87,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x06,0x11,0x06,\r\n\t0x0d,0x1a,0xfa,0x16,0x04,0x1a,0x0e,0xe6,0xbc,0x92,0x81,0x95,0xc0,0xea,0x16,0x11,\r\n\t0x07,0x1f,0x0b,0x06,0x11,0x2b,0x0f,0xe8,0xc2,0x99,0x81,0x81,0x94,0xba,0xdd,0xfc,\r\n\t0x1a,0x1b,0x0b,0x06,0x0b,0x1a,0x21,0x05,0xe3,0xc0,0x9a,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x11,0x05,0x22,0x0f,0x06,0x0d,0x25,0x12,0xef,0xc9,0xa3,0x81,0x81,0x81,0x93,0xb8,\r\n\t0xdb,0xfb,0x18,0x18,0x09,0x04,0x06,0x0f,0x23,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x11,0xfc,0x1a,0x11,0x06,0x0b,0x23,0x13,0xee,0xc8,0xa0,0x81,0x83,0xab,0xd2,\r\n\t0xf6,0x17,0x1a,0x0a,0x04,0x04,0x09,0x0e,0xfa,0xd0,0xa5,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x0e,0x0e,0x0e,0x12,0x26,0x0e,0x0e,0x0e,0x0e,0x0e,0x06,0xda,0xb0,0x85,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x87,0xaf,\r\n\t0xd6,0xfc,0x24,0x0f,0xe7,0xbf,0x98,0xa4,0xcb,0xf3,0x1a,0x15,0xee,0xc7,0x9f,0x81,\r\n\t0x8d,0xb7,0xe0,0x0b,0x1e,0xf5,0xca,0xb2,0xbd,0xbd,0xb9,0xb8,0xe2,0x0b,0x1e,0xf3,\r\n\t0xca,0xa0,0x81,0x81,0xa3,0xc5,0xe6,0x09,0x2b,0x0a,0xe6,0xc4,0xca,0xed,0x10,0x20,\r\n\t0xff,0xdd,0xbb,0x99,0x81,0x84,0xac,0xd3,0xfa,0x22,0x11,0xea,0xc3,0x9b,0xa0,0xc8,\r\n\t0xef,0x18,0x18,0xf1,0xc9,0xa2,0x81,0x8d,0xb8,0xe2,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,\r\n\t0x0e,0x29,0x1a,0xef,0xc5,0x9b,0x81,0x81,0x81,0x86,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x88,0x82,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xc0,0xea,0xf7,0xeb,0xe1,0xda,0xdd,0xec,0x0b,0x2a,0xff,0xd8,\r\n\t0xaf,0x85,0x95,0xc0,0xea,0x16,0x21,0x1d,0xff,0xe8,0xda,0xe8,0x09,0x29,0x04,0xda,\r\n\t0xb2,0x89,0x81,0x81,0xa3,0xc9,0xef,0x12,0x22,0x04,0xec,0xdf,0xdf,0xe5,0xf2,0xf1,\r\n\t0xc7,0x9d,0x81,0x81,0xa5,0xcc,0xf1,0x16,0x16,0xf7,0xe2,0xda,0xdf,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0xa6,0xcd,0xf3,0x18,0x13,0xf1,0xdc,0xd6,0xe2,0xfc,0x1f,0x0f,\r\n\t0xe8,0xc0,0x98,0x81,0x81,0x98,0xc2,0xed,0x19,0x1e,0x1e,0x1e,0x2c,0x21,0x1e,0x1e,\r\n\t0x1e,0x1e,0x13,0xe7,0xbd,0x93,0x81,0x81,0x9a,0xc3,0xec,0x13,0x1a,0xf5,0xd9,0xd1,\r\n\t0xe0,0xff,0x26,0x07,0xdf,0xdb,0xbc,0x95,0x81,0x95,0xc0,0xea,0x16,0x23,0x1d,0xff,\r\n\t0xe5,0xda,0xee,0x13,0x1f,0xf5,0xcc,0xa3,0x81,0x81,0xa9,0xce,0xdf,0xdf,0xdf,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0xa4,0xca,0xdf,0xdf,0xdf,0xdf,\r\n\t0xdf,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xd2,0xf0,\r\n\t0x0f,0x21,0x04,0xe6,0xc8,0xaa,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x0d,0x0b,0xe8,\r\n\t0xfc,0x1f,0x0d,0xfc,0xe5,0x0f,0x16,0xec,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x1e,\r\n\t0x1d,0xff,0xe5,0xdb,0xee,0x13,0x1f,0xf5,0xcc,0xa3,0x81,0x81,0xa6,0xcd,0xf3,0x18,\r\n\t0x18,0xf9,0xe2,0xda,0xe2,0xf7,0x16,0x1e,0xf9,0xd2,0xaa,0x82,0x95,0xc0,0xea,0x16,\r\n\t0x1c,0x1f,0xff,0xe8,0xda,0xe8,0x09,0x28,0xff,0xda,0xb1,0x89,0x81,0x81,0xa5,0xcc,\r\n\t0xf1,0x16,0x15,0xf5,0xe0,0xd7,0xdc,0xed,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x14,0x1b,0x07,0xec,0xdc,0xe6,0x0a,0x26,0xfc,0xd4,0xab,0x82,0x8c,0xb6,0xdf,\r\n\t0x09,0x23,0xfb,0xe1,0xd9,0xd8,0xdd,0xe5,0xe9,0xcb,0xa2,0x81,0x81,0x91,0xb9,0xdb,\r\n\t0xe2,0xe2,0xe2,0x0b,0x23,0xf7,0xe2,0xe2,0xe2,0xe2,0xe2,0xd0,0xaa,0x82,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x9f,\r\n\t0xc7,0xee,0x15,0x1d,0xf5,0xce,0xa6,0xb2,0xda,0xff,0x2a,0x06,0xdf,0xb7,0x90,0x81,\r\n\t0x87,0xb1,0xda,0x04,0x23,0xfa,0xd0,0xd0,0xe7,0xe7,0xdd,0xbd,0xe7,0x11,0x17,0xed,\r\n\t0xc4,0x9a,0x81,0x81,0x8a,0xac,0xce,0xf0,0x12,0x22,0xff,0xdb,0xe2,0x05,0x27,0x07,\r\n\t0xe5,0xc3,0xa1,0x81,0x81,0x81,0x9c,0xc4,0xeb,0x12,0x20,0xf9,0xd2,0xaa,0xaf,0xd6,\r\n\t0xfc,0x26,0x0a,0xe1,0xba,0x93,0x81,0x89,0xb2,0xd5,0xe2,0xe2,0xe2,0xe2,0xe2,0xea,\r\n\t0x0d,0x22,0xff,0xdf,0xbc,0x95,0x81,0x81,0x9b,0xaf,0xb2,0xb7,0xdf,0x09,0x1e,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x05,0x23,0xfa,0xd1,0xb5,0xb2,0xaa,0x90,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8c,0xb1,0xcd,0xd0,0xc2,0xbf,0xc2,0xc2,0xd3,0xfc,0x26,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x22,0xff,0xe1,0xc5,0xb1,0xcf,0xf7,0x20,0x0e,0xe5,\r\n\t0xbb,0x91,0x81,0x89,0xb2,0xda,0xff,0x28,0x0b,0xe6,0xc8,0xb6,0xb5,0xbc,0xcc,0xd0,\r\n\t0xb7,0x93,0x81,0x89,0xb3,0xdb,0x04,0x28,0xff,0xdb,0xbd,0xb0,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x8a,0xb3,0xdc,0x04,0x27,0xff,0xd9,0xbd,0xbd,0xc1,0xe7,0x0e,0x1e,\r\n\t0xf5,0xcc,0xa2,0x81,0x81,0x98,0xc2,0xed,0xff,0xff,0xff,0xff,0x21,0x0e,0xff,0xff,\r\n\t0xff,0xff,0xff,0xe7,0xbd,0x93,0x81,0x81,0xa0,0xca,0xf5,0x1e,0x0e,0xe5,0xbc,0xa7,\r\n\t0xc8,0xf2,0x1b,0x12,0xe7,0xbd,0xa0,0x82,0x81,0x95,0xc0,0xea,0x16,0x20,0xff,0xe1,\r\n\t0xc3,0xb5,0xde,0x09,0x26,0xfc,0xd2,0xa8,0x81,0x81,0x92,0xac,0xb5,0xb5,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x8e,0xa9,0xb5,0xb5,0xb5,0xb5,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xf0,0x0f,\r\n\t0x21,0x04,0xe4,0xc8,0xaa,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf7,0xd2,\r\n\t0xfa,0x26,0x0f,0xe8,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x21,\r\n\t0xff,0xe1,0xc3,0xb5,0xde,0x09,0x26,0xfc,0xd2,0xa8,0x81,0x8a,0xb3,0xdc,0x04,0x29,\r\n\t0xff,0xdd,0xbd,0xb0,0xbc,0xdb,0xff,0x28,0x09,0xdf,0xb6,0x8d,0x95,0xc0,0xea,0x16,\r\n\t0x23,0xff,0xe3,0xc5,0xb1,0xcf,0xf7,0x20,0x0e,0xe5,0xbb,0x91,0x81,0x89,0xb2,0xdb,\r\n\t0x04,0x28,0xff,0xdb,0xba,0xad,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x27,0x07,0xe8,0xca,0xb3,0xd4,0xfc,0x29,0x06,0xda,0xb1,0x87,0x8d,0xb8,0xe2,\r\n\t0x0e,0x21,0xf9,0xda,0xc8,0xbb,0xb4,0xbb,0xbf,0xaf,0x91,0x81,0x81,0x81,0x9f,0xb4,\r\n\t0xb8,0xb8,0xdf,0x0b,0x23,0xf7,0xcd,0xb8,0xb8,0xb8,0xb8,0xae,0x94,0x81,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x90,\r\n\t0xb7,0xde,0x06,0x2c,0x04,0xdc,0xb5,0xc1,0xe8,0x11,0x1e,0xf6,0xcf,0xa8,0x81,0x81,\r\n\t0x81,0xaa,0xd4,0xfc,0x29,0xff,0xd5,0xdf,0x07,0x13,0xef,0xc8,0xea,0x16,0x11,0xe7,\r\n\t0xbd,0x94,0x81,0x81,0x81,0x93,0xb5,0xd6,0xf7,0x1a,0x17,0xf3,0xf9,0x1d,0x0f,0xee,\r\n\t0xcc,0xaa,0x88,0x81,0x81,0x81,0x8d,0xb4,0xdb,0x04,0x2a,0x09,0xe1,0xb9,0xbd,0xe4,\r\n\t0x0c,0x22,0xfa,0xd3,0xab,0x84,0x81,0x81,0x9a,0xb2,0xb8,0xb8,0xb8,0xc2,0xe3,0x05,\r\n\t0x26,0x09,0xe6,0xc5,0xa4,0x82,0x81,0x90,0xb6,0xd6,0xdd,0xe1,0xf1,0x13,0x13,0xec,\r\n\t0xc3,0x9a,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x81,0xa9,0xd2,0xfb,0x22,0x09,0xeb,0xdf,0xdd,0xcc,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9f,0xba,0xcf,0xdf,0xe7,0xed,0xed,0xed,0xfa,0x26,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xc6,0xa6,0x9b,0xc5,0xef,0x19,0x16,0xea,\r\n\t0xc0,0x97,0x81,0x91,0xbb,0xe5,0x0e,0x22,0xfa,0xd2,0xac,0x8e,0x8b,0x94,0xa4,0xa7,\r\n\t0x97,0x81,0x81,0x92,0xbb,0xe5,0x0e,0x1e,0xf3,0xca,0xa2,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x92,0xbc,0xe5,0x0f,0x1e,0xf3,0xe7,0xe7,0xe7,0xe7,0xe7,0x06,0x26,\r\n\t0xfa,0xd2,0xa8,0x81,0x81,0x8f,0xb5,0xd1,0xd5,0xd5,0xd5,0xf5,0x21,0x0e,0xe2,0xd5,\r\n\t0xd5,0xd5,0xd5,0xce,0xb0,0x8a,0x81,0x81,0xa0,0xca,0xf5,0x1f,0x0f,0xe6,0xbe,0xac,\r\n\t0xcb,0xf2,0x1c,0x11,0xe7,0xbd,0x93,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc5,\r\n\t0xa5,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x85,0x8b,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x8b,0x8b,0x8b,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xf0,0x0f,0x21,\r\n\t0x04,0xe4,0xc7,0xa9,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd6,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc5,0xa5,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x92,0xbc,0xe5,0x0f,0x1e,\r\n\t0xf5,0xcc,0xa3,0x86,0xa2,0xcb,0xf4,0x1e,0x11,0xe7,0xbd,0x93,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc6,0xa7,0x9b,0xc5,0xef,0x19,0x16,0xea,0xc0,0x96,0x81,0x91,0xbb,0xe4,\r\n\t0x0e,0x1e,0xf4,0xca,0xa2,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xcb,0xac,0xa5,0xd0,0xfa,0x04,0x04,0xdd,0xb2,0x88,0x89,0xb3,0xdb,\r\n\t0x04,0x25,0x14,0xff,0xf1,0xe4,0xd6,0xc7,0xb4,0x9d,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0x8d,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x8d,0x8d,0x8d,0x87,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0xa8,0xcf,0xf6,0x1e,0x13,0xec,0xc3,0xcf,0xf7,0x1f,0x0f,0xe7,0xc0,0x99,0x81,0x81,\r\n\t0x81,0xa4,0xce,0xf7,0x22,0x04,0xda,0xec,0x14,0x25,0xfc,0xd6,0xef,0x1a,0x0b,0xe1,\r\n\t0xb7,0x8d,0x81,0x81,0x81,0x81,0x9b,0xbd,0xdf,0xff,0x23,0x0c,0x11,0x18,0xf5,0xd4,\r\n\t0xb2,0x91,0x81,0x81,0x81,0x81,0x81,0xa4,0xcc,0xf3,0x1a,0x17,0xef,0xc8,0xcb,0xf2,\r\n\t0x1a,0x13,0xec,0xc4,0x9c,0x81,0x81,0x81,0x81,0x89,0x8d,0x99,0xba,0xdb,0xfc,0x1e,\r\n\t0x10,0xee,0xcd,0xac,0x8a,0x81,0x81,0x95,0xc0,0xea,0x09,0x0b,0x15,0x12,0xf9,0xd9,\r\n\t0xb4,0x8e,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x81,0x9d,0xc4,0xe7,0x06,0x18,0x12,0x09,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9b,0xbd,0xdb,0xf5,0x07,0x12,0x17,0x19,0x19,0x19,0x2d,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x96,0xc0,0xea,0x16,0x19,0xed,\r\n\t0xc2,0x98,0x81,0x95,0xc0,0xea,0x14,0x1b,0xf1,0xc7,0x9d,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xc0,0xea,0x14,0x19,0xed,0xc4,0x9a,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x95,0xc0,0xea,0x16,0x22,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x29,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x96,0xa8,0xab,0xab,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0xab,0xab,0xab,0xa7,0x93,0x81,0x81,0x81,0x9a,0xc3,0xec,0x13,0x1d,0xf7,0xde,0xd5,\r\n\t0xe4,0x04,0x29,0x05,0xdd,0xb5,0x8c,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0x0f,0x2c,0x04,\r\n\t0xe4,0xc7,0xa9,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd5,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc4,0x9a,0x81,0x9a,0xc4,0xed,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0x96,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,\r\n\t0x14,0x19,0xed,0xc4,0x9a,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x9c,0xc1,0xd7,0xd7,0xd7,0xca,0xa8,0x81,0x81,0xa4,0xc8,\r\n\t0xea,0x07,0x1d,0x26,0x19,0x0c,0xff,0xee,0xd8,0xbd,0x9d,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x98,0xc0,0xe7,0x0f,0x21,0xfa,0xd2,0xde,0x06,0x26,0xff,0xd7,0xb0,0x89,0x81,0x81,\r\n\t0x81,0x9e,0xc8,0xf2,0x1c,0x09,0xdf,0xfa,0x1f,0x14,0x0b,0xe4,0xf5,0x1f,0x06,0xdb,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x82,0xa4,0xc6,0xe8,0x0a,0x2a,0x20,0xff,0xdd,0xbb,\r\n\t0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xbc,0xe3,0x0b,0x26,0xff,0xd7,0xd9,0xff,\r\n\t0x29,0x04,0xdc,0xb4,0x8d,0x81,0x81,0x81,0x81,0x81,0x91,0xb2,0xd4,0xf5,0x17,0x18,\r\n\t0xf5,0xd5,0xb3,0x92,0x81,0x81,0x81,0x95,0xc0,0xea,0x13,0x16,0x18,0x09,0xf3,0xd4,\r\n\t0xb1,0x8a,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x81,0x98,0xbd,0xdf,0xfb,0x0c,0x19,0x13,0x06,0xda,0xb0,0x85,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x87,0xae,0xd4,0xf9,0x18,0x1d,0x0a,0xff,0xff,0xff,0xff,0x26,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x98,0xc2,0xec,0x16,0x16,0xed,\r\n\t0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc6,0x9c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x95,0xc0,0xea,0x16,0x1c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xb6,0xd9,0xfb,0x23,0x18,0x05,0xff,\r\n\t0x0a,0x20,0x10,0xf0,0xcc,0xa7,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xf3,0x14,0x1c,\r\n\t0xfc,0xdd,0xbf,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd5,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc4,0x9a,0x81,0x9a,0xc4,0xed,0x19,0x14,0xea,0xc0,0x95,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0x98,0xc2,0xec,0x16,0x16,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x99,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x85,0xa0,0xad,0xad,0xad,0xa6,0x8e,0x81,0x81,0x8d,0xae,\r\n\t0xcb,0xe3,0xf6,0x05,0x11,0x1f,0x26,0x13,0xf9,0xd8,0xb3,0x8c,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x89,0xb0,0xd7,0xff,0x26,0x09,0xe1,0xed,0x14,0x17,0xef,0xc8,0xa1,0x81,0x81,0x81,\r\n\t0x81,0x98,0xc2,0xec,0x16,0x0e,0xe4,0x06,0x12,0x05,0x19,0xf1,0xfa,0x23,0xff,0xd5,\r\n\t0xab,0x81,0x81,0x81,0x81,0x81,0x85,0xa7,0xc8,0xea,0x0b,0x28,0x20,0xfc,0xdd,0xbb,\r\n\t0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xac,0xd3,0xfa,0x22,0x0e,0xe7,0xe7,0x0f,\r\n\t0x1c,0xf5,0xcd,0xa6,0x81,0x81,0x81,0x81,0x81,0x8a,0xab,0xcc,0xee,0x0f,0x1f,0xfc,\r\n\t0xdc,0xbb,0x99,0x81,0x81,0x81,0x81,0x92,0xbb,0xdf,0xe7,0xec,0xfc,0x1b,0x0f,0xe8,\r\n\t0xc1,0x98,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x81,0xa7,0xcf,0xf6,0x1b,0x0b,0xf1,0xe9,0xe7,0xd3,0xac,0x83,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x92,0xbb,0xe4,0x0d,0x26,0xff,0xe3,0xd7,0xd5,0xd5,0xfa,0x26,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0xa1,0xc9,0xf2,0x1b,0x11,0xe7,\r\n\t0xbd,0x94,0x81,0x93,0xbd,0xe7,0x11,0x20,0xf6,0xcd,0xa6,0x8b,0x8a,0x94,0xa4,0xa6,\r\n\t0x96,0x81,0x81,0x94,0xbd,0xe7,0x13,0x1b,0xf1,0xc7,0x9e,0xac,0xcd,0xef,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x93,0xbd,0xe7,0x11,0x1e,0xf2,0xda,0xda,0xda,0xda,0xda,0xda,0xda,\r\n\t0xda,0xc4,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xcb,0xf0,0x14,0x0f,0x09,0x13,0x16,\r\n\t0x11,0x04,0xef,0xd4,0xb5,0x92,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x8b,0x8d,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x8d,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xf9,0x18,\r\n\t0x1a,0xfb,0xdb,0xbb,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x8d,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x8d,0x84,0x81,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd5,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x93,0xbd,0xe7,0x11,0x1e,\r\n\t0xf4,0xcb,0xa2,0x86,0xa4,0xcc,0xf5,0x1e,0x0e,0xe5,0xbb,0x92,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xa1,0xc9,0xf2,0x1b,0x11,0xe7,0xbd,0x94,0x81,0x94,0xbd,0xe7,\r\n\t0x13,0x1b,0xf2,0xc8,0x9e,0xac,0xcd,0xef,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x8c,0x9d,\r\n\t0xa9,0xbe,0xcf,0xdc,0xe9,0xf7,0x0b,0x27,0x11,0xea,0xc1,0x97,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x88,0x8e,0x95,0x8f,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x16,0x19,0xed,0xc2,0x99,0xb8,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0xa1,0xc8,0xef,0x17,0x17,0xef,0xfb,0x23,0x07,0xe0,0xb9,0x91,0x81,0x81,0x81,\r\n\t0x81,0x92,0xbc,0xe6,0x11,0x13,0xec,0x14,0x06,0xf7,0x20,0xff,0xfc,0x23,0xf7,0xcf,\r\n\t0xa5,0x81,0x81,0x81,0x81,0x81,0x9f,0xc1,0xe3,0x04,0x25,0x07,0x16,0x18,0xf7,0xd5,\r\n\t0xb5,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xc4,0xeb,0x12,0x1d,0xf5,0xf5,0x1d,\r\n\t0x0d,0xe6,0xbe,0x97,0x81,0x81,0x81,0x81,0x82,0xa3,0xc5,0xe6,0x07,0x27,0x05,0xe4,\r\n\t0xc3,0xa1,0x8d,0x8d,0x85,0x81,0x81,0x82,0xa3,0xb9,0xbd,0xc3,0xe2,0x0b,0x1d,0xf2,\r\n\t0xc9,0x9f,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xaf,0xd9,0x04,0x24,0xfa,0xd2,0xbf,0xbd,0xb3,0x97,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc9,0xb4,0xc6,0xde,0xfa,0x26,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xb0,0xbb,0xda,0xff,0x26,0x05,0xdc,\r\n\t0xb4,0x8b,0x81,0x8d,0xb6,0xdf,0x07,0x2b,0x05,0xe0,0xc3,0xb5,0xb5,0xbc,0xcc,0xcf,\r\n\t0xb5,0x92,0x81,0x8f,0xb8,0xe2,0x0b,0x23,0xfa,0xd3,0xb4,0xcb,0xe8,0x09,0x2b,0x16,\r\n\t0xea,0xc0,0x95,0x8c,0xb6,0xdf,0x07,0x27,0xff,0xdb,0xbf,0xb2,0xb0,0xb5,0xbb,0xc4,\r\n\t0xbe,0xa3,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xad,0xd6,0xff,0x26,0xfb,0xe0,0xe8,0xea,\r\n\t0xe7,0xdc,0xcb,0xb9,0xa7,0x91,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x9f,0xb4,0xb8,0xb8,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0xb8,0xb8,0xaa,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xdd,0xfc,\r\n\t0x1d,0x18,0xf7,0xd9,0xb9,0x9a,0x81,0x81,0x81,0x81,0x9f,0xb4,0xb8,0xb8,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0xb8,0xb8,0xaa,0x8e,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd5,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x8c,0xb6,0xdf,0x07,0x28,\r\n\t0xff,0xdb,0xbc,0xb0,0xbd,0xdd,0x04,0x29,0x04,0xdb,0xb3,0x89,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0xb0,0xbc,0xda,0xff,0x26,0x05,0xdd,0xb4,0x8c,0x81,0x8f,0xb8,0xe2,\r\n\t0x0b,0x23,0xfa,0xd3,0xb4,0xca,0xe8,0x09,0x2b,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0xac,0xc6,\r\n\t0xc7,0xbd,0xb5,0xb4,0xc1,0xd1,0xed,0x16,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xb5,0xdf,0x0b,0x24,0xfa,0xd1,0xb3,0xb2,0xb7,0xc0,0xb5,0x99,0x81,0x95,0xc0,\r\n\t0xea,0x13,0x1b,0xf1,0xc7,0xba,0xd4,0xf3,0x14,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x92,0xb9,0xe0,0x07,0x25,0xfc,0x09,0x1f,0xf7,0xd1,0xa9,0x82,0x81,0x81,0x81,\r\n\t0x81,0x8c,0xb6,0xdf,0x0a,0x19,0xf7,0x20,0xf7,0xea,0x12,0x0e,0x04,0x1d,0xf2,0xc9,\r\n\t0x9f,0x81,0x81,0x81,0x81,0x98,0xb9,0xdb,0xfc,0x1d,0x12,0xef,0xfc,0x20,0x11,0xf0,\r\n\t0xce,0xae,0x8c,0x81,0x81,0x81,0x81,0x81,0x8d,0xb4,0xdb,0x04,0x2a,0x04,0x04,0x26,\r\n\t0xfc,0xd6,0xaf,0x87,0x81,0x81,0x81,0x81,0x9c,0xbd,0xdf,0xff,0x21,0x0d,0xec,0xca,\r\n\t0xb8,0xb8,0xb8,0xb8,0xac,0x90,0x81,0x81,0x81,0x90,0x93,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x93,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xbf,0xe7,0x12,0x23,0xfb,0xdf,0xdd,0xeb,0xff,0x1a,0x2e,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x19,0xed,0xdf,0xda,0xe2,0xf6,0x15,0x17,0xf3,0xcd,\r\n\t0xa6,0x81,0x81,0x81,0xa9,0xd1,0xf7,0x1c,0x1c,0xff,0xe9,0xdf,0xde,0xe5,0xf1,0xf1,\r\n\t0xc7,0x9d,0x81,0x86,0xaf,0xd6,0xff,0x26,0x0d,0xec,0xdd,0xed,0x07,0x19,0x13,0x16,\r\n\t0xea,0xc0,0x95,0x82,0xaa,0xd2,0xf7,0x1d,0x16,0xf9,0xe5,0xdc,0xda,0xdf,0xe5,0xed,\r\n\t0xde,0xb6,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0xff,0x2a,0x09,0xf5,0xf2,0xf2,\r\n\t0xf2,0xf2,0xec,0xe0,0xcc,0xb2,0x93,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x91,0xb9,0xdb,0xe2,0xe2,0xe2,0xef,\r\n\t0x1b,0x13,0xe7,0xe2,0xe2,0xe2,0xc9,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xe1,\r\n\t0xff,0x21,0x14,0xf5,0xd5,0xb8,0x98,0x81,0x81,0x91,0xb9,0xdb,0xe2,0xe2,0xe2,0xef,\r\n\t0x1b,0x13,0xe7,0xe2,0xe2,0xe2,0xc9,0xa3,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd5,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0xa9,0xd1,0xf7,0x1d,\r\n\t0x16,0xf7,0xe1,0xda,0xe2,0xf9,0x18,0x16,0xf1,0xcc,0xa5,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xdf,0xda,0xe1,0xf7,0x16,0x18,0xf3,0xcd,0xa7,0x81,0x81,0x86,0xaf,0xd7,\r\n\t0xff,0x26,0x0d,0xec,0xdd,0xec,0x07,0x16,0x19,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xbf,0xe7,\r\n\t0xef,0xe7,0xdf,0xdb,0xda,0xe1,0xf5,0x1a,0x14,0xec,0xc2,0x99,0x81,0x81,0x81,0x81,\r\n\t0x87,0xb1,0xda,0x04,0x2b,0x0a,0xea,0xdd,0xdc,0xe1,0xea,0xd4,0xad,0x83,0x91,0xba,\r\n\t0xe4,0x0d,0x25,0xff,0xe2,0xe0,0xf4,0x10,0x16,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x82,0xa9,0xd1,0xf7,0x1f,0x0b,0x16,0x0f,0xe8,0xc1,0x9a,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0xb0,0xda,0x04,0x1e,0x06,0x13,0xeb,0xdc,0x05,0x1b,0x09,0x16,0xed,0xc2,\r\n\t0x99,0x81,0x81,0x81,0x90,0xb2,0xd3,0xf4,0x16,0x1c,0xf9,0xd7,0xe5,0x07,0x2b,0x0b,\r\n\t0xe8,0xc8,0xa6,0x85,0x81,0x81,0x81,0x81,0x81,0xa4,0xcc,0xf3,0x1a,0x11,0x12,0x17,\r\n\t0xef,0xc8,0xa0,0x81,0x81,0x81,0x81,0x8f,0xb5,0xd7,0xf9,0x1a,0x15,0xf3,0xe2,0xe2,\r\n\t0xe2,0xe2,0xe2,0xe2,0xcb,0xa5,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0xb5,0xdc,0x04,0x25,0x18,0x09,0x06,0x12,0x1d,0x04,0x1e,0x09,0xdd,\r\n\t0xb2,0x88,0x95,0xc0,0xea,0x16,0x25,0x13,0x09,0x06,0x0b,0x1a,0x18,0xfb,0xdb,0xb9,\r\n\t0x94,0x81,0x81,0x81,0x99,0xbe,0xe1,0xff,0x1d,0x21,0x11,0x09,0x09,0x0e,0x19,0xf2,\r\n\t0xc8,0x9d,0x81,0x81,0xa0,0xc7,0xec,0x0f,0x29,0x11,0x09,0x12,0x1c,0xfc,0x11,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x99,0xbf,0xe3,0x04,0x1f,0x1d,0x0e,0x06,0x06,0x09,0x0e,0x0e,\r\n\t0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x21,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xcc,0xf1,0x0f,0x2b,0x1e,0x1e,0x1e,\r\n\t0x1e,0x1d,0x15,0x06,0xee,0xce,0xab,0x85,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x0e,0x0e,0x0e,0x0e,\r\n\t0x1f,0x18,0x0e,0x0e,0x0e,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xc5,\r\n\t0xe4,0x05,0x25,0x12,0xf3,0xd4,0xb4,0x93,0x81,0x95,0xc0,0xea,0x0e,0x0e,0x0e,0x0e,\r\n\t0x1f,0x18,0x0e,0x0e,0x0e,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x16,0x11,0xe5,0xd0,\r\n\t0xfa,0x26,0xff,0xd5,0xe2,0x0e,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x99,0xbe,0xe2,0x04,\r\n\t0x1f,0x1a,0x0b,0x06,0x0b,0x1b,0x18,0xfb,0xdb,0xb8,0x93,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x25,0x13,0x09,0x06,0x0b,0x1a,0x18,0xfb,0xdc,0xba,0x94,0x81,0x81,0x81,0xa1,0xc7,\r\n\t0xed,0x10,0x29,0x11,0x09,0x12,0x1a,0xfb,0x16,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x11,0x09,0x06,0x06,0x0b,0x18,0x1c,0xff,0xdb,0xb5,0x8f,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa5,0xcd,0xf3,0x16,0x25,0x0f,0x06,0x06,0x0b,0x06,0xda,0xb0,0x85,0x87,0xaf,\r\n\t0xd6,0xfc,0x20,0x1c,0x0b,0x0a,0x18,0x10,0xfc,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9a,0xc1,0xe9,0x11,0x24,0x28,0xff,0xd9,0xb2,0x8a,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xaa,0xd4,0xfc,0x28,0x22,0x05,0xdc,0xce,0xf6,0x1f,0x1f,0x11,0xe7,0xbd,\r\n\t0x92,0x81,0x81,0x86,0xaa,0xcc,0xed,0x0f,0x27,0x04,0xe1,0xbf,0xcd,0xef,0x12,0x24,\r\n\t0x04,0xe1,0xc1,0x9f,0x81,0x81,0x81,0x81,0x81,0x95,0xbc,0xe3,0x0b,0x28,0x2a,0x07,\r\n\t0xe0,0xb9,0x91,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x12,0x33,0x0f,0x0e,0x0e,0x0e,\r\n\t0x0e,0x0e,0x0e,0xff,0xd5,0xab,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa4,0xc8,0xe8,0xff,0x12,0x19,0x16,0x0b,0xf9,0xf2,0x11,0x09,0xdd,\r\n\t0xb2,0x88,0x94,0xbe,0xe6,0xfa,0x07,0x0f,0x14,0x16,0x11,0x06,0xf4,0xdc,0xbf,0xa0,\r\n\t0x81,0x81,0x81,0x81,0x83,0xa6,0xc5,0xe2,0xf9,0x0a,0x13,0x19,0x16,0x11,0x09,0xf1,\r\n\t0xc7,0x9d,0x81,0x81,0x8e,0xb2,0xd4,0xf1,0x0a,0x16,0x17,0x0d,0xf9,0xe5,0x0e,0x0e,\r\n\t0xea,0xc0,0x95,0x81,0x85,0xa7,0xc7,0xe3,0xfa,0x0b,0x14,0x19,0x19,0x13,0x0e,0x06,\r\n\t0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x11,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xab,0xcf,0xf0,0x0f,0x1d,0x06,0x06,0x06,\r\n\t0x06,0x09,0x16,0x29,0x09,0xe3,0xbb,0x92,0x81,0x95,0xc0,0xea,0x11,0x11,0xed,0xc2,\r\n\t0x98,0xb0,0xda,0x06,0x11,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x11,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x89,0x89,0x81,0x81,0x8b,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x95,0xc0,0xea,0x11,0x11,0xed,0xc2,0xa9,\r\n\t0xc8,0xe8,0x09,0x11,0x10,0xf0,0xcb,0xa1,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x11,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,0x11,0x11,0xe5,0xd0,\r\n\t0xfa,0x11,0xff,0xd5,0xe2,0x0e,0x11,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x11,0x11,\r\n\t0xed,0xc2,0x98,0xb0,0xda,0x06,0x11,0xfc,0xd2,0xa8,0x81,0x81,0x84,0xa7,0xc7,0xe4,\r\n\t0xfb,0x0c,0x16,0x19,0x14,0x09,0xf5,0xdd,0xbf,0xa0,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x1b,0x0e,0x14,0x16,0x11,0x06,0xf4,0xdd,0xbf,0xa1,0x81,0x81,0x81,0x81,0x8e,0xb2,\r\n\t0xd4,0xf1,0x0a,0x16,0x16,0x0c,0xf7,0xea,0x16,0x16,0xea,0xc0,0x95,0x95,0xc0,0xea,\r\n\t0x11,0x11,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x0a,0x11,0x16,0x19,0x19,0x13,0x09,0xf7,0xe0,0xc3,0xa1,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x94,0xb8,0xd9,0xf5,0x0a,0x14,0x19,0x17,0x13,0x06,0xda,0xb0,0x85,0x81,0x9f,\r\n\t0xc3,0xe4,0xff,0x12,0x19,0x14,0x07,0xf0,0xfc,0x0e,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8b,0xb2,0xd9,0xff,0x11,0x11,0xf1,0xc9,0xa2,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa4,0xcd,0xf7,0x11,0x11,0xf7,0xcf,0xc1,0xe8,0x11,0x11,0x0b,0xe0,0xb7,\r\n\t0x8d,0x81,0x81,0x92,0xbc,0xe5,0x07,0x11,0x0f,0xec,0xc9,0xa7,0xb5,0xd7,0xf9,0x11,\r\n\t0x11,0xfb,0xd8,0xaf,0x85,0x81,0x81,0x81,0x81,0x85,0xac,0xd3,0xfa,0x22,0x1f,0xf7,\r\n\t0xd1,0xa9,0x82,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0xff,0xd5,0xab,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x83,0x93,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,\r\n\t0x94,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8d,0xac,0xc8,0xdc,0xe8,0xed,0xec,0xe3,0xd4,0xe1,0xe5,0xe5,0xd3,\r\n\t0xae,0x85,0x87,0xaa,0xc5,0xd2,0xdd,0xe5,0xea,0xea,0xe7,0xde,0xce,0xba,0xa1,0x83,\r\n\t0x81,0x81,0x81,0x81,0x81,0x89,0xa7,0xbf,0xd3,0xe1,0xea,0xed,0xed,0xe7,0xdf,0xd2,\r\n\t0xb7,0x93,0x81,0x81,0x81,0x98,0xb6,0xcf,0xe2,0xec,0xed,0xe5,0xd5,0xd7,0xe2,0xe2,\r\n\t0xdb,0xb9,0x91,0x81,0x81,0x8b,0xa8,0xc1,0xd4,0xe2,0xea,0xed,0xed,0xea,0xe4,0xdc,\r\n\t0xcd,0xad,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xc4,0xe2,0xe5,0xe5,0xd7,0xb3,\r\n\t0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xba,0xe2,0x0a,0x26,0xff,0xe1,0xda,0xda,\r\n\t0xda,0xdf,0xf6,0x1e,0x17,0xed,0xc2,0x98,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xde,0xbc,\r\n\t0x94,0xab,0xd1,0xe5,0xe5,0xe4,0xcb,0xa4,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe4,0xcb,0xa4,0x81,0x81,0x9d,0xb2,0xb3,0xa3,0x97,0x94,\r\n\t0xb9,0xe2,0x0e,0x21,0xf5,0xcc,0xa2,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xde,0xbc,0x94,\r\n\t0xae,0xcd,0xe5,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe4,0xcb,0xa4,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xd9,0xc8,\r\n\t0xe4,0xe5,0xe5,0xcd,0xd7,0xe5,0xe5,0xde,0xbc,0x94,0x81,0x92,0xba,0xdd,0xe5,0xe5,\r\n\t0xde,0xbc,0x94,0xab,0xd1,0xe5,0xe5,0xe4,0xcb,0xa4,0x81,0x81,0x81,0x8b,0xa8,0xc2,\r\n\t0xd5,0xe4,0xeb,0xed,0xea,0xe1,0xd1,0xbb,0xa1,0x83,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xea,0xea,0xe7,0xdd,0xce,0xba,0xa1,0x83,0x81,0x81,0x81,0x81,0x81,0x98,\r\n\t0xb6,0xd0,0xe3,0xed,0xed,0xe4,0xd3,0xea,0x16,0x16,0xea,0xc0,0x95,0x92,0xba,0xdd,\r\n\t0xe5,0xe5,0xde,0xbc,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xb5,0xd4,\r\n\t0xe0,0xe7,0xea,0xed,0xed,0xea,0xe0,0xd2,0xbe,0xa5,0x87,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9d,0xba,0xd2,0xe1,0xea,0xed,0xed,0xe9,0xe2,0xce,0xa9,0x81,0x81,0x88,\r\n\t0xa9,0xc5,0xdb,0xe8,0xed,0xea,0xe0,0xcd,0xe2,0xe2,0xe2,0xc9,0xa3,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa3,0xc9,0xe4,0xe5,0xe5,0xdd,0xba,0x93,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9c,0xc4,0xe2,0xe5,0xe5,0xe1,0xc1,0xb3,0xd7,0xe5,0xe5,0xe5,0xd3,0xae,\r\n\t0x85,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xd3,0xb1,0x8e,0x9c,0xbf,0xde,0xe5,\r\n\t0xe5,0xe5,0xd1,0xab,0x82,0x81,0x88,0x98,0x9b,0x9b,0xb9,0xdc,0xff,0x27,0x0d,0xe6,\r\n\t0xc0,0x9a,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xcd,0xa6,0x81,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0xf5,\r\n\t0xca,0xa0,0x93,0x8d,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,0x81,\r\n\t0x90,0x93,0xb0,0xda,0x06,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x83,0xa5,0xbc,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,\r\n\t0xbe,0xaa,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8c,0xa3,0xb4,0xbf,0xc2,0xc2,0xba,0xad,0xb9,0xba,0xba,0xb2,\r\n\t0x98,0x81,0x81,0x8b,0x9d,0xaa,0xb4,0xbb,0xc0,0xc0,0xbd,0xb5,0xa8,0x95,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x9a,0xac,0xb8,0xc0,0xc2,0xc2,0xbe,0xb6,0xaa,\r\n\t0x98,0x81,0x81,0x81,0x81,0x81,0x95,0xab,0xba,0xc2,0xc2,0xbc,0xaf,0xb3,0xb8,0xb8,\r\n\t0xb4,0x9f,0x81,0x81,0x81,0x81,0x86,0x9b,0xad,0xb9,0xc0,0xc2,0xc2,0xc0,0xba,0xb3,\r\n\t0xa8,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xa8,0xb9,0xba,0xba,0xb4,0x9b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc9,0xba,0xb8,\r\n\t0xbc,0xce,0xf3,0x1c,0x15,0xeb,0xc2,0x98,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb8,0xa3,\r\n\t0x83,0x96,0xb1,0xba,0xba,0xba,0xac,0x8f,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xba,0xac,0x8f,0x81,0x90,0xb8,0xd9,0xda,0xcb,0xc1,0xbd,\r\n\t0xcd,0xef,0x16,0x17,0xef,0xc6,0x9c,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb8,0xa3,0x83,\r\n\t0x92,0xae,0xba,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xba,0xac,0x8f,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb5,0xab,\r\n\t0xba,0xba,0xba,0xae,0xb4,0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0xa1,0xb7,0xba,0xba,\r\n\t0xb8,0xa3,0x83,0x96,0xb1,0xba,0xba,0xba,0xac,0x8f,0x81,0x81,0x81,0x81,0x87,0x9c,\r\n\t0xaf,0xbb,0xc2,0xc2,0xc0,0xb8,0xaa,0x97,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0xc0,0xbd,0xb5,0xa8,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xab,0xbb,0xc2,0xc2,0xbb,0xc0,0xea,0x16,0x16,0xea,0xc0,0x95,0x81,0xa1,0xb7,\r\n\t0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xae,\r\n\t0xb7,0xbd,0xc0,0xc2,0xc2,0xc0,0xb8,0xab,0x99,0x83,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xab,0xb9,0xc0,0xc2,0xc2,0xbf,0xb9,0xac,0x92,0x81,0x81,0x81,\r\n\t0x8a,0xa2,0xb4,0xbf,0xc2,0xc1,0xb8,0xaa,0xb8,0xb8,0xb8,0xaa,0x8e,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xab,0xba,0xba,0xba,0xb7,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x89,0xa8,0xb9,0xba,0xba,0xb9,0xa6,0x9b,0xb4,0xba,0xba,0xba,0xb2,0x98,\r\n\t0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xb2,0x98,0x81,0x83,0xa3,0xb8,0xba,\r\n\t0xba,0xba,0xb1,0x96,0x81,0x86,0xa8,0xc1,0xc5,0xc4,0xd5,0xf3,0x17,0x1d,0xf9,0xd3,\r\n\t0xae,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xae,0x92,0x81,0x81,0x81,0x81,0x87,0xb1,0xda,0x05,0x24,0xfc,\r\n\t0xd5,0xc0,0xbd,0xb4,0x99,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x82,0xa3,\r\n\t0xb9,0xbd,0xc3,0xe3,0x0b,0x1e,0xf5,0xca,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x93,0xbc,0xe1,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,\r\n\t0xe6,0xc3,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0x95,0x98,0x98,0x91,0x85,0x8f,0x90,0x90,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x92,0x95,0x95,0x93,0x8c,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8f,0x95,0x98,0x98,0x94,0x8d,0x82,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x91,0x98,0x98,0x93,0x87,0x8a,0x8d,0x8d,\r\n\t0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x96,0x98,0x98,0x95,0x90,0x8a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8f,0x90,0x90,0x8c,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbe,0xe7,0x11,0x25,0xff,0xed,0xe5,0xe2,\r\n\t0xe6,0xf1,0x0b,0x29,0x06,0xe0,0xb8,0x90,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x81,\r\n\t0x81,0x81,0x8a,0x90,0x90,0x90,0x87,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x90,0x87,0x81,0x81,0x95,0xc0,0xea,0xff,0xf3,0xea,0xe7,\r\n\t0xf1,0x09,0x29,0x07,0xe1,0xb9,0x91,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x81,0x81,\r\n\t0x81,0x88,0x90,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x90,0x87,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8d,0x86,\r\n\t0x90,0x90,0x90,0x88,0x8c,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,\r\n\t0x8e,0x81,0x81,0x81,0x8a,0x90,0x90,0x90,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0x91,0x98,0x98,0x96,0x8f,0x83,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0x93,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x85,0x92,0x98,0x98,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,0x95,0x81,0x81,0x8e,\r\n\t0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,\r\n\t0x8d,0x93,0x96,0x98,0x98,0x95,0x8e,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x84,0x90,0x96,0x98,0x98,0x95,0x8f,0x85,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8c,0x95,0x98,0x97,0x8f,0x84,0x8d,0x8d,0x8d,0x84,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x86,0x90,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x84,0x8f,0x90,0x90,0x8f,0x82,0x81,0x8c,0x90,0x90,0x90,0x8b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x8b,0x81,0x81,0x81,0x81,0x8e,0x90,\r\n\t0x90,0x90,0x8a,0x81,0x81,0x94,0xbd,0xe4,0xef,0xed,0xf9,0x12,0x25,0x05,0xe2,0xbf,\r\n\t0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0xa9,0xd2,0xfa,0x20,0x10,\r\n\t0xf5,0xea,0xe7,0xd5,0xaf,0x86,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x92,0xbb,\r\n\t0xdf,0xe7,0xec,0xfc,0x1d,0x12,0xeb,0xc3,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,\r\n\t0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xb2,0xd8,0xfb,0x16,0x25,0x16,0x0f,0x0e,\r\n\t0x11,0x19,0x1f,0x09,0xec,0xcb,0xa7,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1c,0x16,0x13,\r\n\t0x19,0x24,0x0d,0xee,0xcc,0xa8,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0x20,0x1d,0x05,0xe8,0xc8,0xa7,\r\n\t0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc1,0xe6,0x07,0x1f,\r\n\t0x1c,0x13,0x09,0xdd,0xb2,0x88,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x95,0xc0,\r\n\t0xea,0x13,0x16,0x21,0x18,0xfb,0xd9,0xb4,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,\r\n\t0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9e,0xbf,0xdb,0xf1,0xff,0x09,0x0e,0x0e,\r\n\t0x0b,0x04,0xf7,0xe5,0xcd,0xb0,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbe,0xe6,0xfb,0x06,0x0b,0x0e,\r\n\t0x09,0xfc,0xea,0xd0,0xb2,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,\r\n\t0x09,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,0x09,0xea,0xc0,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x0b,0x0b,0x05,0xf7,0xe3,0xca,0xac,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0xaa,0xca,0xe6,0xf9,\r\n\t0x04,0x09,0x09,0xdd,0xb2,0x88,0x95,0xc0,0xea,0x09,0x09,0xe7,0xbd,0x93,0x95,0xc0,\r\n\t0xea,0x09,0x09,0xff,0xf3,0xdd,0xbf,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x90,0xb6,0xd6,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,\r\n\t0xda,0xbd,0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xa0,0xb8,0xca,0xd7,0xdf,0xe2,0xe2,\r\n\t0xdf,0xda,0xcf,0xc0,0xab,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xaa,0xc5,0xd3,0xdd,0xe2,0xe2,\r\n\t0xdf,0xd5,0xc5,0xaf,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,\r\n\t0xdd,0xd8,0xb9,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xd6,0xb6,0x90,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd7,0xdf,0xdf,0xdb,0xd0,0xbf,0xa8,0x8e,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xaa,0xc0,0xd1,\r\n\t0xda,0xdd,0xdd,0xce,0xab,0x83,0x90,0xb6,0xd6,0xdd,0xdd,0xd5,0xb4,0x8d,0x90,0xb6,\r\n\t0xd6,0xdd,0xdd,0xd7,0xcc,0xba,0xa1,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9b,0xaf,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,\r\n\t0xb1,0xa0,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xa2,0xad,0xb5,0xb8,0xb8,\r\n\t0xb6,0xb1,0xa7,0x99,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x9e,0xaa,0xb3,0xb8,0xb8,\r\n\t0xb5,0xac,0x9e,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,\r\n\t0xb2,0xb0,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xaf,0x9b,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,0xb5,0xb2,0xa8,0x99,0x85,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x9a,0xa8,\r\n\t0xb0,0xb2,0xb2,0xab,0x92,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xaf,0x99,0x81,0x81,0x9b,\r\n\t0xaf,0xb2,0xb2,0xae,0xa4,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x86,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,\r\n\t0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8b,0x8d,0x8d,\r\n\t0x8c,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x8d,0x8d,\r\n\t0x8b,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,\r\n\t0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x86,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x88,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0x88,0x88,0x83,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x86,0x81,0x81,0x81,0x81,\r\n\t0x86,0x88,0x88,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x88,0x88,0x85,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xc9,0xad,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xae,0xb2,0xb2,0xae,0x98,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xe7,0xbd,0x92,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0x8d,0x90,0x90,0x8d,0x89,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0x85,0x81,0x81,0x81,0x84,0x85,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x86,0x8c,0x8d,0x8b,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x89,0x90,0x90,0x8c,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x89,0x91,0x93,0x90,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8a,0x90,0x93,0x93,0x8f,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x87,0x8b,0x8b,0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x84,0x88,0x88,0x88,0x88,0x88,0x88,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8c,0x8d,0x8d,0x85,0x81,0x81,0x81,0x81,0x87,0x88,0x88,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x82,0x8f,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x8a,0x8b,0x8b,\r\n\t0x86,0x81,0x81,0x81,0x81,0x81,0x86,0x8e,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,\r\n\t0x87,0x88,0x88,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xb2,0xd3,0xdd,0xdd,0xd3,0xb2,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x88,0x88,0x82,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x81,0x81,0x8d,0xa0,0xae,0xb7,0xba,0xba,0xb8,0xb2,0xa8,0x90,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x89,0xa0,0xaf,0xb0,0xa5,0x8f,0x9f,0xae,0xb0,0xa6,0x91,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x85,0x84,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x85,0x85,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8e,0xa1,0xaf,0xb6,0xb8,0xb5,0xab,0x9c,0x8a,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8e,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x92,0x81,0x81,0x81,\r\n\t0x81,0x81,0x91,0xa5,0xb3,0xba,0xba,0xb6,0xab,0x9a,0x84,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x90,0xa4,0xb3,0xbb,0xbd,0xba,0xb1,0xa1,0x8b,0x81,0x81,0x81,0x81,0x92,0xa9,\r\n\t0xb4,0xba,0xbd,0xbd,0xb9,0xaf,0x9e,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xaf,0xb5,0xb5,0xb5,0xb4,0xa2,0x84,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8a,0x9a,0xa6,0xae,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xa6,0x8a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x85,0x98,0xab,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0x85,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x91,0xa5,0xb6,0xb8,0xb8,0xac,0x90,0x81,0x83,0xa0,0xb1,0xb2,0xb2,0xac,0x94,0x81,\r\n\t0x81,0x81,0x81,0x93,0xa7,0xb9,0xba,0xba,0xae,0x92,0x81,0x84,0xa2,0xb4,0xb5,0xb5,\r\n\t0xae,0x96,0x81,0x81,0x81,0x9b,0xaf,0xb8,0xba,0xba,0xb0,0x9f,0x87,0x81,0x83,0xa0,\r\n\t0xb1,0xb2,0xb2,0xac,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbb,0xe5,0x09,0x09,0xe5,0xba,0x90,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x98,0xa6,0xaf,0xb2,0xb2,0xac,0xa0,0x8f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x8d,0x81,0x81,0x81,0x81,0x81,0x8a,0x90,\r\n\t0x89,0x81,0x81,0x81,0x81,0x81,0x91,0xa4,0xa8,0xa8,0xa8,0x9c,0x83,0x81,0x81,0x81,\r\n\t0x9a,0xa7,0xa8,0xa8,0xa4,0x91,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x81,0x96,0xb0,0xc6,0xd6,0xe1,0xe5,0xe5,0xe2,0xdc,0xcc,0xaa,0x82,0x81,0x81,\r\n\t0x81,0x81,0x84,0xa7,0xc4,0xd7,0xda,0xca,0xae,0xc3,0xd6,0xda,0xcb,0xb0,0x8f,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8a,0x9b,0xa7,0xae,0xb0,0xae,0xa7,0x9b,0x8a,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8b,0x9c,0xa7,0xad,0xb0,0xb0,0xaa,0x9d,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9b,0xb3,0xc7,0xd7,0xdf,0xe2,0xdf,0xd3,0xc2,0xad,0x94,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x94,0xb3,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xb9,0x9d,0x81,0x81,\r\n\t0x81,0x98,0xb5,0xcb,0xdb,0xe4,0xe5,0xdf,0xd3,0xbf,0xa5,0x86,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x98,0xb3,0xc9,0xdb,0xe5,0xe7,0xe4,0xd9,0xc5,0xaa,0x8c,0x81,0x81,0x86,0xad,0xce,\r\n\t0xdd,0xe4,0xe7,0xe7,0xe2,0xd6,0xc1,0xa5,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x98,0xb6,0xd4,0xdf,0xdf,0xdf,0xdc,0xbf,0x98,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9a,0xaf,0xc2,0xcf,0xd7,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xc6,0xa1,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x84,0x98,0xab,0xbe,0xd1,0xe3,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8a,0x9c,0xa9,0xb0,0xb0,0xab,0xa0,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xa2,\r\n\t0xb6,0xcb,0xdf,0xe2,0xe2,0xcb,0xa5,0x81,0x9b,0xbe,0xda,0xdd,0xdd,0xd0,0xad,0x85,\r\n\t0x81,0x8e,0xa5,0xb9,0xcd,0xe1,0xe5,0xe5,0xcd,0xa6,0x81,0x9c,0xbf,0xdc,0xdf,0xdf,\r\n\t0xd2,0xae,0x86,0x81,0x91,0xb7,0xd5,0xe2,0xe5,0xe3,0xd8,0xc3,0xa4,0x81,0x9c,0xbf,\r\n\t0xda,0xdd,0xdd,0xd0,0xad,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xc1,0xea,0x16,0x0b,0xdf,0xb6,0x8c,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xa8,0xbe,0xce,0xd9,0xdd,0xdd,0xd5,0xc7,0xb5,\r\n\t0x9e,0x84,0x81,0x81,0x81,0x94,0xaa,0xba,0xb5,0x9d,0x81,0x81,0x81,0x96,0xb1,0xba,\r\n\t0xaf,0x99,0x83,0x81,0x81,0x89,0xaf,0xcc,0xd2,0xd2,0xd2,0xbf,0x9e,0x81,0x81,0x99,\r\n\t0xbb,0xd1,0xd2,0xd2,0xcc,0xaf,0x89,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x91,0xb2,0xd2,0xeb,0xfc,0x0b,0x11,0x11,0x0c,0x06,0xdd,0xb2,0x88,0x81,0x81,\r\n\t0x81,0x81,0x96,0xbe,0xe2,0xff,0x04,0xea,0xc7,0xe0,0xfc,0x04,0xec,0xc9,0xa3,0x81,\r\n\t0x81,0x81,0x81,0x81,0x99,0xaf,0xc2,0xd0,0xd7,0xda,0xd7,0xd0,0xc2,0xaf,0x98,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8b,0xac,0xc4,0xd0,0xd7,0xda,0xda,0xd3,0xc5,0xae,0x90,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9b,0xb9,0xd5,0xed,0xff,0x0b,0x0e,0x09,0xfb,0xe8,0xd0,0xb2,0x94,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa6,0xce,0xec,0xed,0xed,0xed,0xed,0xed,0xed,0xd8,0xb0,0x86,0x81,\r\n\t0x94,0xb6,0xd4,0xef,0x04,0x0e,0x11,0x09,0xf9,0xe0,0xc2,0x9f,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x89,0xa0,0xa8,0xa8,0xa8,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,\r\n\t0xb3,0xd4,0xee,0x04,0x0f,0x13,0x0e,0xff,0xe6,0xc8,0xa4,0x81,0x81,0x8d,0xb8,0xe2,\r\n\t0x06,0x0e,0x13,0x13,0x0c,0xfb,0xe0,0xbe,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x98,0xb6,0xd4,0xf1,0x0b,0x0b,0x0a,0xef,0xc7,0x9d,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,\r\n\t0xbb,0xd5,0xe8,0xf7,0x04,0x06,0x09,0x09,0x09,0x09,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x82,0xa5,0xbe,0xd1,0xe3,0xf6,0x0a,0x11,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,\r\n\t0x81,0x92,0xad,0xc2,0xd2,0xda,0xda,0xd5,0xc8,0xb3,0x99,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xa9,0xc7,\r\n\t0xdb,0xef,0x04,0x0e,0xff,0xd5,0xab,0x8e,0xb2,0xd5,0xf9,0x09,0x06,0xdf,0xb5,0x8b,\r\n\t0x86,0xab,0xc9,0xde,0xf1,0x06,0x11,0xff,0xd5,0xab,0x8f,0xb2,0xd5,0xf9,0x0b,0x04,\r\n\t0xde,0xb5,0x8a,0x81,0x98,0xc2,0xed,0x0b,0x11,0x0e,0xfc,0xdf,0xba,0x93,0xb3,0xd6,\r\n\t0xf9,0x09,0x05,0xdf,0xb5,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x9c,0xaa,0xc6,0xef,0x1b,0x05,0xda,0xb1,0x90,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8a,0xaa,0xc8,0xe3,0xf6,0x04,0x09,0x06,0xfc,0xee,0xd9,\r\n\t0xbf,0xa2,0x81,0x81,0xa1,0xb9,0xce,0xe3,0xd9,0xb7,0x94,0x8b,0x8b,0xaf,0xd2,0xe5,\r\n\t0xd3,0xbd,0xa6,0x87,0x81,0x93,0xbd,0xe7,0xfc,0xfc,0xfb,0xd7,0xb2,0x8e,0x89,0xae,\r\n\t0xd3,0xf7,0xfc,0xfc,0xe7,0xbd,0x93,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0xa5,0xcb,0xee,0x0d,0x25,0x14,0x0e,0x0e,0x12,0x09,0xdd,0xb2,0x88,0x81,0x81,\r\n\t0x81,0x81,0x9d,0xc8,0xf2,0x1c,0x25,0xfc,0xd2,0xef,0x19,0x27,0xff,0xd5,0xab,0x81,\r\n\t0x81,0x81,0x81,0x9b,0xb9,0xd3,0xe8,0xf9,0x04,0x06,0x04,0xf9,0xe8,0xd3,0xb9,0x9b,\r\n\t0x81,0x81,0x81,0x81,0x99,0xc3,0xe8,0xf9,0xff,0x06,0x04,0xfb,0xe9,0xcc,0xab,0x86,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,\r\n\t0xb6,0xd7,0xf5,0x11,0x0d,0xff,0xfa,0xff,0x12,0x0b,0xee,0xcf,0xac,0x88,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa8,0xd2,0xfc,0x19,0x19,0x19,0x19,0x19,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0xa8,0xcd,0xf1,0x10,0x1a,0x0b,0x09,0x15,0x1c,0xfc,0xd9,0xb4,0x8c,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa3,0xc4,0xd2,0xd2,0xd2,0xbd,0x9a,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x0b,0x1e,0x11,0x0e,0x1a,0x23,0x04,0xdc,0xb5,0x8c,0x81,0x8d,0xb8,0xe2,\r\n\t0x0e,0x0b,0x09,0x0b,0x1f,0x1c,0xf6,0xce,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xb6,0xd4,0xf1,0x10,0x1b,0xff,0xe8,0xce,0xb4,0x91,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xb9,\r\n\t0xd9,0xf7,0x0f,0x20,0x2b,0x2c,0x16,0x16,0x17,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x91,0xba,0xe0,0xf6,0x0a,0x1d,0x23,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,\r\n\t0x8e,0xb0,0xce,0xe8,0xfa,0x04,0x06,0xfc,0xee,0xd5,0xb6,0x94,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xba,0xe3,\r\n\t0xff,0x15,0x17,0x2a,0xff,0xd5,0xab,0xa5,0xc9,0xec,0x0f,0x12,0xef,0xcb,0xa8,0x82,\r\n\t0x90,0xba,0xe4,0x04,0x18,0x14,0x28,0xff,0xd5,0xab,0xa6,0xc9,0xed,0x10,0x10,0xed,\r\n\t0xc9,0xa6,0x81,0x81,0x98,0xc2,0xed,0x04,0xff,0x17,0x19,0xef,0xc5,0xa6,0xca,0xed,\r\n\t0x11,0x12,0xee,0xcb,0xa7,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x96,0x9b,0x97,0x88,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x96,0xaf,0xc3,0xd2,0xdd,0xf5,0x20,0xff,0xd5,0xc9,0xb2,\r\n\t0x8f,0x81,0x81,0x81,0x81,0xa0,0xc5,0xe6,0x05,0x1d,0x1f,0x19,0x1a,0x24,0x13,0xfb,\r\n\t0xdc,0xb4,0x8a,0x92,0xba,0xdd,0xf3,0x09,0xf1,0xce,0xb2,0xb5,0xb5,0xc5,0xe8,0x0d,\r\n\t0xf7,0xe1,0xc1,0x99,0x81,0x8d,0xb4,0xd9,0xfc,0x21,0x11,0xec,0xc7,0xa3,0x9e,0xc2,\r\n\t0xe7,0x0c,0x22,0xfc,0xd9,0xb4,0x8d,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x89,0xb3,0xdb,0x04,0x29,0x05,0xec,0xe3,0xe2,0xe7,0xf1,0xda,0xb1,0x87,0x81,0x81,\r\n\t0x81,0x81,0x9b,0xc3,0xeb,0x0d,0x12,0xf4,0xcd,0xe8,0x0b,0x13,0xf6,0xd0,0xa8,0x81,\r\n\t0x81,0x81,0x98,0xb9,0xd7,0xf5,0x0d,0x20,0x14,0x11,0x14,0x20,0x0d,0xf3,0xd7,0xb8,\r\n\t0x96,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x12,0x0e,0x12,0x23,0x09,0xe5,0xbd,0x95,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa6,\r\n\t0xcc,0xf1,0x13,0x05,0x04,0x04,0x04,0xfb,0xef,0x0d,0x0b,0xe7,0xc2,0x9b,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa8,0xd2,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xdd,0xb2,0x88,0x8e,\r\n\t0xb7,0xe0,0x07,0x1e,0xfa,0xe1,0xdf,0xf3,0x17,0x12,0xea,0xc1,0x98,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0xb0,0xda,0xfc,0xfc,0xf9,0xcf,0xa5,0x81,0x81,0x81,0x81,0x81,0x89,\r\n\t0xaf,0xd0,0xf0,0xf9,0xe7,0xe4,0xfb,0x23,0x11,0xe7,0xbd,0x93,0x81,0x8c,0xb5,0xdc,\r\n\t0xeb,0xe2,0xdd,0xe3,0x09,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa9,0xd0,0xf1,0x10,0x13,0xf9,0xe0,0xc6,0xac,0x93,0x81,0x81,0x81,0x81,0x8e,0x90,\r\n\t0x90,0x8e,0x81,0x81,0x81,0x8b,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x82,0xaa,0xcf,\r\n\t0xf4,0x16,0x32,0x47,0x50,0x26,0xfa,0xea,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x91,0xbb,0xe2,0x09,0x18,0x05,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,\r\n\t0xa4,0xc8,0xec,0x0b,0x21,0x14,0x14,0x22,0x10,0xf1,0xce,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xb4,0xdb,\r\n\t0xff,0x06,0xf7,0x23,0xff,0xd5,0xab,0xbd,0xe0,0x04,0x1f,0xfb,0xd8,0xb5,0x91,0x81,\r\n\t0x8b,0xb3,0xda,0xff,0x04,0xf7,0x23,0xff,0xd5,0xab,0xbd,0xe0,0x04,0x1d,0xf9,0xd5,\r\n\t0xb2,0x8e,0x81,0x81,0x92,0xb9,0xda,0xed,0xee,0x0f,0x15,0xed,0xc4,0xbd,0xe0,0x05,\r\n\t0x1e,0xfa,0xd7,0xb4,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x9a,0x9b,0x91,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xaa,0xbe,0xc5,0xbf,0xad,0x92,\r\n\t0x81,0x81,0x81,0x81,0x98,0xb6,0xd2,0xe8,0xfa,0x06,0x0b,0x26,0x06,0xfc,0xee,0xc6,\r\n\t0x9d,0x81,0x81,0x81,0x8b,0xb2,0xd9,0xff,0x22,0x10,0xf7,0xed,0xef,0xfc,0x14,0xf5,\r\n\t0xd5,0xb0,0x88,0x94,0xbe,0xe6,0x07,0x29,0x09,0xe5,0xdc,0xdf,0xde,0xdc,0xff,0x23,\r\n\t0x0d,0xec,0xc6,0x9c,0x81,0x81,0x9e,0xc2,0xe7,0x0c,0x26,0xff,0xdc,0xb8,0xb2,0xd6,\r\n\t0xfb,0x21,0x0c,0xe8,0xc4,0x9f,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x8d,0xb8,0xe2,0x0e,0x23,0xf7,0xcd,0xba,0xb9,0xbf,0xc7,0xbd,0xa0,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8c,0xb1,0xd0,0xe7,0xea,0xd7,0xb9,0xce,0xe6,0xea,0xd9,0xbb,0x98,0x81,\r\n\t0x81,0x8a,0xaf,0xd3,0xf5,0x14,0x12,0xfa,0xeb,0xe5,0xec,0xfc,0x16,0x14,0xf3,0xd0,\r\n\t0xac,0x87,0x81,0x81,0x9b,0xc5,0xef,0xf4,0xe8,0xe2,0xeb,0x0d,0x1b,0xf1,0xc7,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8b,0x9d,0x9e,0x8f,0x81,0x85,0x99,0x9d,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xb4,\r\n\t0xdc,0x04,0x0f,0xe9,0x04,0x06,0xfc,0x13,0xfc,0xf3,0x18,0xfa,0xd2,0xaa,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9e,0xc1,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xc8,0xa7,0x81,0x95,\r\n\t0xbf,0xe9,0x13,0x11,0xe7,0xbf,0xb8,0xe0,0x0a,0x1c,0xf2,0xc8,0x9d,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0xb0,0xda,0x06,0x26,0xfa,0xd0,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0xb5,0xd3,0xd6,0xc0,0xd2,0xf7,0x21,0x11,0xe7,0xbd,0x92,0x81,0x81,0xa1,0xbb,\r\n\t0xd4,0xea,0xea,0xf3,0x11,0x18,0xf4,0xcd,0xa4,0x81,0x81,0x81,0x81,0x81,0x81,0x82,\r\n\t0xab,0xd4,0xef,0xef,0xef,0xd8,0xbe,0xa5,0x8b,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,\r\n\t0xba,0xb8,0xa3,0x83,0x9a,0xb3,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x8e,0xb8,0xe0,\r\n\t0x09,0x2e,0x51,0x6d,0x50,0x26,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x84,0xab,0xd2,0xf7,0xf1,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x8b,\r\n\t0xb4,0xdb,0x04,0x26,0x04,0xec,0xeb,0xff,0x24,0x06,0xdf,0xb6,0x8d,0x81,0x81,0x81,\r\n\t0x94,0x9d,0x96,0x81,0x81,0x94,0xa0,0x9a,0x84,0x81,0x81,0x81,0x81,0x81,0xa2,0xc8,\r\n\t0xe9,0xe0,0xf7,0x23,0xff,0xd5,0xb0,0xd3,0xf7,0x1a,0x07,0xe4,0xc1,0x9d,0x81,0x81,\r\n\t0x81,0xa1,0xc7,0xe7,0xde,0xf7,0x23,0xff,0xd5,0xb1,0xd4,0xf7,0x1b,0x05,0xe2,0xbf,\r\n\t0x9b,0x81,0x81,0x81,0x8b,0xb5,0xdf,0x0b,0x19,0x21,0xff,0xec,0xc9,0xd4,0xf7,0x1b,\r\n\t0x07,0xe3,0xc0,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb4,0xc4,0xc5,0xb8,\r\n\t0xa1,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xa9,0xca,0xe5,0xef,0xe7,0xce,0xae,\r\n\t0x88,0x81,0x81,0x8e,0xb1,0xd3,0xf1,0x0d,0x21,0x1d,0x16,0x25,0x19,0x1e,0xf2,0xc8,\r\n\t0x9d,0x81,0x81,0x81,0x94,0xbe,0xe7,0x11,0x1e,0xf6,0xd5,0xc4,0xc7,0xd9,0xef,0xd9,\r\n\t0xb9,0x9a,0x81,0x87,0xaa,0xcc,0xee,0x0f,0x20,0xfb,0x05,0x0b,0x09,0xfc,0x17,0x15,\r\n\t0xf3,0xd2,0xb1,0x8e,0x81,0x81,0x89,0xad,0xd2,0xf5,0x1a,0x17,0xf1,0xcd,0xc7,0xec,\r\n\t0x11,0x1b,0xf6,0xd2,0xae,0x8a,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x8c,0xb6,0xdf,0x09,0x2c,0x09,0xec,0xd4,0xbf,0xa9,0x9d,0x97,0x82,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x94,0xae,0xbe,0xc0,0xb3,0x9b,0xad,0xbd,0xc0,0xb4,0x9d,0x81,0x81,\r\n\t0x81,0x9b,0xc2,0xe8,0x0d,0x16,0xf3,0xd7,0xd5,0xdd,0xdd,0xda,0xf7,0x1a,0x0b,0xe6,\r\n\t0xc0,0x99,0x81,0x81,0x92,0xb5,0xcf,0xe3,0xef,0xf5,0xf5,0x09,0x1e,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x88,0xaa,0xc5,0xc8,0xb5,0xa2,0xa5,0xc0,0xc6,0xb5,0xa1,0x8a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbd,\r\n\t0xe7,0x11,0xff,0xd7,0x04,0x06,0xe8,0x0b,0xff,0xe1,0x0b,0x06,0xdd,0xb3,0x89,0x81,\r\n\t0x81,0x81,0x81,0x85,0x9f,0xaa,0xab,0xab,0xab,0xab,0xab,0xab,0xa3,0x8c,0x81,0x95,\r\n\t0xc0,0xea,0x15,0x11,0xe7,0xbd,0xb6,0xdf,0x09,0x1b,0xf2,0xc8,0x9d,0x81,0x81,0x81,\r\n\t0x8e,0x90,0x90,0xb0,0xda,0x06,0x26,0xfa,0xd0,0xa5,0x90,0x90,0x8b,0x81,0x81,0x81,\r\n\t0x81,0x97,0xac,0xba,0xd4,0xf0,0x0f,0x24,0xff,0xdb,0xb4,0x8b,0x81,0x81,0x85,0xb0,\r\n\t0xda,0x06,0x16,0x1b,0x19,0xf7,0xe3,0xc7,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9a,0xb8,0xc5,0xc5,0xc5,0xb6,0x9d,0x83,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,\r\n\t0xe5,0xde,0xbc,0x94,0xb0,0xd5,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x95,0xbf,0xe9,\r\n\t0x13,0x3c,0x66,0x7b,0x50,0x26,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x99,0xbd,0xd4,0xcd,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x94,\r\n\t0xbd,0xe7,0x11,0x17,0xee,0xc8,0xc5,0xed,0x16,0x13,0xe7,0xbe,0x94,0x81,0x91,0xa5,\r\n\t0xba,0xc8,0xbc,0x9e,0xa6,0xb9,0xca,0xc0,0xa2,0x81,0x81,0x81,0x81,0x81,0x8e,0xae,\r\n\t0xc1,0xcd,0xf7,0x23,0xff,0xd5,0xc7,0xeb,0x0f,0x14,0xf1,0xcd,0xa9,0x86,0x81,0x81,\r\n\t0x81,0x8d,0xac,0xbf,0xcd,0xf7,0x23,0xff,0xd5,0xc8,0xec,0x0f,0x12,0xee,0xcb,0xa7,\r\n\t0x84,0x81,0x81,0x81,0x92,0xb5,0xdd,0xf5,0xf5,0x05,0x27,0xff,0xd7,0xec,0x0f,0x13,\r\n\t0xf0,0xcc,0xa9,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xb9,0xd7,0xec,0xef,0xdd,\r\n\t0xbf,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8b,0x94,0x95,0x91,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbb,0xe2,0x07,0x1b,0x0b,0xe7,0xc0,\r\n\t0x98,0x81,0x81,0xa1,0xc7,0xec,0x0f,0x27,0x0b,0xf5,0x06,0x19,0xef,0xfc,0xf2,0xc8,\r\n\t0x9d,0x81,0x81,0x81,0x9b,0xc5,0xef,0x19,0x14,0xea,0xc1,0x9a,0x9f,0xb7,0xc5,0xba,\r\n\t0x9d,0x81,0x81,0x81,0x91,0xb2,0xd4,0xf5,0x18,0x21,0x1f,0x16,0x1b,0x26,0x1e,0xfb,\r\n\t0xd9,0xb8,0x97,0x81,0x81,0x81,0x81,0x98,0xbc,0xe0,0x05,0x2a,0x07,0xe2,0xdb,0xff,\r\n\t0x25,0x05,0xe1,0xbd,0x99,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x94,0xb5,0xd4,0xf1,0x14,0x27,0x0f,0xf9,0xe3,0xcd,0xb5,0x9c,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0x94,0x95,0x8c,0x81,0x87,0x94,0x95,0x8d,0x81,0x81,0x81,\r\n\t0x81,0xaa,0xd2,0xfa,0x21,0xff,0xdb,0xe8,0xfc,0x07,0x07,0xff,0xe4,0x05,0x1e,0xf7,\r\n\t0xcf,0xa7,0x81,0x81,0xa7,0xcd,0xee,0x09,0x19,0x16,0x16,0x18,0x1e,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x9e,0xc2,0xe6,0xee,0xdb,0xc6,0xbd,0xe0,0xee,0xda,0xc5,0xa7,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x16,0xfa,0xd7,0x04,0x12,0x11,0x04,0xea,0xda,0x06,0x0b,0xdf,0xb5,0x8b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x91,\r\n\t0xbb,0xe4,0x0c,0x1b,0xf5,0xdc,0xda,0xf1,0x14,0x11,0xe8,0xc0,0x97,0x81,0x81,0xa1,\r\n\t0xb7,0xba,0xba,0xba,0xda,0x06,0x26,0xfa,0xd0,0xba,0xba,0xba,0xb3,0x9a,0x81,0x81,\r\n\t0x8e,0xa8,0xc2,0xdb,0xf5,0x10,0x22,0x07,0xe8,0xc7,0xa2,0x81,0x81,0x81,0x8a,0xb0,\r\n\t0xda,0xff,0xff,0x04,0x12,0x1e,0x04,0xdf,0xb7,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x93,0x9b,0x9b,0x9b,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,\r\n\t0x11,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x11,0xf7,0xcd,0xa3,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x40,0x69,0x7b,0x50,0x26,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x81,0x82,0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9c,0xaa,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x9a,0x84,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x13,0xe7,0xbd,0xbd,0xe7,0x13,0x16,0xea,0xc0,0x95,0x8b,0xaf,0xcb,\r\n\t0xdf,0xf2,0xd9,0xb5,0xcc,0xdf,0xf3,0xdd,0xb9,0x96,0x81,0x81,0x81,0x81,0x81,0x8b,\r\n\t0xa3,0xcd,0xf7,0x23,0xff,0xd5,0xde,0xff,0x20,0xfc,0xd9,0xb6,0x92,0x81,0x81,0x81,\r\n\t0x81,0x81,0x88,0xa3,0xcd,0xf7,0x23,0xff,0xd5,0xdf,0x04,0x1e,0xfb,0xd8,0xb4,0x91,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc7,0xf1,0xf7,0xf5,0x09,0x25,0xff,0xdf,0x04,0x20,0xfc,\r\n\t0xd9,0xb5,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xcd,0xf3,0x13,0x17,0xfa,\r\n\t0xd4,0xac,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x88,0xa1,0xb4,0xbe,0xc0,0xbb,0xac,0x97,0x81,0x93,0xa1,0xa3,0xa3,0x9c,\r\n\t0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x15,0x3c,0x1a,0xef,0xc5,\r\n\t0x9b,0x81,0x88,0xb0,0xd8,0xff,0x26,0x0d,0xea,0xe2,0x0b,0x13,0xe8,0xd5,0xda,0xbd,\r\n\t0x97,0x81,0x81,0x99,0xad,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0xb0,0xb0,0xb0,0xad,0x9b,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa6,0xcd,0xf4,0x19,0x18,0xfa,0xea,0xf4,0x10,0x26,0xff,\r\n\t0xd9,0xb1,0x89,0x81,0x81,0x81,0x81,0x82,0xa7,0xcb,0xef,0x14,0x1b,0xf5,0xef,0x14,\r\n\t0x14,0xf0,0xcb,0xa7,0x83,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x82,\r\n\t0xa8,0xcd,0xf1,0x10,0x1c,0x09,0x1e,0x1d,0x07,0xf0,0xd7,0xbd,0x9f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8c,0xb5,0xde,0x07,0x19,0xf1,0xe6,0x09,0x21,0x0e,0x0b,0x11,0xe5,0xf5,0x1d,0x04,\r\n\t0xdb,0xb2,0x89,0x8a,0xb4,0xdd,0x06,0x23,0xfc,0xec,0xea,0x09,0x1e,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x81,0x91,0xb5,0xd9,0xfc,0x14,0xff,0xdd,0xd5,0xf7,0x13,0xff,0xdf,0xb5,\r\n\t0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbd,\r\n\t0xe7,0x11,0xff,0xd7,0x04,0x06,0xfb,0x10,0xeb,0xe1,0x0a,0x07,0xdd,0xb3,0x8a,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,\r\n\t0xaf,0xd5,0xfa,0x1b,0x14,0x06,0x04,0x11,0x1a,0xfb,0xd7,0xb2,0x8b,0x81,0x92,0xba,\r\n\t0xdd,0xe5,0xe5,0xe5,0xe5,0x06,0x26,0xfa,0xe5,0xe5,0xe5,0xe5,0xd5,0xb0,0x88,0x88,\r\n\t0xac,0xc9,0xe3,0xfc,0x17,0x1a,0xff,0xe6,0xd0,0xcf,0xbd,0x9b,0x81,0x87,0xaa,0xc3,\r\n\t0xc6,0xd5,0xd5,0xda,0xf6,0x21,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x92,0xbc,0xe6,\r\n\t0x0f,0x38,0x60,0x7b,0x50,0x26,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x96,0xaa,0xb5,0xb4,0xa8,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9b,0xbb,0xca,0xca,0xdf,0x0b,0x23,0xf7,0xcd,0xca,0xc0,0xa1,0x81,0x94,\r\n\t0xbe,0xe7,0x13,0x16,0xed,0xc7,0xc8,0xef,0x17,0x11,0xe7,0xbd,0x93,0x95,0xbf,0xe9,\r\n\t0x04,0x13,0xf0,0xcd,0xe7,0x05,0x18,0xf3,0xd0,0xac,0x89,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa3,0xcd,0xf7,0x16,0xff,0xd5,0xf5,0x19,0x09,0xe6,0xc2,0x9e,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa3,0xcd,0xf7,0x13,0xff,0xd5,0xf5,0x19,0x07,0xe3,0xc0,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x19,0x1b,0x14,0x05,0xea,0xf5,0x19,0x09,0xe5,\r\n\t0xc2,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x28,0x2f,0x06,\r\n\t0xda,0xb0,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0xa7,0xc4,0xda,0xe7,0xea,0xe3,0xd2,0xba,0x9f,0xb4,0xcb,0xcd,0xcd,0xc2,\r\n\t0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb9,0xdf,0xff,0x13,0x05,0xe3,0xbd,\r\n\t0x95,0x81,0x91,0xba,0xe4,0x0d,0x23,0xfa,0xd3,0xe7,0x11,0x0e,0xe2,0xb9,0xb1,0xa0,\r\n\t0x82,0x81,0x8f,0xb5,0xd4,0xda,0xef,0x1b,0x13,0xe7,0xda,0xda,0xda,0xda,0xd5,0xb7,\r\n\t0x91,0x81,0x81,0x81,0x88,0xb1,0xda,0x04,0x2c,0x04,0xde,0xc1,0xd4,0xfa,0x23,0x0e,\r\n\t0xe5,0xbb,0x92,0x81,0x81,0x81,0x81,0x81,0x91,0xb5,0xda,0xff,0x22,0x0a,0x04,0x22,\r\n\t0xff,0xda,0xb6,0x92,0x81,0x81,0x81,0x94,0xbd,0xe4,0xef,0xef,0xe2,0xbb,0x91,0x8f,\r\n\t0xb8,0xe0,0x07,0x24,0xff,0xe3,0xfa,0x0f,0x26,0x12,0xf7,0xda,0xba,0x96,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x92,0xbc,0xe6,0x11,0x11,0xe7,0xf9,0x20,0x05,0xe7,0xe1,0xed,0xe1,0xea,0x13,0x0d,\r\n\t0xe2,0xb9,0x8f,0x8b,0xb5,0xdf,0x0b,0x1e,0xf5,0xe4,0xf5,0x10,0x1e,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x85,0xa8,0xcc,0xef,0x13,0x15,0xf1,0xce,0xee,0x10,0x17,0xf4,0xd2,0xad,\r\n\t0x85,0x81,0x91,0xa2,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa2,0x91,\r\n\t0x81,0x81,0x95,0xa8,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xa8,0x95,0x81,0x8c,0xb5,\r\n\t0xdd,0x05,0x0d,0xe8,0x04,0x06,0xe9,0x11,0xfc,0xf1,0x17,0xfb,0xd3,0xab,0x82,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9c,0xbf,0xdf,0xf9,0x0b,0x14,0x14,0x0b,0xf7,0xdd,0xbf,0x9d,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x11,0x11,0x11,0x11,0x12,0x2a,0x11,0x11,0x11,0x11,0x0b,0xdf,0xb5,0x8b,0x95,\r\n\t0xbf,0xe7,0x05,0x1f,0x16,0xfa,0xfa,0xfa,0xfa,0xf9,0xd2,0xa8,0x81,0x94,0xbe,0xe6,\r\n\t0xef,0xeb,0xea,0xef,0x04,0x27,0x0c,0xe4,0xba,0x91,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x8a,0xb3,0xdb,\r\n\t0xff,0x27,0x47,0x5e,0x50,0x26,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x99,\r\n\t0xb8,0xd1,0xdf,0xdd,0xce,0xb4,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xaa,0xd3,0xf5,0xf5,0xf5,0x0b,0x23,0xf7,0xf5,0xf5,0xdb,0xb2,0x88,0x8d,\r\n\t0xb6,0xdf,0x06,0x25,0x04,0xeb,0xeb,0x04,0x26,0xff,0xdb,0xb3,0x8b,0x90,0xb6,0xda,\r\n\t0xfc,0x1f,0x09,0xe5,0xd6,0xf9,0x1d,0x0b,0xe7,0xc3,0x9f,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa0,0xc8,0xe8,0xea,0xea,0xe8,0x0d,0x15,0xf1,0xce,0xab,0x8b,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9f,0xc7,0xe6,0xe7,0xe7,0xe9,0x0d,0x14,0xf0,0xcd,0xa9,0x8b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9b,0xc3,0xe6,0xee,0xef,0xec,0xdf,0xe9,0x0d,0x14,0xf1,0xce,\r\n\t0xaa,0x8d,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa2,0xc9,0xef,0x0c,0x0f,0xf5,\r\n\t0xd1,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9e,0xc2,0xe3,0xff,0x11,0x16,0x0b,0xf5,0xdb,0xbd,0xc7,0xef,0xf7,0xf7,0xdc,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xc5,0xde,0xe7,0xe0,0xc8,0xa9,\r\n\t0x85,0x81,0x95,0xc0,0xea,0x14,0x1b,0xf2,0xc8,0xed,0x17,0x09,0xdd,0xb4,0x8a,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x06,0x06,0x1c,0x14,0x06,0x06,0x06,0x06,0x06,0xed,0xc2,\r\n\t0x98,0x81,0x81,0x81,0x8d,0xb8,0xe2,0x0b,0x23,0xfa,0xd0,0xa7,0xc7,0xf1,0x1b,0x14,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x96,0xaf,0xb8,0xc5,0xe8,0x0d,0x1f,0x1a,0x0d,\r\n\t0xe8,0xc5,0xb8,0xae,0x94,0x81,0x81,0x86,0xa8,0xc1,0xc5,0xc5,0xc0,0xa7,0x84,0x95,\r\n\t0xc0,0xea,0x13,0x16,0xed,0xc5,0xd5,0xec,0x04,0x1f,0x16,0xf4,0xd1,0xab,0x83,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x15,0x0b,0xe1,0x04,0x1f,0xf5,0xcd,0xb8,0xc6,0xc1,0xe4,0x0e,0x12,\r\n\t0xe7,0xbd,0x93,0x86,0xb0,0xd8,0xff,0x21,0x14,0x0e,0x18,0xff,0x1e,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x9c,0xbf,0xe3,0x06,0x21,0xfc,0xdb,0xe3,0x05,0x20,0xfc,0xdb,0xb9,0x97,\r\n\t0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xcb,0xaf,\r\n\t0x8b,0x8d,0xb2,0xcf,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xcf,0xb2,0x8d,0x81,0xa6,\r\n\t0xcd,0xf1,0x14,0x04,0x04,0x04,0xda,0xff,0x04,0x0b,0x0c,0xe8,0xc2,0x9c,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x83,0xa3,0xbf,0xd4,0xe3,0xea,0xea,0xe2,0xd3,0xbd,0xa1,0x83,0x81,0x81,0x95,0xc0,\r\n\t0xea,0x0e,0x0e,0x0e,0x0e,0x0f,0x29,0x0e,0x0e,0x0e,0x0e,0x0b,0xdf,0xb5,0x8b,0x95,\r\n\t0xc0,0xea,0x16,0x29,0x29,0x26,0x26,0x26,0x26,0xfc,0xd2,0xa8,0x81,0x95,0xc0,0xea,\r\n\t0x16,0x16,0x16,0x19,0x23,0x11,0xf5,0xd3,0xad,0x86,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0xa3,0xc8,\r\n\t0xec,0x0b,0x25,0x36,0x41,0x26,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x89,0xaf,\r\n\t0xd4,0xf3,0x09,0x06,0xf0,0xd0,0xab,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xab,0xd5,0xff,0x21,0x21,0x23,0x29,0x21,0x21,0x09,0xdd,0xb2,0x88,0x81,\r\n\t0xa8,0xce,0xf1,0x10,0x23,0x14,0x14,0x21,0x0a,0xeb,0xc8,0xa2,0x81,0x81,0x9f,0xc1,\r\n\t0xe3,0x06,0x20,0xfc,0xda,0xe3,0x06,0x21,0xfc,0xda,0xb6,0x93,0x81,0x81,0x81,0x81,\r\n\t0x8e,0xae,0xbf,0xc0,0xdc,0xff,0x22,0xfc,0xdb,0xb7,0xb5,0xb5,0xa7,0x8a,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8d,0xac,0xbc,0xbd,0xdd,0xff,0x20,0xfc,0xd9,0xc0,0xbd,0xb3,0xa0,\r\n\t0x85,0x81,0x81,0x81,0x8a,0xaa,0xbe,0xc5,0xc5,0xc2,0xdd,0xff,0x21,0xfc,0xda,0xb8,\r\n\t0xb8,0xb7,0xa9,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xb4,0xd2,0xe5,0xe7,0xd6,\r\n\t0xb9,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0xaf,0xd6,0xfb,0x1f,0x14,0x0e,0x1f,0x16,0xf7,0xdb,0xcb,0xf5,0x1f,0x06,0xdc,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xaa,0xd4,0xfa,0xfa,0xfa,0xda,0xb0,\r\n\t0x85,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc9,0xf2,0x1d,0x04,0xd7,0xad,0x84,0x81,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0x25,0x20,0x19,0x19,0x19,0x19,0x19,0xed,0xc2,\r\n\t0x98,0x81,0x81,0x81,0x8d,0xb8,0xe2,0x0e,0x23,0xf7,0xcd,0xa4,0xc7,0xf1,0x1b,0x15,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x84,0xad,0xd2,0xe2,0xe2,0xe2,0xf7,0x1d,0x1d,0xf7,\r\n\t0xe2,0xe2,0xe2,0xd0,0xaa,0x82,0x81,0x81,0x88,0x98,0x9b,0x9b,0x98,0x86,0x81,0x95,\r\n\t0xc0,0xea,0x13,0x19,0xf1,0xcd,0xb1,0xc8,0xe3,0x04,0x26,0x09,0xe1,0xb8,0x8f,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x0b,0xdf,0x06,0x1e,0xf2,0xc8,0xa5,0xb4,0xb8,0xe2,0x0e,0x13,\r\n\t0xe7,0xbd,0x93,0x81,0xa1,0xc5,0xe4,0xfc,0x06,0x04,0xf4,0xf9,0xfc,0xf1,0xc7,0x9f,\r\n\t0x81,0x8b,0xb2,0xd5,0xf9,0x1d,0x0b,0xe7,0xd8,0xfa,0x1d,0x09,0xe6,0xc3,0xa1,0x81,\r\n\t0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xe9,0xbf,\r\n\t0x95,0x95,0xc0,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xea,0xc0,0x95,0x81,0x93,\r\n\t0xb7,0xd9,0xf7,0x13,0x0b,0xfc,0xf7,0xff,0x10,0x0d,0xf0,0xd0,0xae,0x8a,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x83,0x9b,0xae,0xba,0xc0,0xc0,0xb9,0xad,0x9a,0x82,0x81,0x81,0x81,0x91,0xb9,\r\n\t0xdb,0xe2,0xe2,0xe2,0xe2,0x06,0x26,0xfa,0xe2,0xe2,0xe2,0xe2,0xd4,0xaf,0x87,0x95,\r\n\t0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfb,0xd2,0xa8,0x81,0x95,0xc0,0xea,\r\n\t0x04,0x06,0x06,0x04,0xfa,0xec,0xd6,0xb9,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x8e,0xb0,\r\n\t0xce,0xea,0xff,0x0e,0x19,0x1d,0xfa,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x94,0xbd,\r\n\t0xe7,0x0f,0x2f,0x2c,0x0a,0xe1,0xb8,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xaa,0xd5,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xdd,0xb2,0x88,0x81,\r\n\t0x9f,0xb6,0xd4,0xed,0xfc,0x06,0x04,0xfa,0xe7,0xce,0xb7,0xa1,0x81,0x81,0x86,0xa9,\r\n\t0xcb,0xee,0x10,0x15,0xf1,0xcf,0xef,0x13,0x14,0xf1,0xcd,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8a,0xac,0xd0,0xf3,0x17,0x0b,0xe7,0xdf,0xdf,0xdf,0xdf,0xc5,0x9f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8a,0xad,0xd1,0xf4,0x18,0x09,0xe6,0xe4,0xea,0xe7,0xd9,0xc1,\r\n\t0xa3,0x81,0x81,0x81,0x81,0x87,0x95,0x9a,0xad,0xd0,0xf3,0x18,0x0b,0xe6,0xe1,0xe2,\r\n\t0xe2,0xe1,0xc7,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xba,0xe4,0xfc,0xfc,0xea,\r\n\t0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x90,0xba,0xe3,0x0c,0x19,0xf3,0xe5,0xfc,0x1c,0x16,0xfb,0xea,0xff,0x25,0xfc,0xd4,\r\n\t0xab,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x26,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x93,0xbd,0xe7,0x11,0x20,0xf7,0xcf,0xf7,0x23,0xfc,0xd2,0xa8,0xa9,0x99,\r\n\t0x81,0x81,0x94,0xbd,0xe3,0xed,0xef,0x1b,0x13,0xed,0xed,0xed,0xed,0xed,0xe4,0xbf,\r\n\t0x96,0x81,0x81,0x81,0x8b,0xb5,0xdf,0x09,0x28,0xff,0xd6,0xb6,0xd2,0xf9,0x22,0x0e,\r\n\t0xe4,0xbb,0x91,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x0e,0x0e,0x0e,0x1d,0x1d,0x0e,\r\n\t0x0e,0x0e,0x06,0xda,0xb0,0x85,0x81,0x86,0xa8,0xc1,0xc5,0xc5,0xc0,0xa7,0x84,0x8f,\r\n\t0xb7,0xdf,0x05,0x29,0x09,0xeb,0xd2,0xba,0xc8,0xef,0x19,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0xbd,0xe7,0x13,0x0e,0xe4,0xff,0x23,0xfa,0xd6,0xcf,0xdc,0xd5,0xe7,0x11,0x11,\r\n\t0xe5,0xbb,0x91,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xdb,0xb8,\r\n\t0x8f,0x93,0xbd,0xe7,0x10,0x1e,0xf3,0xd0,0xea,0x12,0x19,0xef,0xcd,0xaa,0x88,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x16,0xea,0xc0,\r\n\t0x95,0x95,0xc0,0xea,0x16,0x29,0x29,0x29,0x29,0x29,0x16,0xea,0xc0,0x95,0x81,0x81,\r\n\t0x9d,0xbb,0xd8,0xef,0x04,0x0d,0x11,0x0b,0xfc,0xea,0xd2,0xb4,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x85,0x90,0x95,0x95,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,\r\n\t0xb4,0xb8,0xb8,0xb8,0xda,0x06,0x26,0xfa,0xd0,0xb8,0xb8,0xb8,0xb1,0x98,0x81,0x8c,\r\n\t0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xbf,0x9c,0x81,0x8c,0xb1,0xce,\r\n\t0xd7,0xda,0xda,0xd7,0xd2,0xc5,0xb3,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x92,\r\n\t0xaf,0xc6,0xd8,0xe6,0xed,0xf2,0xf1,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x95,0xc0,\r\n\t0xea,0x14,0x3c,0x38,0x0f,0xe5,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9f,0xc1,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xc6,0xa6,0x81,0x8f,\r\n\t0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xdd,0xba,0x92,0x81,0x81,0x90,\r\n\t0xb3,0xd5,0xf7,0x21,0x0b,0xdf,0xd9,0xfb,0x26,0x07,0xdd,0xb2,0x88,0x81,0x81,0x81,\r\n\t0x81,0xa0,0xc4,0xe7,0x0b,0x17,0xf3,0xde,0x04,0x0b,0x0b,0xfa,0xd0,0xa5,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa1,0xc5,0xe8,0x0b,0x15,0xf1,0xf9,0x0d,0x16,0x11,0xfc,0xde,\r\n\t0xba,0x94,0x81,0x81,0x81,0x81,0x81,0xa1,0xc4,0xe7,0x0b,0x17,0xf3,0xdf,0x04,0x0e,\r\n\t0x0e,0xfa,0xd0,0xa5,0x81,0x81,0x81,0x81,0x81,0x88,0x9a,0xba,0xe5,0x11,0x16,0xea,\r\n\t0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x13,0x11,0xe7,0xc2,0xdf,0xfc,0x19,0x1f,0x16,0x20,0x10,0xed,0xc7,\r\n\t0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x8d,0xb6,0xdf,0x07,0x2c,0x06,0xe3,0xfc,0x21,0xf5,0xcc,0xce,0xd2,0xb9,\r\n\t0x94,0x81,0x85,0xa7,0xbe,0xc5,0xef,0x1b,0x13,0xe7,0xc2,0xc2,0xc2,0xc2,0xbf,0xa9,\r\n\t0x87,0x81,0x81,0x81,0x84,0xad,0xd5,0xfc,0x24,0x0f,0xf0,0xdf,0xed,0x0c,0x25,0xff,\r\n\t0xd8,0xb1,0x88,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x0b,0x0b,0x0b,0x1b,0x1b,0x0b,\r\n\t0x0b,0x0b,0x06,0xda,0xb0,0x85,0x81,0x94,0xbd,0xe4,0xef,0xef,0xe2,0xbb,0x91,0x81,\r\n\t0xa6,0xcb,0xee,0x0f,0x27,0x0d,0xf4,0xdf,0xce,0xf3,0x1c,0x0e,0xe5,0xbb,0x92,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8f,0xb8,0xe2,0x0b,0x15,0xec,0xf4,0x1a,0x12,0xfc,0xf7,0x04,0xe5,0xee,0x17,0x09,\r\n\t0xdf,0xb6,0x8c,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xe7,0xbd,\r\n\t0x93,0x8b,0xb2,0xd5,0xf9,0x1d,0x0b,0xe6,0xd8,0xfa,0x1d,0x09,0xe5,0xc3,0xa0,0x81,\r\n\t0x81,0x95,0xbf,0xe9,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0x16,0x16,0xea,0xc0,\r\n\t0x95,0x95,0xc0,0xea,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xea,0xc0,0x95,0x81,0x81,\r\n\t0x81,0x9d,0xb5,0xc9,0xda,0xe2,0xe5,0xe1,0xd6,0xc5,0xaf,0x96,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0x8d,0x8d,0xb0,0xda,0x06,0x26,0xfa,0xd0,0xa5,0x8d,0x8d,0x89,0x81,0x81,0x81,\r\n\t0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x9c,0x83,0x81,0x81,0x93,0xa7,\r\n\t0xad,0xb0,0xb0,0xaf,0xa8,0x9e,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8c,0xa0,0xb1,0xbd,0xc4,0xc8,0xc7,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x8f,0xb7,\r\n\t0xde,0xff,0x1a,0x18,0xfc,0xd9,0xb2,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0x9e,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa1,0x8a,0x81,0x93,\r\n\t0xbd,0xe7,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xea,0xc0,0x95,0x81,0x86,0xa9,\r\n\t0xcb,0xee,0x10,0x15,0xf1,0xd0,0xef,0x13,0x14,0xf1,0xcd,0xa8,0x81,0x81,0x81,0x81,\r\n\t0x94,0xb7,0xdb,0xfc,0x22,0xff,0xdc,0xf5,0x19,0x04,0x26,0xfa,0xd0,0xa5,0x81,0x81,\r\n\t0x81,0x81,0x81,0x94,0xb8,0xdb,0xff,0x22,0xff,0xdb,0xff,0x0a,0xfc,0x0f,0x19,0xf1,\r\n\t0xc8,0x9e,0x81,0x81,0x81,0x81,0x94,0xb7,0xdb,0xff,0x22,0xff,0xdc,0xf5,0x1a,0x04,\r\n\t0x26,0xfa,0xd0,0xa5,0x81,0x81,0x81,0x81,0x94,0xad,0xc1,0xcd,0xe5,0x11,0x16,0xea,\r\n\t0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0xbe,0xe6,0xf2,0xf2,0xe1,0xb9,0xc1,0xdd,0xf6,0x09,0x0e,0x06,0xf1,0xd4,0xb2,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0xa9,0xd1,0xf6,0x1a,0x1e,0xff,0x04,0x1b,0xef,0xea,0xf5,0xf2,0xc8,\r\n\t0x9d,0x81,0x81,0x86,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x98,0x98,0x98,0x96,0x90,\r\n\t0x8a,0x81,0x81,0x81,0x8a,0xac,0xcd,0xee,0x13,0x2b,0x14,0x0b,0x12,0x29,0x19,0xf5,\r\n\t0xd4,0xb2,0x91,0x81,0x81,0x81,0x84,0xac,0xd0,0xdf,0xdf,0xdf,0xed,0x19,0x19,0xed,\r\n\t0xdf,0xdf,0xdf,0xce,0xa9,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x91,0xb2,0xd2,0xee,0x07,0x1f,0x19,0x04,0xed,0x0a,0x21,0xfc,0xd8,0xb1,0x89,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0xaf,0xd7,0xff,0x21,0xfa,0xdf,0xfc,0x12,0x1b,0x19,0x0f,0xe5,0xfb,0x23,0xfc,\r\n\t0xd5,0xad,0x84,0x95,0xc0,0xea,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0xe7,0xbd,\r\n\t0x93,0x81,0x9c,0xbf,0xe3,0x07,0x21,0xfc,0xda,0xe3,0x05,0x20,0xfc,0xdb,0xb9,0x96,\r\n\t0x81,0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xea,0x16,0x16,0xea,0xc0,\r\n\t0x95,0x8c,0xb1,0xcd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xcd,0xb1,0x8c,0x81,0x81,\r\n\t0x81,0x81,0x91,0xa4,0xb1,0xb9,0xba,0xb7,0xaf,0x9f,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x87,0x8d,0x8d,0xb0,0xda,0x06,0x26,0xfa,0xd0,0xa5,0x8d,0x8d,0x84,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x84,0x85,0x85,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x9a,0xba,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x89,0x94,0x9a,0x9d,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0xa4,\r\n\t0xc5,0xe0,0xf1,0xef,0xde,0xc1,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbd,0xe7,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0xea,0xc0,0x95,0x81,0x9e,0xc1,\r\n\t0xe3,0x06,0x20,0xfc,0xdb,0xe3,0x06,0x22,0xfc,0xda,0xb7,0x93,0x81,0x81,0x81,0x87,\r\n\t0xab,0xce,0xf1,0x15,0x0c,0xe8,0xe8,0x0d,0x0f,0xfc,0x26,0xfa,0xd0,0xaa,0x8e,0x81,\r\n\t0x81,0x81,0x88,0xac,0xcf,0xf1,0x16,0x0b,0xe7,0xc4,0xe6,0xe6,0xdb,0x04,0x1f,0xf5,\r\n\t0xca,0xa0,0x81,0x81,0x81,0x88,0xab,0xce,0xf1,0x15,0x0c,0xe8,0xe9,0x0d,0x0f,0xfc,\r\n\t0x26,0xfa,0xd0,0xaa,0x8e,0x81,0x81,0x91,0xb2,0xd0,0xe7,0xf6,0xfc,0x11,0x16,0xea,\r\n\t0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x87,0xaa,0xc3,0xc8,0xc8,0xc1,0xa6,0xa2,0xbc,0xd1,0xdf,0xe2,0xdd,0xcd,0xb5,0x98,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x98,0xbc,0xdf,0xfc,0x18,0x25,0x19,0x1d,0x0e,0x13,0x1e,0xf2,0xc8,\r\n\t0x9d,0x81,0x81,0xa1,0xb7,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0xba,0xba,0xba,0xba,0xba,\r\n\t0xb1,0x96,0x81,0x82,0xa4,0xc5,0xe6,0x09,0x23,0x04,0x11,0x16,0x11,0x04,0x1f,0x0f,\r\n\t0xee,0xcc,0xaa,0x89,0x81,0x81,0x88,0xb2,0xdc,0xf7,0xf7,0xf7,0xf7,0x19,0x19,0xf7,\r\n\t0xf7,0xf7,0xf7,0xd9,0xaf,0x85,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x96,0xb2,0xcd,0xe4,0xfb,0x10,0x25,0x16,0x1d,0x05,0xe6,0xc4,0xa0,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa2,0xca,0xf1,0x17,0x0d,0xea,0xda,0xea,0xef,0xef,0xe7,0xea,0x0f,0x14,0xee,\r\n\t0xc7,0xa0,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xd5,0xb4,\r\n\t0x8d,0x81,0x85,0xa8,0xcc,0xf0,0x14,0x14,0xf1,0xcd,0xee,0x10,0x16,0xf3,0xd2,0xad,\r\n\t0x85,0x81,0x91,0xa2,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xc0,0xea,0x16,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x93,0xa5,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa5,0x93,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0x8f,0x90,0x8d,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,\r\n\t0xae,0xb8,0xb8,0xb8,0xda,0xfa,0xfa,0xf7,0xcf,0xb8,0xb8,0xb8,0xaa,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x1b,0xf1,0xc8,0xb9,0xd5,0xf5,0x18,0x23,0xf7,0xcd,0xae,0x96,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x89,\r\n\t0xa6,0xbb,0xc7,0xc6,0xb9,0xa2,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,\r\n\t0xb4,0xd5,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xd6,0xb6,0x90,0x90,0xb6,0xd9,\r\n\t0xfb,0x1f,0x09,0xe6,0xd6,0xf9,0x1d,0x0b,0xe7,0xc4,0xa0,0x81,0x81,0x81,0x81,0x9e,\r\n\t0xc2,0xe6,0x09,0x18,0xf5,0xdc,0xff,0x1d,0xf9,0xfc,0x26,0xfa,0xe2,0xc9,0xa3,0x81,\r\n\t0x81,0x81,0x9f,0xc2,0xe6,0x0a,0x18,0xf3,0xd0,0xad,0xc6,0xe0,0xfa,0x17,0x0b,0xe8,\r\n\t0xc2,0x99,0x81,0x81,0x81,0x9e,0xc2,0xe6,0x09,0x18,0xf4,0xdc,0xff,0x1d,0xf9,0xfc,\r\n\t0x26,0xfa,0xe2,0xc9,0xa3,0x81,0x81,0xa6,0xcc,0xee,0x0b,0x1f,0x1d,0x19,0x16,0xea,\r\n\t0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8a,0x9b,0x9d,0x9d,0x99,0x87,0x81,0x98,0xaa,0xb6,0xb8,0xb4,0xa7,0x94,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0xa3,0xc1,0xde,0xf3,0x04,0x14,0x16,0x0f,0x0b,0xff,0xef,0xc7,\r\n\t0x9d,0x81,0x92,0xba,0xdd,0xe5,0xef,0x1b,0x13,0xe7,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xd1,0xab,0x82,0x92,0xbb,0xdf,0xff,0x22,0x0d,0xe8,0xe7,0xea,0xe7,0xe4,0x07,0x29,\r\n\t0x07,0xe6,0xc2,0x9a,0x81,0x81,0x88,0xb2,0xdd,0x09,0x21,0x21,0x21,0x29,0x29,0x21,\r\n\t0x21,0x21,0x06,0xda,0xb0,0x85,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x81,0x92,0xa9,0xc1,0xd6,0xec,0x04,0x1c,0x18,0xf9,0xd4,0xae,0x89,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x92,0xb8,0xde,0xff,0x22,0x07,0xec,0xd9,0xd2,0xda,0xec,0x07,0x1f,0xfc,0xdb,\r\n\t0xb5,0x8f,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xaf,0x99,\r\n\t0x81,0x81,0x81,0x92,0xb5,0xd9,0xfc,0x15,0xff,0xdd,0xd5,0xf9,0x14,0xff,0xdf,0xb5,\r\n\t0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xaa,\r\n\t0xd0,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xc9,0xa3,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x25,0xff,0xe2,0xe0,0xf4,0x12,0x11,0x26,0xfc,0xdf,0xd2,0xae,0x86,0x81,0x81,0x81,\r\n\t0x85,0x9b,0xa3,0x99,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x81,0x81,0x81,\r\n\t0x82,0x95,0x9d,0x9d,0x92,0x81,0x81,0x81,0x81,0x81,0x8c,0x9a,0x9b,0x9b,0x96,0x83,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x99,0xaf,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xaf,0x9b,0x81,0x95,0xbf,0xe9,\r\n\t0x05,0x13,0xf1,0xcd,0xe5,0x06,0x18,0xf4,0xd1,0xad,0x89,0x81,0x81,0x81,0x92,0xb5,\r\n\t0xd9,0xfc,0x20,0xff,0xde,0xe7,0x13,0x16,0x0e,0x0e,0x29,0x0e,0xfc,0xd2,0xa8,0x81,\r\n\t0x81,0x93,0xb6,0xda,0xfc,0x20,0xff,0xdd,0xb9,0xcc,0xe7,0xff,0x1c,0x09,0xee,0xd7,\r\n\t0xc3,0x9f,0x81,0x81,0x92,0xb5,0xd9,0xfc,0x20,0xff,0xde,0xe7,0x13,0x16,0x0e,0x0e,\r\n\t0x29,0x0e,0xfc,0xd2,0xa8,0x81,0x8d,0xb6,0xde,0x05,0x2a,0x0d,0xf5,0xed,0xed,0xe3,\r\n\t0xbd,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x8c,0x8d,0x8a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x85,0xa2,0xba,0xcd,0xea,0x14,0x0b,0xe5,0xe0,0xd8,0xcc,0xb4,\r\n\t0x91,0x81,0x95,0xc0,0xea,0x11,0x11,0x20,0x1a,0x11,0x11,0x11,0x11,0x11,0x11,0x06,\r\n\t0xda,0xb0,0x85,0x94,0xbd,0xe4,0xfc,0x12,0xf5,0xd2,0xbd,0xc0,0xbd,0xcd,0xf1,0x14,\r\n\t0xff,0xea,0xc5,0x9c,0x81,0x81,0x88,0xb2,0xdb,0xf5,0xf5,0xf5,0xf5,0x19,0x19,0xf5,\r\n\t0xf5,0xf5,0xf5,0xd8,0xaf,0x85,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x8e,0xa7,0xb0,0xa7,0x9d,0xb2,0xc8,0xe0,0xff,0x26,0x0b,0xe2,0xb8,0x8d,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa3,0xc5,0xe6,0x05,0x1e,0x11,0x04,0xfc,0x04,0x11,0x1c,0xff,0xe3,0xc3,\r\n\t0xa0,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x86,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9f,0xc2,0xe6,0xef,0xdb,0xc6,0xbd,0xe0,0xee,0xda,0xc5,0xa7,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xdd,0xba,\r\n\t0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,\r\n\t0xda,0x06,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0xfc,0xd2,0xa8,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x22,0x1c,0x0b,0x0a,0x18,0x0f,0xf9,0x20,0x16,0x0b,0xdf,0xb5,0x8b,0x81,0x81,0x81,\r\n\t0xa2,0xc0,0xcd,0xbd,0xa6,0x9b,0xb6,0xdf,0x09,0x24,0xfa,0xd0,0xa7,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xae,0xc3,0xc5,0xc5,0xbe,0xa2,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x86,0x81,0x81,0x8b,0xaf,0xcb,\r\n\t0xdf,0xf2,0xd9,0xb5,0xcd,0xe0,0xf4,0xde,0xba,0x96,0x81,0x81,0x81,0x85,0xa9,0xcd,\r\n\t0xf0,0x13,0x0d,0xea,0xc7,0xe7,0x06,0x06,0x06,0x06,0x26,0x06,0xfc,0xd2,0xa8,0x81,\r\n\t0x85,0xaa,0xcd,0xf1,0x14,0x0d,0xe9,0xc6,0xb5,0xdf,0x09,0x23,0x05,0x04,0x04,0xfc,\r\n\t0xd2,0xa8,0x81,0x85,0xa9,0xcd,0xf0,0x14,0x0d,0xea,0xc7,0xe7,0x06,0x06,0x06,0x06,\r\n\t0x26,0x06,0xfc,0xd2,0xa8,0x81,0x95,0xbf,0xe7,0x12,0x21,0xf6,0xd0,0xc3,0xc2,0xbe,\r\n\t0xa7,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x81,0x81,0x9c,0xc6,0xef,0x1a,0x05,0xda,0xb7,0xaf,0xa4,0x93,\r\n\t0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x06,\r\n\t0xda,0xb0,0x85,0x86,0xa8,0xc2,0xd9,0xee,0xdf,0xbb,0x98,0x95,0x94,0xb6,0xd9,0xef,\r\n\t0xdc,0xc6,0xae,0x8d,0x81,0x81,0x81,0xa1,0xc0,0xca,0xca,0xca,0xed,0x13,0x13,0xed,\r\n\t0xca,0xca,0xca,0xbe,0x9f,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0xa7,0xca,0xda,0xd0,0xc7,0xc5,0xc8,0xd5,0xfa,0x24,0x0b,0xe1,0xb7,0x8d,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8a,0xaa,0xc8,0xe3,0xfa,0x0b,0x15,0x19,0x14,0x0a,0xf7,0xe1,0xc6,0xa8,\r\n\t0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0xaa,0xc5,0xc8,0xb6,0xa2,0xa5,0xc0,0xc6,0xb5,0xa1,0x8a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb7,0xa1,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,\r\n\t0xda,0x06,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xfc,0xd2,0xa8,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x13,0x07,0x16,0x16,0x07,0xf0,0xe6,0x05,0x13,0x0b,0xdf,0xb5,0x8b,0x81,0x81,0x97,\r\n\t0xba,0xdd,0xf7,0xdf,0xcd,0xc5,0xd0,0xee,0x14,0x1a,0xf2,0xc9,0xa0,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xc5,0xea,0xef,0xef,0xde,0xb6,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xa6,\r\n\t0xba,0xc8,0xbc,0x9e,0xa7,0xba,0xca,0xc0,0xa2,0x81,0x81,0x81,0x81,0x92,0xbb,0xe3,\r\n\t0x07,0x13,0xf6,0xd3,0xb3,0xd3,0xda,0xda,0xda,0xfc,0x13,0xfa,0xda,0xc4,0xa0,0x81,\r\n\t0x92,0xbb,0xe3,0x09,0x11,0xf5,0xd2,0xaf,0xb5,0xdf,0x0b,0x11,0x11,0x11,0x11,0xfc,\r\n\t0xd2,0xa8,0x81,0x92,0xbb,0xe3,0x07,0x13,0xf6,0xd3,0xb3,0xd3,0xda,0xda,0xda,0xfc,\r\n\t0x13,0xfa,0xda,0xc4,0xa0,0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc9,0x9f,0x98,0x96,\r\n\t0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x81,0x81,0xa2,0xcc,0xf5,0x20,0xff,0xd5,0xab,0x86,0x81,0x81,\r\n\t0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xd1,0xab,0x82,0x81,0x88,0x9e,0xb4,0xc6,0xc0,0xa4,0x81,0x81,0x81,0x9e,0xbb,0xc5,\r\n\t0xb8,0xa2,0x8c,0x81,0x81,0x81,0x81,0x84,0x9a,0xa0,0xa0,0xbd,0xe0,0xe7,0xe7,0xe0,\r\n\t0xbd,0xa0,0xa0,0x99,0x83,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x85,\r\n\t0xb0,0xda,0x05,0xf7,0xef,0xef,0xf2,0xfa,0x12,0x1f,0xfc,0xd6,0xaf,0x86,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8c,0xa8,0xc0,0xd4,0xe2,0xea,0xed,0xea,0xe1,0xd2,0xbe,0xa6,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8b,0x9d,0x9f,0x91,0x81,0x85,0x99,0x9d,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xab,\r\n\t0xd1,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe4,0xcb,0xa4,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x16,0xea,0xed,0xec,0xe1,0xcd,0xca,0xe0,0xea,0xe8,0xd5,0xb0,0x88,0x81,0x82,0xab,\r\n\t0xd2,0xf4,0x18,0x05,0xf5,0xef,0xf6,0x0b,0x29,0x07,0xe2,0xbc,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa6,0xcf,0xf7,0x1b,0x06,0xdd,0xb5,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0x9d,0x96,0x81,0x81,0x95,0xa0,0x9a,0x84,0x81,0x81,0x81,0x81,0x90,0xb9,0xdd,\r\n\t0xe7,0xe7,0xdd,0xbc,0x99,0xac,0xb0,0xb0,0xcc,0xe7,0xe7,0xe7,0xc9,0xa3,0x89,0x81,\r\n\t0x8f,0xb8,0xdb,0xe5,0xe5,0xdd,0xbb,0x98,0xb0,0xd5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe4,\r\n\t0xcb,0xa4,0x81,0x90,0xb9,0xdd,0xe7,0xe7,0xdd,0xbc,0x99,0xac,0xb0,0xb0,0xcc,0xe7,\r\n\t0xe7,0xe7,0xc9,0xa3,0x89,0x81,0x92,0xbc,0xe6,0x0f,0x24,0xfc,0xd7,0xb7,0xa4,0x9d,\r\n\t0x9a,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x81,0x81,0xa7,0xd1,0xfa,0x23,0xf7,0xcf,0xa5,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xb1,0x96,0x81,0x81,0x81,0x81,0x8f,0x9d,0x99,0x85,0x81,0x81,0x81,0x81,0x95,0x9b,\r\n\t0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xa5,0xba,0xbd,0xbd,0xba,\r\n\t0xa5,0x84,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x85,\r\n\t0xb0,0xda,0x06,0x21,0x1b,0x1b,0x1b,0x23,0x15,0xff,0xe3,0xc2,0x9e,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x86,0x9b,0xad,0xb9,0xc1,0xc2,0xc0,0xb8,0xab,0x99,0x83,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,\r\n\t0xb1,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xac,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0xc2,0xb9,0xa8,0xa7,0xb8,0xc0,0xbf,0xb4,0x9a,0x81,0x81,0x85,0xaf,\r\n\t0xd8,0xf9,0x10,0x22,0x1f,0x1b,0x1f,0x1f,0x0a,0xee,0xcd,0xa9,0x84,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xaf,0xd9,0x04,0x23,0xfa,0xd2,0xa9,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb9,\r\n\t0xbd,0xbd,0xb9,0xa1,0x81,0x83,0x85,0x91,0xaf,0xbd,0xbd,0xbd,0xad,0x8f,0x81,0x81,\r\n\t0x81,0x9f,0xb6,0xba,0xba,0xb7,0xa1,0x81,0x9a,0xb3,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xac,0x8f,0x81,0x81,0xa1,0xb9,0xbd,0xbd,0xb9,0xa1,0x81,0x83,0x85,0x91,0xaf,0xbd,\r\n\t0xbd,0xbd,0xad,0x8f,0x81,0x81,0x89,0xb1,0xd9,0xff,0x23,0x12,0xf3,0xdb,0xcd,0xc6,\r\n\t0xc4,0xb0,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0xff,0x0e,0xf2,0xc9,0x9f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x91,0x93,0x93,0x91,\r\n\t0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x85,\r\n\t0xaf,0xd7,0xf5,0xfc,0x04,0x04,0xff,0xfa,0xef,0xdc,0xc4,0xa7,0x86,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,0x8f,0x84,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8a,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x87,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0x90,0x82,0x81,0x8f,0x95,0x95,0x8d,0x81,0x81,0x81,0x81,0x9f,\r\n\t0xbf,0xd6,0xeb,0xfa,0x04,0x06,0x04,0xf7,0xe6,0xce,0xb2,0x92,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xb9,0xe2,0x0b,0x17,0xef,0xc6,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,\r\n\t0x93,0x93,0x90,0x81,0x81,0x81,0x81,0x81,0x89,0x93,0x93,0x92,0x88,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0x90,0x90,0x8e,0x81,0x81,0x81,0x8b,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x87,0x81,0x81,0x81,0x81,0x90,0x93,0x93,0x90,0x81,0x81,0x81,0x81,0x81,0x89,0x93,\r\n\t0x93,0x92,0x88,0x81,0x81,0x81,0x81,0xa0,0xc5,0xe8,0x09,0x25,0x15,0x04,0xf5,0xef,\r\n\t0xec,0xc8,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x2b,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x81,0x81,0xa8,0xcd,0xe2,0xe2,0xde,0xbf,0x98,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xbd,0x93,0x81,\r\n\t0x9e,0xbc,0xcc,0xd4,0xd7,0xd7,0xd7,0xd2,0xc7,0xb6,0xa1,0x88,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,\r\n\t0x9c,0xb2,0xc4,0xd1,0xd8,0xda,0xd7,0xcf,0xc0,0xac,0x93,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbc,0xe6,0xf7,0xf7,0xe2,0xba,0x91,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xac,0xcc,0xe9,0x04,0x16,0x24,0x20,0x1b,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x09,0x06,0xda,0xb0,\r\n\t0x85,0x81,0x81,0x81,0x81,0x81,0x92,0xad,0xb8,0xb8,0xb6,0xa2,0x84,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,0x09,0xe7,0xbd,0x93,0x81,\r\n\t0x81,0x97,0xa3,0xaa,0xad,0xad,0xad,0xa8,0x9f,0x91,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x09,\r\n\t0x09,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8c,0x9c,0xa8,0xaf,0xb0,0xad,0xa6,0x9a,0x87,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xac,0xc7,0xcd,0xcd,0xc5,0xa8,0x84,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xae,0xc8,0xde,0xef,0xfb,0x04,0x09,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xc8,0xdd,0xdd,0xdd,0xcc,0xa8,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x8d,0x8d,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,0xdd,0xd5,0xb4,0x8d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb6,0xd6,0xdd,\r\n\t0xdd,0xd8,0xb9,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x85,0x85,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x9f,0xa3,0xa3,0x9e,0x8a,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa4,0xb8,0xc7,0xd2,0xda,0xdd,\r\n\t0xdb,0xc0,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xa7,0xb2,0xb2,0xb2,0xaa,0x90,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,0xb2,0xaf,0x99,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xaf,0xb2,\r\n\t0xb2,0xb0,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0x9f,0xa9,0xb0,0xb2,\r\n\t0xb2,0xa1,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x88,0x88,0x82,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,0x88,0x86,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,\r\n\t0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x88,\r\n\t0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa5,0xc8,0xda,0xda,0xda,0xda,0xc3,0xa5,0x87,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xbd,0xd7,0xda,\r\n\t0xda,0xda,0xce,0xac,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xa8,0xc5,\r\n\t0xda,0xda,0xda,0xca,0xae,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,\r\n\t0xa3,0xbf,0xd4,0xdf,0xdf,0xd4,0xc2,0xbd,0xd7,0xd1,0xb6,0x98,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x86,0xa8,0xc5,0xd8,0xd9,0xc8,0xac,0xc2,0xd6,0xda,0xcb,0xb0,0x8e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xc3,0xe3,0xfa,0x04,0xfc,0xe8,\r\n\t0xca,0xa6,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa5,0xc8,0xda,0xda,0xda,0xda,0xc3,0xa5,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd6,0xda,0xda,0xda,0xd0,0xae,0x87,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xa7,0xc4,0xda,0xda,0xda,0xca,0xac,0x90,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xa8,0xc5,0xd8,0xd9,0xc8,0xac,0xc2,0xd6,0xda,\r\n\t0xcb,0xb0,0x8e,0x81,0x81,0x81,0x81,0x81,0xa5,0xc8,0xda,0xda,0xda,0xda,0xc3,0xa5,\r\n\t0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,\r\n\t0xbb,0xd6,0xda,0xda,0xda,0xd1,0xb1,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xa7,\r\n\t0xc3,0xda,0xda,0xda,0xca,0xae,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xa8,\r\n\t0xc5,0xd8,0xd9,0xc8,0xac,0xc2,0xd6,0xda,0xcb,0xb0,0x8e,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x83,0xa1,0xbe,0xd3,0xdf,0xdf,0xd5,0xc2,0xba,0xd6,0xd3,0xb8,0x9a,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa2,0xc6,0xda,0xda,0xda,0xda,0xc5,0xa5,0x87,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xbd,0xd7,\r\n\t0xda,0xda,0xda,0xce,0xac,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xa7,0xc5,\r\n\t0xda,0xda,0xda,0xca,0xae,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xa3,\r\n\t0xbf,0xd4,0xdf,0xdf,0xd5,0xc2,0xbd,0xd7,0xd1,0xb5,0x98,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0xa8,0xc5,0xd8,0xd9,0xc8,0xac,0xc2,0xd6,0xda,0xcb,0xb0,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x94,0x98,0x98,0x94,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa5,0xc8,0xda,0xda,0xda,0xda,0xc3,0xa5,0x87,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd6,\r\n\t0xda,0xda,0xda,0xd0,0xae,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x83,0xad,0xd7,0xff,0x06,0x06,0xff,0xe1,0xc3,0xa5,0x87,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xbd,0xdb,0xf9,0x06,\r\n\t0x06,0x04,0xdf,0xb5,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xaa,0xc7,0xe4,\r\n\t0xff,0x06,0x06,0xea,0xcc,0xb0,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,\r\n\t0xc0,0xdf,0xfa,0x09,0x09,0xfb,0xe6,0xd8,0xf7,0xf1,0xd4,0xb1,0x89,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x97,0xbf,0xe3,0xff,0xff,0xe8,0xc4,0xdf,0xfc,0x04,0xec,0xc8,0xa1,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xaf,0xd7,0xfc,0x16,0x06,0x11,0x05,\r\n\t0xdf,0xb7,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,\r\n\t0xad,0xd7,0xff,0x06,0x06,0xff,0xe1,0xc2,0xa3,0x85,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd9,0xf7,0x06,0x06,0x05,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8c,0xa9,0xc7,0xe3,0xff,0x06,0x05,0xe8,0xcc,0xb0,0x92,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xbf,0xe3,0xff,0xff,0xe8,0xc4,0xdf,0xfc,0x04,\r\n\t0xec,0xc8,0xa1,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0xff,0x06,0x06,0xff,0xe1,0xc3,\r\n\t0xa5,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,\r\n\t0xd9,0xf7,0x06,0x06,0x06,0xe4,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x8c,0xa9,0xc5,\r\n\t0xe3,0xff,0x06,0x06,0xea,0xcd,0xb0,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xbf,\r\n\t0xe3,0xff,0xff,0xe8,0xc4,0xdf,0xfc,0x04,0xec,0xc8,0xa1,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9c,0xbf,0xdd,0xf9,0x09,0x09,0xfc,0xe7,0xd6,0xf5,0xf3,0xd5,0xb3,\r\n\t0x8b,0x81,0x81,0x81,0x81,0xaa,0xd5,0xfc,0x06,0x06,0xff,0xe1,0xc3,0xa5,0x87,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xdb,0xf9,\r\n\t0x06,0x06,0x04,0xdf,0xb5,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xa9,0xc7,0xe3,\r\n\t0xff,0x06,0x06,0xea,0xcc,0xb0,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbf,\r\n\t0xdf,0xf9,0x09,0x09,0xfb,0xe6,0xd8,0xf7,0xf1,0xd4,0xb1,0x89,0x81,0x81,0x81,0x81,\r\n\t0x81,0x97,0xbf,0xe3,0xff,0xff,0xe8,0xc4,0xdf,0xfc,0x04,0xec,0xc8,0xa1,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xbc,0xc2,0xc2,0xbb,0xa1,\r\n\t0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0xfc,0x06,0x06,0xff,0xe1,0xc3,0xa5,0x87,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd9,0xf7,\r\n\t0x06,0x06,0x05,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa1,0xc3,0xdd,0xf5,0x0f,0x1d,0xff,0xe1,0xc3,0xa4,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbd,0xdb,0xf9,0x18,0x14,\r\n\t0xfb,0xe2,0xc8,0xa8,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0xac,0xca,0xe6,0x04,\r\n\t0x1f,0x09,0x1d,0x09,0xec,0xd0,0xb2,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xae,\r\n\t0xd6,0xfb,0x1c,0x0d,0x0f,0x20,0x0a,0xff,0x14,0x09,0xe2,0xb8,0x8d,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1d,0x21,0xf7,0xcd,0xed,0x18,0x26,0xfc,0xd2,0xa8,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xb5,0xdf,0x0b,0x04,0xdc,0xfa,0x13,\r\n\t0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x83,0x85,0x85,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa1,0xc3,0xdd,0xf6,0x10,0x1d,0xfc,0xdf,0xc1,0xa2,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9c,0xbb,0xd9,0xf7,0x16,0x16,0xfc,0xe3,0xca,0xaa,0x84,\r\n\t0x81,0x81,0x81,0x81,0x88,0xaa,0xc8,0xe4,0x04,0x1f,0x0b,0x1f,0x09,0xeb,0xce,0xb2,\r\n\t0x91,0x81,0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1d,0x21,0xf7,0xcd,0xed,0x18,0x26,\r\n\t0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0xa1,0xc3,0xdd,0xf5,0x0f,0x1d,0xff,0xe1,\r\n\t0xc3,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbb,0xd9,\r\n\t0xf7,0x16,0x17,0xfc,0xe4,0xcb,0xac,0x87,0x81,0x81,0x81,0x81,0x88,0xaa,0xc7,0xe4,\r\n\t0xff,0x1e,0x0a,0x1e,0x09,0xec,0xd0,0xb4,0x94,0x81,0x81,0x81,0x81,0x81,0x9d,0xc8,\r\n\t0xf2,0x1d,0x21,0xf7,0xcd,0xed,0x18,0x26,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x82,0xac,0xd5,0xf9,0x1a,0x0d,0x0f,0x21,0x0b,0xff,0x12,0x0b,0xe4,0xba,\r\n\t0x90,0x81,0x81,0x81,0x81,0x9f,0xc1,0xdb,0xf5,0x0f,0x1d,0xff,0xe1,0xc3,0xa4,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbb,0xd9,0xf7,0x18,\r\n\t0x14,0xfb,0xe2,0xc8,0xa8,0x82,0x81,0x81,0x81,0x81,0x81,0x87,0xaa,0xc8,0xe4,0x04,\r\n\t0x1f,0x0a,0x1d,0x09,0xec,0xd0,0xb2,0x90,0x81,0x81,0x81,0x81,0x81,0x82,0xac,0xd5,\r\n\t0xfa,0x1b,0x0d,0x0f,0x20,0x0a,0xff,0x14,0x09,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9d,0xc8,0xf2,0x1d,0x21,0xf7,0xcd,0xed,0x18,0x26,0xfc,0xd2,0xa8,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x90,0xb8,0xde,0xed,0xed,0xdc,0xb5,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x81,0xa1,0xc3,0xdc,0xf5,0x0f,0x1d,0xff,0xe1,0xc3,0xa4,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbb,0xd9,0xf7,0x16,\r\n\t0x15,0xfb,0xe3,0xc9,0xaa,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x87,0xa1,0xbb,0xd4,0xee,0x07,0x11,0xff,0xdf,0xb6,0x8c,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xac,0xd5,0xf9,0x11,0x0c,0xf1,\r\n\t0xd9,0xc0,0xa7,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xc1,0xe8,0x05,0x11,\r\n\t0xff,0xe6,0xfb,0x11,0x0b,0xee,0xc8,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xad,\r\n\t0xd4,0xf1,0x05,0xe6,0xea,0xff,0x11,0x15,0x07,0xec,0xcd,0xaa,0x84,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9a,0xc3,0xe9,0x0a,0x0b,0xee,0xc8,0xe5,0x07,0x0e,0xf1,0xcd,0xa4,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xb3,0xdc,0x04,0x0f,0xf7,0x09,0x0b,\r\n\t0xe3,0xba,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,\r\n\t0xa2,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa6,0x96,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x87,0x99,0xa5,0xad,0xb0,0xb0,0xad,0xa5,0x9a,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x89,0xa2,0xbb,0xd5,0xee,0x09,0x13,0xfc,0xde,0xb6,0xa8,0xa6,0x96,0x81,0x81,0x81,\r\n\t0x81,0x81,0x89,0xa0,0xa8,0xae,0xd6,0xf7,0x13,0x0d,0xf3,0xdb,0xc1,0xa8,0x96,0x81,\r\n\t0x81,0x81,0x81,0x81,0x97,0xc0,0xe6,0x05,0x13,0xff,0xe7,0xfc,0x13,0x0b,0xee,0xca,\r\n\t0xa1,0x81,0x81,0x81,0x81,0x81,0x9a,0xc3,0xe9,0x0a,0x0b,0xee,0xc8,0xe5,0x07,0x0e,\r\n\t0xf1,0xcd,0xa4,0x81,0x81,0x81,0x81,0x81,0x91,0xa4,0xbb,0xd4,0xee,0x07,0x13,0xff,\r\n\t0xe0,0xb8,0xa8,0xa7,0x99,0x81,0x81,0x81,0x81,0x81,0x91,0xa4,0xa8,0xae,0xd6,0xf7,\r\n\t0x13,0x0f,0xf4,0xdb,0xc2,0xa9,0x99,0x81,0x81,0x81,0x81,0x81,0x97,0xc0,0xe6,0x04,\r\n\t0x13,0xff,0xe8,0xfc,0x13,0x0d,0xf0,0xcd,0xa4,0x81,0x81,0x81,0x81,0x81,0x9a,0xc3,\r\n\t0xe9,0x0a,0x0b,0xee,0xc8,0xe5,0x07,0x0e,0xf1,0xcd,0xa4,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9b,0xa8,0xa8,0xa8,0xa8,0xa8,0xa7,0xa2,0x99,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x87,0xaa,0xd2,0xf1,0x06,0xe6,0xe9,0xff,0x11,0x16,0x09,0xee,0xd0,0xac,\r\n\t0x8f,0x81,0x81,0x81,0x81,0x85,0xa0,0xba,0xd3,0xed,0x07,0x11,0xff,0xdf,0xb6,0x8f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xac,0xd5,0xf7,0x11,0x0d,\r\n\t0xf3,0xd9,0xc0,0xa7,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbe,0xe6,0x05,0x11,\r\n\t0xff,0xe6,0xfb,0x11,0x0b,0xee,0xc8,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0xaa,0xd2,\r\n\t0xf1,0x06,0xe6,0xe9,0xff,0x11,0x15,0x07,0xec,0xcd,0xaa,0x84,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9a,0xc3,0xe9,0x0a,0x0b,0xee,0xc8,0xe5,0x07,0x0e,0xf1,0xcd,0xa4,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xa2,0xad,0xb2,0xc4,0xed,0x15,0x07,0xdf,0xb6,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x8c,0xa3,0xab,0xba,0xd4,0xed,0x07,0x11,0xff,0xdf,0xb6,\r\n\t0xab,0xab,0xa7,0x93,0x81,0x81,0x81,0x8c,0xa3,0xab,0xab,0xac,0xd5,0xf7,0x11,0x0d,\r\n\t0xf3,0xda,0xc1,0xab,0xa7,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x99,0xb2,0xcc,0xe3,0xe5,0xe5,0xd7,0xb5,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xac,0xcf,0xe5,0xe5,0xe5,0xd1,\r\n\t0xb7,0x9e,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbc,0xde,0xe5,0xe5,\r\n\t0xde,0xd5,0xda,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x99,\r\n\t0xb7,0xd4,0xe4,0xcb,0xd5,0xdb,0xe7,0xea,0xe1,0xcd,0xb0,0x92,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8b,0xaf,0xce,0xe2,0xe3,0xd5,0xd5,0xd5,0xe1,0xe4,0xd4,0xb7,0x94,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa5,0xcb,0xec,0x05,0x11,0x09,0xf1,\r\n\t0xd1,0xac,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0xa8,\r\n\t0xc8,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xcf,0xb5,0x91,0x81,0x81,0x81,0x81,0x81,\r\n\t0x96,0xad,0xc0,0xce,0xd7,0xda,0xda,0xd6,0xcf,0xc3,0xb2,0x96,0x81,0x81,0x81,0x81,\r\n\t0xa3,0xc4,0xd2,0xd2,0xd2,0xe5,0xe7,0xe7,0xd9,0xd2,0xd2,0xcf,0xb5,0x91,0x81,0x81,\r\n\t0x81,0x81,0xa3,0xc4,0xd2,0xd2,0xd3,0xe7,0xe7,0xe7,0xd2,0xd2,0xd2,0xcf,0xb5,0x91,\r\n\t0x81,0x81,0x81,0x81,0xa3,0xc4,0xe0,0xe7,0xe7,0xdf,0xd2,0xdb,0xe7,0xe7,0xe6,0xcf,\r\n\t0xb5,0x91,0x81,0x81,0x81,0x81,0xa3,0xc4,0xd2,0xe2,0xe3,0xd2,0xd2,0xd2,0xe1,0xe4,\r\n\t0xd4,0xcf,0xb5,0x91,0x81,0x81,0x81,0x89,0xaf,0xcc,0xd2,0xd2,0xd2,0xe5,0xe7,0xe7,\r\n\t0xdb,0xd2,0xd2,0xd1,0xb9,0x95,0x81,0x81,0x81,0x89,0xaf,0xcc,0xd2,0xd2,0xd3,0xe7,\r\n\t0xe7,0xe7,0xd3,0xd2,0xd2,0xd1,0xb9,0x95,0x81,0x81,0x81,0x89,0xaf,0xcc,0xe0,0xe7,\r\n\t0xe7,0xe0,0xd2,0xdb,0xe7,0xe7,0xe7,0xd1,0xb9,0x95,0x81,0x81,0x81,0x89,0xaf,0xcc,\r\n\t0xd2,0xe2,0xe3,0xd2,0xd2,0xd2,0xe1,0xe4,0xd4,0xd1,0xb9,0x95,0x81,0x81,0x81,0x9a,\r\n\t0xbd,0xd2,0xd2,0xd2,0xd2,0xd2,0xd1,0xcc,0xc2,0xb4,0xa1,0x8a,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa1,0xc3,0xd2,0xd3,0xe4,0xcf,0xc5,0xda,0xe7,0xea,0xe2,0xd2,0xd2,0xcb,\r\n\t0xac,0x87,0x81,0x81,0x81,0x81,0x90,0xa9,0xbf,0xce,0xe3,0xe5,0xe5,0xd7,0xc8,0xb5,\r\n\t0x9e,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xa9,0xbf,0xcf,0xe5,0xe5,0xe5,\r\n\t0xd5,0xc8,0xb5,0x9e,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,\r\n\t0xde,0xdd,0xdc,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xb6,\r\n\t0xd3,0xe4,0xce,0xd9,0xdd,0xe7,0xea,0xe1,0xcd,0xb0,0x92,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8b,0xaf,0xce,0xe2,0xe3,0xd9,0xdd,0xdc,0xe1,0xe4,0xd4,0xb7,0x94,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0xa2,0xb9,0xca,0xd6,0xdd,0xdd,0xf9,0x21,0xfa,0xd2,0xaa,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa7,0xc8,0xd5,0xd5,0xd4,0xcb,0xe3,0xe5,0xe5,0xd7,0xd2,\r\n\t0xd5,0xd5,0xce,0xb0,0x8a,0x81,0x81,0xa7,0xc8,0xd5,0xd5,0xd4,0xcf,0xe5,0xe5,0xe5,\r\n\t0xd2,0xd2,0xd5,0xd5,0xce,0xb0,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x94,0xbc,0xe4,0xff,0xff,0xff,0xee,0xc6,0x9e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbc,0xe4,0xff,0xff,0xff,0xee,\r\n\t0xc6,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xa3,0xb8,0xbc,0xe4,\r\n\t0xff,0xff,0xff,0xee,0xc6,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x98,0xb2,0xbc,0xe4,0xff,0xff,0xff,0xef,0xc6,0xa8,0x92,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x92,0xab,0xba,0xe2,0xff,0xff,0xff,0xef,0xc7,0xaf,0x99,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0xff,0xff,0xff,0xee,\r\n\t0xc6,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xba,\r\n\t0xe1,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x9b,\r\n\t0xb8,0xd1,0xe6,0xf6,0xff,0x06,0x06,0xff,0xf7,0xea,0xd1,0xab,0x82,0x81,0x81,0x85,\r\n\t0xb0,0xda,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xef,0xc5,0x9b,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xef,0xc5,0x9b,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xef,\r\n\t0xc5,0x9b,0x81,0x81,0x81,0x85,0xb0,0xda,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xef,0xc5,0x9b,0x81,0x81,0x81,0x93,0xbd,0xe7,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xf4,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0xfc,0xfc,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xfc,0xfc,0xf4,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0xfc,0xfc,\r\n\t0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xf4,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,\r\n\t0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xf4,0xca,0xa0,0x81,0x81,0x81,0xa5,\r\n\t0xcf,0xf9,0xfc,0xfc,0xfc,0xfc,0xfa,0xf5,0xea,0xda,0xc5,0xac,0x8e,0x81,0x81,0x81,\r\n\t0x81,0x83,0xad,0xd7,0xfc,0xfc,0xfc,0xf1,0xc9,0xb3,0xbe,0xc2,0xec,0xfc,0xfc,0xe4,\r\n\t0xba,0x90,0x81,0x81,0x81,0x90,0xb0,0xcc,0xe3,0xf6,0x04,0x09,0x06,0xfc,0xee,0xd9,\r\n\t0xbf,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb0,0xcc,0xe3,0xf6,0x04,0x09,0x06,\r\n\t0xfc,0xee,0xd9,0xbf,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb0,0xcc,0xe3,0xf6,\r\n\t0x04,0x09,0x06,0xfc,0xee,0xd9,0xbf,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xb0,\r\n\t0xcc,0xe3,0xf6,0x04,0x09,0x06,0xfc,0xee,0xd9,0xbf,0xa0,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x90,0xb0,0xcc,0xe3,0xf6,0x04,0x09,0x06,0xfc,0xee,0xd9,0xbf,0xa0,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x87,0xa7,0xc3,0xdd,0xf1,0xff,0x07,0x09,0x07,0x17,0xef,0xc7,0xa9,\r\n\t0x8a,0x81,0x81,0x81,0x88,0xb2,0xdd,0xff,0xff,0xfa,0xd0,0xba,0xba,0xba,0xc5,0xef,\r\n\t0xff,0xff,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0xff,0xff,0xfa,0xd0,0xba,0xba,0xba,\r\n\t0xc5,0xef,0xff,0xff,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa1,0xc9,0xf1,0x19,0x2b,0x24,0xfb,0xd3,0xab,0x83,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xc9,0xf1,0x19,0x2b,0x24,0xfb,\r\n\t0xd3,0xab,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xc9,0xf1,\r\n\t0x19,0x2b,0x24,0xfb,0xd3,0xab,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa1,0xc9,0xf1,0x19,0x2b,0x24,0xfb,0xd3,0xab,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9f,0xc8,0xef,0x18,0x2b,0x24,0xfc,0xd4,0xac,0x84,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x29,0x23,0xfa,\r\n\t0xd2,0xaa,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xca,\r\n\t0xf1,0x19,0x21,0x29,0x1e,0x1e,0x1e,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x97,0xb8,\r\n\t0xd7,0xf3,0x0b,0x1e,0x24,0x1e,0x1e,0x23,0x20,0x06,0xda,0xb0,0x85,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0x23,0x23,0x23,0x23,0x23,0x23,0x1b,0xef,0xc5,0x9b,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0x23,0x23,0x23,0x23,0x23,0x23,0x1b,0xef,0xc5,0x9b,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0x23,0x23,0x23,0x23,0x23,0x23,0x1b,0xef,\r\n\t0xc5,0x9b,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0x23,0x23,0x23,0x23,0x23,0x23,\r\n\t0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x93,0xbd,0xe7,0x13,0x23,0x23,0x23,0x29,0x24,\r\n\t0x23,0x23,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0x13,0x23,0x23,0x23,\r\n\t0x29,0x24,0x23,0x23,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0x13,0x23,\r\n\t0x23,0x23,0x29,0x24,0x23,0x23,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,\r\n\t0x13,0x23,0x23,0x23,0x29,0x24,0x23,0x23,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x24,0x23,0x23,0x26,0x1e,0x12,0xff,0xe7,0xca,0xaa,0x88,0x81,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x29,0x28,0x04,0xdc,0xb5,0x98,0xc2,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x81,0x87,0xab,0xcc,0xec,0x07,0x1e,0x21,0x1b,0x1e,0x26,0x14,0xf9,\r\n\t0xdb,0xba,0x97,0x81,0x81,0x81,0x81,0x87,0xab,0xcc,0xec,0x07,0x1e,0x21,0x1b,0x1e,\r\n\t0x26,0x14,0xf9,0xdb,0xba,0x97,0x81,0x81,0x81,0x81,0x87,0xab,0xcc,0xec,0x07,0x1e,\r\n\t0x21,0x1b,0x1e,0x26,0x14,0xf9,0xdb,0xba,0x97,0x81,0x81,0x81,0x81,0x87,0xab,0xcc,\r\n\t0xec,0x07,0x1e,0x21,0x1b,0x1e,0x26,0x14,0xf9,0xdb,0xba,0x97,0x81,0x81,0x81,0x81,\r\n\t0x87,0xab,0xcc,0xec,0x07,0x1e,0x21,0x1b,0x1e,0x26,0x14,0xf9,0xdb,0xba,0x97,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa0,0xc2,0xe3,0xff,0x17,0x25,0x1b,0x1c,0x2b,0x1c,0x04,0xe4,0xc5,\r\n\t0xa2,0x81,0x81,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x90,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x90,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x86,0xaf,0xd6,0xff,0x27,0xff,0x25,0x09,0xe1,0xb9,0x90,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xaf,0xd6,0xff,0x27,0xff,0x25,0x09,\r\n\t0xe1,0xb9,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xaf,0xd6,0xff,\r\n\t0x27,0xff,0x25,0x09,0xe1,0xb9,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0xaf,0xd6,0xff,0x27,0xff,0x25,0x09,0xe1,0xb9,0x90,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x85,0xad,0xd5,0xfc,0x25,0x04,0x24,0x0a,0xe1,0xb9,0x90,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0xff,0x25,0x09,\r\n\t0xe0,0xb8,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xb3,0xda,\r\n\t0xff,0x1e,0x06,0x23,0xf7,0xf2,0xf2,0xf2,0xea,0xc3,0x9a,0x81,0x81,0x88,0xae,0xd2,\r\n\t0xf3,0x14,0x25,0x0c,0xfb,0xf2,0xf3,0xfa,0x06,0x06,0xda,0xb0,0x85,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xed,0xc4,0x9a,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xed,0xc4,0x9a,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xed,\r\n\t0xc4,0x9a,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xf7,0xf7,0xf7,0xf7,0xf7,\r\n\t0xf7,0xed,0xc4,0x9a,0x81,0x81,0x81,0x92,0xbc,0xe6,0xf7,0xf7,0xf7,0xfc,0x29,0x09,\r\n\t0xf7,0xf7,0xf7,0xf1,0xc9,0x9f,0x81,0x81,0x81,0x92,0xbc,0xe6,0xf7,0xf7,0xf7,0xfc,\r\n\t0x29,0x09,0xf7,0xf7,0xf7,0xf1,0xc9,0x9f,0x81,0x81,0x81,0x92,0xbc,0xe6,0xf7,0xf7,\r\n\t0xf7,0xfc,0x29,0x09,0xf7,0xf7,0xf7,0xf1,0xc9,0x9f,0x81,0x81,0x81,0x92,0xbc,0xe6,\r\n\t0xf7,0xf7,0xf7,0xfc,0x29,0x09,0xf7,0xf7,0xf7,0xf1,0xc9,0x9f,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x09,0xf7,0xf7,0xfc,0x06,0x18,0x22,0x07,0xe5,0xc2,0x9c,0x81,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x2e,0x23,0x14,0xee,0xc8,0xa1,0xc2,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x81,0x9b,0xc1,0xe6,0x09,0x27,0x0f,0xf9,0xef,0xf5,0x07,0x21,0x18,\r\n\t0xf5,0xd1,0xab,0x84,0x81,0x81,0x81,0x9b,0xc1,0xe6,0x09,0x27,0x0f,0xf9,0xef,0xf5,\r\n\t0x07,0x21,0x18,0xf5,0xd1,0xab,0x84,0x81,0x81,0x81,0x9b,0xc1,0xe6,0x09,0x27,0x0f,\r\n\t0xf9,0xef,0xf5,0x07,0x21,0x18,0xf5,0xd1,0xab,0x84,0x81,0x81,0x81,0x9b,0xc1,0xe6,\r\n\t0x09,0x27,0x0f,0xf9,0xef,0xf5,0x07,0x21,0x18,0xf5,0xd1,0xab,0x84,0x81,0x81,0x81,\r\n\t0x9b,0xc1,0xe6,0x09,0x27,0x0f,0xf9,0xef,0xf5,0x07,0x21,0x18,0xf5,0xd1,0xab,0x84,\r\n\t0x81,0x81,0x81,0x89,0xa0,0xa8,0x9c,0x83,0x81,0x81,0x83,0x9a,0xa3,0x9a,0x83,0x81,\r\n\t0x81,0x81,0x8f,0xb5,0xda,0xfc,0x1d,0x18,0xff,0xf1,0xf4,0x1c,0x1f,0x21,0xff,0xdc,\r\n\t0xb6,0x91,0x81,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x93,0xbb,0xe4,0x0c,0x1d,0xf5,0x19,0x16,0xee,0xc5,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe4,0x0c,0x1d,0xf5,0x19,0x16,\r\n\t0xee,0xc5,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe4,0x0c,\r\n\t0x1d,0xf5,0x19,0x16,0xee,0xc5,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0xbc,0xe4,0x0c,0x1d,0xf5,0x19,0x16,0xee,0xc6,0x9d,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x92,0xba,0xe2,0x0b,0x1e,0xf5,0x18,0x16,0xee,0xc6,0x9e,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x1d,0xf4,0x19,0x15,\r\n\t0xed,0xc5,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xc3,0xea,\r\n\t0x11,0x0f,0x06,0x23,0xf7,0xcd,0xc8,0xc8,0xc5,0xae,0x8c,0x81,0x81,0x9b,0xc1,0xe7,\r\n\t0x0c,0x27,0x07,0xe8,0xd3,0xc9,0xca,0xd1,0xde,0xef,0xd5,0xad,0x84,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xd2,0xcd,0xcd,0xcd,0xcd,0xcd,0xca,0xb2,0x8e,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xcd,0xcd,0xcd,0xcd,0xcd,0xca,0xb2,0x8e,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xcd,0xcd,0xcd,0xcd,0xcd,0xca,\r\n\t0xb2,0x8e,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xcd,0xcd,0xcd,0xcd,\r\n\t0xcd,0xca,0xb2,0x8e,0x81,0x81,0x81,0x87,0xac,0xc7,0xcd,0xcd,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xcd,0xcd,0xcc,0xb6,0x93,0x81,0x81,0x81,0x87,0xac,0xc7,0xcd,0xcd,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xcd,0xcd,0xcc,0xb6,0x93,0x81,0x81,0x81,0x87,0xac,0xc7,0xcd,0xcd,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xcd,0xcd,0xcc,0xb6,0x93,0x81,0x81,0x81,0x87,0xac,0xc7,\r\n\t0xcd,0xcd,0xd2,0xfc,0x29,0x09,0xdd,0xcd,0xcd,0xcc,0xb6,0x93,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x09,0xdd,0xcd,0xd2,0xdf,0xf5,0x16,0x20,0xfb,0xd5,0xaf,0x86,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xff,0x26,0xff,0xda,0xb4,0xc2,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x85,0xad,0xd3,0xfa,0x20,0x12,0xf0,0xd3,0xc5,0xcd,0xe5,0x07,0x2c,\r\n\t0x0a,0xe2,0xbb,0x93,0x81,0x81,0x85,0xad,0xd3,0xfa,0x20,0x12,0xf0,0xd3,0xc5,0xcd,\r\n\t0xe5,0x07,0x2c,0x0a,0xe2,0xbb,0x93,0x81,0x81,0x85,0xad,0xd3,0xfa,0x20,0x12,0xf0,\r\n\t0xd3,0xc5,0xcd,0xe5,0x07,0x2c,0x0a,0xe2,0xbb,0x93,0x81,0x81,0x85,0xad,0xd3,0xfa,\r\n\t0x20,0x12,0xf0,0xd3,0xc5,0xcd,0xe5,0x07,0x2c,0x0a,0xe2,0xbb,0x93,0x81,0x81,0x85,\r\n\t0xad,0xd3,0xfa,0x20,0x12,0xf0,0xd3,0xc5,0xcd,0xe5,0x07,0x2c,0x0a,0xe2,0xbb,0x93,\r\n\t0x81,0x81,0x89,0xa7,0xc4,0xd2,0xbf,0x9f,0x81,0x83,0xa1,0xbf,0xcd,0xbf,0xa1,0x83,\r\n\t0x81,0x81,0xa0,0xc7,0xee,0x14,0x1e,0xfa,0xdb,0xd7,0xff,0x1c,0xfc,0x20,0x15,0xef,\r\n\t0xc8,0x9f,0x81,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x11,0xe7,0x0c,0x23,0xfa,0xd2,0xaa,0x82,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x11,0xe7,0x0c,0x23,\r\n\t0xfa,0xd2,0xaa,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,\r\n\t0x11,0xe7,0x0c,0x23,0xfa,0xd2,0xaa,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa0,0xc9,0xf1,0x19,0x11,0xe7,0x0c,0x23,0xfa,0xd2,0xaa,0x82,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9f,0xc8,0xef,0x18,0x11,0xe9,0x0b,0x24,0xfb,0xd3,0xab,0x83,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x0f,0xe7,0x0c,0x23,\r\n\t0xfa,0xd2,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xac,0xd3,0xfa,\r\n\t0x21,0xff,0x06,0x23,0xf7,0xcd,0xa3,0x9d,0x9c,0x8d,0x81,0x81,0x81,0xa9,0xd2,0xf9,\r\n\t0x20,0x12,0xed,0xca,0xae,0x9f,0xa0,0xa8,0xb7,0xc5,0xb8,0x9b,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0xa3,0xa3,0xa3,0xa3,0xa1,0x91,0x81,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0xa3,0xa3,0xa3,0xa3,0xa1,0x91,0x81,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0xa3,0xa3,0xa3,0xa3,0xa1,\r\n\t0x91,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0xa3,0xa3,0xa3,\r\n\t0xa3,0xa1,0x91,0x81,0x81,0x81,0x81,0x81,0x8d,0x9f,0xa3,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0xa3,0xa2,0x94,0x81,0x81,0x81,0x81,0x81,0x8d,0x9f,0xa3,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0xa3,0xa2,0x94,0x81,0x81,0x81,0x81,0x81,0x8d,0x9f,0xa3,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0xa3,0xa2,0x94,0x81,0x81,0x81,0x81,0x81,0x8d,0x9f,\r\n\t0xa3,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0xa3,0xa2,0x94,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x09,0xdd,0xb2,0xa9,0xbb,0xdb,0xff,0x27,0x0c,0xe4,0xbb,0x92,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0x18,0x12,0xec,0xc6,0xc2,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x91,0xba,0xe2,0x0b,0x27,0xff,0xd9,0xb5,0x9c,0xaa,0xcd,0xf3,0x1b,\r\n\t0x19,0xf1,0xc8,0x9e,0x81,0x81,0x91,0xba,0xe2,0x0b,0x27,0xff,0xd9,0xb5,0x9c,0xaa,\r\n\t0xcd,0xf3,0x1b,0x19,0xf1,0xc8,0x9e,0x81,0x81,0x91,0xba,0xe2,0x0b,0x27,0xff,0xd9,\r\n\t0xb5,0x9c,0xaa,0xcd,0xf3,0x1b,0x19,0xf1,0xc8,0x9e,0x81,0x81,0x91,0xba,0xe2,0x0b,\r\n\t0x27,0xff,0xd9,0xb5,0x9c,0xaa,0xcd,0xf3,0x1b,0x19,0xf1,0xc8,0x9e,0x81,0x81,0x91,\r\n\t0xba,0xe2,0x0b,0x27,0xff,0xd9,0xb5,0x9c,0xaa,0xcd,0xf3,0x1b,0x19,0xf1,0xc8,0x9e,\r\n\t0x81,0x84,0xa7,0xc5,0xe3,0xfb,0xdb,0xbd,0x9f,0xa1,0xbf,0xdd,0xf7,0xdd,0xbf,0xa0,\r\n\t0x81,0x84,0xad,0xd6,0xfc,0x26,0x0c,0xe5,0xc0,0xe4,0x0c,0x0f,0xe7,0x0f,0x25,0xfc,\r\n\t0xd4,0xab,0x82,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x04,0xdb,0xff,0x28,0x09,0xe0,0xb8,0x90,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x04,0xdb,0xff,0x28,\r\n\t0x09,0xe0,0xb8,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,\r\n\t0x04,0xdb,0xff,0x28,0x09,0xe0,0xb8,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,\r\n\t0xae,0xd6,0xfc,0x26,0x04,0xdb,0xff,0x28,0x09,0xe0,0xb8,0x90,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x85,0xad,0xd5,0xfc,0x25,0x05,0xdc,0xff,0x27,0x09,0xe1,0xb8,0x90,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x04,0xdb,0xff,0x28,\r\n\t0x07,0xdf,0xb7,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xbb,0xe2,0x0a,\r\n\t0x17,0xef,0x06,0x23,0xf7,0xcd,0xba,0xba,0xb6,0x9f,0x81,0x81,0x8b,0xb4,0xdd,0x06,\r\n\t0x2b,0x04,0xdb,0xb4,0x8f,0x81,0x81,0x81,0x92,0x9b,0x93,0x81,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xd2,0xbd,0xbd,0xbd,0xbd,0xbd,0xb6,0x9d,0x81,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xbd,0xbd,0xbd,0xbd,0xbd,0xb6,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xbd,0xbd,0xbd,0xbd,0xbd,0xb6,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xbd,0xbd,0xbd,0xbd,\r\n\t0xbd,0xb6,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x82,0xa3,0xb9,\r\n\t0xd0,0xfa,0x26,0x09,0xdd,0xbd,0xbd,0xad,0xc9,0xf1,0x1b,0x18,0xef,0xc5,0x9b,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0x07,0x25,0xfc,0xd8,0xc2,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x9a,0xc4,0xed,0x16,0x1b,0xf2,0xc9,0xa1,0x81,0x95,0xbd,0xe7,0x11,\r\n\t0x23,0xfa,0xd0,0xa6,0x81,0x81,0x9a,0xc4,0xed,0x16,0x1b,0xf2,0xc9,0xa1,0x81,0x95,\r\n\t0xbd,0xe7,0x11,0x23,0xfa,0xd0,0xa6,0x81,0x81,0x9a,0xc4,0xed,0x16,0x1b,0xf2,0xc9,\r\n\t0xa1,0x81,0x95,0xbd,0xe7,0x11,0x23,0xfa,0xd0,0xa6,0x81,0x81,0x9a,0xc4,0xed,0x16,\r\n\t0x1b,0xf2,0xc9,0xa1,0x81,0x95,0xbd,0xe7,0x11,0x23,0xfa,0xd0,0xa6,0x81,0x81,0x9a,\r\n\t0xc4,0xed,0x16,0x1b,0xf2,0xc9,0xa1,0x81,0x95,0xbd,0xe7,0x11,0x23,0xfa,0xd0,0xa6,\r\n\t0x81,0x91,0xbb,0xe2,0xff,0x18,0xf9,0xdb,0xbd,0xbf,0xdd,0xfb,0x1a,0xfb,0xdb,0xb3,\r\n\t0x8a,0x8d,0xb7,0xe0,0x0a,0x29,0xff,0xd6,0xc8,0xef,0x19,0x04,0xdb,0x04,0x2c,0x06,\r\n\t0xdd,0xb3,0x8a,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x1f,0xf6,0xce,0xf2,0x1a,0x15,0xed,0xc5,0x9c,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x1f,0xf6,0xce,0xf2,0x1a,\r\n\t0x15,0xed,0xc5,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x1f,\r\n\t0xf6,0xce,0xf2,0x1a,0x15,0xed,0xc5,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,\r\n\t0xbb,0xe3,0x0b,0x1f,0xf6,0xce,0xf2,0x1a,0x15,0xed,0xc5,0x9d,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x92,0xba,0xe2,0x0b,0x20,0xf7,0xcf,0xf1,0x19,0x15,0xed,0xc5,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x1f,0xf6,0xce,0xf2,0x1b,\r\n\t0x14,0xec,0xc4,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xcc,0xf3,0x19,\r\n\t0x09,0xe1,0x06,0x23,0xf7,0xe5,0xe5,0xe5,0xdb,0xb8,0x8f,0x81,0x92,0xbb,0xe5,0x0f,\r\n\t0x23,0xf7,0xcf,0xa6,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xd9,0xb4,0x8b,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xd9,0xb4,0x8b,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xd9,\r\n\t0xb4,0x8b,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe7,0xe7,0xe7,0xe7,0xe7,\r\n\t0xe7,0xd9,0xb4,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x92,0xbb,0xdf,\r\n\t0xe7,0xfa,0x26,0x09,0xe7,0xe7,0xe7,0xc9,0xc0,0xea,0x13,0x1f,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xf6,0x1d,0x11,0xea,0xc4,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0xa0,0xca,0xf4,0x1e,0x14,0xea,0xc0,0x97,0x81,0x8c,0xb5,0xdf,0x09,\r\n\t0x29,0xff,0xd5,0xab,0x81,0x81,0xa0,0xca,0xf4,0x1e,0x14,0xea,0xc0,0x97,0x81,0x8c,\r\n\t0xb5,0xdf,0x09,0x29,0xff,0xd5,0xab,0x81,0x81,0xa0,0xca,0xf4,0x1e,0x14,0xea,0xc0,\r\n\t0x97,0x81,0x8c,0xb5,0xdf,0x09,0x29,0xff,0xd5,0xab,0x81,0x81,0xa0,0xca,0xf4,0x1e,\r\n\t0x14,0xea,0xc0,0x97,0x81,0x8c,0xb5,0xdf,0x09,0x29,0xff,0xd5,0xab,0x81,0x81,0xa0,\r\n\t0xca,0xf4,0x1e,0x14,0xea,0xc0,0x97,0x81,0x8c,0xb5,0xdf,0x09,0x29,0xff,0xd5,0xab,\r\n\t0x81,0x90,0xb9,0xdf,0xfc,0x1c,0x18,0xf9,0xdb,0xdd,0xfb,0x1a,0x14,0xf5,0xd7,0xb1,\r\n\t0x88,0x93,0xbd,0xe7,0x11,0x21,0xf7,0xcd,0xd3,0xfc,0x20,0xf7,0xd2,0xfc,0x26,0x0d,\r\n\t0xe2,0xb8,0x8d,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x12,0xea,0xc2,0xe6,0x0e,0x22,0xfa,0xd2,0xa9,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x12,0xea,0xc2,0xe6,0x0e,\r\n\t0x22,0xfa,0xd2,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x12,\r\n\t0xea,0xc2,0xe6,0x0e,0x22,0xfa,0xd2,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,\r\n\t0xc8,0xf1,0x19,0x12,0xea,0xc2,0xe6,0x0e,0x22,0xfa,0xd2,0xa9,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9f,0xc8,0xef,0x18,0x13,0xeb,0xc3,0xe5,0x0d,0x23,0xfa,0xd2,0xaa,\r\n\t0x82,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x12,0xea,0xc2,0xe6,0x0f,\r\n\t0x22,0xfa,0xd1,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xb4,0xdb,0x04,0x20,\r\n\t0xf9,0xda,0x06,0x27,0x11,0x11,0x11,0x11,0xe7,0xbd,0x93,0x81,0x95,0xc0,0xea,0x14,\r\n\t0x1e,0xf2,0xc9,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x2d,0x13,0x13,0x13,0x13,0x13,0x13,0x0e,0xe2,0xb8,0x8d,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x2d,0x13,0x13,0x13,0x13,0x13,0x13,0x0e,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2d,0x13,0x13,0x13,0x13,0x13,0x13,0x0e,0xe2,\r\n\t0xb8,0x8d,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2d,0x13,0x13,0x13,0x13,0x13,0x13,\r\n\t0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x13,0x13,0x2b,0x15,0x13,0x13,0xfa,0xd0,0xbb,0xe5,0x11,0x23,0xf7,0xcd,0xa3,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xe5,0x0b,0x22,0xfc,0xd5,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xbb,0x92,0x81,0x88,0xb2,0xdb,0x06,\r\n\t0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xbb,0x92,0x81,0x88,\r\n\t0xb2,0xdb,0x06,0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xbb,\r\n\t0x92,0x81,0x88,0xb2,0xdb,0x06,0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,0xcd,0xf7,0x23,\r\n\t0x11,0xe5,0xbb,0x92,0x81,0x88,0xb2,0xdb,0x06,0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,\r\n\t0xcd,0xf7,0x23,0x11,0xe5,0xbb,0x92,0x81,0x88,0xb2,0xdb,0x06,0x2e,0x04,0xd7,0xad,\r\n\t0x83,0x81,0xa3,0xc1,0xdf,0xfc,0x1c,0x18,0xf9,0xfb,0x1a,0x14,0xf5,0xd7,0xb9,0x9b,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc8,0xe0,0x09,0x14,0xec,0xce,0xf7,0x23,0x11,\r\n\t0xe5,0xba,0x90,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x06,0xdd,0xb4,0xd9,0xff,0x2a,0x07,0xdf,0xb7,\r\n\t0x8f,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x06,0xdd,0xb4,0xd9,0xff,\r\n\t0x2a,0x07,0xdf,0xb7,0x8f,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x06,\r\n\t0xdd,0xb4,0xd9,0xff,0x2a,0x07,0xdf,0xb7,0x8f,0x81,0x81,0x81,0x81,0x81,0x85,0xae,\r\n\t0xd6,0xfc,0x26,0x06,0xdd,0xb4,0xd9,0xff,0x2a,0x07,0xdf,0xb7,0x8f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0xad,0xd5,0xfc,0x25,0x06,0xde,0xb6,0xd8,0xff,0x29,0x09,0xe0,0xb8,\r\n\t0x90,0x81,0x81,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x06,0xdd,0xb5,0xd9,0x04,\r\n\t0x2a,0x06,0xde,0xb6,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xc4,0xec,0x13,0x11,\r\n\t0xe9,0xda,0x06,0x25,0x0b,0x0b,0x0b,0x0b,0xe7,0xbd,0x93,0x81,0x95,0xc0,0xea,0x16,\r\n\t0x1e,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x2b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0xe2,0xb8,0x8d,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x2b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0xe2,0xb8,0x8d,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0xe2,\r\n\t0xb8,0x8d,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,\r\n\t0x0e,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,\r\n\t0x0e,0x0e,0x29,0x11,0x0e,0x0e,0xfa,0xd0,0xba,0xe5,0x11,0x23,0xf7,0xcd,0xa3,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd2,0xf9,0x1f,0x0f,0xe8,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xba,0x90,0x81,0x85,0xb0,0xda,0x06,\r\n\t0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xba,0x90,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,0xcd,0xf7,0x23,0x11,0xe5,0xba,\r\n\t0x90,0x81,0x85,0xb0,0xda,0x06,0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,0xcd,0xf7,0x23,\r\n\t0x11,0xe5,0xba,0x90,0x81,0x85,0xb0,0xda,0x06,0x2e,0x04,0xd7,0xad,0x83,0x81,0xa3,\r\n\t0xcd,0xf7,0x23,0x11,0xe5,0xba,0x90,0x81,0x85,0xb0,0xda,0x06,0x2e,0x04,0xd7,0xad,\r\n\t0x83,0x81,0x85,0xa3,0xc1,0xdf,0xfc,0x1c,0x18,0x1a,0x14,0xf5,0xd7,0xb9,0x9b,0x81,\r\n\t0x81,0x95,0xc0,0xea,0x16,0x1e,0xf2,0xc8,0xec,0x14,0x09,0xdf,0xcd,0xf7,0x23,0x11,\r\n\t0xe5,0xba,0x90,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x93,0xbb,0xe3,0x0b,0x21,0xf9,0xd0,0xd0,0xd0,0xf5,0x1d,0x14,0xec,0xc4,\r\n\t0x9b,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x21,0xf9,0xd0,0xd0,0xd0,0xf5,\r\n\t0x1d,0x14,0xec,0xc4,0x9b,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x21,0xf9,\r\n\t0xd0,0xd0,0xd0,0xf5,0x1d,0x14,0xec,0xc4,0x9b,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,\r\n\t0xe3,0x0b,0x21,0xf9,0xd0,0xd0,0xd0,0xf5,0x1d,0x14,0xec,0xc4,0x9c,0x81,0x81,0x81,\r\n\t0x81,0x81,0x92,0xba,0xe2,0x0b,0x22,0xfa,0xd2,0xd0,0xd0,0xf4,0x1c,0x15,0xed,0xc4,\r\n\t0x9c,0x81,0x81,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x21,0xf9,0xd1,0xd0,0xd0,0xf5,\r\n\t0x1e,0x14,0xec,0xc3,0x9b,0x81,0x81,0x81,0x81,0x81,0x86,0xad,0xd4,0xfb,0x22,0x04,\r\n\t0xda,0xda,0x06,0x23,0xf7,0xdf,0xdf,0xdf,0xd7,0xb5,0x8e,0x81,0x95,0xbf,0xe9,0x13,\r\n\t0x21,0xf5,0xcc,0xa2,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xd5,0xb2,0x89,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xd5,0xb2,0x89,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xd5,\r\n\t0xb2,0x89,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe2,0xe2,0xe2,0xe2,0xe2,\r\n\t0xe2,0xd5,0xb2,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x91,0xb9,0xdb,\r\n\t0xe2,0xfa,0x26,0x09,0xe2,0xe2,0xe1,0xc7,0xbf,0xe8,0x13,0x1f,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd0,0xe7,0x0d,0x20,0xfa,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0xa2,0xcc,0xf5,0x21,0x13,0xe7,0xbd,0x94,0x81,0x8a,0xb4,0xdd,0x09,\r\n\t0x2b,0xff,0xd5,0xab,0x81,0x81,0xa2,0xcc,0xf5,0x21,0x13,0xe7,0xbd,0x94,0x81,0x8a,\r\n\t0xb4,0xdd,0x09,0x2b,0xff,0xd5,0xab,0x81,0x81,0xa2,0xcc,0xf5,0x21,0x13,0xe7,0xbd,\r\n\t0x94,0x81,0x8a,0xb4,0xdd,0x09,0x2b,0xff,0xd5,0xab,0x81,0x81,0xa2,0xcc,0xf5,0x21,\r\n\t0x13,0xe7,0xbd,0x94,0x81,0x8a,0xb4,0xdd,0x09,0x2b,0xff,0xd5,0xab,0x81,0x81,0xa2,\r\n\t0xcc,0xf5,0x21,0x13,0xe7,0xbd,0x94,0x81,0x8a,0xb4,0xdd,0x09,0x2b,0xff,0xd5,0xab,\r\n\t0x81,0x81,0x81,0x85,0xa3,0xc1,0xdf,0xfc,0x26,0x21,0xf9,0xdb,0xbd,0x9f,0x81,0x81,\r\n\t0x81,0x95,0xbf,0xe8,0x13,0x21,0xf5,0xcf,0xf7,0x20,0xfb,0xd3,0xd1,0xfa,0x26,0x0e,\r\n\t0xe2,0xb8,0x8f,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa0,0xc8,0xf1,0x19,0x16,0xfa,0xfa,0xfa,0xfa,0xfa,0x11,0x21,0xf9,0xd1,\r\n\t0xa9,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x16,0xfa,0xfa,0xfa,0xfa,0xfa,\r\n\t0x11,0x21,0xf9,0xd1,0xa9,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x16,0xfa,\r\n\t0xfa,0xfa,0xfa,0xfa,0x11,0x21,0xf9,0xd1,0xa9,0x81,0x81,0x81,0x81,0x81,0xa0,0xc8,\r\n\t0xf1,0x19,0x16,0xfa,0xfa,0xfa,0xfa,0xfa,0x11,0x21,0xf9,0xd1,0xa9,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9f,0xc8,0xef,0x18,0x16,0xfa,0xfa,0xfa,0xfa,0xfa,0x11,0x22,0xfa,0xd2,\r\n\t0xa9,0x81,0x81,0x81,0x81,0x81,0x9f,0xc8,0xf1,0x19,0x16,0xfa,0xfa,0xfa,0xfa,0xfa,\r\n\t0x11,0x21,0xf9,0xd1,0xa8,0x81,0x81,0x81,0x81,0x81,0x95,0xbd,0xe4,0x0b,0x1a,0xf2,\r\n\t0xef,0xef,0x06,0x23,0xf7,0xcd,0xb5,0xb5,0xb1,0x9b,0x81,0x81,0x91,0xba,0xe5,0x0e,\r\n\t0x26,0xfc,0xd4,0xab,0x84,0x81,0x81,0x81,0x81,0x88,0x82,0x81,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xd2,0xb8,0xb8,0xb8,0xb8,0xb8,0xb2,0x9a,0x81,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xb8,0xb8,0xb8,0xb8,0xb8,0xb2,0x9a,0x81,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xb8,0xb8,0xb8,0xb8,0xb8,0xb2,\r\n\t0x9a,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xb8,0xb8,0xb8,0xb8,\r\n\t0xb8,0xb2,0x9a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x9f,0xb4,\r\n\t0xd0,0xfa,0x26,0x09,0xdd,0xb8,0xb7,0xa9,0xc8,0xf1,0x19,0x19,0xef,0xc5,0x9c,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd0,0xd4,0xfb,0x21,0x0b,0xed,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x9e,0xc8,0xf2,0x1c,0x18,0xed,0xc4,0x9b,0x81,0x92,0xbb,0xe4,0x0e,\r\n\t0x24,0xfa,0xd1,0xa7,0x81,0x81,0x9e,0xc8,0xf2,0x1c,0x18,0xed,0xc4,0x9b,0x81,0x92,\r\n\t0xbb,0xe4,0x0e,0x24,0xfa,0xd1,0xa7,0x81,0x81,0x9e,0xc8,0xf2,0x1c,0x18,0xed,0xc4,\r\n\t0x9b,0x81,0x92,0xbb,0xe4,0x0e,0x24,0xfa,0xd1,0xa7,0x81,0x81,0x9e,0xc8,0xf2,0x1c,\r\n\t0x18,0xed,0xc4,0x9b,0x81,0x92,0xbb,0xe4,0x0e,0x24,0xfa,0xd1,0xa7,0x81,0x81,0x9e,\r\n\t0xc8,0xf2,0x1c,0x18,0xed,0xc4,0x9b,0x81,0x92,0xbb,0xe4,0x0e,0x24,0xfa,0xd1,0xa7,\r\n\t0x81,0x81,0x83,0xa1,0xbf,0xdd,0xfb,0x1a,0x14,0x1c,0x18,0xf9,0xdb,0xbd,0x9f,0x81,\r\n\t0x81,0x91,0xba,0xe5,0x0f,0x24,0xfa,0xdc,0x04,0x19,0xef,0xc8,0xd7,0xff,0x2b,0x09,\r\n\t0xdd,0xb4,0x8a,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,\r\n\t0x1b,0x13,0xe7,0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,\r\n\t0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x85,0xae,0xd6,0xfc,0x26,0x2b,0x26,0x26,0x26,0x26,0x26,0x2a,0x2e,0x06,0xde,\r\n\t0xb6,0x8e,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x2b,0x26,0x26,0x26,0x26,0x26,\r\n\t0x2a,0x2e,0x06,0xde,0xb6,0x8e,0x81,0x81,0x81,0x85,0xae,0xd6,0xfc,0x26,0x2b,0x26,\r\n\t0x26,0x26,0x26,0x26,0x2a,0x2e,0x06,0xde,0xb6,0x8e,0x81,0x81,0x81,0x85,0xae,0xd6,\r\n\t0xfc,0x26,0x2b,0x26,0x26,0x26,0x26,0x26,0x2a,0x2e,0x06,0xde,0xb6,0x8e,0x81,0x81,\r\n\t0x81,0x85,0xad,0xd5,0xfc,0x25,0x2b,0x26,0x26,0x26,0x26,0x26,0x2a,0x2f,0x07,0xdf,\r\n\t0xb7,0x8f,0x81,0x81,0x81,0x85,0xad,0xd5,0xfc,0x25,0x2b,0x26,0x26,0x26,0x26,0x26,\r\n\t0x2a,0x2e,0x06,0xdd,0xb5,0x8d,0x81,0x81,0x81,0x81,0xa6,0xcd,0xf4,0x1b,0x23,0x1b,\r\n\t0x1b,0x1b,0x1c,0x23,0xf7,0xcd,0xa3,0x8d,0x8d,0x81,0x81,0x81,0x8a,0xb3,0xdc,0x06,\r\n\t0x2e,0x09,0xe2,0xbd,0x9e,0x90,0x90,0x98,0xa7,0xb2,0xaa,0x90,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x90,0x90,0x90,0x90,0x8f,0x81,0x81,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x90,0x90,0x90,0x90,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x90,0x90,0x90,0x90,0x8f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xa8,0x90,0x90,0x90,\r\n\t0x90,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0xa8,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xb2,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0xa8,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xb2,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0xa8,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,\r\n\t0x90,0xa8,0xd2,0xfc,0x29,0x09,0xdd,0xb2,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x09,0xdd,0xb2,0x9e,0xb6,0xd9,0xfc,0x25,0x0d,0xe5,0xbd,0x94,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd0,0xc2,0xe9,0x0f,0x1d,0xf5,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x98,0xc1,0xea,0x13,0x20,0xf7,0xd0,0xaa,0x8c,0xa3,0xc8,0xef,0x18,\r\n\t0x19,0xf1,0xc8,0x9f,0x81,0x81,0x98,0xc1,0xea,0x13,0x20,0xf7,0xd0,0xaa,0x8c,0xa3,\r\n\t0xc8,0xef,0x18,0x19,0xf1,0xc8,0x9f,0x81,0x81,0x98,0xc1,0xea,0x13,0x20,0xf7,0xd0,\r\n\t0xaa,0x8c,0xa3,0xc8,0xef,0x18,0x19,0xf1,0xc8,0x9f,0x81,0x81,0x98,0xc1,0xea,0x13,\r\n\t0x20,0xf7,0xd0,0xaa,0x8c,0xa3,0xc8,0xef,0x18,0x19,0xf1,0xc8,0x9f,0x81,0x81,0x98,\r\n\t0xc1,0xea,0x13,0x20,0xf7,0xd0,0xaa,0x8c,0xa3,0xc8,0xef,0x18,0x19,0xf1,0xc8,0x9f,\r\n\t0x81,0x81,0xa1,0xbf,0xdd,0xfb,0x1a,0x14,0xf5,0xfc,0x1c,0x18,0xf9,0xdb,0xbd,0x9f,\r\n\t0x81,0x8b,0xb4,0xdd,0x06,0x2c,0x04,0xe7,0x11,0x0c,0xe4,0xbc,0xe3,0x0b,0x26,0xfc,\r\n\t0xd5,0xac,0x83,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfc,0xd2,0xa9,0x89,0xa0,0xc9,0xf2,\r\n\t0x1e,0x11,0xe5,0xbc,0x92,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfc,0xd2,0xa9,0x89,0xa0,\r\n\t0xc9,0xf2,0x1e,0x11,0xe5,0xbc,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x93,0xbb,0xe3,0x0b,0x23,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x14,0xec,\r\n\t0xc3,0x9b,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x23,0xff,0xff,0xff,0xff,0xff,0xff,\r\n\t0xff,0x1f,0x14,0xec,0xc3,0x9b,0x81,0x81,0x81,0x93,0xbb,0xe3,0x0b,0x23,0xff,0xff,\r\n\t0xff,0xff,0xff,0xff,0xff,0x1f,0x14,0xec,0xc3,0x9b,0x81,0x81,0x81,0x93,0xbb,0xe3,\r\n\t0x0b,0x23,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x14,0xec,0xc3,0x9b,0x81,0x81,\r\n\t0x81,0x91,0xba,0xe2,0x0b,0x24,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1e,0x14,0xec,\r\n\t0xc4,0x9b,0x81,0x81,0x81,0x92,0xba,0xe2,0x0b,0x23,0xff,0xff,0xff,0xff,0xff,0xff,\r\n\t0xff,0x1f,0x13,0xeb,0xc3,0x9a,0x81,0x81,0x81,0x8e,0xb5,0xdc,0x04,0x24,0x04,0x04,\r\n\t0x04,0x04,0x07,0x23,0xf7,0xcd,0xb8,0xb8,0xb7,0xa6,0x88,0x81,0x81,0xa8,0xd0,0xf7,\r\n\t0x1e,0x1b,0xf9,0xd9,0xc3,0xba,0xba,0xc1,0xcd,0xdd,0xcc,0xa8,0x81,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xd2,0xba,0xba,0xba,0xba,0xba,0xb8,0xa5,0x85,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xba,0xba,0xba,0xba,0xba,0xb8,0xa5,0x85,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xba,0xba,0xba,0xba,0xba,0xb8,\r\n\t0xa5,0x85,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xd2,0xba,0xba,0xba,0xba,\r\n\t0xba,0xb8,0xa5,0x85,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xd2,0xfc,0x29,0x09,\r\n\t0xdd,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xd2,0xfc,\r\n\t0x29,0x09,0xdd,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,\r\n\t0xd2,0xfc,0x29,0x09,0xdd,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x9f,0xb6,\r\n\t0xba,0xba,0xd2,0xfc,0x29,0x09,0xdd,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x09,0xdd,0xbf,0xc6,0xd6,0xf1,0x12,0x22,0xfc,0xd6,0xaf,0x87,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd0,0xb1,0xd6,0xfc,0x24,0x06,0x19,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x8e,0xb7,0xdf,0x07,0x2e,0x09,0xe3,0xc4,0xb6,0xc1,0xde,0xff,0x27,\r\n\t0x0a,0xe3,0xbb,0x94,0x81,0x81,0x8e,0xb7,0xdf,0x07,0x2e,0x09,0xe3,0xc4,0xb6,0xc1,\r\n\t0xde,0xff,0x27,0x0a,0xe3,0xbb,0x94,0x81,0x81,0x8e,0xb7,0xdf,0x07,0x2e,0x09,0xe3,\r\n\t0xc4,0xb6,0xc1,0xde,0xff,0x27,0x0a,0xe3,0xbb,0x94,0x81,0x81,0x8e,0xb7,0xdf,0x07,\r\n\t0x2e,0x09,0xe3,0xc4,0xb6,0xc1,0xde,0xff,0x27,0x0a,0xe3,0xbb,0x94,0x81,0x81,0x8e,\r\n\t0xb7,0xdf,0x07,0x2e,0x09,0xe3,0xc4,0xb6,0xc1,0xde,0xff,0x27,0x0a,0xe3,0xbb,0x94,\r\n\t0x81,0x8e,0xb7,0xdd,0xfb,0x1a,0x14,0xf5,0xd7,0xdf,0xfc,0x1c,0x18,0xf9,0xda,0xb3,\r\n\t0x89,0x81,0xa9,0xd2,0xfa,0x21,0x13,0xf4,0x1c,0xff,0xd7,0xd4,0xf6,0x1b,0x17,0xef,\r\n\t0xc8,0xa0,0x81,0x81,0x84,0xae,0xd7,0xff,0x2a,0x05,0xde,0xbd,0xb2,0xb9,0xd7,0xfc,\r\n\t0x25,0x07,0xdf,0xb5,0x8c,0x81,0x84,0xae,0xd7,0xff,0x2a,0x05,0xde,0xbd,0xb2,0xb9,\r\n\t0xd7,0xfc,0x25,0x07,0xdf,0xb5,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa0,0xc8,0xf1,0x19,0x16,0xed,0xd5,0xd5,0xd5,0xd5,0xd5,0xea,0x12,0x21,0xf7,\r\n\t0xd0,0xa8,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x16,0xed,0xd5,0xd5,0xd5,0xd5,0xd5,\r\n\t0xea,0x12,0x21,0xf7,0xd0,0xa8,0x81,0x81,0x81,0xa0,0xc8,0xf1,0x19,0x16,0xed,0xd5,\r\n\t0xd5,0xd5,0xd5,0xd5,0xea,0x12,0x21,0xf7,0xd0,0xa8,0x81,0x81,0x81,0xa0,0xc8,0xf1,\r\n\t0x19,0x16,0xed,0xd5,0xd5,0xd5,0xd5,0xd5,0xea,0x12,0x21,0xf7,0xd0,0xa8,0x81,0x81,\r\n\t0x81,0x9f,0xc7,0xef,0x17,0x17,0xef,0xd5,0xd5,0xd5,0xd5,0xd5,0xe9,0x11,0x21,0xf9,\r\n\t0xd1,0xa9,0x81,0x81,0x81,0x9f,0xc8,0xef,0x18,0x16,0xee,0xd5,0xd5,0xd5,0xd5,0xd5,\r\n\t0xea,0x13,0x20,0xf7,0xd0,0xa8,0x81,0x81,0x81,0x9e,0xc6,0xed,0x14,0x14,0xec,0xd7,\r\n\t0xd7,0xda,0x06,0x23,0xf7,0xe2,0xe2,0xe2,0xe0,0xc2,0x9b,0x81,0x81,0x99,0xbf,0xe5,\r\n\t0x09,0x2b,0x16,0xfc,0xeb,0xe3,0xe3,0xea,0xf5,0x05,0xda,0xb0,0x85,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x29,0xfc,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,0xbf,0x97,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,0xbf,0x97,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,\r\n\t0xbf,0x97,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x29,0xfc,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe0,0xbf,0x97,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xfc,0x29,0x09,\r\n\t0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xfc,\r\n\t0x29,0x09,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,\r\n\t0xe5,0xfc,0x29,0x09,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x8f,0xb8,0xdb,\r\n\t0xe5,0xe5,0xe5,0xfc,0x29,0x09,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x09,0xe7,0xe7,0xef,0xfc,0x12,0x27,0x09,0xe7,0xc4,0x9e,0x81,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd0,0xa5,0xc5,0xeb,0x12,0x1a,0x20,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x81,0xa8,0xcf,0xf5,0x1a,0x1f,0xff,0xe9,0xdf,0xe7,0xfb,0x1a,0x1a,\r\n\t0xf6,0xd2,0xac,0x85,0x81,0x81,0x81,0xa8,0xcf,0xf5,0x1a,0x1f,0xff,0xe9,0xdf,0xe7,\r\n\t0xfb,0x1a,0x1a,0xf6,0xd2,0xac,0x85,0x81,0x81,0x81,0xa8,0xcf,0xf5,0x1a,0x1f,0xff,\r\n\t0xe9,0xdf,0xe7,0xfb,0x1a,0x1a,0xf6,0xd2,0xac,0x85,0x81,0x81,0x81,0xa8,0xcf,0xf5,\r\n\t0x1a,0x1f,0xff,0xe9,0xdf,0xe7,0xfb,0x1a,0x1a,0xf6,0xd2,0xac,0x85,0x81,0x81,0x81,\r\n\t0xa8,0xcf,0xf5,0x1a,0x1f,0xff,0xe9,0xdf,0xe7,0xfb,0x1a,0x1a,0xf6,0xd2,0xac,0x85,\r\n\t0x81,0x8f,0xb8,0xe0,0xff,0x14,0xf5,0xd7,0xb9,0xc1,0xdf,0xff,0x18,0xf9,0xda,0xb3,\r\n\t0x89,0x81,0x9c,0xc3,0xe9,0x0f,0x28,0x0b,0x1d,0xf4,0xe2,0xf3,0x10,0x25,0xff,0xde,\r\n\t0xb8,0x91,0x81,0x81,0x81,0xa4,0xcd,0xf5,0x1b,0x18,0xf7,0xe3,0xdd,0xe2,0xf3,0x12,\r\n\t0x1d,0xf7,0xd2,0xa9,0x81,0x81,0x81,0xa4,0xcd,0xf5,0x1b,0x18,0xf7,0xe3,0xdd,0xe2,\r\n\t0xf3,0x12,0x1d,0xf7,0xd2,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x85,0xad,0xd6,0xfc,0x26,0x09,0xe1,0xb9,0xab,0xab,0xab,0xb4,0xdc,0x06,0x2e,0x06,\r\n\t0xdd,0xb5,0x8d,0x81,0x85,0xad,0xd6,0xfc,0x26,0x09,0xe1,0xb9,0xab,0xab,0xab,0xb4,\r\n\t0xdc,0x06,0x2e,0x06,0xdd,0xb5,0x8d,0x81,0x85,0xad,0xd6,0xfc,0x26,0x09,0xe1,0xb9,\r\n\t0xab,0xab,0xab,0xb4,0xdc,0x06,0x2e,0x06,0xdd,0xb5,0x8d,0x81,0x85,0xad,0xd6,0xfc,\r\n\t0x26,0x09,0xe1,0xb9,0xab,0xab,0xab,0xb4,0xdc,0x06,0x2e,0x06,0xdd,0xb5,0x8d,0x81,\r\n\t0x84,0xac,0xd4,0xfc,0x24,0x0a,0xe1,0xb9,0xab,0xab,0xab,0xb4,0xdc,0x05,0x2d,0x06,\r\n\t0xde,0xb6,0x8e,0x81,0x85,0xad,0xd5,0xfc,0x25,0x09,0xe1,0xb9,0xab,0xab,0xab,0xb5,\r\n\t0xdd,0x06,0x2d,0x05,0xdc,0xb4,0x8c,0x81,0x87,0xae,0xd5,0xfc,0x24,0x05,0xdd,0xb6,\r\n\t0xb0,0xda,0x06,0x26,0x0e,0x0e,0x0e,0x0e,0xf5,0xca,0xa0,0x81,0x81,0x86,0xaa,0xcd,\r\n\t0xee,0x0b,0x24,0x21,0x14,0x0e,0x0e,0x13,0x1e,0x06,0xda,0xb0,0x85,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x2c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,0xc5,0x9b,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x2c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,0xc5,0x9b,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,\r\n\t0xc5,0x9b,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2c,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0xef,0xc5,0x9b,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,0x2c,0x13,\r\n\t0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,\r\n\t0x2c,0x13,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,\r\n\t0x11,0x11,0x2c,0x13,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,\r\n\t0x11,0x11,0x11,0x11,0x2c,0x13,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x26,0x15,0x13,0x13,0x19,0x23,0x1b,0x06,0xec,0xcd,0xac,0x89,0x81,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x26,0xfa,0xd0,0xa5,0xb3,0xd9,0xff,0x26,0x3b,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x81,0x97,0xbb,0xde,0xff,0x1c,0x22,0x11,0x0b,0x0f,0x1f,0x1a,0xfc,\r\n\t0xde,0xbc,0x98,0x81,0x81,0x81,0x81,0x97,0xbb,0xde,0xff,0x1c,0x22,0x11,0x0b,0x0f,\r\n\t0x1f,0x1a,0xfc,0xde,0xbc,0x98,0x81,0x81,0x81,0x81,0x97,0xbb,0xde,0xff,0x1c,0x22,\r\n\t0x11,0x0b,0x0f,0x1f,0x1a,0xfc,0xde,0xbc,0x98,0x81,0x81,0x81,0x81,0x97,0xbb,0xde,\r\n\t0xff,0x1c,0x22,0x11,0x0b,0x0f,0x1f,0x1a,0xfc,0xde,0xbc,0x98,0x81,0x81,0x81,0x81,\r\n\t0x97,0xbb,0xde,0xff,0x1c,0x22,0x11,0x0b,0x0f,0x1f,0x1a,0xfc,0xde,0xbc,0x98,0x81,\r\n\t0x81,0x81,0xa5,0xc3,0xe1,0xf5,0xd7,0xb9,0x9b,0xa3,0xc3,0xe1,0xf9,0xdb,0xbd,0x9f,\r\n\t0x81,0x81,0x8b,0xb0,0xd4,0xf5,0x14,0x2c,0x1a,0x0b,0x0c,0x19,0x22,0x07,0xe8,0xc7,\r\n\t0xa4,0x81,0x81,0x81,0x81,0x97,0xbc,0xe1,0x04,0x20,0x1b,0x0d,0x09,0x0b,0x18,0x1f,\r\n\t0x04,0xe2,0xbf,0x99,0x81,0x81,0x81,0x97,0xbc,0xe1,0x04,0x20,0x1b,0x0d,0x09,0x0b,\r\n\t0x18,0x1f,0x04,0xe2,0xbf,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8f,0xb9,0xe2,0x0b,0x11,0xfc,0xd3,0xab,0x83,0x81,0x81,0xa8,0xd0,0xf7,0x11,0x11,\r\n\t0xeb,0xc2,0x98,0x81,0x8f,0xb9,0xe2,0x0b,0x11,0xfc,0xd3,0xab,0x83,0x81,0x81,0xa8,\r\n\t0xd0,0xf7,0x11,0x11,0xeb,0xc2,0x98,0x81,0x8f,0xb9,0xe2,0x0b,0x11,0xfc,0xd3,0xab,\r\n\t0x83,0x81,0x81,0xa8,0xd0,0xf7,0x11,0x11,0xeb,0xc2,0x98,0x81,0x8f,0xb9,0xe2,0x0b,\r\n\t0x11,0xfc,0xd3,0xab,0x83,0x81,0x81,0xa8,0xd0,0xf7,0x11,0x11,0xeb,0xc2,0x98,0x81,\r\n\t0x8f,0xb9,0xe1,0x0a,0x11,0xfc,0xd5,0xac,0x84,0x81,0x81,0xa7,0xcf,0xf7,0x11,0x11,\r\n\t0xec,0xc3,0x9a,0x81,0x8f,0xb9,0xe2,0x0b,0x11,0xfc,0xd4,0xac,0x84,0x81,0x81,0xa8,\r\n\t0xd1,0xf9,0x11,0x11,0xea,0xc1,0x97,0x81,0x92,0xbc,0xe6,0x0d,0x11,0xf5,0xce,0xa7,\r\n\t0xb0,0xda,0x06,0x11,0x11,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x92,0xb2,\r\n\t0xd0,0xe9,0xfc,0x0c,0x20,0x1d,0x17,0x11,0x07,0xfa,0xd9,0xaf,0x85,0x81,0x81,0x85,\r\n\t0xb0,0xda,0x06,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,0xc5,0x9b,0x81,0x81,\r\n\t0x81,0x85,0xb0,0xda,0x06,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,0xc5,0x9b,\r\n\t0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xef,\r\n\t0xc5,0x9b,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x11,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0xef,0xc5,0x9b,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x93,0xbd,0xe7,\r\n\t0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa5,\r\n\t0xd0,0xfa,0x11,0x11,0x11,0x0f,0x0b,0x04,0xf4,0xe2,0xcb,0xb0,0x92,0x81,0x81,0x81,\r\n\t0x81,0x83,0xad,0xd7,0x04,0x11,0xfa,0xd0,0xa5,0xa1,0xc7,0xed,0x11,0x11,0x11,0xe5,\r\n\t0xba,0x90,0x81,0x81,0x81,0xa3,0xc3,0xe0,0xf9,0x0b,0x15,0x19,0x14,0x09,0xf6,0xdf,\r\n\t0xc1,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xc3,0xe0,0xf9,0x0b,0x15,0x19,0x14,\r\n\t0x09,0xf6,0xdf,0xc1,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xc3,0xe0,0xf9,0x0b,\r\n\t0x15,0x19,0x14,0x09,0xf6,0xdf,0xc1,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xc3,\r\n\t0xe0,0xf9,0x0b,0x15,0x19,0x14,0x09,0xf6,0xdf,0xc1,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0xa3,0xc3,0xe0,0xf9,0x0b,0x15,0x19,0x14,0x09,0xf6,0xdf,0xc1,0xa3,0x81,0x81,\r\n\t0x81,0x81,0x87,0xa5,0xc2,0xcc,0xb9,0x9b,0x81,0x87,0xa5,0xc2,0xcf,0xbd,0x9f,0x81,\r\n\t0x81,0x81,0x81,0x99,0xb9,0xd7,0xf1,0x19,0x13,0x19,0x16,0x0d,0xfc,0xe6,0xcc,0xac,\r\n\t0x8c,0x81,0x81,0x81,0x81,0x83,0xa7,0xc7,0xe4,0xfc,0x0d,0x16,0x19,0x16,0x0c,0xfb,\r\n\t0xe3,0xc7,0xa7,0x84,0x81,0x81,0x81,0x83,0xa7,0xc7,0xe4,0xfc,0x0d,0x16,0x19,0x16,\r\n\t0x0c,0xfb,0xe3,0xc7,0xa7,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8d,0xb5,0xd9,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x9a,0xc1,0xe1,0xe5,0xe5,\r\n\t0xde,0xbc,0x94,0x81,0x8d,0xb5,0xd9,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x9a,\r\n\t0xc1,0xe1,0xe5,0xe5,0xde,0xbc,0x94,0x81,0x8d,0xb5,0xd9,0xe5,0xe5,0xe3,0xc6,0x9f,\r\n\t0x81,0x81,0x81,0x9a,0xc1,0xe1,0xe5,0xe5,0xde,0xbc,0x94,0x81,0x8d,0xb5,0xd9,0xe5,\r\n\t0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x9a,0xc1,0xe1,0xe5,0xe5,0xde,0xbc,0x94,0x81,\r\n\t0x8d,0xb5,0xd9,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x9a,0xc1,0xe1,0xe5,0xe5,\r\n\t0xe0,0xbf,0x97,0x81,0x8d,0xb5,0xd9,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x9b,\r\n\t0xc2,0xe1,0xe5,0xe5,0xde,0xbc,0x94,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe0,0xbf,0x98,\r\n\t0xab,0xd1,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x81,0x94,\r\n\t0xaf,0xc5,0xd6,0xf7,0x20,0x09,0xed,0xe7,0xdf,0xd2,0xc0,0xa1,0x81,0x81,0x81,0x82,\r\n\t0xab,0xd1,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,0xbf,0x97,0x81,0x81,\r\n\t0x81,0x82,0xab,0xd1,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,0xbf,0x97,\r\n\t0x81,0x81,0x81,0x82,0xab,0xd1,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe0,\r\n\t0xbf,0x97,0x81,0x81,0x81,0x82,0xab,0xd1,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe0,0xbf,0x97,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x8f,0xb8,0xdb,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0xa1,\r\n\t0xc8,0xe4,0xe5,0xe5,0xe5,0xe5,0xe0,0xd9,0xcd,0xbc,0xa8,0x90,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa9,0xcf,0xe5,0xe5,0xe4,0xc8,0xa1,0x8f,0xb5,0xd9,0xe5,0xe5,0xe5,0xd9,\r\n\t0xb5,0x8d,0x81,0x81,0x81,0x87,0xa5,0xbe,0xd3,0xe2,0xea,0xed,0xea,0xe1,0xd1,0xbd,\r\n\t0xa3,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xbe,0xd3,0xe2,0xea,0xed,0xea,\r\n\t0xe1,0xd1,0xbd,0xa3,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xbe,0xd3,0xe2,\r\n\t0xea,0xed,0xea,0xe1,0xd1,0xbd,0xa3,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,\r\n\t0xbe,0xd3,0xe2,0xea,0xed,0xea,0xe1,0xd1,0xbd,0xa3,0x85,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x87,0xa5,0xbe,0xd3,0xe2,0xea,0xed,0xea,0xe1,0xd1,0xbd,0xa3,0x85,0x81,0x81,\r\n\t0x81,0x81,0x81,0x86,0x9c,0xa2,0x97,0x81,0x81,0x81,0x87,0x9d,0xa5,0x9a,0x81,0x81,\r\n\t0x81,0x81,0x81,0x82,0xaa,0xd3,0xfb,0x21,0xf7,0xed,0xec,0xe4,0xd6,0xc4,0xac,0x90,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xa9,0xc2,0xd6,0xe4,0xea,0xed,0xea,0xe3,0xd5,\r\n\t0xc1,0xa8,0x8b,0x81,0x81,0x81,0x81,0x81,0x8b,0xa9,0xc2,0xd6,0xe4,0xea,0xed,0xea,\r\n\t0xe3,0xd5,0xc1,0xa8,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9d,0xb5,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x87,0xa6,0xb9,0xba,0xba,\r\n\t0xb8,0xa3,0x83,0x81,0x81,0x9d,0xb5,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x87,\r\n\t0xa6,0xb9,0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0x9d,0xb5,0xba,0xba,0xba,0xa9,0x8b,\r\n\t0x81,0x81,0x81,0x87,0xa6,0xb9,0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0x9d,0xb5,0xba,\r\n\t0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x87,0xa6,0xb9,0xba,0xba,0xb8,0xa3,0x83,0x81,\r\n\t0x81,0x9d,0xb5,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x87,0xa6,0xb9,0xba,0xba,\r\n\t0xb8,0xa5,0x85,0x81,0x81,0x9d,0xb5,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x88,\r\n\t0xa6,0xb9,0xba,0xba,0xb8,0xa3,0x83,0x81,0x81,0x9f,0xb6,0xba,0xba,0xb8,0xa5,0x85,\r\n\t0x96,0xb1,0xba,0xba,0xba,0xba,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xae,0xd7,0xff,0x25,0xfc,0xd4,0xbe,0xb6,0xaa,0x9b,0x85,0x81,0x81,0x81,0x81,\r\n\t0x96,0xb1,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xb8,0xa5,0x85,0x81,0x81,\r\n\t0x81,0x81,0x96,0xb1,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xb8,0xa5,0x85,\r\n\t0x81,0x81,0x81,0x81,0x96,0xb1,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xb8,\r\n\t0xa5,0x85,0x81,0x81,0x81,0x81,0x96,0xb1,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xb8,0xa5,0x85,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x9f,0xb6,\r\n\t0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x8d,\r\n\t0xab,0xba,0xba,0xba,0xba,0xba,0xb7,0xaf,0xa4,0x96,0x84,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x94,0xaf,0xba,0xba,0xba,0xab,0x8d,0x81,0x9d,0xb5,0xba,0xba,0xba,0xb5,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x81,0x83,0x9a,0xad,0xb9,0xc1,0xc2,0xc0,0xb8,0xab,0x98,\r\n\t0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x9a,0xad,0xb9,0xc1,0xc2,0xc0,\r\n\t0xb8,0xab,0x98,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x9a,0xad,0xb9,\r\n\t0xc1,0xc2,0xc0,0xb8,0xab,0x98,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,\r\n\t0x9a,0xad,0xb9,0xc1,0xc2,0xc0,0xb8,0xab,0x98,0x82,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x83,0x9a,0xad,0xb9,0xc1,0xc2,0xc0,0xb8,0xab,0x98,0x82,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xb6,0xdf,0x09,0x15,0xec,0xc4,0xc2,0xbb,0xaf,0x9f,0x89,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x9e,0xaf,0xbb,0xc1,0xc2,0xc1,0xba,0xae,\r\n\t0x9c,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x9e,0xaf,0xbb,0xc1,0xc2,0xc1,\r\n\t0xba,0xae,0x9c,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x82,0x8f,0x90,0x90,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,\r\n\t0x82,0x8f,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x82,0x8f,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,\r\n\t0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x82,0x8f,0x90,0x90,0x8e,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x82,0x8f,0x90,0x90,\r\n\t0x8f,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,\r\n\t0x82,0x8f,0x90,0x90,0x8e,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x8f,0x81,0x81,\r\n\t0x81,0x8a,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8e,0xb7,0xe0,0x0a,0x19,0xf1,0xc8,0x9f,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8a,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8a,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8a,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,\r\n\t0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,\r\n\t0x86,0x90,0x90,0x90,0x90,0x90,0x8d,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x89,0x90,0x90,0x90,0x86,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x8d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,0x8f,0x83,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,\r\n\t0x8f,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,\r\n\t0x97,0x98,0x97,0x8f,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x85,0x90,0x97,0x98,0x97,0x8f,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,0x8f,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x92,0xbd,0xe7,0xfa,0xfa,0xe1,0xb8,0x98,0x92,0x87,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x91,0x97,0x98,0x97,0x91,0x86,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x91,0x97,0x98,0x97,\r\n\t0x91,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x92,0xbd,0xe7,0xfa,0xfa,0xe5,0xbc,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x88,0xad,0xc9,0xd0,0xd0,0xc5,0xa7,0x82,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x88,0xad,0xc9,0xd0,0xd0,0xc8,0xab,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8f,0xa2,0xa5,0xa5,0x9f,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8f,0xa2,0xa5,0xa5,0xa1,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8b,0xa7,0xc5,0xda,0xda,0xda,0xcb,0xae,0x92,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x86,0xa8,0xc5,0xd8,0xd9,0xc8,0xac,0xc2,0xd6,0xda,0xcb,\r\n\t0xb0,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd6,0xda,\r\n\t0xda,0xda,0xd0,0xae,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x8b,0x89,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8d,0xaa,0xc7,0xe3,0xff,0x06,0x06,0xea,0xce,0xb1,0x94,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x97,0xbf,0xe3,0xff,0xff,0xe8,0xc4,0xdf,0xfc,0x04,0xec,\r\n\t0xc8,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd9,0xf7,0x06,\r\n\t0x06,0x05,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8c,\r\n\t0x90,0x90,0x8c,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,\r\n\t0x8b,0x8b,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x8b,0x8b,0x82,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8b,0x8b,0x84,0x81,0x81,0x85,0x82,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x85,0x81,0x81,0x81,0x85,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa2,0xb1,0xb5,0xb2,0xa5,\r\n\t0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,\r\n\t0x8b,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x87,0x8b,0x8b,0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8a,0x8b,0x8b,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0x85,0x81,0x81,0x81,0x85,0x85,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x8b,0x89,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x8b,0x8b,\r\n\t0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x8b,0x8b,\r\n\t0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x85,0x81,\r\n\t0x81,0x81,0x84,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x8b,0x8b,\r\n\t0x8b,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0x88,0x81,0x81,0x81,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x88,0x8b,0x8b,0x8b,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x8b,0x8b,0x8b,0x8a,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0x8b,0x8b,0x83,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8b,0x8b,0x84,0x81,\r\n\t0x81,0x84,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x85,\r\n\t0x81,0x81,0x81,0x84,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8a,0xac,0xc8,0xe6,0x04,0x1f,0x0a,0x1d,0x0a,0xec,0xd0,0xb4,0x93,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1d,0x21,0xf7,0xcd,0xed,0x18,0x26,0xfc,\r\n\t0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbb,0xd9,0xf7,0x16,0x16,\r\n\t0xfc,0xe3,0xca,0xaa,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0x9d,0xac,0xb6,\r\n\t0xba,0xba,0xb6,0xac,0x9b,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,\r\n\t0xb5,0xb5,0xb3,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9a,0xb0,0xb5,0xb5,0xb5,0xb3,0xa0,0x82,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x87,0xa4,0xb4,0xb5,0xb5,0xa8,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x83,0x9b,0xac,0xb5,0xb5,0xad,0x9c,0x9e,0xaf,0xab,0x96,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0xa1,0xaf,0xaf,0xa4,0x8d,0xa0,0xaf,0xb0,0xa5,\r\n\t0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xac,0xc7,0xd9,0xdf,0xdc,0xcb,\r\n\t0xb2,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,0xb5,\r\n\t0xb5,0xb3,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x98,0xaf,0xb5,0xb5,0xb5,0xb3,0xa0,0x82,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x87,0xa4,0xb4,0xb5,0xb5,0xa9,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8a,0xa1,0xaf,0xaf,0xa4,0x8d,0xa0,0xaf,0xb0,0xa5,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,0xb5,0xb5,0xb3,0x9f,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xae,0xb5,0xb5,\r\n\t0xb5,0xb4,0xa2,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xa2,0xb4,0xb5,0xb5,\r\n\t0xa9,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xa0,0xaf,0xb0,0xa5,\r\n\t0x8f,0x9f,0xae,0xb0,0xa6,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xa9,0xb5,0xb5,\r\n\t0xb5,0xb3,0x9f,0x91,0x9a,0xa0,0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x82,0x99,\r\n\t0xaa,0xb2,0xb2,0xaa,0x99,0x9d,0xac,0xa9,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x9a,\r\n\t0xb0,0xb5,0xb5,0xb5,0xb3,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xaf,0xb5,0xb5,0xb5,0xb3,0xa0,0x82,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa4,0xb4,0xb5,0xb5,0xa9,0x8e,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x9b,0xac,0xb5,0xb5,0xad,0x9c,\r\n\t0x9c,0xae,0xac,0x97,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x89,0xa0,0xaf,0xb0,\r\n\t0xa5,0x8f,0x9f,0xae,0xb0,0xa6,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8c,0xa3,0xc1,0xe8,0x05,0x11,0xff,0xe6,0xfb,0x11,0x0d,0xf0,0xcb,0xa7,\r\n\t0x93,0x81,0x81,0x81,0x8c,0xa3,0xc3,0xe9,0x0a,0x0b,0xee,0xc8,0xe5,0x07,0x0e,0xf1,\r\n\t0xcd,0xa7,0x93,0x81,0x81,0x95,0xa8,0xab,0xab,0xab,0xae,0xd6,0xf7,0x13,0x0f,0xf4,\r\n\t0xdb,0xc2,0xab,0xab,0xaa,0x9b,0x81,0x81,0x81,0x93,0xa5,0xa8,0xa8,0xa6,0x94,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xac,0xc3,0xd4,0xdf,\r\n\t0xe5,0xe5,0xdf,0xd4,0xc1,0xa8,0x8b,0x81,0x81,0x81,0x81,0x81,0x8e,0xb5,0xd7,0xdf,\r\n\t0xdf,0xdf,0xda,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x98,0xb6,0xd5,0xdf,0xdf,0xdf,0xdb,0xbc,0x95,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x87,0xa5,0xc3,0xdd,0xdf,0xdf,0xc8,0xaa,0x8c,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x84,0xa3,0xbf,0xd4,0xdf,0xdf,0xd4,0xc1,0xbd,0xd7,0xd1,0xb4,0x96,\r\n\t0x81,0x81,0x81,0x81,0x81,0x86,0xa8,0xc6,0xd8,0xd9,0xc8,0xac,0xc4,0xd7,0xda,0xca,\r\n\t0xae,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa6,0xca,0xe8,0xff,0x0b,0x04,0xee,\r\n\t0xd0,0xad,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb5,0xd7,0xdf,0xdf,\r\n\t0xdf,0xda,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xb6,0xd4,0xdf,0xdf,0xdf,0xdb,0xbc,0x95,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x87,0xa5,0xc3,0xdd,0xdf,0xdf,0xca,0xac,0x8e,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x86,0xa8,0xc6,0xd8,0xd9,0xc8,0xac,0xc4,0xd7,0xda,0xca,0xae,0x8d,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xb5,0xd7,0xdf,0xdf,0xdf,0xda,0xbd,0x9f,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xb4,0xd2,0xdf,0xdf,\r\n\t0xdf,0xdc,0xbf,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xa3,0xc1,0xdc,0xdf,0xdf,\r\n\t0xca,0xac,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xa7,0xc4,0xd7,0xda,0xca,\r\n\t0xae,0xc3,0xd6,0xda,0xcb,0xb0,0x8f,0x81,0x81,0x81,0x81,0x81,0xa4,0xca,0xdf,0xdf,\r\n\t0xdf,0xda,0xbc,0xbb,0xc4,0xca,0xbb,0x9b,0x81,0x81,0x81,0x81,0x81,0x83,0xa1,0xbd,\r\n\t0xd2,0xdd,0xdd,0xd2,0xbf,0xbd,0xd6,0xcf,0xb2,0x94,0x81,0x81,0x81,0x81,0x8b,0xb3,\r\n\t0xd5,0xdf,0xdf,0xdf,0xda,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xb6,0xd4,0xdf,0xdf,0xdf,0xdb,0xbc,0x95,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc3,0xdd,0xdf,0xdf,0xca,0xac,0x8e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xa1,0xbe,0xd3,0xdf,0xdf,0xd5,0xc2,\r\n\t0xbb,0xd6,0xd3,0xb6,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xa7,0xc4,0xd7,0xda,\r\n\t0xca,0xae,0xc3,0xd6,0xda,0xcb,0xb0,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa7,0xc8,0xd5,0xde,0xe5,0xe5,0xde,0xc5,0xd9,0xe5,0xe5,0xe3,0xd5,0xce,\r\n\t0xb0,0x8a,0x81,0x81,0xa7,0xc8,0xd5,0xd5,0xe2,0xe3,0xd1,0xb3,0xca,0xe1,0xe4,0xd5,\r\n\t0xd5,0xce,0xb0,0x8a,0x8d,0xb2,0xcf,0xd5,0xd5,0xd5,0xc5,0xd3,0xe7,0xe7,0xe7,0xd3,\r\n\t0xb9,0xd2,0xd5,0xd5,0xd3,0xbb,0x97,0x81,0x8c,0xb1,0xcd,0xd2,0xd2,0xce,0xb3,0x8e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0xad,0xcc,0xe7,0xfb,0x09,\r\n\t0x11,0x11,0x09,0xfa,0xe4,0xc7,0xa4,0x81,0x81,0x81,0x81,0x81,0x92,0xbc,0xe6,0x04,\r\n\t0x0b,0x0b,0xf9,0xdb,0xbb,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xb6,0xd4,0xf1,0x0b,0x0b,0x09,0xed,0xc4,0x9a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x87,0xa5,0xc3,0xe1,0xff,0x0b,0x05,0xe6,0xc8,0xaa,0x8c,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9c,0xbf,0xdf,0xf9,0x09,0x09,0xfa,0xe5,0xd9,0xf9,0xf0,0xd2,0xaf,\r\n\t0x88,0x81,0x81,0x81,0x81,0x99,0xc0,0xe4,0xff,0x04,0xe8,0xc5,0xe2,0xff,0x04,0xea,\r\n\t0xc7,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb7,0xdf,0x05,0x12,0xff,0x0f,0x0b,\r\n\t0xe6,0xbe,0x96,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbc,0xe6,0x04,0x0b,\r\n\t0x0b,0xf9,0xdb,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x98,0xb6,0xd4,0xf1,0x0b,0x0b,0x09,0xed,0xc4,0x9a,0x81,0x81,0x81,0x81,\r\n\t0x81,0x87,0xa5,0xc3,0xe1,0xff,0x0b,0x07,0xe8,0xca,0xac,0x8e,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x99,0xc0,0xe4,0xff,0x04,0xe8,0xc5,0xe2,0xff,0x04,0xea,0xc7,0xa0,0x81,\r\n\t0x81,0x81,0x81,0x92,0xbc,0xe6,0x04,0x0b,0x0b,0xf9,0xdb,0xbd,0x9f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xb4,0xd2,0xf0,0x0b,0x0b,\r\n\t0x0b,0xef,0xc7,0x9d,0x81,0x81,0x81,0x81,0x81,0x85,0xa3,0xc1,0xdf,0xfc,0x0b,0x07,\r\n\t0xe8,0xca,0xac,0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x96,0xbe,0xe2,0xff,0x04,0xea,\r\n\t0xc7,0xe0,0xfc,0x04,0xec,0xc9,0xa3,0x81,0x81,0x81,0x81,0x85,0xaa,0xd4,0xfb,0x0b,\r\n\t0x0b,0xf7,0xdc,0xe4,0xed,0xf5,0xd3,0xaa,0x81,0x81,0x81,0x81,0x81,0x9c,0xbe,0xdd,\r\n\t0xf7,0x06,0x06,0xf7,0xe3,0xd7,0xf7,0xee,0xd0,0xae,0x87,0x81,0x81,0x81,0x90,0xba,\r\n\t0xe3,0x04,0x0b,0x0b,0xf9,0xdb,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xb6,0xd4,0xf1,0x0b,0x0b,0x09,0xed,0xc4,0x9a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc3,0xe1,0xff,0x0b,0x07,0xe8,0xca,0xac,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbf,0xdd,0xf9,0x09,0x09,0xfb,0xe6,\r\n\t0xd8,0xf6,0xf1,0xd4,0xb2,0x8b,0x81,0x81,0x81,0x81,0x81,0x96,0xbe,0xe2,0xff,0x04,\r\n\t0xea,0xc7,0xe0,0xfc,0x04,0xec,0xc9,0xa3,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0xff,0xff,0xfa,0xd0,0xb8,0xa3,0xb5,0xc5,0xef,0xff,0xff,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0xff,0xff,0xfa,0xd0,0xad,0x96,0xa8,0xc5,0xef,0xff,\r\n\t0xff,0xe7,0xbd,0x93,0x95,0xc0,0xea,0xff,0xff,0xff,0xdb,0xb6,0xbd,0xbd,0xbd,0xb0,\r\n\t0xcd,0xf3,0xff,0xff,0xf5,0xca,0xa0,0x81,0x95,0xc0,0xea,0xfc,0xfc,0xec,0xc2,0x9d,\r\n\t0x9b,0x96,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc5,0xe8,0x09,0x21,0x14,\r\n\t0x0b,0x0d,0x19,0x1f,0x04,0xdf,0xb9,0x91,0x81,0x81,0x81,0x81,0x87,0xac,0xc8,0xe1,\r\n\t0xfb,0x14,0x16,0xf7,0xd9,0xbb,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x97,0xb6,0xd4,0xf1,0x10,0x1a,0xff,0xe6,0xcd,0xb2,0x8e,0x81,0x81,0x81,\r\n\t0x81,0x84,0xa5,0xc3,0xe1,0xff,0x1d,0x09,0x1f,0x05,0xe6,0xc8,0xaa,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x84,0xae,0xd6,0xfa,0x1c,0x0f,0x12,0x20,0x0a,0xff,0x14,0x09,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,0x1f,0x23,0xfa,0xd0,0xf2,0x1c,0x25,0xfc,\r\n\t0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xbd,0xe7,0x13,0xfc,0xd7,0xf5,0x1a,\r\n\t0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xac,0xc8,0xe1,0xfb,\r\n\t0x14,0x18,0xf9,0xdb,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x97,0xb6,0xd4,0xf1,0x10,0x1a,0xff,0xe7,0xce,0xb2,0x8e,0x81,0x81,0x81,0x81,\r\n\t0x86,0xa7,0xc3,0xe1,0xff,0x1d,0x0a,0x1f,0x07,0xe8,0xca,0xac,0x8d,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa0,0xca,0xf5,0x1f,0x23,0xfa,0xd0,0xf2,0x1c,0x25,0xfc,0xd2,0xa8,0x81,\r\n\t0x81,0x81,0x81,0x87,0xac,0xc8,0xe1,0xfb,0x14,0x18,0xf9,0xdb,0xbd,0x9f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xb4,0xd2,0xf0,0x0f,0x1d,0x04,\r\n\t0xe9,0xd0,0xb4,0x91,0x81,0x81,0x81,0x81,0x82,0xa3,0xc1,0xdf,0xfc,0x1c,0x0c,0x1f,\r\n\t0x07,0xe8,0xca,0xac,0x8d,0x81,0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1c,0x25,0xfc,\r\n\t0xd2,0xef,0x19,0x27,0xff,0xd5,0xab,0x81,0x81,0x81,0x81,0x9c,0xc1,0xd9,0xe2,0xff,\r\n\t0x22,0x12,0x06,0x0e,0x16,0xff,0xd5,0xab,0x81,0x81,0x81,0x81,0x84,0xad,0xd5,0xf9,\r\n\t0x1a,0x12,0x14,0x1d,0x07,0xfc,0x12,0x0b,0xe2,0xb8,0x8d,0x81,0x81,0x81,0x85,0xa9,\r\n\t0xc8,0xe1,0xfa,0x14,0x18,0xf9,0xdb,0xbd,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x97,0xb6,0xd4,0xf1,0x10,0x1a,0xff,0xe7,0xce,0xb2,0x8e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x84,0xa5,0xc3,0xe1,0xff,0x1d,0x0a,0x1f,0x07,0xe8,0xca,\r\n\t0xac,0x8d,0x81,0x81,0x81,0x81,0x81,0x84,0xad,0xd5,0xf9,0x1a,0x0f,0x12,0x20,0x0b,\r\n\t0xff,0x13,0x0b,0xe4,0xba,0x90,0x81,0x81,0x81,0x81,0x81,0x9d,0xc8,0xf2,0x1c,0x25,\r\n\t0xfc,0xd2,0xef,0x19,0x27,0xff,0xd5,0xab,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x8e,0xb4,0xd9,0xfc,0x22,0x15,0xf0,0xcb,0xa6,0x93,0x97,0xbb,\r\n\t0xe1,0x07,0x2b,0x07,0xe2,0xbd,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc8,0xc8,\r\n\t0xc5,0xbf,0xb4,0xa4,0x8f,0x81,0x81,0x81,0x81,0x88,0xb1,0xd8,0xff,0x23,0x0a,0xed,\r\n\t0xe1,0xe2,0xf5,0x19,0x17,0xee,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,0x8d,0xa6,0xc0,\r\n\t0xd9,0xf3,0x0d,0x16,0xf7,0xd9,0xb4,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x83,0xac,0xd3,0xf1,0x10,0x12,0xf7,0xdf,0xc5,0xac,0x92,0x81,0x81,0x81,0x81,\r\n\t0x81,0x95,0xbd,0xe1,0xff,0x1b,0x04,0xe8,0xff,0x1b,0x05,0xe6,0xc5,0x9d,0x81,0x81,\r\n\t0x81,0x81,0x83,0xad,0xd4,0xf3,0x07,0xe8,0xec,0x04,0x14,0x18,0x0a,0xee,0xce,0xab,\r\n\t0x84,0x81,0x81,0x81,0x81,0x9d,0xc6,0xed,0x0f,0x10,0xf1,0xcb,0xeb,0x0d,0x12,0xf4,\r\n\t0xcd,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x91,0xba,0xe3,0x0b,0x09,0xf2,0x04,0x12,\r\n\t0xeb,0xc2,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0x90,0x98,0x9b,0x9a,0x92,0x85,\r\n\t0x94,0x9b,0x9b,0x94,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,\r\n\t0x95,0x98,0x98,0x95,0x8e,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa6,0xc0,0xd9,\r\n\t0xf3,0x0d,0x18,0xf9,0xdb,0xb6,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x83,0xac,0xd3,0xf1,0x10,0x12,0xf9,0xdf,0xc6,0xac,0x93,0x81,0x81,0x81,0x81,0x81,\r\n\t0x98,0xc0,0xe3,0xff,0x1b,0x04,0xe8,0xff,0x1a,0x07,0xe8,0xc7,0x9f,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9d,0xc6,0xed,0x0f,0x10,0xf1,0xcb,0xeb,0x0d,0x12,0xf4,0xcd,0xa5,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8d,0xa6,0xc0,0xd9,0xf3,0x0d,0x18,0xf9,0xdb,0xb6,0x8d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x93,0xa9,0xd0,0xf0,0x0f,0x14,0xfb,0xe1,\r\n\t0xc8,0xae,0x94,0x81,0x81,0x81,0x81,0x81,0x92,0xbb,0xdf,0xfc,0x1b,0x06,0xea,0xff,\r\n\t0x1a,0x07,0xe8,0xc7,0x9f,0x81,0x81,0x81,0x81,0x81,0x9b,0xc3,0xeb,0x0d,0x12,0xf4,\r\n\t0xcd,0xe8,0x0b,0x13,0xf6,0xd0,0xa8,0x81,0x81,0x81,0x81,0xa5,0xd0,0xfa,0x0b,0x14,\r\n\t0x27,0x2e,0x22,0x0f,0x06,0xfc,0xd5,0xaa,0x81,0x81,0x81,0x81,0x84,0xad,0xd5,0xf5,\r\n\t0x09,0xea,0xee,0x05,0x17,0x1a,0x0b,0xf0,0xcf,0xac,0x85,0x81,0x81,0x81,0x81,0x8c,\r\n\t0xa6,0xbf,0xd9,0xf1,0x0d,0x18,0xf9,0xdb,0xb6,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x83,0xac,0xd3,0xf1,0x10,0x12,0xf9,0xdf,0xc6,0xac,0x93,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x95,0xbd,0xe1,0xff,0x1b,0x04,0xe8,0xff,0x1a,0x07,0xe8,\r\n\t0xc7,0x9f,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd4,0xf1,0x07,0xe8,0xec,0x04,0x14,\r\n\t0x18,0x0b,0xf0,0xcf,0xac,0x87,0x81,0x81,0x81,0x81,0x81,0x9b,0xc3,0xeb,0x0d,0x12,\r\n\t0xf4,0xcd,0xe8,0x0b,0x13,0xf6,0xd0,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x9f,0xc4,0xe8,0x0d,0x2a,0x04,0xdf,0xba,0x94,0xab,0xcf,\r\n\t0xf5,0x1a,0x17,0xf1,0xcd,0xa8,0x84,0x81,0x95,0xc0,0xea,0x16,0x19,0xf2,0xf2,0xf2,\r\n\t0xef,0xe7,0xdb,0xc9,0xb2,0x96,0x81,0x81,0x81,0x92,0xbb,0xe5,0x0e,0x1e,0xf5,0xcf,\r\n\t0xb7,0xbb,0xe5,0x11,0x1e,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x9a,0xa9,\r\n\t0xb7,0xd1,0xeb,0xef,0xef,0xde,0xb6,0xa2,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9a,0xa9,0xb5,0xd6,0xef,0xef,0xef,0xd6,0xbd,0xa3,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x97,0xc0,0xe6,0xef,0xef,0xe3,0xc8,0xdf,0xef,0xef,0xec,0xc8,0x9e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x99,0xb8,0xd4,0xe7,0xcc,0xc8,0xde,0xea,0xed,0xe3,0xce,0xb2,0x93,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8e,0xb3,0xd2,0xe7,0xe9,0xd5,0xc5,0xd0,0xe7,0xea,0xd7,\r\n\t0xb9,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x9a,0xac,0xd2,0xf3,0x0d,0x19,0x11,0xf7,\r\n\t0xd8,0xb3,0x8d,0x81,0x81,0x81,0x81,0x81,0x9a,0xab,0xb9,0xc2,0xc5,0xc3,0xba,0xab,\r\n\t0xbc,0xc5,0xc5,0xbd,0xac,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x93,0xa6,0xb4,\r\n\t0xbf,0xc2,0xc2,0xbf,0xb8,0xac,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x9e,0xb7,\r\n\t0xd1,0xea,0xef,0xef,0xe0,0xb8,0x9f,0x89,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x92,0xae,0xd6,0xef,0xef,0xef,0xd7,0xbe,0xa4,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x99,0xc3,0xe8,0xef,0xef,0xe3,0xc8,0xde,0xef,0xef,0xed,0xca,0xa1,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8e,0xb3,0xd2,0xe7,0xe9,0xd5,0xc5,0xd0,0xe7,0xea,0xd7,0xb9,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xb2,0xbd,0xbd,0xd1,0xea,0xef,0xef,0xe0,0xb8,0x8f,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xb2,0xbd,0xbd,0xd4,0xef,0xef,0xef,0xd9,0xc0,\r\n\t0xa6,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xbd,0xe4,0xef,0xef,0xe6,0xca,0xdf,\r\n\t0xef,0xef,0xed,0xca,0xa1,0x81,0x81,0x81,0x81,0x81,0x95,0xb2,0xd0,0xe7,0xea,0xd7,\r\n\t0xbd,0xce,0xe6,0xea,0xd9,0xbb,0x98,0x81,0x81,0x81,0x81,0xa5,0xd0,0xfa,0x13,0x0a,\r\n\t0xff,0x11,0x23,0xff,0xde,0xd5,0xc1,0x9f,0x81,0x81,0x81,0x81,0x85,0xa5,0xb9,0xd7,\r\n\t0xea,0xcd,0xcb,0xe0,0xed,0xef,0xe6,0xd0,0xb4,0x94,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x84,0x9e,0xb7,0xd0,0xea,0xef,0xef,0xe0,0xb8,0xa1,0x8b,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x97,0xae,0xd6,0xef,0xef,0xef,0xd7,0xbe,0xa4,0x8b,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x97,0xc0,0xe6,0xef,0xef,0xe4,0xc8,0xde,0xef,0xef,0xed,\r\n\t0xca,0xa1,0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xb7,0xd4,0xe7,0xcc,0xc8,0xdc,0xea,\r\n\t0xed,0xe4,0xd0,0xb4,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xb1,0xd0,0xe7,0xea,\r\n\t0xd7,0xc5,0xce,0xe6,0xea,0xd9,0xbb,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x8b,0xaf,0xd4,0xf9,0x1e,0x18,0xf3,0xce,0xa9,0xbe,0xe3,\r\n\t0x09,0x27,0x04,0xde,0xb9,0x94,0x81,0x81,0x95,0xc0,0xea,0x16,0x27,0x1e,0x1e,0x1e,\r\n\t0x19,0x11,0x04,0xed,0xd2,0xb3,0x91,0x81,0x81,0x95,0xc0,0xea,0x15,0x19,0xed,0xc4,\r\n\t0xc0,0xd9,0xf5,0x19,0x14,0xed,0xc4,0x9a,0x81,0x81,0x81,0x81,0x81,0x9b,0xbd,0xd2,\r\n\t0xde,0xe7,0xed,0xef,0xef,0xe7,0xdb,0xc7,0xac,0x8e,0x81,0x81,0x81,0x81,0x81,0x9b,\r\n\t0xbd,0xd2,0xde,0xe7,0xed,0xef,0xef,0xe7,0xdb,0xc7,0xac,0x8e,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9b,0xbd,0xd2,0xde,0xe7,0xed,0xef,0xef,0xe7,0xdb,0xc7,0xb0,0x8f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9b,0xbd,0xd2,0xde,0xe7,0xed,0xef,0xef,0xe7,0xdb,0xc7,0xac,0x8e,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9e,0xbf,0xd2,0xde,0xe7,0xed,0xef,0xee,0xe7,0xdb,0xc7,\r\n\t0xac,0x8e,0x81,0x81,0x81,0x81,0x81,0x9b,0xbd,0xd2,0xde,0xe7,0xed,0xef,0xef,0xe7,\r\n\t0xdb,0xc7,0xac,0x8e,0x81,0x81,0x81,0x99,0xbb,0xd2,0xe1,0xec,0xef,0xed,0xe2,0xce,\r\n\t0xe3,0xef,0xef,0xe5,0xd0,0xb2,0x93,0x81,0x81,0x81,0x81,0x81,0x9d,0xb7,0xcc,0xdc,\r\n\t0xe7,0xed,0xed,0xe9,0xe1,0xd3,0xb9,0x94,0x81,0x81,0x81,0x81,0x81,0x9a,0xb5,0xcd,\r\n\t0xdf,0xeb,0xef,0xee,0xe7,0xd8,0xc3,0xaa,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x9a,\r\n\t0xb5,0xcd,0xdf,0xeb,0xef,0xee,0xe7,0xd8,0xc3,0xaa,0x8c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xac,0xc3,0xcd,0xdf,0xeb,0xef,0xee,0xe7,0xd8,0xc4,0xb2,0x91,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9a,0xb5,0xcd,0xdf,0xeb,0xef,0xee,0xe7,0xd8,0xc3,0xaa,0x8c,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa9,0xd0,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xdf,0xbb,0x92,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa9,0xd0,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xdf,0xbb,\r\n\t0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa9,0xd0,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,\r\n\t0xdf,0xc5,0xc4,0xb2,0x91,0x81,0x81,0x81,0x81,0x81,0xa9,0xd0,0xe7,0xe7,0xe7,0xe7,\r\n\t0xe7,0xe7,0xdf,0xc0,0xb4,0x9d,0x81,0x81,0x81,0x81,0x81,0xa4,0xcd,0xee,0xe9,0xe1,\r\n\t0xea,0xf9,0x1b,0x18,0xf4,0xd1,0xac,0x88,0x81,0x81,0x81,0x81,0x97,0xbf,0xe0,0xe5,\r\n\t0xe5,0xd5,0xde,0xeb,0xef,0xed,0xe2,0xce,0xb2,0x94,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9f,0xba,0xd1,0xe1,0xec,0xef,0xef,0xe7,0xda,0xc6,0xae,0x90,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9f,0xba,0xd1,0xe1,0xec,0xef,0xef,0xe7,0xda,0xc6,0xae,0x90,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x88,0xaa,0xc2,0xd1,0xe1,0xec,0xef,0xef,0xe7,0xda,0xc6,\r\n\t0xb2,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xba,0xd1,0xe1,0xec,0xef,0xef,\r\n\t0xe7,0xda,0xc6,0xae,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9f,0xba,0xd1,0xe1,\r\n\t0xec,0xef,0xef,0xe7,0xda,0xc6,0xae,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x9a,0xbf,0xe3,0x09,0x2d,0x07,0xe2,0xbd,0xd2,0xf7,\r\n\t0x1d,0x12,0xee,0xc8,0xa4,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xff,0xff,0xff,\r\n\t0x06,0x15,0x27,0x0f,0xee,0xcb,0xa6,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0xdf,0xfb,0x14,0x1a,0xfc,0xdb,0xb5,0x8f,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xf9,\r\n\t0x07,0x11,0x18,0x1b,0x19,0x11,0xff,0xe8,0xca,0xa7,0x82,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xf9,0x07,0x11,0x18,0x1b,0x19,0x11,0xff,0xe8,0xca,0xa7,0x82,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xf9,0x07,0x11,0x18,0x1b,0x19,0x11,0xff,0xe8,0xca,0xa7,0x82,0x81,\r\n\t0x81,0x81,0x81,0xa8,0xd2,0xf9,0x07,0x11,0x18,0x1b,0x19,0x11,0xff,0xe8,0xca,0xa7,\r\n\t0x82,0x81,0x81,0x81,0x81,0xaa,0xd4,0xfa,0x07,0x11,0x19,0x1b,0x19,0x11,0xff,0xe8,\r\n\t0xca,0xa7,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xf9,0x07,0x11,0x18,0x1b,0x19,0x11,\r\n\t0xff,0xe8,0xca,0xa7,0x82,0x81,0x81,0xa5,0xcf,0xf7,0x09,0x15,0x1b,0x17,0x09,0xee,\r\n\t0x09,0x19,0x19,0x0b,0xee,0xcd,0xa8,0x82,0x81,0x81,0x81,0x9c,0xbb,0xd9,0xf1,0x05,\r\n\t0x11,0x19,0x19,0x13,0x0a,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x95,0xb6,0xd5,0xf0,\r\n\t0x06,0x14,0x1b,0x19,0x0f,0xfc,0xe6,0xc8,0xa7,0x84,0x81,0x81,0x81,0x81,0x95,0xb6,\r\n\t0xd5,0xf0,0x06,0x14,0x1b,0x19,0x0f,0xfc,0xe6,0xc8,0xa7,0x84,0x81,0x81,0x81,0x81,\r\n\t0x95,0xb6,0xd5,0xf0,0x06,0x14,0x1b,0x19,0x0f,0xfc,0xe6,0xc8,0xa7,0x84,0x81,0x81,\r\n\t0x81,0x81,0x95,0xb6,0xd5,0xf0,0x06,0x14,0x1b,0x19,0x0f,0xfc,0xe6,0xc8,0xa7,0x84,\r\n\t0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x13,0x13,0x13,0x13,0x13,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x13,0x13,0x13,0x13,0x13,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x13,0x13,0x13,0x13,0x13,\r\n\t0xea,0xc0,0x9a,0x8e,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x13,0x13,0x13,\r\n\t0x13,0x13,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x9e,0xbd,0xdb,0xf4,0x09,\r\n\t0x14,0x19,0x1d,0x2f,0x0b,0xe6,0xc1,0x9b,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,0x11,\r\n\t0x0b,0xea,0x04,0x14,0x1b,0x17,0x09,0xee,0xcf,0xab,0x85,0x81,0x81,0x81,0x81,0x9d,\r\n\t0xbd,0xdb,0xf5,0x09,0x15,0x1b,0x19,0x11,0xff,0xe8,0xcc,0xac,0x8a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x9d,0xbd,0xdb,0xf5,0x09,0x15,0x1b,0x19,0x11,0xff,0xe8,0xcc,0xac,0x8a,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9d,0xbd,0xdb,0xf5,0x09,0x15,0x1b,0x19,0x11,0xff,0xe8,\r\n\t0xcc,0xac,0x8a,0x81,0x81,0x81,0x81,0x81,0x9d,0xbd,0xdb,0xf5,0x09,0x15,0x1b,0x19,\r\n\t0x11,0xff,0xe8,0xcc,0xac,0x8a,0x81,0x81,0x81,0x81,0x81,0x9d,0xbd,0xdb,0xf5,0x09,\r\n\t0x15,0x1b,0x19,0x11,0xff,0xe8,0xcc,0xac,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x86,0xab,0xcf,0xf4,0x19,0x1b,0xf6,0xd2,0xe6,0x0b,\r\n\t0x22,0xfc,0xd9,0xb4,0x8f,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xd5,0xd5,\r\n\t0xdd,0xf1,0x0f,0x29,0x05,0xde,0xb6,0x8e,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xd8,\r\n\t0xfc,0x1c,0x12,0xf7,0xdf,0xc1,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,\r\n\t0x19,0x0f,0x09,0x06,0x0a,0x19,0x25,0x05,0xe1,0xba,0x92,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfc,0x19,0x0f,0x09,0x06,0x0a,0x19,0x25,0x05,0xe1,0xba,0x92,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfc,0x19,0x0f,0x09,0x06,0x0a,0x19,0x25,0x05,0xe1,0xba,0x92,0x81,\r\n\t0x81,0x81,0x81,0xa8,0xd2,0xfc,0x19,0x0f,0x09,0x06,0x0a,0x19,0x25,0x05,0xe1,0xba,\r\n\t0x92,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0x19,0x0f,0x09,0x06,0x0a,0x19,0x24,0x05,\r\n\t0xe0,0xba,0x92,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x19,0x0f,0x09,0x06,0x0a,0x19,\r\n\t0x25,0x05,0xe1,0xba,0x92,0x81,0x81,0xa5,0xd0,0xfa,0x12,0x06,0xff,0x0a,0x25,0x0b,\r\n\t0x1c,0x04,0x06,0x21,0x07,0xe1,0xba,0x92,0x81,0x81,0x91,0xb5,0xd7,0xf7,0x14,0x26,\r\n\t0x13,0x09,0x09,0x0e,0x19,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x86,0xac,0xd0,0xf1,0x10,\r\n\t0x1d,0x09,0xff,0x04,0x14,0x21,0x04,0xe2,0xbe,0x98,0x81,0x81,0x81,0x86,0xac,0xd0,\r\n\t0xf1,0x10,0x1d,0x09,0xff,0x04,0x14,0x21,0x04,0xe2,0xbe,0x98,0x81,0x81,0x81,0x86,\r\n\t0xac,0xd0,0xf1,0x10,0x1d,0x09,0xff,0x04,0x14,0x21,0x04,0xe2,0xbe,0x98,0x81,0x81,\r\n\t0x81,0x86,0xac,0xd0,0xf1,0x10,0x1d,0x09,0xff,0x04,0x14,0x21,0x04,0xe2,0xbe,0x98,\r\n\t0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x0b,0x0b,0x0b,0x1b,0x16,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x0b,0x0b,0x0b,0x1b,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x0b,0x0b,0x0b,0x1b,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xad,0xd7,0x04,0x0b,0x0b,0x0b,\r\n\t0x1b,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x91,0xb5,0xd9,0xf9,0x17,0x1c,\r\n\t0x0b,0x06,0x09,0x12,0x20,0xfa,0xd4,0xae,0x87,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x0b,0x0b,0x1c,0x0a,0x06,0x13,0x2b,0x0a,0xe3,0xbd,0x94,0x81,0x81,0x81,0x8f,0xb5,\r\n\t0xd9,0xf9,0x18,0x1e,0x0c,0x06,0x09,0x18,0x24,0x09,0xe8,0xc4,0x9f,0x81,0x81,0x81,\r\n\t0x81,0x8f,0xb5,0xd9,0xf9,0x18,0x1e,0x0c,0x06,0x09,0x18,0x24,0x09,0xe8,0xc4,0x9f,\r\n\t0x81,0x81,0x81,0x81,0x8f,0xb5,0xd9,0xf9,0x18,0x1e,0x0c,0x06,0x09,0x18,0x24,0x09,\r\n\t0xe8,0xc4,0x9f,0x81,0x81,0x81,0x81,0x8f,0xb5,0xd9,0xf9,0x18,0x1e,0x0c,0x06,0x09,\r\n\t0x18,0x24,0x09,0xe8,0xc4,0x9f,0x81,0x81,0x81,0x81,0x8f,0xb5,0xd9,0xf9,0x18,0x1e,\r\n\t0x0c,0x06,0x09,0x18,0x24,0x09,0xe8,0xc4,0x9f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x95,0xba,0xdf,0x04,0x29,0x0b,0xe5,0xf9,0x1f,\r\n\t0x0f,0xe9,0xc4,0x9f,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xac,\r\n\t0xb6,0xd3,0xf9,0x21,0x13,0xea,0xc0,0x96,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe6,\r\n\t0x0f,0x1e,0xf6,0xd7,0xbd,0xa3,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfb,\r\n\t0xf1,0xe6,0xdd,0xda,0xe1,0xf7,0x1b,0x18,0xef,0xc6,0x9d,0x81,0x81,0x81,0x81,0xa8,\r\n\t0xd2,0xfb,0xf1,0xe6,0xdd,0xda,0xe1,0xf7,0x1b,0x18,0xef,0xc6,0x9d,0x81,0x81,0x81,\r\n\t0x81,0xa8,0xd2,0xfb,0xf1,0xe6,0xdd,0xda,0xe1,0xf7,0x1b,0x18,0xef,0xc6,0x9d,0x81,\r\n\t0x81,0x81,0x81,0xa8,0xd2,0xfb,0xf1,0xe6,0xdd,0xda,0xe1,0xf7,0x1b,0x18,0xef,0xc6,\r\n\t0x9d,0x81,0x81,0x81,0x81,0xab,0xd5,0xff,0xf1,0xe5,0xdd,0xda,0xe1,0xf7,0x1b,0x18,\r\n\t0xef,0xc6,0x9d,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfb,0xf1,0xe6,0xdd,0xda,0xe1,0xf7,\r\n\t0x1a,0x18,0xef,0xc6,0x9d,0x81,0x81,0xa5,0xcf,0xf7,0xeb,0xdc,0xd5,0xe9,0x11,0x2a,\r\n\t0x04,0xdf,0xe7,0x0e,0x18,0xef,0xc6,0x9c,0x81,0x81,0xa3,0xc9,0xef,0x12,0x22,0x04,\r\n\t0xec,0xdf,0xdf,0xe5,0xf2,0xf1,0xc7,0x9d,0x81,0x81,0x81,0x97,0xbe,0xe5,0x0b,0x20,\r\n\t0xff,0xe3,0xd5,0xdc,0xf1,0x12,0x1d,0xf6,0xcf,0xa7,0x81,0x81,0x81,0x97,0xbe,0xe5,\r\n\t0x0b,0x20,0xff,0xe3,0xd5,0xdc,0xf1,0x12,0x1d,0xf6,0xcf,0xa7,0x81,0x81,0x81,0x97,\r\n\t0xbe,0xe5,0x0b,0x20,0xff,0xe3,0xd5,0xdc,0xf1,0x12,0x1d,0xf6,0xcf,0xa7,0x81,0x81,\r\n\t0x81,0x97,0xbe,0xe5,0x0b,0x20,0xff,0xe3,0xd5,0xdc,0xf1,0x12,0x1d,0xf6,0xcf,0xa7,\r\n\t0x81,0x81,0x81,0x81,0xa7,0xcc,0xdf,0xdf,0xdf,0xed,0x19,0x16,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0xa7,0xcc,0xdf,0xdf,0xdf,0xed,0x19,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa7,0xcc,0xdf,0xdf,0xdf,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa7,0xcc,0xdf,0xdf,0xdf,0xed,\r\n\t0x19,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0xa3,0xc9,0xef,0x14,0x18,0xf9,\r\n\t0xe3,0xda,0xdd,0xfb,0x21,0x0c,0xe6,0xbe,0x96,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x1b,0x18,0xfb,0xe2,0xdc,0xf3,0x18,0x19,0xf1,0xc7,0x9e,0x81,0x81,0x81,0xa1,0xc8,\r\n\t0xee,0x13,0x1c,0xfb,0xe4,0xda,0xe0,0xf3,0x12,0x22,0xfc,0xd6,0xaf,0x87,0x81,0x81,\r\n\t0x81,0xa1,0xc8,0xee,0x13,0x1c,0xfb,0xe4,0xda,0xe0,0xf3,0x12,0x22,0xfc,0xd6,0xaf,\r\n\t0x87,0x81,0x81,0x81,0xa1,0xc8,0xee,0x13,0x1c,0xfb,0xe4,0xda,0xe0,0xf3,0x12,0x22,\r\n\t0xfc,0xd6,0xaf,0x87,0x81,0x81,0x81,0xa1,0xc8,0xee,0x13,0x1c,0xfb,0xe4,0xda,0xe0,\r\n\t0xf3,0x12,0x22,0xfc,0xd6,0xaf,0x87,0x81,0x81,0x81,0xa1,0xc8,0xee,0x13,0x1c,0xfb,\r\n\t0xe4,0xda,0xe0,0xf3,0x12,0x22,0xfc,0xd6,0xaf,0x87,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0xa6,0xcb,0xef,0x14,0x1e,0xf7,0x0c,0x1e,\r\n\t0xf9,0xd4,0xaf,0x8b,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0x9c,0xc6,0xef,0x1b,0x19,0xed,0xc2,0x98,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe7,\r\n\t0x12,0x1c,0xf4,0xd4,0xb9,0xa0,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x9c,0xbf,0xd2,\r\n\t0xc9,0xbd,0xc0,0xc2,0xc2,0xe5,0x0f,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x9c,\r\n\t0xbf,0xd2,0xc9,0xbd,0xc0,0xc2,0xc2,0xe5,0x0f,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0x81,0x9c,0xbf,0xd2,0xc9,0xbd,0xc0,0xc2,0xc2,0xe5,0x0f,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0x81,0x9c,0xbf,0xd2,0xc9,0xbd,0xc0,0xc2,0xc2,0xe5,0x0f,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0x81,0xa0,0xc3,0xd5,0xc9,0xbd,0xc0,0xc2,0xc2,0xe5,0x0f,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x9c,0xbf,0xd2,0xc9,0xbd,0xc0,0xc2,0xc2,0xe4,\r\n\t0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x99,0xbb,0xcf,0xc5,0xbc,0xc0,0xdf,0x09,0x20,\r\n\t0xf5,0xcd,0xda,0x04,0x21,0xf7,0xcd,0xa3,0x81,0x89,0xb2,0xda,0xff,0x28,0x0b,0xe6,\r\n\t0xc8,0xb6,0xb5,0xbc,0xcc,0xd0,0xb7,0x93,0x81,0x81,0x81,0xa4,0xcd,0xf5,0x1d,0x0e,\r\n\t0xe7,0xc3,0xbd,0xbd,0xd8,0xff,0x28,0x04,0xdb,0xb2,0x88,0x81,0x81,0xa4,0xcd,0xf5,\r\n\t0x1d,0x0e,0xe7,0xc3,0xbd,0xbd,0xd8,0xff,0x28,0x04,0xdb,0xb2,0x88,0x81,0x81,0xa4,\r\n\t0xcd,0xf5,0x1d,0x0e,0xe7,0xc3,0xbd,0xbd,0xd8,0xff,0x28,0x04,0xdb,0xb2,0x88,0x81,\r\n\t0x81,0xa4,0xcd,0xf5,0x1d,0x0e,0xe7,0xc3,0xbd,0xbd,0xd8,0xff,0x28,0x04,0xdb,0xb2,\r\n\t0x88,0x81,0x81,0x81,0x90,0xab,0xb5,0xb5,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xab,0xb5,0xb5,0xc2,0xed,0x19,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xab,0xb5,0xb5,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,0xab,0xb5,0xb5,0xc2,0xed,\r\n\t0x19,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x88,0xb1,0xd9,0xff,0x28,0x04,0xde,\r\n\t0xbe,0xb1,0xc3,0xea,0x11,0x1c,0xf4,0xcc,0xa2,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x1d,0xfc,0xdd,0xbf,0xba,0xe3,0x0e,0x21,0xf7,0xcd,0xa3,0x81,0x81,0x85,0xae,0xd6,\r\n\t0xff,0x27,0x06,0xe1,0xc1,0xb1,0xb9,0xd7,0xfc,0x23,0x0d,0xe4,0xbb,0x92,0x81,0x81,\r\n\t0x85,0xae,0xd6,0xff,0x27,0x06,0xe1,0xc1,0xb1,0xb9,0xd7,0xfc,0x23,0x0d,0xe4,0xbb,\r\n\t0x92,0x81,0x81,0x85,0xae,0xd6,0xff,0x27,0x06,0xe1,0xc1,0xb1,0xb9,0xd7,0xfc,0x23,\r\n\t0x0d,0xe4,0xbb,0x92,0x81,0x81,0x85,0xae,0xd6,0xff,0x27,0x06,0xe1,0xc1,0xb1,0xb9,\r\n\t0xd7,0xfc,0x23,0x0d,0xe4,0xbb,0x92,0x81,0x81,0x85,0xae,0xd6,0xff,0x27,0x06,0xe1,\r\n\t0xc1,0xb1,0xb9,0xd7,0xfc,0x23,0x0d,0xe4,0xbb,0x92,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x91,0xb5,0xda,0xff,0x24,0x0b,0x20,0x0a,\r\n\t0xe5,0xc0,0x9b,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,\r\n\t0xa3,0xca,0xf3,0x1e,0x14,0xea,0xc1,0x97,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xdf,\r\n\t0x05,0x27,0x10,0xf3,0xdb,0xc2,0xa5,0x87,0x81,0x81,0x81,0x81,0x81,0x8e,0xac,0xc5,\r\n\t0xd7,0xe4,0xea,0xed,0xed,0xed,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x8e,\r\n\t0xac,0xc5,0xd7,0xe4,0xea,0xed,0xed,0xed,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0x81,0x8e,0xac,0xc5,0xd7,0xe4,0xea,0xed,0xed,0xed,0x0e,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0x81,0x8e,0xac,0xc5,0xd7,0xe4,0xea,0xed,0xed,0xed,0x0e,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0x81,0x8e,0xac,0xc5,0xd7,0xe4,0xea,0xed,0xed,0xed,0x0e,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x81,0x8e,0xac,0xc5,0xd7,0xe4,0xea,0xed,0xed,0xed,\r\n\t0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x8a,0xa9,0xc4,0xd9,0xe5,0xea,0xea,0x09,0x1b,\r\n\t0xef,0xea,0xea,0xff,0x26,0xfa,0xd0,0xa5,0x81,0x91,0xbb,0xe5,0x0e,0x22,0xfa,0xd2,\r\n\t0xac,0x8e,0x8b,0x94,0xa4,0xa7,0x97,0x81,0x81,0x81,0x82,0xac,0xd6,0xff,0x29,0x04,\r\n\t0xe7,0xe7,0xe7,0xe7,0xe7,0xf7,0x21,0x0b,0xe1,0xb7,0x8d,0x81,0x82,0xac,0xd6,0xff,\r\n\t0x29,0x04,0xe7,0xe7,0xe7,0xe7,0xe7,0xf7,0x21,0x0b,0xe1,0xb7,0x8d,0x81,0x82,0xac,\r\n\t0xd6,0xff,0x29,0x04,0xe7,0xe7,0xe7,0xe7,0xe7,0xf7,0x21,0x0b,0xe1,0xb7,0x8d,0x81,\r\n\t0x82,0xac,0xd6,0xff,0x29,0x04,0xe7,0xe7,0xe7,0xe7,0xe7,0xf7,0x21,0x0b,0xe1,0xb7,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x84,0x8b,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8b,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8b,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x8b,0x98,0xc2,0xed,\r\n\t0x19,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x90,0xba,0xe4,0x0e,0x1e,0xf5,0xcc,\r\n\t0xa4,0x8c,0xb4,0xdc,0x06,0x28,0xff,0xd5,0xac,0x82,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xc1,0xa1,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x8d,0xb7,0xe0,\r\n\t0x0b,0x23,0xfa,0xd1,0xa8,0x87,0x9e,0xc6,0xef,0x19,0x16,0xed,0xc2,0x98,0x81,0x81,\r\n\t0x8d,0xb7,0xe0,0x0b,0x23,0xfa,0xd1,0xa8,0x87,0x9e,0xc6,0xef,0x19,0x16,0xed,0xc2,\r\n\t0x98,0x81,0x81,0x8d,0xb7,0xe0,0x0b,0x23,0xfa,0xd1,0xa8,0x87,0x9e,0xc6,0xef,0x19,\r\n\t0x16,0xed,0xc2,0x98,0x81,0x81,0x8d,0xb7,0xe0,0x0b,0x23,0xfa,0xd1,0xa8,0x87,0x9e,\r\n\t0xc6,0xef,0x19,0x16,0xed,0xc2,0x98,0x81,0x81,0x8d,0xb7,0xe0,0x0b,0x23,0xfa,0xd1,\r\n\t0xa8,0x87,0x9e,0xc6,0xef,0x19,0x16,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0xa1,0xc6,0xeb,0x0f,0x31,0x1a,0xf4,\r\n\t0xd0,0xab,0x86,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xbc,\r\n\t0xc6,0xdf,0xff,0x28,0x09,0xe1,0xb8,0x8f,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xcb,\r\n\t0xec,0x0b,0x25,0x16,0xfc,0xe1,0xc3,0xa1,0x81,0x81,0x81,0x81,0x86,0xaa,0xca,0xe8,\r\n\t0xfc,0x0d,0x15,0x19,0x19,0x19,0x1d,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x86,0xaa,\r\n\t0xca,0xe8,0xfc,0x0d,0x15,0x19,0x19,0x19,0x1d,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0x86,0xaa,0xca,0xe8,0xfc,0x0d,0x15,0x19,0x19,0x19,0x1d,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0x86,0xaa,0xca,0xe8,0xfc,0x0d,0x15,0x19,0x19,0x19,0x1d,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0x86,0xaa,0xca,0xe8,0xfc,0x0d,0x15,0x19,0x19,0x19,0x1d,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x86,0xaa,0xca,0xe8,0xfc,0x0d,0x15,0x19,0x19,0x19,\r\n\t0x1d,0x21,0xf5,0xca,0xa0,0x81,0x81,0xa1,0xc5,0xe4,0xff,0x0e,0x16,0x16,0x18,0x23,\r\n\t0x16,0x16,0x16,0x16,0x26,0xfa,0xd0,0xa5,0x81,0x95,0xc0,0xea,0x14,0x1b,0xf1,0xc7,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2f,0x13,\r\n\t0x13,0x13,0x13,0x13,0x13,0x13,0x26,0x0e,0xe2,0xb8,0x8d,0x81,0x85,0xb0,0xda,0x06,\r\n\t0x2f,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x26,0x0e,0xe2,0xb8,0x8d,0x81,0x85,0xb0,\r\n\t0xda,0x06,0x2f,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x26,0x0e,0xe2,0xb8,0x8d,0x81,\r\n\t0x85,0xb0,0xda,0x06,0x2f,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x26,0x0e,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,\r\n\t0x19,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x13,0x19,0xef,0xc5,\r\n\t0x9b,0x81,0xaa,0xd5,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x90,0xba,0xe5,\r\n\t0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,0xbf,0xe7,0x13,0x1b,0xef,0xc5,0x9b,0x81,0x81,\r\n\t0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,0xbf,0xe7,0x13,0x1b,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,0xbf,0xe7,0x13,\r\n\t0x1b,0xef,0xc5,0x9b,0x81,0x81,0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,\r\n\t0xbf,0xe7,0x13,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,\r\n\t0x9f,0x81,0x95,0xbf,0xe7,0x13,0x1b,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfa,0xd0,0xa5,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0x81,0x81,0x81,0x81,0x81,0x8c,0xb1,0xd5,0xfc,0x29,0x09,0xe0,\r\n\t0xbb,0x96,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe5,0xe6,\r\n\t0xee,0xff,0x1a,0x18,0xf5,0xd1,0xaa,0x83,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0xce,0xea,0x04,0x1d,0x1d,0xff,0xdc,0xb6,0x90,0x81,0x81,0x81,0x99,0xbf,0xe5,0x07,\r\n\t0x22,0x13,0x05,0xff,0xff,0xff,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x99,0xbf,\r\n\t0xe5,0x07,0x22,0x13,0x05,0xff,0xff,0xff,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0x99,0xbf,0xe5,0x07,0x22,0x13,0x05,0xff,0xff,0xff,0x0e,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0x99,0xbf,0xe5,0x07,0x22,0x13,0x05,0xff,0xff,0xff,0x0e,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0x99,0xbf,0xe5,0x07,0x22,0x13,0x05,0xff,0xff,0xff,0x0e,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x99,0xbf,0xe5,0x07,0x22,0x13,0x05,0xff,0xff,0xff,\r\n\t0x0e,0x21,0xf5,0xca,0xa0,0x81,0x8a,0xb2,0xda,0xff,0x21,0x0f,0xff,0xff,0x09,0x1b,\r\n\t0xff,0xff,0xff,0xff,0xff,0xfa,0xd0,0xa5,0x81,0x95,0xc0,0xea,0x16,0x1b,0xef,0xc6,\r\n\t0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xb0,0xda,0x06,0x2c,0x06,\r\n\t0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0xe2,0xb8,0x8d,0x81,0x85,0xb0,0xda,0x06,\r\n\t0x2c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0xe2,0xb8,0x8d,0x81,0x85,0xb0,\r\n\t0xda,0x06,0x2c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0xe2,0xb8,0x8d,0x81,\r\n\t0x85,0xb0,0xda,0x06,0x2c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0xe2,0xb8,\r\n\t0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,\r\n\t0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xc2,0xed,\r\n\t0x19,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc3,\r\n\t0x99,0x81,0xaa,0xd3,0xfc,0x29,0x06,0xda,0xb0,0x85,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x90,0xba,0xe5,\r\n\t0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,0xbf,0xe8,0x13,0x19,0xef,0xc5,0x9b,0x81,0x81,\r\n\t0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,0xbf,0xe8,0x13,0x19,0xef,0xc5,\r\n\t0x9b,0x81,0x81,0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,0xbf,0xe8,0x13,\r\n\t0x19,0xef,0xc5,0x9b,0x81,0x81,0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,0x9f,0x81,0x95,\r\n\t0xbf,0xe8,0x13,0x19,0xef,0xc5,0x9b,0x81,0x81,0x90,0xba,0xe5,0x11,0x1e,0xf2,0xc9,\r\n\t0x9f,0x81,0x95,0xbf,0xe8,0x13,0x19,0xef,0xc5,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x88,0xb2,0xdd,0x09,0x26,0xfc,0xd2,0xa9,0x89,0xa0,0xc9,0xf2,0x1e,0x11,0xe5,\r\n\t0xbc,0x92,0x81,0x88,0xb2,0xdd,0x09,0x26,0xfc,0xd2,0xa9,0x89,0xa0,0xc9,0xf2,0x1e,\r\n\t0x11,0xe5,0xbc,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0x11,0x11,0x11,\r\n\t0x16,0x25,0x13,0xf9,0xdb,0xba,0x97,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0xae,0xc8,0xe1,0xfc,0x1e,0x15,0xee,0xc6,0x9c,0x81,0x81,0x81,0xa4,0xcd,0xf6,0x1e,\r\n\t0x14,0xf1,0xdc,0xd5,0xd5,0xe2,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa4,0xcd,\r\n\t0xf6,0x1e,0x14,0xf1,0xdc,0xd5,0xd5,0xe2,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0xa4,0xcd,0xf6,0x1e,0x14,0xf1,0xdc,0xd5,0xd5,0xe2,0x0e,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0xa4,0xcd,0xf6,0x1e,0x14,0xf1,0xdc,0xd5,0xd5,0xe2,0x0e,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0xa4,0xcd,0xf6,0x1e,0x14,0xf1,0xdc,0xd5,0xd5,0xe2,0x0e,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0xa4,0xcd,0xf6,0x1e,0x14,0xf1,0xdc,0xd5,0xd5,0xe2,\r\n\t0x0e,0x21,0xf5,0xca,0xa0,0x81,0x92,0xbc,0xe6,0x0f,0x19,0xf3,0xd7,0xdd,0x09,0x1c,\r\n\t0xf2,0xd5,0xd5,0xd5,0xd5,0xd4,0xbf,0x9b,0x81,0x93,0xbd,0xe7,0x11,0x20,0xf6,0xcd,\r\n\t0xa6,0x8b,0x8a,0x94,0xa4,0xa6,0x96,0x81,0x81,0x81,0x83,0xad,0xd7,0xff,0x2b,0x04,\r\n\t0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xd0,0xae,0x87,0x81,0x83,0xad,0xd7,0xff,\r\n\t0x2b,0x04,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xd0,0xae,0x87,0x81,0x83,0xad,\r\n\t0xd7,0xff,0x2b,0x04,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xd0,0xae,0x87,0x81,\r\n\t0x83,0xad,0xd7,0xff,0x2b,0x04,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xd0,0xae,\r\n\t0x87,0x81,0x81,0x81,0x81,0x8b,0x8d,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,0x95,0x8d,\r\n\t0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x8d,0x98,0xc2,0xed,0x19,0x16,0xea,0xc0,\r\n\t0x95,0x8d,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x8d,0x98,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0x95,0x8d,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x8b,0x8d,0x98,0xc2,0xed,\r\n\t0x19,0x16,0xea,0xc0,0x95,0x8d,0x85,0x81,0x81,0x93,0xbd,0xe7,0x11,0x1d,0xf3,0xca,\r\n\t0xa2,0x89,0xb1,0xda,0x04,0x29,0xff,0xd6,0xac,0x82,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x8d,0xb8,0xe2,\r\n\t0x0b,0x23,0xf9,0xd0,0xa7,0x87,0x9f,0xc6,0xef,0x19,0x13,0xea,0xc1,0x97,0x81,0x81,\r\n\t0x8d,0xb8,0xe2,0x0b,0x23,0xf9,0xd0,0xa7,0x87,0x9f,0xc6,0xef,0x19,0x13,0xea,0xc1,\r\n\t0x97,0x81,0x81,0x8d,0xb8,0xe2,0x0b,0x23,0xf9,0xd0,0xa7,0x87,0x9f,0xc6,0xef,0x19,\r\n\t0x13,0xea,0xc1,0x97,0x81,0x81,0x8d,0xb8,0xe2,0x0b,0x23,0xf9,0xd0,0xa7,0x87,0x9f,\r\n\t0xc6,0xef,0x19,0x13,0xea,0xc1,0x97,0x81,0x81,0x8d,0xb8,0xe2,0x0b,0x23,0xf9,0xd0,\r\n\t0xa7,0x87,0x9f,0xc6,0xef,0x19,0x13,0xea,0xc1,0x97,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x84,0xae,0xd7,0xff,0x2a,0x05,0xde,0xbd,0xb2,0xb9,0xd7,0xfc,0x25,0x07,0xdf,\r\n\t0xb5,0x8c,0x81,0x84,0xae,0xd7,0xff,0x2a,0x05,0xde,0xbd,0xb2,0xb9,0xd7,0xfc,0x25,\r\n\t0x07,0xdf,0xb5,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x1e,0x11,0x11,0x11,\r\n\t0x0b,0xff,0xee,0xd9,0xbd,0x9f,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,\r\n\t0xba,0xb2,0xc1,0xe5,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,\r\n\t0x0b,0xe0,0xb7,0xba,0xd0,0xea,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa8,0xd2,\r\n\t0xfc,0x29,0x0b,0xe0,0xb7,0xba,0xd0,0xea,0x0e,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0xa8,0xd2,0xfc,0x29,0x0b,0xe0,0xb7,0xba,0xd0,0xea,0x0e,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0xa8,0xd2,0xfc,0x29,0x0b,0xe0,0xb7,0xba,0xd0,0xea,0x0e,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x0b,0xe0,0xb7,0xba,0xd0,0xea,0x0e,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x0b,0xe0,0xb7,0xba,0xd0,0xe9,\r\n\t0x0e,0x21,0xf5,0xca,0xa0,0x81,0x95,0xc0,0xea,0x16,0x13,0xe7,0xc0,0xe2,0x09,0x23,\r\n\t0xf9,0xd1,0xb0,0xb6,0xc2,0xc1,0xa8,0x86,0x81,0x8d,0xb6,0xdf,0x07,0x2b,0x05,0xe0,\r\n\t0xc3,0xb5,0xb5,0xbc,0xcc,0xcf,0xb5,0x92,0x81,0x81,0x81,0xa6,0xcf,0xf7,0x21,0x0f,\r\n\t0xe8,0xc8,0xb5,0xb0,0xb2,0xb8,0xc1,0xc3,0xae,0x94,0x81,0x81,0x81,0xa6,0xcf,0xf7,\r\n\t0x21,0x0f,0xe8,0xc8,0xb5,0xb0,0xb2,0xb8,0xc1,0xc3,0xae,0x94,0x81,0x81,0x81,0xa6,\r\n\t0xcf,0xf7,0x21,0x0f,0xe8,0xc8,0xb5,0xb0,0xb2,0xb8,0xc1,0xc3,0xae,0x94,0x81,0x81,\r\n\t0x81,0xa6,0xcf,0xf7,0x21,0x0f,0xe8,0xc8,0xb5,0xb0,0xb2,0xb8,0xc1,0xc3,0xae,0x94,\r\n\t0x81,0x81,0x81,0x81,0x9d,0xb4,0xb8,0xb8,0xc2,0xed,0x19,0x16,0xea,0xc0,0xb8,0xb8,\r\n\t0xac,0x90,0x81,0x81,0x81,0x81,0x9d,0xb4,0xb8,0xb8,0xc2,0xed,0x19,0x16,0xea,0xc0,\r\n\t0xb8,0xb8,0xac,0x90,0x81,0x81,0x81,0x81,0x9d,0xb4,0xb8,0xb8,0xc2,0xed,0x19,0x16,\r\n\t0xea,0xc0,0xb8,0xb8,0xac,0x90,0x81,0x81,0x81,0x81,0x9d,0xb4,0xb8,0xb8,0xc2,0xed,\r\n\t0x19,0x16,0xea,0xc0,0xb8,0xb8,0xac,0x90,0x81,0x8d,0xb6,0xdf,0x09,0x28,0xff,0xdb,\r\n\t0xbb,0xb1,0xc5,0xe7,0x0f,0x1e,0xf5,0xcd,0xa4,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x87,0xb1,0xda,\r\n\t0x04,0x2a,0x06,0xe0,0xbf,0xb1,0xba,0xd9,0xfc,0x24,0x09,0xe0,0xb8,0x8f,0x81,0x81,\r\n\t0x87,0xb1,0xda,0x04,0x2a,0x06,0xe0,0xbf,0xb1,0xba,0xd9,0xfc,0x24,0x09,0xe0,0xb8,\r\n\t0x8f,0x81,0x81,0x87,0xb1,0xda,0x04,0x2a,0x06,0xe0,0xbf,0xb1,0xba,0xd9,0xfc,0x24,\r\n\t0x09,0xe0,0xb8,0x8f,0x81,0x81,0x87,0xb1,0xda,0x04,0x2a,0x06,0xe0,0xbf,0xb1,0xba,\r\n\t0xd9,0xfc,0x24,0x09,0xe0,0xb8,0x8f,0x81,0x81,0x87,0xb1,0xda,0x04,0x2a,0x06,0xe0,\r\n\t0xbf,0xb1,0xba,0xd9,0xfc,0x24,0x09,0xe0,0xb8,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa4,0xcd,0xf5,0x1b,0x18,0xf7,0xe3,0xdd,0xe2,0xf3,0x12,0x1d,0xf7,0xd2,\r\n\t0xa9,0x81,0x81,0x81,0xa4,0xcd,0xf5,0x1b,0x18,0xf7,0xe3,0xdd,0xe2,0xf3,0x12,0x1d,\r\n\t0xf7,0xd2,0xa9,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xe5,0xe5,\r\n\t0xe1,0xd7,0xc8,0xb5,0x9e,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xdf,\r\n\t0xe2,0xdd,0xdf,0xf0,0x13,0x19,0xf1,0xc7,0x9e,0x81,0x81,0x81,0xa7,0xd1,0xfa,0x24,\r\n\t0x11,0xec,0xdb,0xe1,0xf3,0x0b,0x24,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0xa7,0xd1,\r\n\t0xfa,0x24,0x11,0xec,0xdb,0xe1,0xf3,0x0b,0x24,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0xa7,0xd1,0xfa,0x24,0x11,0xec,0xdb,0xe1,0xf3,0x0b,0x24,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0xa7,0xd1,0xfa,0x24,0x11,0xec,0xdb,0xe1,0xf3,0x0b,0x24,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0xa7,0xd1,0xfa,0x24,0x11,0xec,0xdb,0xe1,0xf3,0x0b,0x24,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0xa7,0xd1,0xfa,0x24,0x11,0xec,0xdb,0xe1,0xf3,0x0b,\r\n\t0x24,0x21,0xf5,0xca,0xa0,0x81,0x95,0xbf,0xe9,0x13,0x16,0xed,0xe0,0xfb,0x1c,0x21,\r\n\t0x09,0xe8,0xda,0xdf,0xe9,0xe4,0xbd,0x94,0x81,0x81,0xa9,0xd1,0xf6,0x1c,0x1c,0xff,\r\n\t0xe9,0xdf,0xde,0xe5,0xf1,0xf1,0xc7,0x9d,0x81,0x81,0x81,0x9b,0xc3,0xe9,0x0f,0x23,\r\n\t0x04,0xeb,0xde,0xda,0xdd,0xe2,0xea,0xea,0xc5,0x9c,0x81,0x81,0x81,0x9b,0xc3,0xe9,\r\n\t0x0f,0x23,0x04,0xeb,0xde,0xda,0xdd,0xe2,0xea,0xea,0xc5,0x9c,0x81,0x81,0x81,0x9b,\r\n\t0xc3,0xe9,0x0f,0x23,0x04,0xeb,0xde,0xda,0xdd,0xe2,0xea,0xea,0xc5,0x9c,0x81,0x81,\r\n\t0x81,0x9b,0xc3,0xe9,0x0f,0x23,0x04,0xeb,0xde,0xda,0xdd,0xe2,0xea,0xea,0xc5,0x9c,\r\n\t0x81,0x81,0x81,0x8f,0xb6,0xd9,0xe2,0xe2,0xe2,0xed,0x19,0x16,0xea,0xe2,0xe2,0xe2,\r\n\t0xcb,0xa5,0x81,0x81,0x81,0x8f,0xb6,0xd9,0xe2,0xe2,0xe2,0xed,0x19,0x16,0xea,0xe2,\r\n\t0xe2,0xe2,0xcb,0xa5,0x81,0x81,0x81,0x8f,0xb6,0xd9,0xe2,0xe2,0xe2,0xed,0x19,0x16,\r\n\t0xea,0xe2,0xe2,0xe2,0xcb,0xa5,0x81,0x81,0x81,0x8f,0xb6,0xd9,0xe2,0xe2,0xe2,0xed,\r\n\t0x19,0x16,0xea,0xe2,0xe2,0xe2,0xcb,0xa5,0x81,0x82,0xaa,0xd2,0xf9,0x1e,0x16,0xf5,\r\n\t0xe1,0xda,0xe6,0xff,0x22,0x0c,0xe6,0xc0,0x98,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0xa4,0xcc,\r\n\t0xf3,0x18,0x1a,0xfb,0xe3,0xda,0xe0,0xf5,0x14,0x1a,0xf6,0xd1,0xaa,0x82,0x81,0x81,\r\n\t0x81,0xa4,0xcc,0xf3,0x18,0x1a,0xfb,0xe3,0xda,0xe0,0xf5,0x14,0x1a,0xf6,0xd1,0xaa,\r\n\t0x82,0x81,0x81,0x81,0xa4,0xcc,0xf3,0x18,0x1a,0xfb,0xe3,0xda,0xe0,0xf5,0x14,0x1a,\r\n\t0xf6,0xd1,0xaa,0x82,0x81,0x81,0x81,0xa4,0xcc,0xf3,0x18,0x1a,0xfb,0xe3,0xda,0xe0,\r\n\t0xf5,0x14,0x1a,0xf6,0xd1,0xaa,0x82,0x81,0x81,0x81,0xa4,0xcc,0xf3,0x18,0x1a,0xfb,\r\n\t0xe3,0xda,0xe0,0xf5,0x14,0x1a,0xf6,0xd1,0xaa,0x82,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x97,0xbc,0xe1,0x04,0x20,0x1b,0x0d,0x09,0x0b,0x18,0x1f,0x04,0xe2,0xbf,\r\n\t0x99,0x81,0x81,0x81,0x97,0xbc,0xe1,0x04,0x20,0x1b,0x0d,0x09,0x0b,0x18,0x1f,0x04,\r\n\t0xe2,0xbf,0x99,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x29,0x09,0xdd,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xc2,0xba,\r\n\t0xb7,0xaf,0xa2,0x8f,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xea,\r\n\t0x0b,0x09,0x0b,0x14,0x22,0x05,0xe1,0xbb,0x94,0x81,0x81,0x81,0x9f,0xc7,0xed,0x12,\r\n\t0x29,0x0f,0x06,0x0b,0x19,0x12,0x06,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,0x9f,0xc7,\r\n\t0xed,0x12,0x29,0x0f,0x06,0x0b,0x19,0x12,0x06,0x21,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0x9f,0xc7,0xed,0x12,0x29,0x0f,0x06,0x0b,0x19,0x12,0x06,0x21,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0x9f,0xc7,0xed,0x12,0x29,0x0f,0x06,0x0b,0x19,0x12,0x06,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0x9f,0xc7,0xed,0x12,0x29,0x0f,0x06,0x0b,0x19,0x12,0x06,0x21,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x9f,0xc7,0xed,0x12,0x29,0x0f,0x06,0x0b,0x19,0x12,\r\n\t0x06,0x21,0xf5,0xca,0xa0,0x81,0x8f,0xb8,0xe1,0x09,0x27,0x0b,0x09,0x1b,0x04,0x0d,\r\n\t0x23,0x0d,0x06,0x09,0x12,0xea,0xc0,0x95,0x81,0x81,0x98,0xbe,0xe1,0xff,0x1d,0x21,\r\n\t0x11,0x09,0x09,0x0e,0x19,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x8b,0xb1,0xd5,0xf7,0x15,\r\n\t0x25,0x12,0x09,0x06,0x09,0x0b,0x13,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x8b,0xb1,0xd5,\r\n\t0xf7,0x15,0x25,0x12,0x09,0x06,0x09,0x0b,0x13,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x8b,\r\n\t0xb1,0xd5,0xf7,0x15,0x25,0x12,0x09,0x06,0x09,0x0b,0x13,0xf2,0xc8,0x9d,0x81,0x81,\r\n\t0x81,0x8b,0xb1,0xd5,0xf7,0x16,0x25,0x12,0x09,0x06,0x09,0x0b,0x13,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x81,0x93,0xbd,0xe7,0x0e,0x0e,0x0e,0x0e,0x1d,0x1a,0x0e,0x0e,0x0e,0xff,\r\n\t0xd5,0xab,0x81,0x81,0x81,0x93,0xbd,0xe7,0x0e,0x0e,0x0e,0x0e,0x1d,0x1a,0x0e,0x0e,\r\n\t0x0e,0xff,0xd5,0xab,0x81,0x81,0x81,0x93,0xbd,0xe7,0x0e,0x0e,0x0e,0x0e,0x1d,0x1a,\r\n\t0x0e,0x0e,0x0e,0xff,0xd5,0xab,0x81,0x81,0x81,0x93,0xbd,0xe7,0x0e,0x0e,0x0e,0x0e,\r\n\t0x1d,0x1a,0x0e,0x0e,0x0e,0xff,0xd5,0xab,0x81,0x81,0x9a,0xc0,0xe3,0x05,0x21,0x19,\r\n\t0x09,0x06,0x0d,0x20,0x12,0xf3,0xd2,0xad,0x87,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x94,0xba,\r\n\t0xde,0xff,0x1c,0x1d,0x0b,0x06,0x09,0x18,0x1c,0xff,0xdf,0xbd,0x98,0x81,0x81,0x81,\r\n\t0x81,0x94,0xba,0xde,0xff,0x1c,0x1d,0x0b,0x06,0x09,0x18,0x1c,0xff,0xdf,0xbd,0x98,\r\n\t0x81,0x81,0x81,0x81,0x94,0xba,0xde,0xff,0x1c,0x1d,0x0b,0x06,0x09,0x18,0x1c,0xff,\r\n\t0xdf,0xbd,0x98,0x81,0x81,0x81,0x81,0x94,0xba,0xde,0xff,0x1c,0x1d,0x0b,0x06,0x09,\r\n\t0x18,0x1c,0xff,0xdf,0xbd,0x98,0x81,0x81,0x81,0x81,0x94,0xba,0xde,0xff,0x1c,0x1d,\r\n\t0x0b,0x06,0x09,0x18,0x1c,0xff,0xdf,0xbd,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x83,0xa7,0xc7,0xe4,0xfc,0x0d,0x16,0x19,0x16,0x0c,0xfb,0xe3,0xc7,0xa7,\r\n\t0x84,0x81,0x81,0x81,0x83,0xa7,0xc7,0xe4,0xfc,0x0d,0x16,0x19,0x16,0x0c,0xfb,0xe3,\r\n\t0xc7,0xa7,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa8,0xd2,0xfc,0x11,0x09,0xdd,\r\n\t0xb2,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0xed,0xc2,0x98,\r\n\t0x8d,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x11,0x11,0xed,0xea,\r\n\t0x11,0x16,0x14,0x0e,0xfc,0xe6,0xc9,0xa7,0x82,0x81,0x81,0x81,0x8e,0xb4,0xd7,0xf4,\r\n\t0x0a,0x16,0x19,0x12,0x05,0xf0,0x06,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,0x8e,0xb4,\r\n\t0xd7,0xf4,0x0a,0x16,0x19,0x12,0x05,0xf0,0x06,0x11,0xf5,0xca,0xa0,0x81,0x81,0x81,\r\n\t0x8e,0xb4,0xd7,0xf4,0x0a,0x16,0x19,0x12,0x05,0xf0,0x06,0x11,0xf5,0xca,0xa0,0x81,\r\n\t0x81,0x81,0x8e,0xb4,0xd7,0xf4,0x0a,0x16,0x19,0x12,0x05,0xf0,0x06,0x11,0xf5,0xca,\r\n\t0xa0,0x81,0x81,0x81,0x8e,0xb4,0xd7,0xf4,0x0a,0x16,0x19,0x12,0x05,0xf0,0x06,0x11,\r\n\t0xf5,0xca,0xa0,0x81,0x81,0x81,0x8e,0xb4,0xd7,0xf4,0x0a,0x16,0x19,0x12,0x05,0xf0,\r\n\t0x06,0x11,0xf5,0xca,0xa0,0x81,0x82,0xaa,0xce,0xf0,0x0b,0x17,0x14,0xff,0xe6,0xf1,\r\n\t0x0a,0x16,0x19,0x13,0x09,0xea,0xc0,0x95,0x81,0x81,0x83,0xa6,0xc5,0xe1,0xf9,0x0a,\r\n\t0x18,0x23,0x19,0x12,0x09,0xf1,0xc7,0x9d,0x81,0x81,0x81,0x81,0x9b,0xbb,0xd9,0xf3,\r\n\t0x06,0x11,0x18,0x19,0x16,0x11,0x09,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,0x9b,0xbb,\r\n\t0xd9,0xf3,0x06,0x11,0x18,0x19,0x16,0x11,0x09,0xf2,0xc8,0x9d,0x81,0x81,0x81,0x81,\r\n\t0x9b,0xbb,0xd9,0xf3,0x06,0x11,0x18,0x19,0x16,0x11,0x09,0xf2,0xc8,0x9d,0x81,0x81,\r\n\t0x81,0x81,0x9b,0xbb,0xd9,0xf3,0x06,0x11,0x18,0x19,0x16,0x11,0x09,0xf2,0xc8,0x9d,\r\n\t0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0xff,\r\n\t0xd5,0xab,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0xff,0xd5,0xab,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0xff,0xd5,0xab,0x81,0x81,0x81,0x93,0xbd,0xe7,0x11,0x11,0x11,0x11,\r\n\t0x11,0x11,0x11,0x11,0x11,0xff,0xd5,0xab,0x81,0x81,0x86,0xa8,0xc8,0xe6,0xfc,0x0e,\r\n\t0x16,0x19,0x13,0x06,0xf1,0xd7,0xb8,0x97,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,0x11,\r\n\t0x11,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x11,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0xa2,\r\n\t0xc3,0xe1,0xf9,0x0b,0x15,0x19,0x15,0x0b,0xf7,0xe0,0xc3,0xa4,0x82,0x81,0x81,0x81,\r\n\t0x81,0x81,0xa2,0xc3,0xe1,0xf9,0x0b,0x15,0x19,0x15,0x0b,0xf7,0xe0,0xc3,0xa4,0x82,\r\n\t0x81,0x81,0x81,0x81,0x81,0xa2,0xc3,0xe1,0xf9,0x0b,0x15,0x19,0x15,0x0b,0xf7,0xe0,\r\n\t0xc3,0xa4,0x82,0x81,0x81,0x81,0x81,0x81,0xa2,0xc3,0xe1,0xf9,0x0b,0x15,0x19,0x15,\r\n\t0x0b,0xf7,0xe0,0xc3,0xa4,0x82,0x81,0x81,0x81,0x81,0x81,0xa2,0xc3,0xe1,0xf9,0x0b,\r\n\t0x15,0x19,0x15,0x0b,0xf7,0xe0,0xc3,0xa4,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x8b,0xa9,0xc2,0xd6,0xe4,0xea,0xed,0xea,0xe3,0xd5,0xc1,0xa8,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8b,0xa9,0xc2,0xd6,0xe4,0xea,0xed,0xea,0xe3,0xd5,0xc1,\r\n\t0xa8,0x8b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xcb,0xe4,0xe5,0xe5,0xd3,\r\n\t0xae,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xde,0xbc,0x94,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xba,0xdd,0xe5,0xe5,0xde,0xdd,\r\n\t0xe7,0xea,0xea,0xe4,0xd8,0xc5,0xab,0x8e,0x81,0x81,0x81,0x81,0x81,0x9b,0xb9,0xd1,\r\n\t0xe2,0xeb,0xed,0xe9,0xdd,0xd1,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,0x81,0x9b,\r\n\t0xb9,0xd1,0xe2,0xeb,0xed,0xe9,0xdd,0xd1,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x81,\r\n\t0x81,0x9b,0xb9,0xd1,0xe2,0xeb,0xed,0xe9,0xdd,0xd1,0xe5,0xe5,0xe2,0xc4,0x9c,0x81,\r\n\t0x81,0x81,0x81,0x9b,0xb9,0xd1,0xe2,0xeb,0xed,0xe9,0xdd,0xd1,0xe5,0xe5,0xe2,0xc4,\r\n\t0x9c,0x81,0x81,0x81,0x81,0x9b,0xb9,0xd1,0xe2,0xeb,0xed,0xe9,0xdd,0xd1,0xe5,0xe5,\r\n\t0xe2,0xc4,0x9c,0x81,0x81,0x81,0x81,0x9b,0xb9,0xd1,0xe2,0xeb,0xed,0xe9,0xdd,0xd1,\r\n\t0xe5,0xe5,0xe2,0xc4,0x9c,0x81,0x81,0x94,0xb4,0xd1,0xe4,0xed,0xeb,0xdc,0xc6,0xd0,\r\n\t0xe3,0xed,0xed,0xe8,0xe0,0xd2,0xb4,0x8e,0x81,0x81,0x81,0x89,0xa6,0xbf,0xd3,0xed,\r\n\t0x16,0x12,0xed,0xe7,0xdf,0xd2,0xb7,0x93,0x81,0x81,0x81,0x81,0x81,0x9d,0xb8,0xcd,\r\n\t0xde,0xe7,0xed,0xed,0xea,0xe7,0xdf,0xd5,0xba,0x95,0x81,0x81,0x81,0x81,0x81,0x9d,\r\n\t0xb8,0xcd,0xde,0xe7,0xed,0xed,0xea,0xe7,0xdf,0xd5,0xba,0x95,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9d,0xb8,0xcd,0xde,0xe7,0xed,0xed,0xea,0xe7,0xdf,0xd5,0xba,0x95,0x81,0x81,\r\n\t0x81,0x81,0x81,0x9d,0xb8,0xce,0xde,0xe7,0xed,0xed,0xea,0xe7,0xdf,0xd5,0xba,0x95,\r\n\t0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xcd,0xa6,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xcd,0xa6,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xcd,0xa6,0x81,0x81,0x81,0x8f,0xb8,0xdb,0xe5,0xe5,0xe5,0xe5,\r\n\t0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xcd,0xa6,0x81,0x81,0x81,0x8c,0xaa,0xc3,0xd8,0xe5,\r\n\t0xed,0xed,0xe9,0xde,0xcd,0xb6,0x9b,0x81,0x81,0x81,0x81,0x81,0x97,0xbf,0xe0,0xe5,\r\n\t0xe5,0xdb,0xb8,0x8f,0xb0,0xd5,0xe5,0xe5,0xe3,0xc6,0x9f,0x81,0x81,0x81,0x81,0x87,\r\n\t0xa5,0xbf,0xd3,0xe2,0xea,0xed,0xea,0xe2,0xd3,0xbe,0xa5,0x87,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x87,0xa5,0xbf,0xd3,0xe2,0xea,0xed,0xea,0xe2,0xd3,0xbe,0xa5,0x87,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xbf,0xd3,0xe2,0xea,0xed,0xea,0xe2,0xd3,0xbe,\r\n\t0xa5,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xbf,0xd3,0xe2,0xea,0xed,0xea,\r\n\t0xe2,0xd3,0xbe,0xa5,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xbf,0xd3,0xe2,\r\n\t0xea,0xed,0xea,0xe2,0xd3,0xbe,0xa5,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x88,0x9e,0xaf,0xbb,0xc1,0xc2,0xc1,0xba,0xae,0x9c,0x86,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x9e,0xaf,0xbb,0xc1,0xc2,0xc1,0xba,0xae,0x9c,\r\n\t0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0xac,0xba,0xba,0xba,0xb2,\r\n\t0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb8,0xa3,0x83,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa1,0xb7,0xba,0xba,0xb8,0xb7,\r\n\t0xbd,0xc0,0xc0,0xbb,0xb0,0x9f,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xac,\r\n\t0xba,0xc2,0xc2,0xbf,0xb5,0xb1,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x81,\r\n\t0x97,0xac,0xba,0xc2,0xc2,0xbf,0xb5,0xb1,0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,\r\n\t0x81,0x81,0x97,0xac,0xba,0xc2,0xc2,0xbf,0xb5,0xb1,0xba,0xba,0xb9,0xa8,0x89,0x81,\r\n\t0x81,0x81,0x81,0x81,0x97,0xac,0xba,0xc2,0xc2,0xbf,0xb5,0xb1,0xba,0xba,0xb9,0xa8,\r\n\t0x89,0x81,0x81,0x81,0x81,0x81,0x97,0xac,0xba,0xc2,0xc2,0xbf,0xb5,0xb1,0xba,0xba,\r\n\t0xb9,0xa8,0x89,0x81,0x81,0x81,0x81,0x81,0x97,0xac,0xba,0xc2,0xc2,0xbf,0xb5,0xb1,\r\n\t0xba,0xba,0xb9,0xa8,0x89,0x81,0x81,0x81,0x96,0xac,0xbc,0xc2,0xc2,0xb6,0xa3,0xab,\r\n\t0xbb,0xc2,0xc2,0xbf,0xb7,0xaa,0x97,0x81,0x81,0x81,0x81,0x81,0x84,0xa3,0xcc,0xf5,\r\n\t0x1f,0x06,0xde,0xbf,0xb6,0xaa,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x94,0xa7,\r\n\t0xb5,0xbe,0xc2,0xc2,0xc0,0xbd,0xb6,0xad,0x9c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x94,0xa7,0xb5,0xbe,0xc2,0xc2,0xc0,0xbd,0xb6,0xad,0x9c,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x94,0xa7,0xb5,0xbe,0xc2,0xc2,0xc0,0xbd,0xb6,0xad,0x9c,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x94,0xa7,0xb5,0xbf,0xc2,0xc2,0xc0,0xbd,0xb6,0xad,0x9c,0x81,\r\n\t0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xae,0x92,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xae,0x92,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xae,0x92,0x81,0x81,0x81,0x81,0x9f,0xb6,0xba,0xba,0xba,0xba,\r\n\t0xba,0xba,0xba,0xba,0xba,0xba,0xae,0x92,0x81,0x81,0x81,0x81,0x89,0x9f,0xb0,0xbc,\r\n\t0xc2,0xc2,0xbf,0xb6,0xa7,0x93,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0xa5,0xb8,0xba,\r\n\t0xba,0xb6,0x9f,0x81,0x9a,0xb3,0xba,0xba,0xba,0xa9,0x8b,0x81,0x81,0x81,0x81,0x81,\r\n\t0x84,0x9a,0xad,0xb9,0xc1,0xc2,0xc1,0xb9,0xac,0x9a,0x83,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x84,0x9a,0xad,0xb9,0xc1,0xc2,0xc1,0xb9,0xac,0x9a,0x83,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x9a,0xad,0xb9,0xc1,0xc2,0xc1,0xb9,0xac,0x9a,\r\n\t0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x9a,0xad,0xb9,0xc1,0xc2,0xc1,\r\n\t0xb9,0xac,0x9a,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x9a,0xad,0xb9,\r\n\t0xc1,0xc2,0xc1,0xb9,0xac,0x9a,0x83,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x91,0x97,0x98,0x97,0x91,0x86,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x91,0x97,0x98,0x97,0x91,0x86,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0x90,0x90,0x90,0x8b,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x90,0x90,0x8e,0x8e,\r\n\t0x93,0x95,0x95,0x91,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,\r\n\t0x91,0x98,0x98,0x95,0x8d,0x8a,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x84,0x91,0x98,0x98,0x95,0x8d,0x8a,0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x84,0x91,0x98,0x98,0x95,0x8d,0x8a,0x90,0x90,0x8f,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x84,0x91,0x98,0x98,0x95,0x8d,0x8a,0x90,0x90,0x8f,0x84,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x91,0x98,0x98,0x95,0x8d,0x8a,0x90,0x90,\r\n\t0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0x91,0x98,0x98,0x95,0x8d,0x8a,\r\n\t0x90,0x90,0x8f,0x84,0x81,0x81,0x81,0x81,0x81,0x86,0x93,0x98,0x98,0x8f,0x81,0x85,\r\n\t0x92,0x98,0x98,0x95,0x8e,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x83,0xac,0xd6,0xff,\r\n\t0x23,0xfa,0xd2,0xa9,0x8d,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8d,0x94,0x98,0x98,0x97,0x92,0x8c,0x84,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x8d,0x94,0x98,0x98,0x97,0x92,0x8c,0x84,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8d,0x94,0x98,0x98,0x97,0x92,0x8c,0x84,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x95,0x98,0x98,0x97,0x92,0x8c,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0x90,0x90,0x90,0x90,\r\n\t0x90,0x90,0x90,0x90,0x90,0x90,0x88,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x93,\r\n\t0x98,0x98,0x95,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8f,0x90,\r\n\t0x90,0x8d,0x81,0x81,0x81,0x8b,0x90,0x90,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x85,0x90,0x97,0x98,0x97,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,0x90,0x85,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,0x90,0x85,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,0x97,0x98,0x97,\r\n\t0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x90,\r\n\t0x97,0x98,0x97,0x90,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0xb2,0xdc,0xfa,\r\n\t0xfa,0xee,0xc6,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa4,0xc4,0xd0,\r\n\t0xd0,0xcd,0xb3,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x9e,0xa5,\r\n\t0xa5,0xa4,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x88,0x8b,0x8b,0x8b,0x89,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x88,0x8b,0x8b,0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8a,0x8b,0x8b,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x85,0x85,0x81,0x81,0x81,0x85,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x86,0x8b,0x8b,0x8b,0x8a,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0x88,0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9b,0xb1,0xb5,0xb5,0xb5,0xb3,0x9f,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9a,\r\n\t0xb0,0xb5,0xb5,0xb5,0xb3,0xa0,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa4,\r\n\t0xb4,0xb5,0xb5,0xa8,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,0xa1,\r\n\t0xaf,0xaf,0xa4,0x8d,0xa0,0xaf,0xb0,0xa5,0x8f,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x96,0xae,0xb5,0xb5,0xb5,0xb4,0xa2,0x84,0x81,0x81,0x81,\r\n\t0x9b,0xaf,0xb2,0xb2,0xaf,0x9b,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0xb5,0xd7,0xdf,0xdf,0xdf,0xda,0xbc,0x9d,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xb8,\r\n\t0xd5,0xdf,0xdf,0xdf,0xdb,0xbc,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc3,\r\n\t0xdd,0xdf,0xdf,0xc8,0xaa,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x86,0xa8,0xc6,\r\n\t0xd8,0xd9,0xc8,0xac,0xc4,0xd7,0xda,0xca,0xae,0x8d,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x96,0xb4,0xd2,0xdf,0xdf,0xdf,0xdc,0xbf,0x98,0x81,0x81,0x90,\r\n\t0xb6,0xd6,0xdd,0xdd,0xd6,0xb6,0x90,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x87,0xa0,0xab,0xab,0xa9,0x99,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x92,0xbc,0xe6,0x04,0x0b,0x0b,0xf7,0xd9,0xbb,0x9d,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x98,0xb6,0xd4,\r\n\t0xf3,0x0b,0x0b,0x09,0xed,0xc4,0x9a,0x81,0x81,0x81,0x81,0x81,0x87,0xa5,0xc3,0xe1,\r\n\t0xff,0x0b,0x05,0xe6,0xc8,0xaa,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xc0,0xe4,\r\n\t0xff,0x04,0xe8,0xc5,0xe2,0xff,0x04,0xea,0xc7,0xa0,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x96,0xb4,0xd2,0xf0,0x0b,0x0b,0x0b,0xef,0xc7,0x9d,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x09,0x09,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x82,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xc3,0xd5,0xd5,0xd2,0xb9,\r\n\t0x94,0x81,0x81,0x81,0x81,0x81,0x87,0xac,0xc8,0xe2,0xfb,0x14,0x16,0xf7,0xd9,0xbb,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x97,0xb6,0xd4,0xf1,\r\n\t0x10,0x1a,0xff,0xe6,0xcd,0xb2,0x8e,0x81,0x81,0x81,0x81,0x84,0xa5,0xc3,0xe1,0xff,\r\n\t0x1d,0x09,0x1f,0x05,0xe6,0xc8,0xaa,0x8b,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,\r\n\t0x1f,0x23,0xfa,0xd0,0xf2,0x1c,0x25,0xfc,0xd2,0xa8,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x95,0xb4,0xd2,0xf0,0x0f,0x1d,0x04,0xe9,0xd0,0xb4,0x91,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x16,0xea,0xc0,0x95,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xaa,0xb0,0xab,0x9b,0x83,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x92,0x99,0xaf,0xd7,0xff,0xff,0xf2,0xc8,\r\n\t0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa7,0xc0,0xd9,0xf3,0x0d,0x16,0xf7,0xd9,\r\n\t0xb4,0x93,0x92,0x87,0x81,0x81,0x81,0x81,0x81,0x84,0x91,0x93,0xac,0xd3,0xf1,0x10,\r\n\t0x12,0xf7,0xde,0xc5,0xab,0x92,0x81,0x81,0x81,0x81,0x81,0x95,0xbd,0xe1,0xff,0x1b,\r\n\t0x04,0xe7,0xff,0x1b,0x05,0xe6,0xc5,0x9d,0x81,0x81,0x81,0x81,0x81,0x9d,0xc6,0xed,\r\n\t0x0f,0x10,0xf1,0xcb,0xeb,0x0d,0x12,0xf4,0xcd,0xa5,0x81,0x81,0x81,0x81,0x85,0x92,\r\n\t0x93,0x93,0xa9,0xd0,0xf0,0x0f,0x14,0xfb,0xe1,0xc8,0xae,0x95,0x88,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x16,0xea,0xc0,0x96,0x9b,0x9b,0x94,0x88,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd2,0xda,0xd4,0xbf,0xa1,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x83,0x9a,0xad,0xbb,0xc2,0xc5,0xe5,0x0d,0x0f,0xe7,0xbf,\r\n\t0x97,0x81,0x81,0x81,0x81,0x81,0x86,0xa7,0xbb,0xbd,0xbd,0xd2,0xeb,0xef,0xef,0xde,\r\n\t0xbd,0xbd,0xbc,0xac,0x8d,0x81,0x81,0x81,0x86,0xa7,0xbb,0xbd,0xbd,0xd6,0xef,0xef,\r\n\t0xee,0xd6,0xbd,0xbd,0xbc,0xac,0x8d,0x81,0x81,0x81,0x86,0xa7,0xc0,0xe6,0xef,0xef,\r\n\t0xe3,0xc8,0xdf,0xef,0xef,0xec,0xc8,0xac,0x8d,0x81,0x81,0x81,0x86,0xa7,0xbb,0xd2,\r\n\t0xe7,0xe9,0xd5,0xb7,0xd0,0xe7,0xea,0xd7,0xbc,0xac,0x8d,0x81,0x81,0x89,0xa8,0xbb,\r\n\t0xbd,0xbd,0xbb,0xd4,0xef,0xef,0xef,0xd9,0xc0,0xbd,0xbd,0xbd,0xad,0x8f,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x16,0xea,0xc0,0xbf,0xc5,0xc5,0xbd,0xae,0x99,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8c,0xb3,0xd9,0xf6,0x06,0xf9,0xdd,0xb8,0x91,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x87,0xa5,0xbe,0xd3,0xe3,0xed,0xef,0xf2,0x1a,0x04,0xda,0xb2,\r\n\t0x8e,0x81,0x81,0x81,0x81,0x81,0x98,0xc0,0xe2,0xe7,0xe7,0xdd,0xc3,0xc5,0xc5,0xd7,\r\n\t0xe7,0xe7,0xe6,0xc7,0x9f,0x81,0x81,0x81,0x98,0xc0,0xe2,0xe7,0xe7,0xdd,0xc5,0xc5,\r\n\t0xc5,0xd7,0xe7,0xe7,0xe6,0xc7,0x9f,0x81,0x81,0x81,0x98,0xc0,0xe2,0xe7,0xe7,0xdd,\r\n\t0xc0,0xa8,0xbe,0xd7,0xe7,0xe7,0xe6,0xc7,0x9f,0x81,0x81,0x81,0x98,0xc0,0xe2,0xe7,\r\n\t0xe7,0xdd,0xb9,0x9a,0xb1,0xd7,0xe7,0xe7,0xe6,0xc7,0x9f,0x81,0x81,0x9a,0xc2,0xe3,\r\n\t0xe7,0xe7,0xe2,0xc1,0xc5,0xc5,0xc5,0xb7,0xd9,0xe7,0xe7,0xe7,0xc9,0xa2,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x16,0xea,0xd9,0xe7,0xef,0xef,0xe6,0xd3,0xb9,0x9b,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x12,0x2f,0x17,0xef,0xc5,0x9b,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0xa3,0xc3,0xe0,0xf9,0x0b,0x16,0x1b,0x19,0x21,0xfc,0xe6,0xca,\r\n\t0xaa,0x87,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,0x13,0x13,0xe7,0xbd,0x9b,0xb5,0xdf,\r\n\t0x0b,0x13,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x13,0x13,0xe7,0xbd,0x9b,\r\n\t0xb5,0xdf,0x0b,0x13,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x13,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x13,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x13,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x13,0xf7,0xcd,0xa3,0x81,0x81,0x9c,0xc5,0xec,\r\n\t0x13,0x13,0xf7,0xd1,0xa9,0x9b,0x9c,0xc4,0xec,0x13,0x13,0xf5,0xce,0xa4,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x16,0xea,0xfc,0x0f,0x19,0x19,0x0d,0xf5,0xd7,0xb5,0x91,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x94,0xbe,0xe7,0x0f,0x28,0x12,0xec,0xc3,0x9a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x95,0xbb,0xde,0xff,0x1c,0x18,0x09,0x04,0x12,0x21,0x22,0x05,0xe5,\r\n\t0xc1,0x9b,0x81,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0xb5,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x8e,0xb5,0xdd,\r\n\t0x05,0x2c,0x07,0xe0,0xb9,0x91,0xaa,0xd2,0xfa,0x22,0x0f,0xe7,0xbf,0x98,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x16,0x04,0x20,0x0f,0x06,0x0d,0x25,0x12,0xef,0xcb,0xa4,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x91,0xa2,0xa5,0xa5,0xaf,0xd3,0xf0,0xfc,0xf3,0xd7,0xb4,0xa5,0xa5,0xa4,0x96,\r\n\t0x81,0x81,0x81,0xa7,0xce,0xf4,0x19,0x16,0xf5,0xdf,0xf2,0x1a,0x04,0x13,0x20,0xfa,\r\n\t0xd4,0xad,0x85,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0xb5,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0xa6,0xcd,\r\n\t0xf5,0x1c,0x17,0xef,0xc8,0xa0,0xb9,0xe0,0x09,0x27,0xff,0xd8,0xb0,0x89,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x21,0x1d,0xff,0xe8,0xda,0xe8,0x09,0x29,0x04,0xda,0xb2,0x89,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,0xd0,0xd0,0xd2,0xd0,0xd0,0xd0,0xd0,0xd0,0xce,0xb7,\r\n\t0x94,0x81,0x8b,0xb4,0xdd,0x06,0x28,0xff,0xdb,0xd7,0xff,0x1d,0xf5,0xfc,0x25,0x0b,\r\n\t0xe2,0xb9,0x8f,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0xb5,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x97,0xbe,\r\n\t0xe5,0x0c,0x26,0xfc,0xd6,0xaf,0xc7,0xee,0x16,0x18,0xf1,0xc9,0xa1,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x22,0xff,0xe1,0xc5,0xb1,0xcf,0xf7,0x20,0x0e,0xe5,0xbb,0x91,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xbf,0xe9,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xf3,0xca,\r\n\t0xa0,0x81,0x92,0xbc,0xe6,0x11,0x1e,0xf4,0xcb,0xe5,0x0d,0x0f,0xe7,0xf1,0x1b,0x13,\r\n\t0xea,0xc0,0x95,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0xb5,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x87,0xae,\r\n\t0xd5,0xfc,0x24,0x0d,0xe6,0xbe,0xd5,0xfc,0x24,0x09,0xe1,0xba,0x92,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc6,0xa6,0x9b,0xc5,0xef,0x19,0x16,0xea,0xc0,0x97,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xc0,0xea,0x16,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x21,0xf5,0xca,\r\n\t0xa0,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xca,0xf2,0x1a,0x04,0xda,0xea,0x16,0x19,\r\n\t0xed,0xc2,0x98,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0xb5,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x9e,\r\n\t0xc6,0xed,0x14,0x1d,0xf5,0xcd,0xe2,0x0b,0x21,0xfa,0xd2,0xab,0x83,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x96,0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x95,0xbf,0xe9,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xf3,0xca,\r\n\t0xa0,0x81,0x95,0xc0,0xea,0x16,0x19,0xed,0xd7,0xff,0x1d,0xf5,0xcd,0xec,0x16,0x18,\r\n\t0xed,0xc2,0x98,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,0xb5,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x93,\r\n\t0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x93,0xb5,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x8f,\r\n\t0xb6,0xdd,0x05,0x2c,0x04,0xdc,0xf1,0x19,0x12,0xeb,0xc3,0x9c,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x98,0xc2,0xec,0x16,0x16,0xed,0xc2,0x98,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8b,0xaf,0xcb,0xd0,0xd0,0xd0,0xd0,0xd0,0xd2,0xd0,0xd0,0xd0,0xd0,0xd0,0xce,0xb7,\r\n\t0x94,0x81,0x93,0xbd,0xe7,0x11,0x1e,0xf4,0xe5,0x0d,0x11,0xe7,0xc9,0xf2,0x1b,0x11,\r\n\t0xe7,0xbf,0x95,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x9d,0xbd,0xdf,\r\n\t0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,0xbd,0x9d,\r\n\t0xbd,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,0x13,0xe7,\r\n\t0xbd,0x9d,0xbd,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x1b,\r\n\t0x13,0xe7,0xbd,0x9d,0xbd,0xdf,0x0b,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0xa6,0xcd,0xf5,0x1c,0x13,0xec,0xff,0x27,0x04,0xdc,0xb4,0x8d,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0xa1,0xc9,0xf2,0x1b,0x11,0xe7,0xbd,0x94,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x91,0xa2,0xa5,0xa5,0xaf,0xd3,0xf0,0xfc,0xf3,0xd7,0xb4,0xa5,0xa5,0xa4,0x96,\r\n\t0x81,0x81,0x8c,0xb6,0xde,0x07,0x28,0xff,0xf2,0x1a,0x04,0xdb,0xda,0xff,0x26,0x06,\r\n\t0xde,0xb6,0x8d,0x81,0x81,0x81,0x9b,0xc5,0xef,0x19,0x16,0xec,0xc2,0xbd,0xd8,0xf7,\r\n\t0x18,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x19,0x16,0xec,0xc2,0xbd,\r\n\t0xd8,0xf7,0x18,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x19,0x16,0xec,\r\n\t0xc2,0xbd,0xd8,0xf7,0x18,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x9b,0xc5,0xef,0x19,\r\n\t0x16,0xec,0xc2,0xbd,0xd8,0xf7,0x18,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x97,0xbe,0xe5,0x0c,0x21,0xf9,0x0d,0x1b,0xf4,0xcd,0xa5,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0xb0,0xbb,0xda,0xff,0x26,0x05,0xdc,0xb4,0x8b,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x94,0xbe,0xe7,0x0f,0x28,0x12,0xec,0xc3,0x9a,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0xa9,0xd1,0xf6,0x1b,0x16,0xff,0x1e,0xf5,0xe1,0xf5,0x14,0x1a,0xf5,\r\n\t0xcf,0xa9,0x81,0x81,0x81,0x81,0x96,0xbf,0xe9,0x12,0x20,0xfb,0xe0,0xe1,0xf7,0x14,\r\n\t0x16,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x96,0xbf,0xe9,0x12,0x20,0xfb,0xe0,0xe1,\r\n\t0xf7,0x14,0x16,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x96,0xbf,0xe9,0x12,0x20,0xfb,\r\n\t0xe0,0xe1,0xf7,0x14,0x16,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x96,0xbf,0xe9,0x12,\r\n\t0x20,0xfb,0xe0,0xe1,0xf7,0x14,0x16,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x87,0xae,0xd5,0xfc,0x24,0x06,0x1c,0x0d,0xe5,0xbd,0x96,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xdf,0xda,0xe2,0xf6,0x15,0x17,0xf3,0xcd,0xa6,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x95,0xc0,0xea,0x12,0x2f,0x17,0xef,0xc5,0x9b,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x98,0xbd,0xe0,0xff,0x1d,0x23,0x14,0x06,0x0a,0x19,0x1c,0xff,0xdf,\r\n\t0xbc,0x97,0x81,0x81,0x81,0x81,0x8c,0xb4,0xdc,0xff,0x25,0x19,0x0a,0x0b,0x1a,0x0d,\r\n\t0x04,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x8c,0xb4,0xdc,0xff,0x25,0x19,0x0a,0x0b,\r\n\t0x1a,0x0d,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x8c,0xb4,0xdc,0xff,0x25,0x19,\r\n\t0x0a,0x0b,0x1a,0x0d,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x8c,0xb4,0xdc,0xff,\r\n\t0x25,0x19,0x0a,0x0b,0x1a,0x0d,0x04,0x23,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x9e,0xc6,0xed,0x14,0x24,0x25,0xfc,0xd6,0xaf,0x87,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x25,0x13,0x09,0x06,0x0b,0x1a,0x18,0xfb,0xdb,0xb9,0x94,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8c,0xb3,0xd9,0xf6,0x06,0xfa,0xdd,0xb8,0x91,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x83,0xa5,0xc5,0xe2,0xfa,0x1b,0x16,0x19,0x14,0x0a,0xf7,0xe0,0xc3,\r\n\t0xa4,0x81,0x81,0x81,0x81,0x81,0x81,0xa3,0xc8,0xe8,0x04,0x13,0x19,0x13,0x04,0xec,\r\n\t0x04,0x0e,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0xa3,0xc8,0xe8,0x04,0x13,0x19,0x13,\r\n\t0x04,0xec,0x04,0x0e,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0xa3,0xc8,0xe8,0x04,0x13,\r\n\t0x19,0x13,0x04,0xec,0x04,0x0e,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0xa3,0xc8,0xe8,\r\n\t0x04,0x13,0x19,0x13,0x05,0xec,0x04,0x0e,0xf7,0xcd,0xa3,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x8f,0xb6,0xdd,0x05,0x2c,0x15,0xee,0xc7,0x9f,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x1b,0x0e,0x14,0x16,0x11,0x06,0xf4,0xdc,0xbf,0xa0,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x9d,0xbb,0xd2,0xda,0xd4,0xbf,0xa1,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x89,0xaf,0xd6,0xff,0x1d,0xf5,0xed,0xea,0xe1,0xd3,0xbe,0xa5,\r\n\t0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x8c,0xac,0xc8,0xdd,0xea,0xed,0xea,0xde,0xcd,\r\n\t0xe2,0xe2,0xe1,0xc5,0x9e,0x81,0x81,0x81,0x81,0x8c,0xac,0xc8,0xdd,0xea,0xed,0xea,\r\n\t0xde,0xcd,0xe2,0xe2,0xe1,0xc5,0x9e,0x81,0x81,0x81,0x81,0x8c,0xac,0xc8,0xdd,0xea,\r\n\t0xed,0xea,0xde,0xcd,0xe2,0xe2,0xe1,0xc5,0x9e,0x81,0x81,0x81,0x81,0x8c,0xac,0xc8,\r\n\t0xdd,0xea,0xed,0xea,0xde,0xcd,0xe2,0xe2,0xe1,0xc5,0x9e,0x81,0x81,0x81,0x8d,0x9a,\r\n\t0x9a,0xa1,0xc2,0xe5,0x0b,0x28,0x04,0xdc,0xb6,0x90,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xea,0xea,0xe7,0xde,0xce,0xba,0xa1,0x83,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x99,0xaa,0xb0,0xab,0x9b,0x83,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x94,0xbc,0xe4,0x0c,0x0f,0xe7,0xc2,0xc0,0xb9,0xac,0x9a,0x83,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8d,0xa5,0xb6,0xc0,0xc2,0xc0,0xb6,0xad,\r\n\t0xb8,0xb8,0xb7,0xa7,0x8a,0x81,0x81,0x81,0x81,0x81,0x8d,0xa5,0xb6,0xc0,0xc2,0xc0,\r\n\t0xb6,0xad,0xb8,0xb8,0xb7,0xa7,0x8a,0x81,0x81,0x81,0x81,0x81,0x8d,0xa5,0xb6,0xc0,\r\n\t0xc2,0xc0,0xb6,0xad,0xb8,0xb8,0xb7,0xa7,0x8a,0x81,0x81,0x81,0x81,0x81,0x8d,0xa5,\r\n\t0xb6,0xc0,0xc2,0xc0,0xb7,0xad,0xb8,0xb8,0xb7,0xa7,0x8a,0x81,0x81,0x8f,0xb0,0xc4,\r\n\t0xc4,0xc6,0xdd,0xfc,0x20,0x14,0xef,0xcb,0xa5,0x81,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0xc0,0xbd,0xb5,0xa8,0x95,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x85,0x82,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x98,0xc2,0xec,0xfa,0xfa,0xda,0xb2,0x97,0x90,0x84,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x96,0x98,0x97,0x8e,0x86,\r\n\t0x8d,0x8d,0x8d,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x96,0x98,0x97,\r\n\t0x8e,0x86,0x8d,0x8d,0x8d,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8e,0x96,\r\n\t0x98,0x97,0x8e,0x86,0x8d,0x8d,0x8d,0x82,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x8e,0x96,0x98,0x97,0x8e,0x86,0x8d,0x8d,0x8d,0x82,0x81,0x81,0x81,0x9e,0xc8,0xec,\r\n\t0xed,0xef,0xff,0x1a,0x1d,0xfb,0xd9,0xb5,0x91,0x81,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x93,0x8c,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x8d,0xb1,0xcc,0xd0,0xd0,0xc2,0xa2,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,\r\n\t0x19,0x19,0x24,0x18,0xff,0xe1,0xc1,0x9e,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x16,0x19,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x92,0xa3,0xa5,0xa5,0x9d,0x87,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0xa0,0xca,0xf5,\r\n\t0x0b,0x09,0x04,0xf3,0xdd,0xc3,0xa5,0x85,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x95,\r\n\t0xc0,0xea,0x09,0x09,0xed,0xc2,0x98,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x9a,0xc0,0xdc,\r\n\t0xdf,0xdf,0xd9,0xcc,0xba,0xa2,0x87,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x90,\r\n\t0xb6,0xd6,0xdd,0xdd,0xd8,0xb9,0x92,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x84,0xa2,0xb4,\r\n\t0xb5,0xb5,0xaf,0xa4,0x94,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x9b,0xaf,0xb2,0xb2,0xb0,0x9d,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8a,\r\n\t0x8b,0x8b,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x86,0x88,0x88,0x86,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,\r\n\t0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/GameCore.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GameCore.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"SystemTime.h\"\r\n#include \"GameInput.h\"\r\n#include \"BufferManager.h\"\r\n#include \"CommandContext.h\"\r\n#include \"PostEffects.h\"\r\n\r\n#include \"ART/GUI/GUICore.h\"\r\n\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    #pragma comment(lib, \"runtimeobject.lib\")\r\n#else\r\n    #include <agile.h>\r\n    using namespace Windows::ApplicationModel;\r\n    using namespace Windows::UI::Core;\r\n    using namespace Windows::UI::ViewManagement;\r\n    using Windows::ApplicationModel::Core::CoreApplication;\r\n    using Windows::ApplicationModel::Core::CoreApplicationView;\r\n    using Windows::ApplicationModel::Activation::IActivatedEventArgs;\r\n    using Windows::Foundation::TypedEventHandler;\r\n#endif\r\n\r\nnamespace Graphics\r\n{\r\n    extern ColorBuffer g_GenMipsBuffer;\r\n}\r\n\r\nnamespace GameCore\r\n{\r\n    using namespace Graphics;\r\n    //const bool TestGenerateMips = false;\r\n\r\n    void InitializeApplication( IGameApp& game )\r\n    {\r\n        Graphics::Initialize();\r\n        SystemTime::Initialize();\r\n        GameInput::Initialize();\r\n        EngineTuning::Initialize();\r\n\r\n        game.Startup();\r\n    }\r\n\r\n    void TerminateApplication( IGameApp& game )\r\n    {\r\n        game.Cleanup();\r\n\r\n        GameInput::Shutdown();\r\n    }\r\n\r\n    bool UpdateApplication( IGameApp& game )\r\n    {\r\n        EngineProfiling::Update();\r\n\r\n        float DeltaTime = Graphics::GetFrameTime();\r\n    \r\n        GameInput::Update(DeltaTime);\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\t\tARTGUI::Update(DeltaTime);\r\n#endif\r\n\r\n        EngineTuning::Update(DeltaTime);\r\n        \r\n        game.Update(DeltaTime);\r\n        game.RenderScene();\r\n\r\n        PostEffects::Render();\r\n\r\n        //if (TestGenerateMips)\r\n        //{\r\n        //    GraphicsContext& MipsContext = GraphicsContext::Begin();\r\n\r\n        //    // Exclude from timings this copy necessary to setup the test\r\n        //    MipsContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);\r\n        //    MipsContext.TransitionResource(g_GenMipsBuffer, D3D12_RESOURCE_STATE_COPY_DEST);\r\n        //    MipsContext.CopySubresource(g_GenMipsBuffer, 0, *g_pSceneColorBuffer, 0);\r\n\r\n        //    EngineProfiling::BeginBlock(L\"GenerateMipMaps()\", &MipsContext);\r\n        //    g_GenMipsBuffer.GenerateMipMaps(MipsContext);\r\n        //    EngineProfiling::EndBlock(&MipsContext);\r\n\r\n        //    MipsContext.Finish();\r\n        //}\r\n\r\n        GraphicsContext& UiContext = GraphicsContext::Begin(L\"Render UI\");\r\n        UiContext.TransitionResource(g_OverlayBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET, true);\r\n        UiContext.ClearColor(g_OverlayBuffer);\r\n        UiContext.SetRenderTarget(g_OverlayBuffer.GetRTV());\r\n        UiContext.SetViewportAndScissor(0, 0, g_OverlayBuffer.GetWidth(), g_OverlayBuffer.GetHeight());\r\n        game.RenderUI(UiContext);\r\n\r\n        EngineTuning::Display( UiContext, 10.0f, 40.0f, 1900.0f, 1040.0f );\r\n\r\n        UiContext.Finish();\r\n\r\n        Graphics::Present();\r\n\r\n        return !game.IsDone();\r\n    }\r\n\r\n    // Default implementation to be overridden by the application\r\n    bool IGameApp::IsDone( void )\r\n    {\r\n        return GameInput::IsFirstPressed(GameInput::kKey_escape);\r\n    }\r\n\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    IGameApp* m_game;\r\n    Platform::Agile<CoreWindow> g_window;\r\n\r\n    ref class MyApplicationView sealed : public Core::IFrameworkView\r\n    {\r\n    public:\r\n        MyApplicationView() {}\r\n\r\n        // IFrameworkView Methods.\r\n        virtual void Initialize(CoreApplicationView^ applicationView);\r\n        virtual void Load(Platform::String^ entryPoint);\r\n        virtual void Run(void);\r\n        virtual void SetWindow(CoreWindow^ window);\r\n        virtual void Uninitialize(void);\r\n\r\n    protected:\r\n        // Event Handlers.\r\n        void OnActivated(Core::CoreApplicationView^ applicationView, Activation::IActivatedEventArgs^ args);\r\n        void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args);\r\n        void OnResuming(Platform::Object^ sender, Platform::Object^ args);\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)\r\n        void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args);\r\n        void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args);\r\n        void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args);\r\n        void OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args);\r\n        void OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args);\r\n        void OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args);\r\n        void OnKeyUp(CoreWindow^ sender, KeyEventArgs^ args);\r\n#endif\r\n\r\n    private:\r\n        bool m_windowClosed;\r\n        bool m_windowVisible;\r\n        volatile bool m_IsRunning;\r\n        volatile bool m_IsCapturingPointer;\r\n        float m_PointerX, m_PointerY;\r\n    };\r\n\r\n    ref class ApplicationViewSource sealed : Core::IFrameworkViewSource\r\n    {\r\n    public:\r\n        virtual Core::IFrameworkView^ CreateView()\r\n        {\r\n            return ref new MyApplicationView();\r\n        }\r\n    };\r\n\r\n\r\n    // Called by the system.  Perform application initialization here, hooking application wide events, etc.\r\n    void MyApplicationView::Initialize(CoreApplicationView^ applicationView)\r\n    {\r\n        applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &MyApplicationView::OnActivated);\r\n    }\r\n\r\n    // Called when we are provided a window.\r\n    void MyApplicationView::SetWindow(CoreWindow^ window)\r\n    {\r\n        // We record the window pointer now, but you can also call this function to retrieve it:\r\n        //     CoreWindow::GetForCurrentThread()\r\n        g_window = window;\r\n\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)\r\n        window->SizeChanged += ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &MyApplicationView::OnWindowSizeChanged);\r\n        window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &MyApplicationView::OnVisibilityChanged);\r\n        window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &MyApplicationView::OnWindowClosed);\r\n        window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &MyApplicationView::OnKeyDown);\r\n        window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &MyApplicationView::OnKeyUp);\r\n        window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &MyApplicationView::OnPointerPressed);\r\n        window->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &MyApplicationView::OnPointerMoved);\r\n#endif\r\n    }\r\n\r\n    void MyApplicationView::Load(Platform::String^ entryPoint)\r\n    {\r\n        InitializeApplication(*m_game);\r\n    }\r\n\r\n    // Called by the system after initialization is complete.  This implements the traditional game loop.\r\n    void MyApplicationView::Run()\r\n    {\r\n        while (m_IsRunning)\r\n        {\r\n            // ProcessEvents will throw if the process is exiting, allowing us to break out of the loop.  This will be\r\n            // cleaned up when we get proper process lifetime management in a future release.\r\n            g_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);\r\n\r\n            m_IsRunning = UpdateApplication(*m_game);\r\n        }\r\n    }\r\n\r\n    void MyApplicationView::Uninitialize()\r\n    {\r\n        Graphics::Terminate();\r\n        TerminateApplication(*m_game);\r\n        Graphics::Shutdown();\r\n    }\r\n\r\n    // Called when the application is activated.  For now, there is just one activation kind - Launch.\r\n    void MyApplicationView::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)\r\n    {\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)\r\n        float DpiScale = 96.0f / Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->LogicalDpi;\r\n        ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize;\r\n        Windows::Foundation::Size DesiredSize(Graphics::g_DisplayWidth * DpiScale, Graphics::g_DisplayHeight * DpiScale);\r\n        ApplicationView::PreferredLaunchViewSize = DesiredSize;\r\n        ApplicationView::GetForCurrentView()->TryResizeView(DesiredSize);\r\n#endif\r\n\r\n        m_IsRunning = true;\r\n        m_IsCapturingPointer = false;\r\n        g_window->Activate();\r\n    }\r\n\r\n    void MyApplicationView::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {}\r\n    void MyApplicationView::OnResuming(Platform::Object^ sender, Platform::Object^ args) {}\r\n\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)\r\n    void MyApplicationView::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)\r\n    {\r\n        Graphics::Resize((uint32_t)sender->Bounds.Width, (uint32_t)sender->Bounds.Height);\r\n    }\r\n\r\n    void MyApplicationView::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) \r\n    {\r\n        m_IsRunning = false;\r\n    }\r\n\r\n    void MyApplicationView::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) {}\r\n\r\n    void MyApplicationView::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)\r\n    {\r\n        //DEBUGPRINT(\"Pointer pressed (%f, %f)\", args->CurrentPoint->RawPosition.X, args->CurrentPoint->RawPosition.Y);\r\n        if (m_IsCapturingPointer)\r\n        {\r\n            g_window->ReleasePointerCapture();\r\n            m_IsCapturingPointer = false;\r\n            g_window->PointerCursor = ref new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Arrow, 0);\r\n            //DEBUGPRINT(\"Pointer released\");\r\n        }\r\n        else\r\n        {\r\n            g_window->SetPointerCapture();\r\n            m_IsCapturingPointer = true;\r\n            g_window->PointerCursor = ref new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Hand, 0);\r\n            m_PointerX = args->CurrentPoint->RawPosition.X;\r\n            m_PointerY = args->CurrentPoint->RawPosition.Y;\r\n            //DEBUGPRINT(\"Pointer captured\");\r\n        }\r\n    }\r\n    \r\n    void MyApplicationView::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)\r\n    {\r\n        if (!m_IsCapturingPointer)\r\n            return;\r\n\r\n        float OldX = m_PointerX;\r\n        float OldY = m_PointerY;\r\n\r\n        m_PointerX = args->CurrentPoint->RawPosition.X;\r\n        m_PointerY = args->CurrentPoint->RawPosition.Y;\r\n\r\n        //DEBUGPRINT(\"Pointer moved (%f, %f)\", m_PointerX, m_PointerY);\r\n        //DEBUGPRINT(\"Pointer was (%f, %f)\", OldX, OldY);\r\n        //GameInput::SetMouseMovement(m_PointerX)\r\n    }\r\n\r\n    void MyApplicationView::OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args)\r\n    {\r\n        GameInput::SetKeyState(args->VirtualKey, true);\r\n    }\r\n\r\n    void MyApplicationView::OnKeyUp(CoreWindow^ sender, KeyEventArgs^ args)\r\n    {\r\n        GameInput::SetKeyState(args->VirtualKey, false);\r\n    }\r\n#endif\r\n\r\n    void RunApplication( IGameApp& app, const wchar_t* className )\r\n    {\r\n        m_game = &app;\r\n        (void)className;\r\n        auto applicationViewSource = ref new ApplicationViewSource();\r\n        CoreApplication::Run(applicationViewSource);\r\n    }\r\n\r\n#else // Win32\r\n\r\n    HWND g_hWnd = nullptr;\r\n\r\n    void InitWindow( const wchar_t* className );\r\n    LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );\r\n\r\n    void RunApplication( IGameApp& app, const wchar_t* className )\r\n    {\r\n        //ASSERT_SUCCEEDED(CoInitializeEx(nullptr, COINITBASE_MULTITHREADED));\r\n        Microsoft::WRL::Wrappers::RoInitializeWrapper InitializeWinRT(RO_INIT_MULTITHREADED);\r\n        ASSERT_SUCCEEDED(InitializeWinRT);\r\n\r\n        HINSTANCE hInst = GetModuleHandle(0);\r\n\r\n        // Register class\r\n        WNDCLASSEX wcex;\r\n        wcex.cbSize = sizeof(WNDCLASSEX);\r\n        wcex.style = CS_HREDRAW | CS_VREDRAW;\r\n        wcex.lpfnWndProc = WndProc;\r\n        wcex.cbClsExtra = 0;\r\n        wcex.cbWndExtra = 0;\r\n        wcex.hInstance = hInst;\r\n        wcex.hIcon = LoadIcon(hInst, IDI_APPLICATION);\r\n        wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);\r\n        wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r\n        wcex.lpszMenuName = nullptr;\r\n        wcex.lpszClassName = className;\r\n        wcex.hIconSm = LoadIcon(hInst, IDI_APPLICATION);\r\n        ASSERT(0 != RegisterClassEx(&wcex), \"Unable to register a window\");\r\n\r\n        // Create window\r\n        RECT rc = { 0, 0, (LONG)g_DisplayWidth, (LONG)g_DisplayHeight };\r\n        AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);\r\n\r\n        g_hWnd = CreateWindow(className, className, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,\r\n            rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInst, nullptr);\r\n\r\n        ASSERT(g_hWnd != 0);\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\t\tARTGUI::SetHwnd(g_hWnd);\r\n#endif\r\n\t\t\r\n\t\t\tInitializeApplication(app);\r\n\r\n\t\t\tif (!app.IsDone())\r\n\t\t\t{\r\n\t\t\t\tShowWindow(g_hWnd, SW_SHOWDEFAULT);\r\n\r\n\t\t\t\tdo\r\n\t\t\t\t{\r\n\t\t\t\t\tMSG msg = {};\r\n\t\t\t\t\twhile (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tTranslateMessage(&msg);\r\n\t\t\t\t\t\tDispatchMessage(&msg);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (msg.message == WM_QUIT)\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t} while (UpdateApplication(app));\t// Returns false to quit loop\r\n\t\t\t}\r\n\r\n\t\t\tGraphics::Terminate();\r\n\t\t\tTerminateApplication(app);\r\n\t\t\tGraphics::Shutdown();\r\n    }\r\n\r\n    //--------------------------------------------------------------------------------------\r\n    // Called every time the application receives a message\r\n    //--------------------------------------------------------------------------------------\r\n    LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )\r\n    {\r\n\t\t\r\n#ifdef ART_ENABLE_GUI\r\n\t\tif(ARTGUI::IsFocused() && ARTGUI::WndProcHandler(hWnd, message, wParam, lParam) != 0)\r\n\t\t\treturn 0;\r\n#endif\r\n\r\n\t\tswitch( message )\r\n        {\r\n            case WM_SIZE:\r\n                Graphics::Resize((UINT)(UINT64)lParam & 0xFFFF, (UINT)(UINT64)lParam >> 16);\r\n                break;\r\n\r\n            case WM_DESTROY:\r\n                PostQuitMessage(0);\r\n                break;\r\n\r\n            default:\r\n                return DefWindowProc( hWnd, message, wParam, lParam );\r\n        }\r\n\r\n        return 0;\r\n    }\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GameCore.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\nnamespace GameCore\r\n{\r\n    class IGameApp\r\n    {\r\n    public:\r\n        // This function can be used to initialize application state and will run after essential\r\n        // hardware resources are allocated.  Some state that does not depend on these resources\r\n        // should still be initialized in the constructor such as pointers and flags.\r\n        virtual void Startup( void ) = 0;\r\n        virtual void Cleanup( void ) = 0;\r\n\r\n        // Decide if you want the app to exit.  By default, app continues until the 'ESC' key is pressed.\r\n        virtual bool IsDone( void );\r\n\r\n        // The update method will be invoked once per frame.  Both state updating and scene\r\n        // rendering should be handled by this method.\r\n        virtual void Update( float deltaT ) = 0;\r\n\r\n        // Official rendering pass\r\n        virtual void RenderScene( void ) = 0;\r\n\r\n        // Optional UI (overlay) rendering pass.  This is LDR.  The buffer is already cleared.\r\n        virtual void RenderUI( class GraphicsContext& ) {};\r\n    };\r\n\r\n    void RunApplication( IGameApp& app, const wchar_t* className );\r\n}\r\n\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    #define MAIN_FUNCTION()  int wmain(int argc, wchar_t** argv)\r\n#else\r\n    #define MAIN_FUNCTION()  [Platform::MTAThread] int main(Platform::Array<Platform::String^>^)\r\n#endif\r\n\r\n#define CREATE_APPLICATION( app_class ) \\\r\n    MAIN_FUNCTION() \\\r\n    { \\\r\n        GameCore::RunApplication( app_class(), L#app_class ); \\\r\n        return 0; \\\r\n    }\r\n"
  },
  {
    "path": "MiniEngine/Core/GameInput.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GameCore.h\"\r\n#include \"GameInput.h\"\r\n\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n\r\n#define USE_XINPUT\r\n#include <XInput.h>\r\n#pragma comment(lib, \"xinput9_1_0.lib\")\r\n\r\n#define USE_KEYBOARD_MOUSE\r\n#define DIRECTINPUT_VERSION 0x0800\r\n#include <dinput.h>\r\n#pragma comment(lib, \"dinput8.lib\")\r\n#pragma comment(lib, \"dxguid.lib\")\r\n\r\nnamespace GameCore\r\n{\r\n    extern HWND g_hWnd;\r\n}\r\n\r\n#else\r\n\r\nusing namespace Windows::Gaming::Input;\r\nusing namespace Windows::Foundation::Collections;\r\n\r\n#define USE_KEYBOARD_MOUSE\r\n\r\nstruct DIMOUSESTATE2\r\n{\r\n    LONG lX, lY, lZ;\r\n    BYTE rgbButtons[8];\r\n};\r\n\r\n#endif\r\n\r\nnamespace\r\n{\r\n\tbool s_allowInputReads = true;\r\n\tbool s_Buttons[2][GameInput::kNumDigitalInputs];\r\n    float s_HoldDuration[GameInput::kNumDigitalInputs] = { 0.0f };\r\n    float s_Analogs[GameInput::kNumAnalogInputs];\r\n    float s_AnalogsTC[GameInput::kNumAnalogInputs];\r\n\r\n#ifdef USE_KEYBOARD_MOUSE\r\n\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    IDirectInput8A* s_DI;\r\n    IDirectInputDevice8A* s_Keyboard;\r\n    IDirectInputDevice8A* s_Mouse;\r\n#endif\r\n\r\n    DIMOUSESTATE2 s_MouseState;\r\n    unsigned char s_Keybuffer[256];\r\n    unsigned char s_DXKeyMapping[GameInput::kNumKeys]; // map DigitalInput enum to DX key codes \r\n\r\n#endif\r\n\r\n#ifdef USE_XINPUT\r\n    float FilterAnalogInput( int val, int deadZone )\r\n    {\r\n        if (val < 0)\r\n        {\r\n            if (val > -deadZone)\r\n                return 0.0f;\r\n            else\r\n                return (val + deadZone) / (32768.0f - deadZone);\r\n        }\r\n        else\r\n        {\r\n            if (val < deadZone)\r\n                return 0.0f;\r\n            else\r\n                return (val - deadZone) / (32767.0f - deadZone);\r\n        }\r\n    }\r\n#else\r\n    float FilterAnalogInput( float val, float deadZone )\r\n    {\r\n        if (val < -deadZone)\r\n            return (val + deadZone) / (1.0f - deadZone);\r\n        else if (val > deadZone)\r\n            return (val - deadZone) / (1.0f - deadZone);\r\n        else\r\n            return 0.0f;\r\n    }\r\n#endif\r\n\r\n#ifdef USE_KEYBOARD_MOUSE\r\n    void KbmBuildKeyMapping()\r\n    {\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n        s_DXKeyMapping[GameInput::kKey_escape] = 1;\r\n        s_DXKeyMapping[GameInput::kKey_1] = 2;\r\n        s_DXKeyMapping[GameInput::kKey_2] = 3;\r\n        s_DXKeyMapping[GameInput::kKey_3] = 4;\r\n        s_DXKeyMapping[GameInput::kKey_4] = 5;\r\n        s_DXKeyMapping[GameInput::kKey_5] = 6;\r\n        s_DXKeyMapping[GameInput::kKey_6] = 7;\r\n        s_DXKeyMapping[GameInput::kKey_7] = 8;\r\n        s_DXKeyMapping[GameInput::kKey_8] = 9;\r\n        s_DXKeyMapping[GameInput::kKey_9] = 10;\r\n        s_DXKeyMapping[GameInput::kKey_0] = 11;\r\n        s_DXKeyMapping[GameInput::kKey_minus] = 12;\r\n        s_DXKeyMapping[GameInput::kKey_equals] = 13;\r\n        s_DXKeyMapping[GameInput::kKey_back] = 14;\r\n        s_DXKeyMapping[GameInput::kKey_tab] = 15;\r\n        s_DXKeyMapping[GameInput::kKey_q] = 16;\r\n        s_DXKeyMapping[GameInput::kKey_w] = 17;\r\n        s_DXKeyMapping[GameInput::kKey_e] = 18;\r\n        s_DXKeyMapping[GameInput::kKey_r] = 19;\r\n        s_DXKeyMapping[GameInput::kKey_t] = 20;\r\n        s_DXKeyMapping[GameInput::kKey_y] = 21;\r\n        s_DXKeyMapping[GameInput::kKey_u] = 22;\r\n        s_DXKeyMapping[GameInput::kKey_i] = 23;\r\n        s_DXKeyMapping[GameInput::kKey_o] = 24;\r\n        s_DXKeyMapping[GameInput::kKey_p] = 25;\r\n        s_DXKeyMapping[GameInput::kKey_lbracket] = 26;\r\n        s_DXKeyMapping[GameInput::kKey_rbracket] = 27;\r\n        s_DXKeyMapping[GameInput::kKey_return] = 28;\r\n        s_DXKeyMapping[GameInput::kKey_lcontrol] = 29;\r\n        s_DXKeyMapping[GameInput::kKey_a] = 30;\r\n        s_DXKeyMapping[GameInput::kKey_s] = 31;\r\n        s_DXKeyMapping[GameInput::kKey_d] = 32;\r\n        s_DXKeyMapping[GameInput::kKey_f] = 33;\r\n        s_DXKeyMapping[GameInput::kKey_g] = 34;\r\n        s_DXKeyMapping[GameInput::kKey_h] = 35;\r\n        s_DXKeyMapping[GameInput::kKey_j] = 36;\r\n        s_DXKeyMapping[GameInput::kKey_k] = 37;\r\n        s_DXKeyMapping[GameInput::kKey_l] = 38;\r\n        s_DXKeyMapping[GameInput::kKey_semicolon] = 39;\r\n        s_DXKeyMapping[GameInput::kKey_apostrophe] = 40;\r\n        s_DXKeyMapping[GameInput::kKey_grave] = 41;\r\n        s_DXKeyMapping[GameInput::kKey_lshift] = 42;\r\n        s_DXKeyMapping[GameInput::kKey_backslash] = 43;\r\n        s_DXKeyMapping[GameInput::kKey_z] = 44;\r\n        s_DXKeyMapping[GameInput::kKey_x] = 45;\r\n        s_DXKeyMapping[GameInput::kKey_c] = 46;\r\n        s_DXKeyMapping[GameInput::kKey_v] = 47;\r\n        s_DXKeyMapping[GameInput::kKey_b] = 48;\r\n        s_DXKeyMapping[GameInput::kKey_n] = 49;\r\n        s_DXKeyMapping[GameInput::kKey_m] = 50;\r\n        s_DXKeyMapping[GameInput::kKey_comma] = 51;\r\n        s_DXKeyMapping[GameInput::kKey_period] = 52;\r\n        s_DXKeyMapping[GameInput::kKey_slash] = 53;\r\n        s_DXKeyMapping[GameInput::kKey_rshift] = 54;\r\n        s_DXKeyMapping[GameInput::kKey_multiply] = 55;\r\n        s_DXKeyMapping[GameInput::kKey_lalt] = 56;\r\n        s_DXKeyMapping[GameInput::kKey_space] = 57;\r\n        s_DXKeyMapping[GameInput::kKey_capital] = 58;\r\n        s_DXKeyMapping[GameInput::kKey_f1] = 59;\r\n        s_DXKeyMapping[GameInput::kKey_f2] = 60;\r\n        s_DXKeyMapping[GameInput::kKey_f3] = 61;\r\n        s_DXKeyMapping[GameInput::kKey_f4] = 62;\r\n        s_DXKeyMapping[GameInput::kKey_f5] = 63;\r\n        s_DXKeyMapping[GameInput::kKey_f6] = 64;\r\n        s_DXKeyMapping[GameInput::kKey_f7] = 65;\r\n        s_DXKeyMapping[GameInput::kKey_f8] = 66;\r\n        s_DXKeyMapping[GameInput::kKey_f9] = 67;\r\n        s_DXKeyMapping[GameInput::kKey_f10] = 68;\r\n        s_DXKeyMapping[GameInput::kKey_numlock] = 69;\r\n        s_DXKeyMapping[GameInput::kKey_scroll] = 70;\r\n        s_DXKeyMapping[GameInput::kKey_numpad7] = 71;\r\n        s_DXKeyMapping[GameInput::kKey_numpad8] = 72;\r\n        s_DXKeyMapping[GameInput::kKey_numpad9] = 73;\r\n        s_DXKeyMapping[GameInput::kKey_subtract] = 74;\r\n        s_DXKeyMapping[GameInput::kKey_numpad4] = 75;\r\n        s_DXKeyMapping[GameInput::kKey_numpad5] = 76;\r\n        s_DXKeyMapping[GameInput::kKey_numpad6] = 77;\r\n        s_DXKeyMapping[GameInput::kKey_add] = 78;\r\n        s_DXKeyMapping[GameInput::kKey_numpad1] = 79;\r\n        s_DXKeyMapping[GameInput::kKey_numpad2] = 80;\r\n        s_DXKeyMapping[GameInput::kKey_numpad3] = 81;\r\n        s_DXKeyMapping[GameInput::kKey_numpad0] = 82;\r\n        s_DXKeyMapping[GameInput::kKey_decimal] = 83;\r\n        s_DXKeyMapping[GameInput::kKey_f11] = 87;\r\n        s_DXKeyMapping[GameInput::kKey_f12] = 88;\r\n        s_DXKeyMapping[GameInput::kKey_numpadenter] = 156;\r\n        s_DXKeyMapping[GameInput::kKey_rcontrol] = 157;\r\n        s_DXKeyMapping[GameInput::kKey_divide] = 181;\r\n        s_DXKeyMapping[GameInput::kKey_sysrq] = 183;\r\n        s_DXKeyMapping[GameInput::kKey_ralt] = 184;\r\n        s_DXKeyMapping[GameInput::kKey_pause] = 197;\r\n        s_DXKeyMapping[GameInput::kKey_home] = 199;\r\n        s_DXKeyMapping[GameInput::kKey_up] = 200;\r\n        s_DXKeyMapping[GameInput::kKey_pgup] = 201;\r\n        s_DXKeyMapping[GameInput::kKey_left] = 203;\r\n        s_DXKeyMapping[GameInput::kKey_right] = 205;\r\n        s_DXKeyMapping[GameInput::kKey_end] = 207;\r\n        s_DXKeyMapping[GameInput::kKey_down] = 208;\r\n        s_DXKeyMapping[GameInput::kKey_pgdn] = 209;\r\n        s_DXKeyMapping[GameInput::kKey_insert] = 210;\r\n        s_DXKeyMapping[GameInput::kKey_delete] = 211;\r\n        s_DXKeyMapping[GameInput::kKey_lwin] = 219;\r\n        s_DXKeyMapping[GameInput::kKey_rwin] = 220;\r\n        s_DXKeyMapping[GameInput::kKey_apps] = 221;\r\n#else\r\n#define WinRTKey(name) (unsigned char)Windows::System::VirtualKey::name\r\n        s_DXKeyMapping[GameInput::kKey_escape] = WinRTKey(Escape);\r\n        s_DXKeyMapping[GameInput::kKey_1] = WinRTKey(Number1);\r\n        s_DXKeyMapping[GameInput::kKey_2] = WinRTKey(Number2);\r\n        s_DXKeyMapping[GameInput::kKey_3] = WinRTKey(Number3);\r\n        s_DXKeyMapping[GameInput::kKey_4] = WinRTKey(Number4);\r\n        s_DXKeyMapping[GameInput::kKey_5] = WinRTKey(Number5);\r\n        s_DXKeyMapping[GameInput::kKey_6] = WinRTKey(Number6);\r\n        s_DXKeyMapping[GameInput::kKey_7] = WinRTKey(Number7);\r\n        s_DXKeyMapping[GameInput::kKey_8] = WinRTKey(Number8);\r\n        s_DXKeyMapping[GameInput::kKey_9] = WinRTKey(Number9);\r\n        s_DXKeyMapping[GameInput::kKey_0] = WinRTKey(Number0);\r\n        s_DXKeyMapping[GameInput::kKey_minus] = WinRTKey(Subtract);\r\n        s_DXKeyMapping[GameInput::kKey_equals] = WinRTKey(Add);\r\n        s_DXKeyMapping[GameInput::kKey_back] = WinRTKey(Back);\r\n        s_DXKeyMapping[GameInput::kKey_tab] = WinRTKey(Tab);\r\n        s_DXKeyMapping[GameInput::kKey_q] = WinRTKey(Q);\r\n        s_DXKeyMapping[GameInput::kKey_w] = WinRTKey(W);\r\n        s_DXKeyMapping[GameInput::kKey_e] = WinRTKey(E);\r\n        s_DXKeyMapping[GameInput::kKey_r] = WinRTKey(R);\r\n        s_DXKeyMapping[GameInput::kKey_t] = WinRTKey(T);\r\n        s_DXKeyMapping[GameInput::kKey_y] = WinRTKey(Y);\r\n        s_DXKeyMapping[GameInput::kKey_u] = WinRTKey(U);\r\n        s_DXKeyMapping[GameInput::kKey_i] = WinRTKey(I);\r\n        s_DXKeyMapping[GameInput::kKey_o] = WinRTKey(O);\r\n        s_DXKeyMapping[GameInput::kKey_p] = WinRTKey(P);\r\n        s_DXKeyMapping[GameInput::kKey_lbracket] = 219;\r\n        s_DXKeyMapping[GameInput::kKey_rbracket] = 221;\r\n        s_DXKeyMapping[GameInput::kKey_return] = WinRTKey(Enter);\r\n        s_DXKeyMapping[GameInput::kKey_lcontrol] = WinRTKey(Control);  // No L/R\r\n        s_DXKeyMapping[GameInput::kKey_a] = WinRTKey(A);\r\n        s_DXKeyMapping[GameInput::kKey_s] = WinRTKey(S);\r\n        s_DXKeyMapping[GameInput::kKey_d] = WinRTKey(D);\r\n        s_DXKeyMapping[GameInput::kKey_f] = WinRTKey(F);\r\n        s_DXKeyMapping[GameInput::kKey_g] = WinRTKey(G);\r\n        s_DXKeyMapping[GameInput::kKey_h] = WinRTKey(H);\r\n        s_DXKeyMapping[GameInput::kKey_j] = WinRTKey(J);\r\n        s_DXKeyMapping[GameInput::kKey_k] = WinRTKey(K);\r\n        s_DXKeyMapping[GameInput::kKey_l] = WinRTKey(L);\r\n        s_DXKeyMapping[GameInput::kKey_semicolon] = 186;\r\n        s_DXKeyMapping[GameInput::kKey_apostrophe] = 222;\r\n        s_DXKeyMapping[GameInput::kKey_grave] = 192; // ` or ~\r\n        s_DXKeyMapping[GameInput::kKey_lshift] = WinRTKey(LeftShift);\r\n        s_DXKeyMapping[GameInput::kKey_backslash] = 220;\r\n        s_DXKeyMapping[GameInput::kKey_z] = WinRTKey(Z);\r\n        s_DXKeyMapping[GameInput::kKey_x] = WinRTKey(X);\r\n        s_DXKeyMapping[GameInput::kKey_c] = WinRTKey(C);\r\n        s_DXKeyMapping[GameInput::kKey_v] = WinRTKey(V);\r\n        s_DXKeyMapping[GameInput::kKey_b] = WinRTKey(B);\r\n        s_DXKeyMapping[GameInput::kKey_n] = WinRTKey(N);\r\n        s_DXKeyMapping[GameInput::kKey_m] = WinRTKey(M);\r\n        s_DXKeyMapping[GameInput::kKey_comma] = 188;\r\n        s_DXKeyMapping[GameInput::kKey_period] = 190;\r\n        s_DXKeyMapping[GameInput::kKey_slash] = 191;\r\n        s_DXKeyMapping[GameInput::kKey_rshift] = WinRTKey(RightShift);\r\n        s_DXKeyMapping[GameInput::kKey_multiply] = WinRTKey(Multiply);\r\n        s_DXKeyMapping[GameInput::kKey_lalt] = 255; // Only a modifier\r\n        s_DXKeyMapping[GameInput::kKey_space] = WinRTKey(Space);\r\n        s_DXKeyMapping[GameInput::kKey_capital] = WinRTKey(CapitalLock);\r\n        s_DXKeyMapping[GameInput::kKey_f1] = WinRTKey(F1);\r\n        s_DXKeyMapping[GameInput::kKey_f2] = WinRTKey(F2);\r\n        s_DXKeyMapping[GameInput::kKey_f3] = WinRTKey(F3);\r\n        s_DXKeyMapping[GameInput::kKey_f4] = WinRTKey(F4);\r\n        s_DXKeyMapping[GameInput::kKey_f5] = WinRTKey(F5);\r\n        s_DXKeyMapping[GameInput::kKey_f6] = WinRTKey(F6);\r\n        s_DXKeyMapping[GameInput::kKey_f7] = WinRTKey(F7);\r\n        s_DXKeyMapping[GameInput::kKey_f8] = WinRTKey(F8);\r\n        s_DXKeyMapping[GameInput::kKey_f9] = WinRTKey(F9);\r\n        s_DXKeyMapping[GameInput::kKey_f10] = WinRTKey(F10);\r\n        s_DXKeyMapping[GameInput::kKey_numlock] = WinRTKey(NumberKeyLock);\r\n        s_DXKeyMapping[GameInput::kKey_scroll] = WinRTKey(Scroll);\r\n        s_DXKeyMapping[GameInput::kKey_numpad7] = WinRTKey(NumberPad7);\r\n        s_DXKeyMapping[GameInput::kKey_numpad8] = WinRTKey(NumberPad8);\r\n        s_DXKeyMapping[GameInput::kKey_numpad9] = WinRTKey(NumberPad9);\r\n        s_DXKeyMapping[GameInput::kKey_subtract] = WinRTKey(Subtract);\r\n        s_DXKeyMapping[GameInput::kKey_numpad4] = WinRTKey(NumberPad4);\r\n        s_DXKeyMapping[GameInput::kKey_numpad5] = WinRTKey(NumberPad5);\r\n        s_DXKeyMapping[GameInput::kKey_numpad6] = WinRTKey(NumberPad6);\r\n        s_DXKeyMapping[GameInput::kKey_add] = WinRTKey(Add);\r\n        s_DXKeyMapping[GameInput::kKey_numpad1] = WinRTKey(NumberPad1);\r\n        s_DXKeyMapping[GameInput::kKey_numpad2] = WinRTKey(NumberPad2);\r\n        s_DXKeyMapping[GameInput::kKey_numpad3] = WinRTKey(NumberPad3);\r\n        s_DXKeyMapping[GameInput::kKey_numpad0] = WinRTKey(NumberPad0);\r\n        s_DXKeyMapping[GameInput::kKey_decimal] = WinRTKey(Decimal);\r\n        s_DXKeyMapping[GameInput::kKey_f11] = WinRTKey(F11);\r\n        s_DXKeyMapping[GameInput::kKey_f12] = WinRTKey(F12);\r\n        s_DXKeyMapping[GameInput::kKey_numpadenter] = WinRTKey(Enter); // No distinction\r\n        s_DXKeyMapping[GameInput::kKey_rcontrol] = WinRTKey(Control);  // No L/R\r\n        s_DXKeyMapping[GameInput::kKey_divide] = WinRTKey(Divide);\r\n        s_DXKeyMapping[GameInput::kKey_sysrq] = 255; // Ignored\r\n        s_DXKeyMapping[GameInput::kKey_ralt] = 255; // Only a modifier\r\n        s_DXKeyMapping[GameInput::kKey_pause] = WinRTKey(Pause);\r\n        s_DXKeyMapping[GameInput::kKey_home] = WinRTKey(Home);\r\n        s_DXKeyMapping[GameInput::kKey_up] = WinRTKey(Up);\r\n        s_DXKeyMapping[GameInput::kKey_pgup] = WinRTKey(PageUp);\r\n        s_DXKeyMapping[GameInput::kKey_left] = WinRTKey(Left);\r\n        s_DXKeyMapping[GameInput::kKey_right] = WinRTKey(Right);\r\n        s_DXKeyMapping[GameInput::kKey_end] = WinRTKey(End);\r\n        s_DXKeyMapping[GameInput::kKey_down] = WinRTKey(Down);\r\n        s_DXKeyMapping[GameInput::kKey_pgdn] = WinRTKey(PageDown);\r\n        s_DXKeyMapping[GameInput::kKey_insert] = WinRTKey(Insert);\r\n        s_DXKeyMapping[GameInput::kKey_delete] = WinRTKey(Delete);\r\n        s_DXKeyMapping[GameInput::kKey_lwin] = WinRTKey(LeftWindows);\r\n        s_DXKeyMapping[GameInput::kKey_rwin] = WinRTKey(RightWindows);\r\n        s_DXKeyMapping[GameInput::kKey_apps] = WinRTKey(Application);\r\n#endif\r\n    }\r\n\r\n    void KbmZeroInputs()\r\n    {\r\n        memset(&s_MouseState, 0, sizeof(DIMOUSESTATE2));\r\n        memset(s_Keybuffer, 0, sizeof(s_Keybuffer));\r\n    }\r\n\r\n    void KbmInitialize()\r\n    {\r\n        KbmBuildKeyMapping();\r\n\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n        if (FAILED(DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&s_DI, nullptr)))\r\n            ASSERT(false, \"DirectInput8 initialization failed.\");\r\n\r\n        if (FAILED(s_DI->CreateDevice(GUID_SysKeyboard, &s_Keyboard, nullptr)))\r\n            ASSERT(false, \"Keyboard CreateDevice failed.\");\r\n        if (FAILED(s_Keyboard->SetDataFormat(&c_dfDIKeyboard)))\r\n            ASSERT(false, \"Keyboard SetDataFormat failed.\");\r\n        if (FAILED(s_Keyboard->SetCooperativeLevel(GameCore::g_hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))\r\n            ASSERT(false, \"Keyboard SetCooperativeLevel failed.\");\r\n\r\n        DIPROPDWORD dipdw;\r\n        dipdw.diph.dwSize = sizeof(DIPROPDWORD);\r\n        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);\r\n        dipdw.diph.dwObj = 0;\r\n        dipdw.diph.dwHow = DIPH_DEVICE;\r\n        dipdw.dwData = 10;\r\n        if (FAILED(s_Keyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))\r\n            ASSERT(false, \"Keyboard set buffer size failed.\");\r\n\r\n        if (FAILED(s_DI->CreateDevice(GUID_SysMouse, &s_Mouse, nullptr)))\r\n            ASSERT(false, \"Mouse CreateDevice failed.\");\r\n        if (FAILED(s_Mouse->SetDataFormat(&c_dfDIMouse2)))\r\n            ASSERT(false, \"Mouse SetDataFormat failed.\");\r\n        if (FAILED(s_Mouse->SetCooperativeLevel(GameCore::g_hWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE)))\r\n            ASSERT(false, \"Mouse SetCooperativeLevel failed.\");\r\n#endif\r\n\r\n        KbmZeroInputs();\r\n    }\r\n\r\n    void KbmShutdown()\r\n    {\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n        if (s_Keyboard)\r\n        {\r\n            s_Keyboard->Unacquire();\r\n            s_Keyboard->Release();\r\n            s_Keyboard = nullptr;\r\n        }\r\n        if (s_Mouse)\r\n        {\r\n            s_Mouse->Unacquire();\r\n            s_Mouse->Release();\r\n            s_Mouse = nullptr;\r\n        }\r\n        if (s_DI)\r\n        {\r\n            s_DI->Release();\r\n            s_DI = nullptr;\r\n        }\r\n#endif\r\n    }\r\n\r\n    void KbmUpdate()\r\n    {\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n        HWND foreground = GetForegroundWindow();\r\n        bool visible = IsWindowVisible(foreground) != 0;\r\n\r\n        if (foreground != GameCore::g_hWnd // wouldn't be able to acquire\r\n            || !visible)\r\n        {\r\n            KbmZeroInputs();\r\n        }\r\n        else\r\n        {\r\n            s_Mouse->Acquire();\r\n            s_Mouse->GetDeviceState(sizeof(DIMOUSESTATE2), &s_MouseState);\r\n            s_Keyboard->Acquire();\r\n            s_Keyboard->GetDeviceState(sizeof(s_Keybuffer), s_Keybuffer);\r\n        }\r\n#endif\r\n    }\r\n\r\n#endif\r\n\r\n}\r\n\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_TV_TITLE)\r\nvoid GameInput::SetKeyState(Windows::System::VirtualKey key, bool IsDown)\r\n{\r\n    s_Keybuffer[(unsigned char)key] = IsDown ? 0x80 : 0x00;\r\n    //DEBUGPRINT(\"%d key is %s\", (unsigned int)key, IsDown ? \"down\" : \"up\");\r\n}\r\n#endif\r\n\r\nvoid GameInput::Initialize()\r\n{\r\n    // For Windows 8\r\n    //\tXInputEnable(TRUE);\r\n\r\n    ZeroMemory( s_Buttons, sizeof(s_Buttons) );\r\n    ZeroMemory( s_Analogs, sizeof(s_Analogs) );\r\n\r\n#ifdef USE_KEYBOARD_MOUSE\r\n    KbmInitialize();\r\n#endif\r\n}\r\n\r\nvoid GameInput::Shutdown()\r\n{\r\n#ifdef USE_KEYBOARD_MOUSE\r\n    KbmShutdown();\r\n#endif\r\n}\r\n\r\nvoid GameInput::Update( float frameDelta )\r\n{\r\n    memcpy(s_Buttons[1], s_Buttons[0], sizeof(s_Buttons[0]));\r\n    memset(s_Buttons[0], 0, sizeof(s_Buttons[0]));\r\n    memset(s_Analogs, 0, sizeof(s_Analogs));\r\n\r\n#ifdef USE_XINPUT\r\n    XINPUT_STATE newInputState;\r\n    if (ERROR_SUCCESS == XInputGetState( 0, &newInputState ))\r\n    {\r\n        if (newInputState.Gamepad.wButtons & (1 << 0)) s_Buttons[0][kDPadUp] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 1)) s_Buttons[0][kDPadDown] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 2)) s_Buttons[0][kDPadLeft] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 3)) s_Buttons[0][kDPadRight] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 4)) s_Buttons[0][kStartButton] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 5)) s_Buttons[0][kBackButton] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 6)) s_Buttons[0][kLThumbClick] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 7)) s_Buttons[0][kRThumbClick] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 8)) s_Buttons[0][kLShoulder] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 9)) s_Buttons[0][kRShoulder] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 12)) s_Buttons[0][kAButton] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 13)) s_Buttons[0][kBButton] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 14)) s_Buttons[0][kXButton] = true;\r\n        if (newInputState.Gamepad.wButtons & (1 << 15)) s_Buttons[0][kYButton] = true;\r\n\r\n        s_Analogs[ kAnalogLeftTrigger ]\t\t= newInputState.Gamepad.bLeftTrigger / 255.0f;\r\n        s_Analogs[ kAnalogRightTrigger ]\t= newInputState.Gamepad.bRightTrigger / 255.0f;\r\n        s_Analogs[ kAnalogLeftStickX ]\t\t= FilterAnalogInput(newInputState.Gamepad.sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE );\r\n        s_Analogs[ kAnalogLeftStickY ]\t\t= FilterAnalogInput(newInputState.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE );\r\n        s_Analogs[ kAnalogRightStickX ]\t\t= FilterAnalogInput(newInputState.Gamepad.sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE );\r\n        s_Analogs[ kAnalogRightStickY ]\t\t= FilterAnalogInput(newInputState.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE );\r\n    }\r\n#else\r\n\r\n    IVectorView<Gamepad^>^ gamepads = Gamepad::Gamepads;\r\n    if (gamepads->Size != 0)\r\n    {\r\n        IGamepad^ gamepad = gamepads->GetAt(0);\r\n        GamepadReading reading = gamepad->GetCurrentReading();\r\n        uint32_t Buttons = (uint32_t)reading.Buttons;\r\n        if (Buttons & (uint32_t)GamepadButtons::DPadUp) s_Buttons[0][kDPadUp] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::DPadDown) s_Buttons[0][kDPadDown] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::DPadLeft) s_Buttons[0][kDPadLeft] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::DPadRight) s_Buttons[0][kDPadRight] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::Menu) s_Buttons[0][kStartButton] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::View) s_Buttons[0][kBackButton] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::LeftThumbstick) s_Buttons[0][kLThumbClick] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::RightThumbstick) s_Buttons[0][kRThumbClick] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::LeftShoulder) s_Buttons[0][kLShoulder] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::RightShoulder) s_Buttons[0][kRShoulder] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::A) s_Buttons[0][kAButton] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::B) s_Buttons[0][kBButton] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::X) s_Buttons[0][kXButton] = true;\r\n        if (Buttons & (uint32_t)GamepadButtons::Y) s_Buttons[0][kYButton] = true;\r\n\r\n        static const float kAnalogStickDeadZone = 0.18f;\r\n\r\n        s_Analogs[ kAnalogLeftTrigger ]\t\t= (float)reading.LeftTrigger;\r\n        s_Analogs[ kAnalogRightTrigger ]\t= (float)reading.RightTrigger;\r\n        s_Analogs[ kAnalogLeftStickX ]\t\t= FilterAnalogInput((float)reading.LeftThumbstickX, kAnalogStickDeadZone );\r\n        s_Analogs[ kAnalogLeftStickY ]\t\t= FilterAnalogInput((float)reading.LeftThumbstickY, kAnalogStickDeadZone );\r\n        s_Analogs[ kAnalogRightStickX ]\t\t= FilterAnalogInput((float)reading.RightThumbstickX, kAnalogStickDeadZone );\r\n        s_Analogs[ kAnalogRightStickY ]\t\t= FilterAnalogInput((float)reading.RightThumbstickY, kAnalogStickDeadZone );\r\n    }\r\n\r\n#endif\r\n\r\n#ifdef USE_KEYBOARD_MOUSE\r\n    KbmUpdate();\r\n\r\n    for (uint32_t i = 0; i < kNumKeys; ++i)\r\n    {\r\n        s_Buttons[0][i] = (s_Keybuffer[s_DXKeyMapping[i]] & 0x80) != 0;\r\n    }\r\n\r\n    for (uint32_t i = 0; i < 8; ++i)\r\n    {\r\n        if (s_MouseState.rgbButtons[i] > 0) s_Buttons[0][kMouse0 + i] = true;\r\n    }\r\n\r\n    s_Analogs[kAnalogMouseX] = (float)s_MouseState.lX * .0018f;\r\n    s_Analogs[kAnalogMouseY] = (float)s_MouseState.lY * -.0018f;\r\n\r\n    if (s_MouseState.lZ > 0)\r\n        s_Analogs[kAnalogMouseScroll] = 1.0f;\r\n    else if (s_MouseState.lZ < 0)\r\n        s_Analogs[kAnalogMouseScroll] = -1.0f;\r\n#endif\r\n\r\n    // Update time duration for buttons pressed\r\n    for (uint32_t i = 0; i < kNumDigitalInputs; ++i)\r\n    {\r\n        if (s_Buttons[0][i])\r\n        {\r\n            if (!s_Buttons[1][i])\r\n                s_HoldDuration[i] = 0.0f;\r\n            else\r\n                s_HoldDuration[i] += frameDelta;\r\n        }\r\n    }\r\n\r\n    for (uint32_t i = 0; i < kNumAnalogInputs; ++i)\r\n    {\r\n        s_AnalogsTC[i] = s_Analogs[i] * frameDelta;\r\n    }\r\n\r\n}\r\n\r\nbool GameInput::IsAnyPressed( void )\r\n{\r\n    return ReadInputAllowed() ? s_Buttons[0] != 0 : false;\r\n}\r\n\r\nbool GameInput::IsPressed( DigitalInput di )\r\n{\r\n\treturn ReadInputAllowed() ? s_Buttons[0][di] : false;\r\n}\r\n\r\nbool GameInput::IsFirstPressed( DigitalInput di )\r\n{\r\n    return ReadInputAllowed() ? (s_Buttons[0][di] && !s_Buttons[1][di]) : false;\r\n}\r\n\r\nbool GameInput::IsReleased( DigitalInput di )\r\n{\r\n    return ReadInputAllowed() ? !s_Buttons[0][di] : true;\r\n}\r\n\r\nbool GameInput::IsFirstReleased( DigitalInput di )\r\n{\r\n    return ReadInputAllowed() ? (!s_Buttons[0][di] && s_Buttons[1][di]) : false;\r\n}\r\n\r\nfloat GameInput::GetDurationPressed( DigitalInput di )\r\n{\r\n    return ReadInputAllowed() ? s_HoldDuration[di] : 0.0f;\r\n}\r\n\r\nvoid GameInput::ClearDigitalInput(DigitalInput di) \r\n{\r\n\ts_Buttons[0][di] = false;\r\n\ts_Buttons[1][di] = false;\r\n\ts_HoldDuration[di] = 0.0f;\r\n}\r\n\r\nvoid GameInput::AllowReadInputs(bool enable) {\r\n\ts_allowInputReads = enable;\r\n}\r\n\r\nbool GameInput::ReadInputAllowed() {\r\n\treturn s_allowInputReads;\r\n}\r\n\r\nfloat GameInput::GetAnalogInput( AnalogInput ai )\r\n{\r\n    return ReadInputAllowed() ?  s_Analogs[ai] : 0.0f;\r\n}\r\n\r\nfloat GameInput::GetTimeCorrectedAnalogInput( AnalogInput ai )\r\n{\r\n    return ReadInputAllowed() ? s_AnalogsTC[ai] : 0.0f;\r\n}\r\n\r\nvoid GameInput::ClearInputStates() {\r\n\tKbmZeroInputs();\r\n\tZeroMemory(s_Buttons, sizeof(s_Buttons));\r\n\tZeroMemory(s_HoldDuration, sizeof(s_HoldDuration));\r\n\tZeroMemory(s_AnalogsTC, sizeof(s_AnalogsTC));\r\n\tZeroMemory(s_Analogs, sizeof(s_Analogs));\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GameInput.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\nnamespace GameInput\r\n{\r\n    void Initialize();\r\n    void Shutdown();\r\n    void Update( float frameDelta );\r\n\r\n    enum DigitalInput\r\n    {\r\n        // keyboard\r\n        // kKey must start at zero, see s_DXKeyMapping\r\n        kKey_escape = 0,\r\n        kKey_1,\r\n        kKey_2,\r\n        kKey_3,\r\n        kKey_4,\r\n        kKey_5,\r\n        kKey_6,\r\n        kKey_7,\r\n        kKey_8,\r\n        kKey_9,\r\n        kKey_0,\r\n        kKey_minus,\r\n        kKey_equals,\r\n        kKey_back,\r\n        kKey_tab,\r\n        kKey_q,\r\n        kKey_w,\r\n        kKey_e,\r\n        kKey_r,\r\n        kKey_t,\r\n        kKey_y,\r\n        kKey_u,\r\n        kKey_i,\r\n        kKey_o,\r\n        kKey_p,\r\n        kKey_lbracket,\r\n        kKey_rbracket,\r\n        kKey_return,\r\n        kKey_lcontrol,\r\n        kKey_a,\r\n        kKey_s,\r\n        kKey_d,\r\n        kKey_f,\r\n        kKey_g,\r\n        kKey_h,\r\n        kKey_j,\r\n        kKey_k,\r\n        kKey_l,\r\n        kKey_semicolon,\r\n        kKey_apostrophe,\r\n        kKey_grave,\r\n        kKey_lshift,\r\n        kKey_backslash,\r\n        kKey_z,\r\n        kKey_x,\r\n        kKey_c,\r\n        kKey_v,\r\n        kKey_b,\r\n        kKey_n,\r\n        kKey_m,\r\n        kKey_comma,\r\n        kKey_period,\r\n        kKey_slash,\r\n        kKey_rshift,\r\n        kKey_multiply,\r\n        kKey_lalt,\r\n        kKey_space,\r\n        kKey_capital,\r\n        kKey_f1,\r\n        kKey_f2,\r\n        kKey_f3,\r\n        kKey_f4,\r\n        kKey_f5,\r\n        kKey_f6,\r\n        kKey_f7,\r\n        kKey_f8,\r\n        kKey_f9,\r\n        kKey_f10,\r\n        kKey_numlock,\r\n        kKey_scroll,\r\n        kKey_numpad7,\r\n        kKey_numpad8,\r\n        kKey_numpad9,\r\n        kKey_subtract,\r\n        kKey_numpad4,\r\n        kKey_numpad5,\r\n        kKey_numpad6,\r\n        kKey_add,\r\n        kKey_numpad1,\r\n        kKey_numpad2,\r\n        kKey_numpad3,\r\n        kKey_numpad0,\r\n        kKey_decimal,\r\n        kKey_f11,\r\n        kKey_f12,\r\n        kKey_numpadenter,\r\n        kKey_rcontrol,\r\n        kKey_divide,\r\n        kKey_sysrq,\r\n        kKey_ralt,\r\n        kKey_pause,\r\n        kKey_home,\r\n        kKey_up,\r\n        kKey_pgup,\r\n        kKey_left,\r\n        kKey_right,\r\n        kKey_end,\r\n        kKey_down,\r\n        kKey_pgdn,\r\n        kKey_insert,\r\n        kKey_delete,\r\n        kKey_lwin,\r\n        kKey_rwin,\r\n        kKey_apps,\r\n\r\n        kNumKeys,\r\n\r\n        // gamepad\r\n        kDPadUp = kNumKeys,\r\n        kDPadDown,\r\n        kDPadLeft,\r\n        kDPadRight,\r\n        kStartButton,\r\n        kBackButton,\r\n        kLThumbClick,\r\n        kRThumbClick,\r\n        kLShoulder,\r\n        kRShoulder,\r\n        kAButton,\r\n        kBButton,\r\n        kXButton,\r\n        kYButton,\r\n\r\n        // mouse\r\n        kMouse0,\r\n        kMouse1,\r\n        kMouse2,\r\n        kMouse3,\r\n        kMouse4,\r\n        kMouse5,\r\n        kMouse6,\r\n        kMouse7,\r\n\r\n        kNumDigitalInputs\r\n    };\r\n\r\n    enum AnalogInput\r\n    {\r\n        // gamepad\r\n        kAnalogLeftTrigger,\r\n        kAnalogRightTrigger,\r\n        kAnalogLeftStickX,\r\n        kAnalogLeftStickY,\r\n        kAnalogRightStickX,\r\n        kAnalogRightStickY,\r\n\r\n        // mouse\r\n        kAnalogMouseX,\r\n        kAnalogMouseY,\r\n        kAnalogMouseScroll,\r\n\r\n        kNumAnalogInputs\r\n    };\r\n\r\n    bool IsAnyPressed( void );\r\n\r\n    bool IsPressed( DigitalInput di );\r\n    bool IsFirstPressed( DigitalInput di );\r\n    bool IsReleased( DigitalInput di );\r\n    bool IsFirstReleased( DigitalInput di );\r\n\r\n\t// added this modification for the GUI: we would like to temporarily disable the game input, but preserve the key states\r\n\t// to keep detecting deltas\r\n\tvoid AllowReadInputs(bool enable);\r\n\tbool ReadInputAllowed();\r\n\r\n\t// we added this method to allow the \"consumption\" of digital inputs by objects in focus\r\n\t// This way other objects will observe the input state (such as a key) as if it has not occured\r\n\tvoid ClearDigitalInput(DigitalInput di);\r\n\r\n    float GetDurationPressed( DigitalInput di );\r\n\r\n    float GetAnalogInput( AnalogInput ai );\r\n    float GetTimeCorrectedAnalogInput( AnalogInput ai );\r\n\r\n\t// we would like to prevent the application to track keys and mouse if the GUI gets focus\r\n\t// the only way to do this is to block it from seeing the keyboard state\r\n\t// (since this is not a message-based system that could be filtered)\r\n\tvoid ClearInputStates();\r\n\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE | WINAPI_PARTITION_DESKTOP)\r\n    void SetKeyState(Windows::System::VirtualKey key, bool IsDown);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GpuBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GpuBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"EsramAllocator.h\"\r\n#include \"CommandContext.h\"\r\n#include \"BufferManager.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nvoid GpuBuffer::Create( const std::wstring& name, uint32_t NumElements, uint32_t ElementSize, const void* initialData )\r\n{\r\n    GpuResource::Destroy();\r\n\r\n    m_ElementCount = NumElements;\r\n    m_ElementSize = ElementSize;\r\n    m_BufferSize = NumElements * ElementSize;\r\n\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeBuffer();\r\n\r\n    m_UsageState = D3D12_RESOURCE_STATE_COMMON;\r\n\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    ASSERT_SUCCEEDED( \r\n        g_Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE,\r\n        &ResourceDesc, m_UsageState, nullptr, MY_IID_PPV_ARGS(&m_pResource)) );\r\n\r\n    m_GpuVirtualAddress = m_pResource->GetGPUVirtualAddress();\r\n\r\n    if (initialData)\r\n        CommandContext::InitializeBuffer(*this, initialData, m_BufferSize);\r\n\r\n#ifdef RELEASE\r\n    (name);\r\n#else\r\n    m_pResource->SetName(name.c_str());\r\n#endif\r\n\r\n    CreateDerivedViews();\r\n}\r\n\r\n// Sub-Allocate a buffer out of a pre-allocated heap.  If initial data is provided, it will be copied into the buffer using the default command context.\r\nvoid GpuBuffer::CreatePlaced(const std::wstring& name, ID3D12Heap* pBackingHeap, uint32_t HeapOffset, uint32_t NumElements, uint32_t ElementSize,\r\n    const void* initialData)\r\n{\r\n    m_ElementCount = NumElements;\r\n    m_ElementSize = ElementSize;\r\n    m_BufferSize = NumElements * ElementSize;\r\n\r\n    D3D12_RESOURCE_DESC ResourceDesc = DescribeBuffer();\r\n\r\n    m_UsageState = D3D12_RESOURCE_STATE_COMMON;\r\n\r\n    ASSERT_SUCCEEDED(g_Device->CreatePlacedResource(pBackingHeap, HeapOffset, &ResourceDesc, m_UsageState, nullptr, MY_IID_PPV_ARGS(&m_pResource)));\r\n\r\n    m_GpuVirtualAddress = m_pResource->GetGPUVirtualAddress();\r\n\r\n    if (initialData)\r\n        CommandContext::InitializeBuffer(*this, initialData, m_BufferSize);\r\n\r\n#ifdef RELEASE\r\n    (name);\r\n#else\r\n    m_pResource->SetName(name.c_str());\r\n#endif\r\n\r\n    CreateDerivedViews();\r\n\r\n}\r\n\r\nvoid GpuBuffer::Create(const std::wstring& name, uint32_t NumElements, uint32_t ElementSize,\r\n    EsramAllocator&, const void* initialData)\r\n{\r\n    Create(name, NumElements, ElementSize, initialData);\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE GpuBuffer::CreateConstantBufferView(uint32_t Offset, uint32_t Size) const\r\n{\r\n    ASSERT(Offset + Size <= m_BufferSize);\r\n\r\n    Size = Math::AlignUp(Size, 16);\r\n\r\n    D3D12_CONSTANT_BUFFER_VIEW_DESC CBVDesc;\r\n    CBVDesc.BufferLocation = m_GpuVirtualAddress + (size_t)Offset;\r\n    CBVDesc.SizeInBytes = Size;\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE hCBV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateConstantBufferView(&CBVDesc, hCBV);\r\n    return hCBV;\r\n}\r\n\r\nD3D12_RESOURCE_DESC GpuBuffer::DescribeBuffer(void)\r\n{\r\n    ASSERT(m_BufferSize != 0);\r\n\r\n    D3D12_RESOURCE_DESC Desc = {};\r\n    Desc.Alignment = 0;\r\n    Desc.DepthOrArraySize = 1;\r\n    Desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;\r\n    Desc.Flags = m_ResourceFlags;\r\n    Desc.Format = DXGI_FORMAT_UNKNOWN;\r\n    Desc.Height = 1;\r\n    Desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;\r\n    Desc.MipLevels = 1;\r\n    Desc.SampleDesc.Count = 1;\r\n    Desc.SampleDesc.Quality = 0;\r\n    Desc.Width = (UINT64)m_BufferSize;\r\n    return Desc;\r\n}\r\n\r\nvoid ByteAddressBuffer::CreateDerivedViews(void)\r\n{\r\n    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n    SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;\r\n    SRVDesc.Format = DXGI_FORMAT_R32_TYPELESS;\r\n    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n    SRVDesc.Buffer.NumElements = (UINT)m_BufferSize / 4;\r\n    SRVDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;\r\n\r\n    if (m_SRV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_SRV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateShaderResourceView(m_pResource.Get(), &SRVDesc, m_SRV);\r\n\r\n    D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};\r\n    UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;\r\n    UAVDesc.Format = DXGI_FORMAT_R32_TYPELESS;\r\n    UAVDesc.Buffer.NumElements = (UINT)m_BufferSize / 4;\r\n    UAVDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;\r\n\r\n    if (m_UAV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_UAV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateUnorderedAccessView( m_pResource.Get(), nullptr, &UAVDesc, m_UAV );\r\n}\r\n\r\nvoid StructuredBuffer::CreateDerivedViews(void)\r\n{\r\n    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n    SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;\r\n    SRVDesc.Format = DXGI_FORMAT_UNKNOWN;\r\n    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n    SRVDesc.Buffer.NumElements = m_ElementCount;\r\n    SRVDesc.Buffer.StructureByteStride = m_ElementSize;\r\n    SRVDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;\r\n\r\n    if (m_SRV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_SRV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateShaderResourceView(m_pResource.Get(), &SRVDesc, m_SRV);\r\n\r\n    D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};\r\n    UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;\r\n    UAVDesc.Format = DXGI_FORMAT_UNKNOWN;\r\n    UAVDesc.Buffer.CounterOffsetInBytes = 0;\r\n    UAVDesc.Buffer.NumElements = m_ElementCount;\r\n    UAVDesc.Buffer.StructureByteStride = m_ElementSize;\r\n    UAVDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;\r\n\r\n    m_CounterBuffer.Create(L\"StructuredBuffer::Counter\", 1, 4);\r\n\r\n    if (m_UAV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_UAV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateUnorderedAccessView(m_pResource.Get(), m_CounterBuffer.GetResource(), &UAVDesc, m_UAV);\r\n}\r\n\r\nvoid TypedBuffer::CreateDerivedViews(void)\r\n{\r\n    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n    SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;\r\n    SRVDesc.Format = m_DataFormat;\r\n    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n    SRVDesc.Buffer.NumElements = m_ElementCount;\r\n    SRVDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;\r\n\r\n    if (m_SRV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_SRV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateShaderResourceView(m_pResource.Get(), &SRVDesc, m_SRV);\r\n\r\n    D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {};\r\n    UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;\r\n    UAVDesc.Format = m_DataFormat;\r\n    UAVDesc.Buffer.NumElements = m_ElementCount;\r\n    UAVDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;\r\n\r\n    if (m_UAV.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_UAV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateUnorderedAccessView(m_pResource.Get(), nullptr, &UAVDesc, m_UAV);\r\n}\r\n\r\nconst D3D12_CPU_DESCRIPTOR_HANDLE& StructuredBuffer::GetCounterSRV(CommandContext& Context)\r\n{\r\n    Context.TransitionResource(m_CounterBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);\r\n    return m_CounterBuffer.GetSRV();\r\n}\r\n\r\nconst D3D12_CPU_DESCRIPTOR_HANDLE& StructuredBuffer::GetCounterUAV(CommandContext& Context)\r\n{\r\n    Context.TransitionResource(m_CounterBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    return m_CounterBuffer.GetUAV();\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GpuBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n#include \"GpuResource.h\"\r\n\r\nclass CommandContext;\r\nclass EsramAllocator;\r\n\r\nclass GpuBuffer : public GpuResource\r\n{\r\npublic:\r\n    virtual ~GpuBuffer() { Destroy(); }\r\n\r\n    // Create a buffer.  If initial data is provided, it will be copied into the buffer using the default command context.\r\n    void Create( const std::wstring& name, uint32_t NumElements, uint32_t ElementSize,\r\n        const void* initialData = nullptr );\r\n\r\n    // Create a buffer in ESRAM.  On Windows, ESRAM is not used.\r\n    void Create( const std::wstring& name, uint32_t NumElements, uint32_t ElementSize,\r\n        EsramAllocator& Allocator, const void* initialData = nullptr);\r\n\r\n    // Sub-Allocate a buffer out of a pre-allocated heap.  If initial data is provided, it will be copied into the buffer using the default command context.\r\n    void CreatePlaced(const std::wstring& name, ID3D12Heap* pBackingHeap, uint32_t HeapOffset, uint32_t NumElements, uint32_t ElementSize,\r\n        const void* initialData = nullptr);\r\n\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetUAV(void) const { return m_UAV; }\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetSRV(void) const { return m_SRV; }\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS RootConstantBufferView(void) const { return m_GpuVirtualAddress; }\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE CreateConstantBufferView( uint32_t Offset, uint32_t Size ) const;\r\n\r\n    D3D12_VERTEX_BUFFER_VIEW VertexBufferView(size_t Offset, uint32_t Size, uint32_t Stride) const;\r\n    D3D12_VERTEX_BUFFER_VIEW VertexBufferView(size_t BaseVertexIndex = 0) const\r\n    {\r\n        size_t Offset = BaseVertexIndex * m_ElementSize;\r\n        return VertexBufferView(Offset, (uint32_t)(m_BufferSize - Offset), m_ElementSize);\r\n    }\r\n\r\n    D3D12_INDEX_BUFFER_VIEW IndexBufferView(size_t Offset, uint32_t Size, bool b32Bit = false) const;\r\n    D3D12_INDEX_BUFFER_VIEW IndexBufferView(size_t StartIndex = 0) const\r\n    {\r\n        size_t Offset = StartIndex * m_ElementSize;\r\n        return IndexBufferView(Offset, (uint32_t)(m_BufferSize - Offset), m_ElementSize == 4);\r\n    }\r\n\r\n    size_t GetBufferSize() const { return m_BufferSize; }\r\n    uint32_t GetElementCount() const { return m_ElementCount; }\r\n    uint32_t GetElementSize() const { return m_ElementSize; }\r\n\r\nprotected:\r\n\r\n    GpuBuffer(void) : m_BufferSize(0), m_ElementCount(0), m_ElementSize(0)\r\n    {\r\n        m_ResourceFlags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;\r\n        m_UAV.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n        m_SRV.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN;\r\n    }\r\n\r\n    D3D12_RESOURCE_DESC DescribeBuffer(void);\r\n    virtual void CreateDerivedViews(void) = 0;\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_UAV;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_SRV;\r\n\r\n    size_t m_BufferSize;\r\n    uint32_t m_ElementCount;\r\n    uint32_t m_ElementSize;\r\n    D3D12_RESOURCE_FLAGS m_ResourceFlags;\r\n};\r\n\r\ninline D3D12_VERTEX_BUFFER_VIEW GpuBuffer::VertexBufferView(size_t Offset, uint32_t Size, uint32_t Stride) const\r\n{\r\n    D3D12_VERTEX_BUFFER_VIEW VBView;\r\n    VBView.BufferLocation = m_GpuVirtualAddress + Offset;\r\n    VBView.SizeInBytes = Size;\r\n    VBView.StrideInBytes = Stride;\r\n    return VBView;\r\n}\r\n\r\ninline D3D12_INDEX_BUFFER_VIEW GpuBuffer::IndexBufferView(size_t Offset, uint32_t Size, bool b32Bit) const\r\n{\r\n    D3D12_INDEX_BUFFER_VIEW IBView;\r\n    IBView.BufferLocation = m_GpuVirtualAddress + Offset;\r\n    IBView.Format = b32Bit ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;\r\n    IBView.SizeInBytes = Size;\r\n    return IBView;\r\n}\r\n\r\nclass ByteAddressBuffer : public GpuBuffer\r\n{\r\npublic:\r\n    virtual void CreateDerivedViews(void) override;\r\n};\r\n\r\nclass IndirectArgsBuffer : public ByteAddressBuffer\r\n{\r\npublic:\r\n    IndirectArgsBuffer(void)\r\n    {\r\n    }\r\n};\r\n\r\nclass StructuredBuffer : public GpuBuffer\r\n{\r\npublic:\r\n    virtual void Destroy(void) override\r\n    {\r\n        m_CounterBuffer.Destroy();\r\n        GpuBuffer::Destroy();\r\n    }\r\n\r\n    virtual void CreateDerivedViews(void) override;\r\n\r\n    ByteAddressBuffer& GetCounterBuffer(void) { return m_CounterBuffer; }\r\n\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetCounterSRV(CommandContext& Context);\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetCounterUAV(CommandContext& Context);\r\n\r\nprivate:\r\n    ByteAddressBuffer m_CounterBuffer;\r\n};\r\n\r\nclass TypedBuffer : public GpuBuffer\r\n{\r\npublic:\r\n    TypedBuffer( DXGI_FORMAT Format ) : m_DataFormat(Format) {}\r\n    virtual void CreateDerivedViews(void) override;\r\n\r\nprotected:\r\n    DXGI_FORMAT m_DataFormat;\r\n};\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/GpuCounterManager.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GpuCounterManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"CommandListManager.h\"\r\n\r\nnamespace\r\n{\r\n    ID3D12QueryHeap* sm_TimerQueryHeap = nullptr;\r\n    ID3D12Resource* sm_TimerReadBackBuffer = nullptr;\r\n    uint64_t* sm_TimeStampBuffer = nullptr;\r\n    uint64_t sm_Fence = 0;\r\n    uint32_t sm_MaxNumTimers = 0;\r\n    uint32_t sm_NumTimers = 1;\r\n    uint64_t sm_ValidTimeStart = 0;\r\n    uint64_t sm_ValidTimeEnd = 0;\r\n    double sm_GpuTickDelta = 0.0;\r\n\r\n\t// pipeline statistics\r\n\tID3D12QueryHeap* sm_PipelineQueryHeap = nullptr;\r\n\tID3D12Resource* sm_PipelineQueryReadbackBuffer = nullptr;\r\n\tD3D12_QUERY_DATA_PIPELINE_STATISTICS* sm_PipelineQueryDataBuffer = nullptr;\r\n\tuint32_t sm_MaxNumPipelineQueries = 0;\r\n\tuint32_t sm_NumPipelineQueries = 0;\r\n\r\n}\r\n\r\nvoid GpuCounterManager::Initialize(uint32_t MaxNumTimers, uint32_t MaxNumPipelineQueries)\r\n{\r\n    uint64_t GpuFrequency;\r\n    Graphics::g_CommandManager.GetCommandQueue()->GetTimestampFrequency(&GpuFrequency);\r\n    sm_GpuTickDelta = 1.0 / static_cast<double>(GpuFrequency);\r\n\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.Type = D3D12_HEAP_TYPE_READBACK;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    D3D12_RESOURCE_DESC TimerQueryBufferDesc;\r\n    TimerQueryBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;\r\n    TimerQueryBufferDesc.Alignment = 0;\r\n    TimerQueryBufferDesc.Width = sizeof(uint64_t) * MaxNumTimers * 2;\r\n    TimerQueryBufferDesc.Height = 1;\r\n    TimerQueryBufferDesc.DepthOrArraySize = 1;\r\n    TimerQueryBufferDesc.MipLevels = 1;\r\n    TimerQueryBufferDesc.Format = DXGI_FORMAT_UNKNOWN;\r\n    TimerQueryBufferDesc.SampleDesc.Count = 1;\r\n    TimerQueryBufferDesc.SampleDesc.Quality = 0;\r\n    TimerQueryBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;\r\n    TimerQueryBufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;\r\n\r\n\tD3D12_RESOURCE_DESC PipelineQueryBufferDesc = TimerQueryBufferDesc;\r\n\tPipelineQueryBufferDesc.Width = sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS) * MaxNumPipelineQueries;\r\n\r\n    ASSERT_SUCCEEDED(Graphics::g_Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE, &TimerQueryBufferDesc,\r\n        D3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&sm_TimerReadBackBuffer) ));\r\n    sm_TimerReadBackBuffer->SetName(L\"GpuTimeStamp Buffer\");\r\n\r\n    D3D12_QUERY_HEAP_DESC QueryHeapDesc;\r\n    QueryHeapDesc.Count = MaxNumTimers * 2;\r\n    QueryHeapDesc.NodeMask = 1;\r\n    QueryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP;\r\n    ASSERT_SUCCEEDED(Graphics::g_Device->CreateQueryHeap(&QueryHeapDesc, MY_IID_PPV_ARGS(&sm_TimerQueryHeap)));\r\n    sm_TimerQueryHeap->SetName(L\"GpuTimeStamp QueryHeap\");\r\n\r\n\tASSERT_SUCCEEDED(Graphics::g_Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &PipelineQueryBufferDesc,\r\n\t\tD3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&sm_PipelineQueryReadbackBuffer)));\r\n\tsm_PipelineQueryReadbackBuffer->SetName(L\"Pipeline Query Buffer\");\r\n\r\n\tD3D12_QUERY_HEAP_DESC PipelineQueryHeapDesc = {};\r\n\tPipelineQueryHeapDesc.Count = MaxNumPipelineQueries;\r\n\t//QueryHeapDesc.NodeMask = 0;\r\n\tPipelineQueryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS;\r\n\tASSERT_SUCCEEDED(Graphics::g_Device->CreateQueryHeap(&PipelineQueryHeapDesc, MY_IID_PPV_ARGS(&sm_PipelineQueryHeap)));\r\n\tsm_PipelineQueryHeap->SetName(L\"Pipeline QueryHeap\");\r\n\t\r\n\tsm_MaxNumTimers = (uint32_t)MaxNumTimers;\r\n\tsm_MaxNumPipelineQueries = (uint32_t)MaxNumPipelineQueries;\r\n}\r\n\r\nvoid GpuCounterManager::Shutdown()\r\n{\r\n    if (sm_TimerReadBackBuffer != nullptr)\r\n        sm_TimerReadBackBuffer->Release();\r\n\r\n    if (sm_TimerQueryHeap != nullptr)\r\n        sm_TimerQueryHeap->Release();\r\n\r\n\tif (sm_PipelineQueryReadbackBuffer != nullptr)\r\n\t\tsm_PipelineQueryReadbackBuffer->Release();\r\n\r\n\tif (sm_PipelineQueryHeap != nullptr)\r\n\t\tsm_PipelineQueryHeap->Release();\r\n}\r\n\r\nuint32_t GpuCounterManager::NewTimer(void)\r\n{\r\n    return sm_NumTimers++;\r\n}\r\n\r\nuint32_t GpuCounterManager::NewPipelineQuery() {\r\n\treturn sm_NumPipelineQueries++;\r\n}\r\n\r\nvoid GpuCounterManager::StartTimer(CommandContext& Context, uint32_t TimerIdx)\r\n{\r\n    Context.InsertTimeStamp(sm_TimerQueryHeap, TimerIdx * 2);\r\n}\r\n\r\nvoid GpuCounterManager::StopTimer(CommandContext& Context, uint32_t TimerIdx)\r\n{\r\n    Context.InsertTimeStamp(sm_TimerQueryHeap, TimerIdx * 2 + 1);\r\n}\r\n\r\nvoid GpuCounterManager::BeginPipelineQuery(CommandContext& Context, uint32_t QueryIdx) {\r\n\tContext.BeginPipelineQuery(sm_PipelineQueryHeap, QueryIdx);\r\n}\r\n\r\nvoid GpuCounterManager::EndPipelineQuery(CommandContext& Context, uint32_t QueryIdx) {\r\n\tContext.EndPipelineQuery(sm_PipelineQueryHeap, QueryIdx);\r\n}\r\n\r\nvoid GpuCounterManager::BeginReadBack(void)\r\n{\r\n    Graphics::g_CommandManager.WaitForFence(sm_Fence);\r\n\r\n    D3D12_RANGE Range;\r\n    Range.Begin = 0;\r\n    Range.End = (sm_NumTimers * 2) * sizeof(uint64_t);\r\n    ASSERT_SUCCEEDED(sm_TimerReadBackBuffer->Map(0, &Range, reinterpret_cast<void**>(&sm_TimeStampBuffer)));\r\n\r\n\tD3D12_RANGE PipelineRange;\r\n\tPipelineRange.Begin = 0;\r\n\tPipelineRange.End = sm_NumPipelineQueries * sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS);\r\n\tASSERT_SUCCEEDED(sm_PipelineQueryReadbackBuffer->Map(0, &Range, reinterpret_cast<void**>(&sm_PipelineQueryDataBuffer)));\r\n\r\n    sm_ValidTimeStart = sm_TimeStampBuffer[0];\r\n    sm_ValidTimeEnd = sm_TimeStampBuffer[1];\r\n\r\n    // On the first frame, with random values in the timestamp query heap, we can avoid a misstart.\r\n    if (sm_ValidTimeEnd < sm_ValidTimeStart)\r\n    {\r\n        sm_ValidTimeStart = 0ull;\r\n        sm_ValidTimeEnd = 0ull;\r\n    }\r\n}\r\n\r\nvoid GpuCounterManager::EndReadBack(void)\r\n{\r\n    // Unmap with an empty range to indicate nothing was written by the CPU\r\n    D3D12_RANGE EmptyRange = {};\r\n    sm_TimerReadBackBuffer->Unmap(0, &EmptyRange);\r\n\tsm_PipelineQueryReadbackBuffer->Unmap(0, &EmptyRange);\r\n    sm_TimeStampBuffer = nullptr;\r\n\tsm_PipelineQueryDataBuffer = nullptr;\r\n\r\n    CommandContext& Context = CommandContext::Begin();\r\n    Context.InsertTimeStamp(sm_TimerQueryHeap, 1);\r\n    Context.ResolveTimeStamps(sm_TimerReadBackBuffer, sm_TimerQueryHeap, sm_NumTimers * 2);\r\n\tContext.ResolvePipelineQueries(sm_PipelineQueryReadbackBuffer, sm_PipelineQueryHeap, sm_NumPipelineQueries);\r\n    Context.InsertTimeStamp(sm_TimerQueryHeap, 0);\r\n    sm_Fence = Context.Finish();\r\n}\r\n\r\nfloat GpuCounterManager::GetTime(uint32_t TimerIdx)\r\n{\r\n    ASSERT(sm_TimeStampBuffer != nullptr, \"Time stamp readback buffer is not mapped\");\r\n    ASSERT(TimerIdx < sm_NumTimers, \"Invalid GPU timer index\");\r\n\r\n    uint64_t TimeStamp1 = sm_TimeStampBuffer[TimerIdx * 2];\r\n    uint64_t TimeStamp2 = sm_TimeStampBuffer[TimerIdx * 2 + 1];\r\n\r\n    if (TimeStamp1 < sm_ValidTimeStart || TimeStamp2 > sm_ValidTimeEnd || TimeStamp2 <= TimeStamp1 )\r\n        return 0.0f;\r\n\r\n    return static_cast<float>(sm_GpuTickDelta * (TimeStamp2 - TimeStamp1));\r\n}\r\n\r\nvoid GpuCounterManager::GetPipelineStatistics(uint32_t QueryIdx, D3D12_QUERY_DATA_PIPELINE_STATISTICS& stats) {\r\n\tASSERT(sm_PipelineQueryDataBuffer != nullptr, \"Pipeline query readback buffer is not mapped\");\r\n\tASSERT(QueryIdx < sm_NumPipelineQueries, \"Invalid pipeline query index\");\r\n\r\n\tstats = sm_PipelineQueryDataBuffer[QueryIdx];\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GpuCounterManager.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"GameCore.h\"\r\n\r\nclass CommandContext;\r\n\r\nnamespace GpuCounterManager\r\n{\r\n    void Initialize( uint32_t MaxNumTimers = 4096, uint32_t MaxNumPipelineQueries = 256 );\r\n    void Shutdown();\r\n\r\n    // Reserve a unique timer index\r\n    uint32_t NewTimer(void);\r\n\t// Reserve a unique pipeline query index\r\n\tuint32_t NewPipelineQuery(void);\r\n\r\n    // Write start and stop time stamps on the GPU timeline\r\n    void StartTimer(CommandContext& Context, uint32_t TimerIdx);\r\n    void StopTimer(CommandContext& Context, uint32_t TimerIdx);\r\n\r\n\t// Collect pipeline statistics on the GPU\r\n\tvoid BeginPipelineQuery(CommandContext& Context, uint32_t QueryIdx);\r\n\tvoid EndPipelineQuery(CommandContext& Context, uint32_t QueryIdx);\r\n\r\n    // Bookend all calls to GetTime() with Begin/End which correspond to Map/Unmap.  This\r\n    // needs to happen either at the very start or very end of a frame.\r\n    void BeginReadBack(void);\r\n    void EndReadBack(void);\r\n\r\n    // Returns the time in milliseconds between start and stop queries\r\n    float GetTime(uint32_t TimerIdx);\r\n\tvoid GetPipelineStatistics(uint32_t QueryIdx, D3D12_QUERY_DATA_PIPELINE_STATISTICS& stats);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GpuResource.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\nclass GpuResource\r\n{\r\n    friend class CommandContext;\r\n    friend class GraphicsContext;\r\n    friend class ComputeContext;\r\n\r\npublic:\r\n    GpuResource() : \r\n        m_GpuVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS_NULL),\r\n        m_UserAllocatedMemory(nullptr),\r\n        m_UsageState(D3D12_RESOURCE_STATE_COMMON),\r\n        m_TransitioningState((D3D12_RESOURCE_STATES)-1)\r\n    {}\r\n\r\n    GpuResource(ID3D12Resource* pResource, D3D12_RESOURCE_STATES CurrentState) :\r\n        m_GpuVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS_NULL),\r\n        m_UserAllocatedMemory(nullptr),\r\n        m_pResource(pResource),\r\n        m_UsageState(CurrentState),\r\n        m_TransitioningState((D3D12_RESOURCE_STATES)-1)\r\n    {\r\n    }\r\n\r\n    virtual void Destroy()\r\n    {\r\n        m_pResource = nullptr;\r\n        m_GpuVirtualAddress = D3D12_GPU_VIRTUAL_ADDRESS_NULL;\r\n        if (m_UserAllocatedMemory != nullptr)\r\n        {\r\n            VirtualFree(m_UserAllocatedMemory, 0, MEM_RELEASE);\r\n            m_UserAllocatedMemory = nullptr;\r\n        }\r\n    }\r\n\r\n    ID3D12Resource* operator->() { return m_pResource.Get(); } \r\n    const ID3D12Resource* operator->() const { return m_pResource.Get(); }\r\n\r\n    ID3D12Resource* GetResource() { return m_pResource.Get(); } \r\n    const ID3D12Resource* GetResource() const { return m_pResource.Get(); }\r\n\r\n    D3D12_GPU_VIRTUAL_ADDRESS GetGpuVirtualAddress() const { return m_GpuVirtualAddress; }\r\n\r\nprotected:\r\n\r\n    Microsoft::WRL::ComPtr<ID3D12Resource> m_pResource;\r\n    D3D12_RESOURCE_STATES m_UsageState;\r\n    D3D12_RESOURCE_STATES m_TransitioningState;\r\n    D3D12_GPU_VIRTUAL_ADDRESS m_GpuVirtualAddress;\r\n\r\n    // When using VirtualAlloc() to allocate memory directly, record the allocation here so that it can be freed.  The\r\n    // GpuVirtualAddress may be offset from the true allocation start.\r\n    void* m_UserAllocatedMemory;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/GraphRenderer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GraphRenderer.h\"\r\n#include \"CommandContext.h\"\r\n#include \"PipelineState.h\"\r\n#include \"RootSignature.h\"\r\n#include \"BufferManager.h\"\r\n#include \"GameInput.h\"\r\n#include \"SystemTime.h\"\r\n#include \"EngineProfiling.h\"\r\n\r\n#include \"CompiledShaders/PerfGraphBackgroundVS.h\"\r\n#include \"CompiledShaders/PerfGraphVS.h\"\r\n#include \"CompiledShaders/PerfGraphPS.h\"\r\n\r\n#define PERF_GRAPH_ERROR uint32_t(0xFFFFFFFF)\r\n#define MAX_GLOBAL_GRAPHS 2\r\n#define MAX_PROFILE_GRAPHS 32\r\n#define MAX_ACTIVE_PROFILE_GRAPHS 4\r\n#define PROFILE_NODE_COUNT 256\r\n#define GLOBAL_NODE_COUNT 512\r\n#define PROFILE_DEBUG_VAR_COUNT 2\r\n\r\nusing namespace Graphics;\r\nusing namespace std;\r\nusing namespace GraphRenderer;\r\nusing namespace Math;\r\n\r\n__declspec(align(16)) struct CBGraph\r\n{\t\r\n    float RGB[3];\r\n    float RcpXScale;\r\n    uint32_t NodeCount;\r\n    uint32_t FrameID;\r\n};\r\n\r\nclass GraphVector;\r\n\r\nclass PerfGraph\r\n{\r\nfriend GraphVector;\r\npublic:\r\n    PerfGraph( uint32_t NodeCount, uint32_t debugVarCount, Color color = Color(1.0f, 0.0f, 0.5f), bool IsGraphed = false ) : m_IsGraphed(IsGraphed), \r\n        m_NodeCount(NodeCount), m_Color(color), m_DebugVarCount(debugVarCount)\r\n    {\r\n        for (uint32_t i = 0; i < debugVarCount; ++i)\t\t\r\n            m_PerfTimesCPUBuffer.emplace_back(new float[NodeCount]);\r\n    }\r\n\r\n    ~PerfGraph()\r\n    {\r\n        Clear();\r\n    }\r\n\r\n    void Clear(){ m_PerfTimesCPUBuffer.clear();} \r\n    bool IsGraphed(){ return m_IsGraphed; }\r\n    Color GetColor(){ return m_Color; }\r\n    void SetColor(Color color){m_Color = color;}\r\n    void UpdateGraph( float* timeStamps, uint32_t frameID )\r\n    {\r\n        for(uint32_t i = 0; i < m_DebugVarCount; i++)\r\n            m_PerfTimesCPUBuffer[i][frameID % m_NodeCount] = timeStamps[i];\r\n    } \t\r\n\r\n    //RenderGraph renders both graph backgrounds and line graphs \r\n    //\r\n    //To render backgrounds, set s_GraphBackgroundPSO, set primitive topology to triangle strip, \r\n    //call RenderGraph without an object and with MaxArray = nullptr.  \r\n    //\r\n    //To render line graph, set s_RenderPerfGraphPSO, set primitive topology to line strip,\r\n    //call RenderGraph on an associated PerfGraph object, and pass in MaxArray\r\n    static void RenderGraph( GraphicsContext& Context, uint32_t vertexCount, D3D12_VIEWPORT& viewport,\r\n        uint32_t debugVarCount, float topMargin);\r\n\r\n    void RenderGraph(GraphicsContext& Context, uint32_t vertexCount, D3D12_VIEWPORT& viewport,\r\n        uint32_t debugVarCount, float topMargin, float MaxValue, uint32_t frameID);\r\n\r\n    void RenderGraph(GraphicsContext& Context, uint32_t vertexCount, D3D12_VIEWPORT& viewport,\r\n        uint32_t debugVarCount, float topMargin, const float* MaxArray, uint32_t frameID);\r\n\r\nprivate:\r\n    std::vector<std::unique_ptr<float[]>> m_PerfTimesCPUBuffer;\r\n    uint32_t m_NodeCount;\r\n    bool m_IsGraphed;\r\n    Color m_Color;\r\n    uint32_t m_ColorKey;\r\n    uint32_t m_DebugVarCount;\r\n};\r\n\r\n\r\nclass GraphVector \r\n{\r\npublic:\r\n    GraphVector(uint32_t MaxActiveGraphs, uint32_t DebugVarCount) : m_MaxActiveGraphs(MaxActiveGraphs),\r\n        m_ActiveGraphs(0), m_DebugVarCount(DebugVarCount), m_MinAbs((float)PERF_GRAPH_ERROR),\r\n        m_MaxAbs(0.0f), m_FrameOfMinAbs(0), m_FrameOfMaxAbs(0)\r\n    {\r\n        // Fill color array with set of possible graph colors (up to 8 different colors)\r\n        m_ColorArray.reset(new Color[MaxActiveGraphs]);\r\n        for (uint32_t i = 0; i < m_MaxActiveGraphs; ++i)\r\n        {\r\n            m_ColorKeyStack.push_back(i);\r\n            uint32_t colorKey = i + 1;\r\n            float R = (float)(colorKey & 1);\r\n            float G = (float)((colorKey >> 1) & 1) + 0.3f;\r\n            float B = (float)((colorKey >> 2) & 1) + 0.3f;\r\n            m_ColorArray[i] = Color(R, G, B);\r\n        }\r\n        \r\n        m_Max.reset(new float[DebugVarCount]); \r\n        m_Min.reset(new float[DebugVarCount]);\r\n        m_FrameOfMax.reset(new uint32_t[DebugVarCount]);\r\n        m_FrameOfMin.reset(new uint32_t[DebugVarCount]);\r\n        m_PresetMax.reset(new float[DebugVarCount]);\r\n\r\n        for (uint32_t i = 0; i < DebugVarCount; ++i)\r\n        {\r\n            m_Max[i] = 0.0f;\r\n            m_Min[i] = (float)PERF_GRAPH_ERROR;\r\n            m_FrameOfMax[i] = m_FrameOfMin[i] = 0;\r\n            m_PresetMax[i] = 30.0f;\r\n        }\r\n\r\n    }\r\n\r\n    void Clear()\r\n    {\r\n        m_Graphs.clear();\r\n    }\r\n\r\n    GraphHandle AddGraph(PerfGraph* graph)\r\n    {\r\n        GraphHandle ret = (GraphHandle)m_Graphs.size();\r\n        m_Graphs.emplace_back(graph);\t\r\n        return ret;\r\n    }\r\n\r\n    bool Toggle(GraphHandle GraphID)\r\n    {\r\n        if (m_ActiveGraphs < m_MaxActiveGraphs && !m_Graphs[GraphID]->m_IsGraphed)\r\n        {\r\n            //add to active list\r\n            m_Graphs[GraphID]->m_IsGraphed = true;\r\n            ++m_ActiveGraphs;\r\n            //set color \r\n            m_Graphs[GraphID]->m_ColorKey = m_ColorKeyStack.back();\r\n            m_ColorKeyStack.pop_back();\r\n            m_Graphs[GraphID]->m_Color = m_ColorArray[m_Graphs[GraphID]->m_ColorKey];\r\n        }\r\n        else if (m_Graphs[GraphID]->m_IsGraphed)\r\n        {\r\n            //take it off of active list\r\n            m_ColorKeyStack.push_back(m_Graphs[GraphID]->m_ColorKey);\r\n            m_Graphs[GraphID]->m_IsGraphed = false;\r\n            --m_ActiveGraphs;\r\n        }\r\n        return m_Graphs[GraphID]->m_IsGraphed;\r\n    }\r\n\r\n    \r\n    Color GetColor(GraphHandle GraphID){ return m_Graphs[GraphID]->m_Color;}\r\n    uint32_t Size(){return (uint32_t)m_Graphs.size();}\r\n    uint32_t GetActiveGraphCount(){return m_ActiveGraphs;}\r\n\r\n    float* GetPresetMax(){return m_PresetMax.get();}\r\n    float GetGlobalPresetMax()\r\n    {\r\n        float max = 0.0f;\r\n        for (uint32_t i = 0; i < m_DebugVarCount; ++i)\r\n        {\r\n            if (m_PresetMax[i] > max)\r\n                max = m_PresetMax[i];\r\n        }\r\n        return max;\r\n    }\r\n    float* GetMaxAbs(){return &m_MaxAbs;}\r\n    float* GetMinAbs(){return &m_MinAbs;}\r\n    float* GetMax(){return m_Max.get();}\r\n    float* GetMin(){return m_Min.get();}\r\n    \r\n    void PresetMax(const float* maxArray)\r\n    {\r\n        for (uint32_t i = 0; i < m_DebugVarCount; ++i)\r\n            m_PresetMax[i] = maxArray[i];\r\n    }\r\n    \r\n    void ManageMax(float* InputNode, uint32_t nodeCount, uint32_t FrameID)\r\n    {\r\n        for (uint32_t i = 0; i < m_DebugVarCount; ++i)\r\n        {\r\n            //Absolute min max\r\n            if (FrameID - m_FrameOfMinAbs > nodeCount)\r\n                m_MinAbs = (float)PERF_GRAPH_ERROR;\r\n        \r\n            if (FrameID - m_FrameOfMaxAbs > nodeCount)\r\n                m_MaxAbs = 0.0f;\r\n        \r\n            if (InputNode[i] > m_MaxAbs)\r\n            {\r\n                m_MaxAbs = InputNode[i];\r\n                m_FrameOfMaxAbs = FrameID;\r\n            }\r\n\r\n            if (InputNode[i] < m_MinAbs)\r\n            {\r\n                m_MinAbs = InputNode[i];\r\n                m_FrameOfMinAbs = FrameID;\r\n            }\r\n\r\n            //Relative min max\r\n            if (FrameID - m_FrameOfMax[i] > nodeCount)\r\n                m_Max[i] = 0.0f;\r\n    \r\n            if (FrameID - m_FrameOfMin[i] > nodeCount)\r\n                m_Min[i] = (float)PERF_GRAPH_ERROR;\r\n\r\n            if (InputNode[i] > m_Max[i])\r\n            {\r\n                m_Max[i] = InputNode[i];\r\n                m_FrameOfMax[i] = FrameID;\r\n            }\r\n            if (InputNode[i] < m_Min[i])\r\n            {\r\n                m_Min[i] = InputNode[i];\r\n                m_FrameOfMin[i] = FrameID;\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    std::vector<std::unique_ptr<PerfGraph>> m_Graphs; // this should be private\r\n\r\nprivate:\r\n    \r\n    uint32_t m_ActiveGraphs;\r\n    uint32_t m_MaxActiveGraphs;\r\n    uint32_t m_DebugVarCount;\r\n    std::unique_ptr<Color[]> m_ColorArray;\r\n    std::vector<uint32_t> m_ColorKeyStack;\r\n    \r\n    float m_MaxAbs;\r\n    float m_MinAbs;\r\n    uint32_t m_FrameOfMaxAbs;\r\n    uint32_t m_FrameOfMinAbs;\r\n\r\n    std::unique_ptr<float[]> m_PresetMax;\r\n    std::unique_ptr<float[]> m_Max; \r\n    std::unique_ptr<float[]> m_Min;\r\n    std::unique_ptr<uint32_t[]> m_FrameOfMax;\r\n    std::unique_ptr<uint32_t[]> m_FrameOfMin;\r\n};\r\n\r\nnamespace\r\n{\r\n    RootSignature s_RootSignature;\r\n    GraphicsPSO s_RenderPerfGraphPSO;\r\n    GraphicsPSO s_GraphBackgroundPSO;\r\n    uint32_t s_FrameID;\r\n    GraphVector GlobalGraphs = GraphVector(2, 1);\r\n    GraphVector ProfileGraphs = GraphVector(MAX_ACTIVE_PROFILE_GRAPHS, PROFILE_DEBUG_VAR_COUNT);\r\n    uint32_t s_NumStamps = 0;\r\n    uint32_t s_SelectedTimerIndex;\r\n} // {anonymous} namespace\r\n\r\n\r\n\r\n//---------------------------------------------------------------------\r\n//\r\n//\tGraphRenderer Methods\r\n//\r\n//---------------------------------------------------------------------\r\n\r\nstatic void DrawGraphHeaders(TextContext& Text, float leftMargin, float topMargin, float offsetY, float graphHeight, float* MinArray, \r\n    float* MaxArray, float* PresetMaxArray, bool GlobalScale,  uint32_t numDebugVar, std::string graphTitles[]);\r\n\r\n\r\nvoid GraphRenderer::Initialize( void )\r\n{\r\n    s_RootSignature.Reset(4);\r\n    s_RootSignature[0].InitAsConstantBuffer(0);\r\n    s_RootSignature[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 2);\r\n    s_RootSignature[2].InitAsBufferSRV(0, D3D12_SHADER_VISIBILITY_VERTEX);\r\n    s_RootSignature[3].InitAsConstants(1, 3);\r\n    s_RootSignature.Finalize(L\"Graph Renderer\");\r\n\r\n    s_RenderPerfGraphPSO.SetRootSignature(s_RootSignature);\r\n    s_RenderPerfGraphPSO.SetRasterizerState(RasterizerDefault);\r\n    s_RenderPerfGraphPSO.SetBlendState(BlendTraditional);\r\n    s_RenderPerfGraphPSO.SetDepthStencilState(Graphics::DepthStateReadOnly);\r\n    s_RenderPerfGraphPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE);\r\n    s_RenderPerfGraphPSO.SetRenderTargetFormats(1, &g_OverlayBuffer.GetFormat(), g_OverlayBuffer.GetFormat());\r\n    s_RenderPerfGraphPSO.SetVertexShader(g_pPerfGraphVS, sizeof(g_pPerfGraphVS));\r\n    s_RenderPerfGraphPSO.SetPixelShader(g_pPerfGraphPS, sizeof(g_pPerfGraphPS));\r\n    s_RenderPerfGraphPSO.Finalize();\r\n\r\n    s_GraphBackgroundPSO = s_RenderPerfGraphPSO;\r\n    s_GraphBackgroundPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);\r\n    s_GraphBackgroundPSO.SetVertexShader(g_pPerfGraphBackgroundVS, sizeof(g_pPerfGraphBackgroundVS));\r\n    s_GraphBackgroundPSO.Finalize();\r\n\r\n    s_FrameID = 0;\r\n\r\n    // Preset max for global and profile graphs\r\n    float profilePresetMax[PROFILE_DEBUG_VAR_COUNT] = {15.0f, 1.0f}; //improve this\r\n    ProfileGraphs.PresetMax(profilePresetMax);\r\n    \r\n    // Create global CPU and GPU graphs\r\n    for (uint32_t i = 0; i < 2; ++i)\r\n    {\t\r\n        InitGraph( GraphType::Global );\r\n        GlobalGraphs.m_Graphs[i]->SetColor(Color((float)i, 0.5, 0.5));\r\n    }\r\n\r\n    float globalPresetMax[1] = {15.0f};\r\n    GlobalGraphs.PresetMax(globalPresetMax); \r\n}\r\n\r\nvoid GraphRenderer::Shutdown(void)\r\n{\r\n    ProfileGraphs.Clear();\r\n    GlobalGraphs.Clear();\r\n}\r\n\r\nGraphHandle GraphRenderer::InitGraph( GraphType type)\r\n{\r\n    if (type == GraphType::Profile)\r\n        return ProfileGraphs.AddGraph(new PerfGraph(PROFILE_NODE_COUNT, 2));\r\n    else if (type == GraphType::Global)\r\n        return GlobalGraphs.AddGraph(new PerfGraph(GLOBAL_NODE_COUNT, 1));\r\n    else\r\n        return PERF_GRAPH_ERROR; \r\n}\r\n\r\nbool GraphRenderer::ManageGraphs( GraphHandle GraphID, GraphType Type)\r\n{\r\n    if (GraphID == PERF_GRAPH_ERROR)\r\n        return false;\r\n\r\n    if (Type == GraphType::Profile)\r\n        return ProfileGraphs.Toggle(GraphID);\r\n    else // Type == GraphType::Global\r\n        return GlobalGraphs.Toggle(GraphID);\r\n}\r\n\r\n//This is used to set the text color \r\nColor GraphRenderer::GetGraphColor( GraphHandle GraphID, GraphType Type)\r\n{\r\n    if (Type == GraphType::Profile)\r\n        return ProfileGraphs.GetColor(GraphID);\r\n    else // Type == GraphType::Global\r\n        return GlobalGraphs.GetColor(GraphID);\t\r\n}\r\n\r\nvoid GraphRenderer::Update( XMFLOAT2 InputNode, GraphHandle GraphID, GraphType Type)\r\n{\r\n    if (GraphID == PERF_GRAPH_ERROR)\r\n        return;\r\n\r\n    if (Type == GraphType::Profile)\r\n    {\r\n        float input[2] = {InputNode.x, InputNode.y};\r\n        ProfileGraphs.m_Graphs[GraphID]->UpdateGraph(input, s_FrameID);\r\n        if (ProfileGraphs.m_Graphs[GraphID]->IsGraphed())\r\n        {\r\n            float times[4] = {InputNode.x, InputNode.y};\r\n            ProfileGraphs.ManageMax(times, PROFILE_NODE_COUNT, s_FrameID);\r\n        }\r\n    }\r\n    else // Type == PerfGraph::Global\r\n    {\r\n        GlobalGraphs.m_Graphs[0]->UpdateGraph(&InputNode.x, s_FrameID);\r\n        GlobalGraphs.m_Graphs[1]->UpdateGraph(&InputNode.y, s_FrameID);\r\n        GlobalGraphs.ManageMax(&InputNode.x, GLOBAL_NODE_COUNT, s_FrameID);\r\n        //GlobalGraphs.ManageMax(&InputNode.y, GLOBAL_NODE_COUNT, s_FrameID);\r\n    }\t\r\n}\r\n\r\nvoid DrawGraphHeaders(TextContext& Text, float leftMargin, float topMargin, float offsetY, float graphHeight, float* MinArray,\r\n    float* MaxArray, float* PresetMaxArray, bool GlobalScale, uint32_t numDebugVar, std::string graphTitles[])\r\n{\t\t\r\n    XMFLOAT2 textSpaceY = XMFLOAT2(0.02f * graphHeight, 0.067f * graphHeight); //top and bottom text space\r\n    textSpaceY.y = graphHeight - topMargin - textSpaceY.x * 3.0f; // make this better\r\n    float textSpaceX = 45.f;\r\n    Text.SetColor(Color(1.0f, 1.0f, 1.0f));\r\n    Text.SetTextSize(12.0f);\r\n        \r\n    float min = MinArray[0];\r\n    float max = MaxArray[0];\r\n    float presetMax = PresetMaxArray[0];\r\n\r\n    for (uint32_t i = 0; i < numDebugVar; i++)\r\n    {\r\n        if (!GlobalScale)\r\n        {\r\n            min = MinArray[i];\r\n            max = MaxArray[i];\r\n            presetMax = PresetMaxArray[i];\r\n        }\r\n\r\n        Text.SetCursorY(topMargin / 2.0f + (i * graphHeight) + offsetY); // division needs to be a factor \r\n        Text.SetCursorX(leftMargin + (0.4f * textSpaceX));\r\n        Text.DrawString(graphTitles[i]);\r\n        Text.DrawFormattedString(\"Min:%3.3f   Max:%3.3f\", min, max);\r\n\r\n        Text.SetCursorX(leftMargin - textSpaceX);\r\n        float topText = topMargin + (i * graphHeight);\r\n        Text.SetCursorY(topText + textSpaceY.x + offsetY);\r\n        Text.DrawFormattedString(\"%3.3f\", presetMax);\r\n\r\n        Text.SetCursorX(leftMargin - textSpaceX);\r\n        Text.SetCursorY(topText + textSpaceY.y + offsetY);\r\n        Text.DrawString(\"0.000\");\r\n    }\r\n}\r\n\r\nvoid GraphRenderer::RenderGraphs(GraphicsContext& Context, GraphType Type)\r\n{\r\n    if (Type == GraphType::Global && GlobalGraphs.Size() == 0 ||\r\n        Type == GraphType::Profile && ProfileGraphs.Size() == 0)\r\n    {\r\n        s_FrameID++; // probably need to reset this after time = uint32_t max val\r\n        return;\r\n    }\r\n\r\n    TextContext Text(Context);\r\n    Text.Begin();\r\n\r\n    if (Type == GraphType::Profile && ProfileGraphs.GetActiveGraphCount() > 0)\r\n    {\r\n        D3D12_VIEWPORT viewport;\r\n        viewport.TopLeftX = (float)g_OverlayBuffer.GetWidth() / 1.3525f;\r\n        viewport.TopLeftY = 0.0f;\r\n        viewport.Width = (float)g_OverlayBuffer.GetWidth() / 4.0f;\r\n        viewport.Height = (float)g_OverlayBuffer.GetHeight() / (PROFILE_DEBUG_VAR_COUNT + 1);\t\r\n        viewport.MinDepth = 0.0;\r\n        viewport.MaxDepth = 1.0;\t\r\n\r\n        std::string graphTitles[PROFILE_DEBUG_VAR_COUNT] = {\"Inclusive CPU   \", \"Inclusive GPU   \"};\r\n        float blankSpace = viewport.Height / (PROFILE_DEBUG_VAR_COUNT + 1); \r\n        XMFLOAT2 textSpace = XMFLOAT2(45.0f, 5.0f);\r\n        DrawGraphHeaders(Text, (viewport.TopLeftX),  blankSpace, 0.0f, (viewport.Height + blankSpace), ProfileGraphs.GetMin(), \r\n            ProfileGraphs.GetMax(), ProfileGraphs.GetPresetMax(), false, PROFILE_DEBUG_VAR_COUNT, graphTitles);\r\n        \r\n        Context.SetRootSignature(s_RootSignature);\r\n        Context.TransitionResource(g_OverlayBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(g_OverlayBuffer.GetRTV());\r\n        Context.SetPipelineState(s_GraphBackgroundPSO);\r\n        Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);\r\n\r\n        // Render backgrounds\r\n        PerfGraph::RenderGraph(Context, 4, viewport, PROFILE_DEBUG_VAR_COUNT, blankSpace);\r\n        Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINESTRIP);\r\n        viewport.TopLeftY = 0.0f;\r\n    \r\n        for (auto iter = ProfileGraphs.m_Graphs.begin(); iter != ProfileGraphs.m_Graphs.end(); ++iter)\r\n        {\r\n            if ((*iter)->IsGraphed())\r\n            {\r\n                (*iter)->RenderGraph(Context, 256, viewport, PROFILE_DEBUG_VAR_COUNT, blankSpace, ProfileGraphs.GetPresetMax(), s_FrameID);\r\n                viewport.TopLeftY = 0.0f;\r\n            }\r\n        }\r\n    }\r\n    else if (Type == GraphType::Global)\r\n    {\r\n        D3D12_VIEWPORT viewport;\r\n        viewport.TopLeftX = (float)g_OverlayBuffer.GetWidth() / 4.0f;\r\n        viewport.TopLeftY = (float)g_OverlayBuffer.GetHeight() / 1.3f;\r\n        viewport.Width = (float)g_OverlayBuffer.GetWidth() / 2.0f;\r\n        viewport.Height = (float)g_OverlayBuffer.GetHeight() / 8.0f;\r\n        viewport.MinDepth = 0.0f;\r\n        viewport.MaxDepth = 1.0f;\r\n    \r\n        float blankSpace = viewport.Height / 8.0f;\r\n        XMFLOAT2 textSpace = XMFLOAT2(45.0f, 5.0f);\r\n        std::string graphTitles[] = { \"CPU - GPU      \" };\r\n        DrawGraphHeaders( Text, (viewport.TopLeftX), blankSpace,  (viewport.TopLeftY - blankSpace - textSpace.y), (viewport.Height + blankSpace), \r\n                                        GlobalGraphs.GetMinAbs(), GlobalGraphs.GetMaxAbs(), GlobalGraphs.GetPresetMax(), true, 1, graphTitles);\r\n\r\n        Context.SetRootSignature(s_RootSignature);\r\n        Context.TransitionResource(g_OverlayBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(g_OverlayBuffer.GetRTV());\r\n        Context.SetPipelineState(s_GraphBackgroundPSO);\r\n        Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);\r\n        \r\n        // Render background\r\n        PerfGraph::RenderGraph(Context, 4, viewport, 1, 0.0f);\r\n    \r\n        // Render graphs\r\n        Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINESTRIP);\r\n        for (auto iter = GlobalGraphs.m_Graphs.begin(); iter != GlobalGraphs.m_Graphs.end(); ++iter)\r\n        {\r\n            (*iter)->RenderGraph(Context, 512, viewport, 1, 0.0f, GlobalGraphs.GetPresetMax(), s_FrameID);\r\n        }\r\n    }\r\n    s_FrameID++;\r\n    Text.End();\r\n    Context.SetViewport(0, 0, 1920, 1080);\r\n}\r\n\r\nvoid GraphRenderer::SetSelectedIndex(uint32_t selectedIndex)\r\n{\r\n    s_SelectedTimerIndex = selectedIndex;\r\n}\r\n\r\n//---------------------------------------------------------------------\r\n//\r\n//\tPerfGraph Methods\r\n//\r\n//---------------------------------------------------------------------\r\n\r\nvoid PerfGraph::RenderGraph(GraphicsContext& Context, uint32_t vertexCount, D3D12_VIEWPORT& viewport, uint32_t debugVarCount, float topMargin)\r\n{\r\n    viewport.TopLeftY += topMargin;\r\n\r\n    Context.SetConstants(3, 0, 20.0f);\r\n\r\n    for (uint32_t i = 0; i < debugVarCount; ++i)\r\n    {\r\n        Context.SetViewport(viewport);\r\n        Context.Draw(vertexCount);\r\n        if (debugVarCount > 1)\r\n            viewport.TopLeftY += viewport.Height + topMargin;\r\n    }\r\n}\r\n\r\nvoid PerfGraph::RenderGraph(GraphicsContext& Context, uint32_t vertexCount, D3D12_VIEWPORT& viewport, uint32_t debugVarCount, float topMargin, float YScale, uint32_t frameID)\r\n{\r\n    viewport.TopLeftY += topMargin;\r\n\r\n    CBGraph graphConstants;\r\n    graphConstants.RGB[0] = m_Color.R();\r\n    graphConstants.RGB[1] = m_Color.G();\r\n    graphConstants.RGB[2] = m_Color.B();\r\n    graphConstants.RcpXScale = 2.0f / m_NodeCount;\r\n    graphConstants.NodeCount = m_NodeCount;\r\n    graphConstants.FrameID = frameID;\r\n    Context.SetDynamicConstantBufferView(0, sizeof(CBGraph), &graphConstants);\r\n    Context.SetPipelineState(s_RenderPerfGraphPSO);\r\n\r\n    for (uint32_t i = 0; i < debugVarCount; ++i)\r\n    {\r\n        Context.SetDynamicSRV(2, sizeof(float) * m_NodeCount, m_PerfTimesCPUBuffer[i].get());\r\n        Context.SetConstants(3, i, 1.0f / YScale);\r\n        Context.SetViewport(viewport);\r\n        Context.Draw(vertexCount);\r\n        if (debugVarCount > 1)\r\n            viewport.TopLeftY += viewport.Height + topMargin;\r\n    }\r\n}\r\n\r\nvoid PerfGraph::RenderGraph( GraphicsContext& Context, uint32_t vertexCount, D3D12_VIEWPORT& viewport, uint32_t debugVarCount, float topMargin, const float* MaxArray, uint32_t frameID)\r\n{\r\n    ASSERT(MaxArray != nullptr);\r\n    viewport.TopLeftY += topMargin;\r\n\r\n    CBGraph graphConstants;\r\n    graphConstants.RGB[0] = m_Color.R();\r\n    graphConstants.RGB[1] = m_Color.G();\r\n    graphConstants.RGB[2] = m_Color.B();\r\n    graphConstants.RcpXScale = 2.0f / m_NodeCount;\r\n    graphConstants.NodeCount = m_NodeCount;\r\n    graphConstants.FrameID = frameID;\r\n    Context.SetDynamicConstantBufferView(0, sizeof(CBGraph), &graphConstants);\r\n    Context.SetPipelineState(s_RenderPerfGraphPSO);\r\n    \r\n    for (uint32_t i = 0; i < debugVarCount; ++i)\r\n    {\r\n        Context.SetDynamicSRV(2, sizeof(float) * m_NodeCount, m_PerfTimesCPUBuffer[i].get());\r\n        Context.SetConstants(3, i, 1.0f / MaxArray[i]);\r\n        Context.SetViewport(viewport);\r\n        Context.Draw(vertexCount);\r\n        if (debugVarCount > 1)\r\n            viewport.TopLeftY += viewport.Height + topMargin;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GraphRenderer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n//\r\n\r\n#include \"GraphicsCore.h\"\r\n\r\nnamespace GraphRenderer\r\n{\r\n    void Initialize();\r\n    void Shutdown();\r\n\r\n    enum class GraphType { Global, Profile };\r\n    typedef uint32_t GraphHandle;\r\n\r\n    bool ManageGraphs( GraphHandle graphID, GraphType Type );\r\n    GraphHandle InitGraph( GraphType Type );\r\n    Color GetGraphColor( GraphHandle GraphID, GraphType Type);\r\n    XMFLOAT4 GetMaxAvg( GraphType Type );\r\n    void Update( XMFLOAT2 InputNode, GraphHandle GraphID, GraphType Type);\r\n    void RenderGraphs( GraphicsContext& Context, GraphType Type );\r\n\r\n    void SetSelectedIndex(uint32_t selectedIndex);\r\n\r\n} // namespace GraphRenderer\r\n"
  },
  {
    "path": "MiniEngine/Core/GraphicsCommon.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"GraphicsCommon.h\"\r\n#include \"SamplerManager.h\"\r\n#include \"CommandSignature.h\"\r\n#include \"BitonicSort.h\"\r\n\r\nnamespace Graphics\r\n{\r\n    SamplerDesc SamplerLinearWrapDesc;\r\n    SamplerDesc SamplerAnisoWrapDesc;\r\n    SamplerDesc SamplerShadowDesc;\r\n    SamplerDesc SamplerLinearClampDesc;\r\n    SamplerDesc SamplerVolumeWrapDesc;\r\n    SamplerDesc SamplerPointClampDesc;\r\n    SamplerDesc SamplerPointBorderDesc;\r\n    SamplerDesc SamplerLinearBorderDesc;\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerLinearWrap;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerAnisoWrap;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerShadow;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerLinearClamp;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerVolumeWrap;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerPointClamp;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerPointBorder;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SamplerLinearBorder;\r\n\r\n    D3D12_RASTERIZER_DESC RasterizerDefault;\t// Counter-clockwise\r\n    D3D12_RASTERIZER_DESC RasterizerDefaultMsaa;\r\n    D3D12_RASTERIZER_DESC RasterizerDefaultCw;\t// Clockwise winding\r\n    D3D12_RASTERIZER_DESC RasterizerDefaultCwMsaa;\r\n    D3D12_RASTERIZER_DESC RasterizerTwoSided;\r\n    D3D12_RASTERIZER_DESC RasterizerTwoSidedMsaa;\r\n    D3D12_RASTERIZER_DESC RasterizerShadow;\r\n    D3D12_RASTERIZER_DESC RasterizerShadowCW;\r\n    D3D12_RASTERIZER_DESC RasterizerShadowTwoSided;\r\n\r\n    D3D12_BLEND_DESC BlendNoColorWrite;\r\n    D3D12_BLEND_DESC BlendDisable;\r\n    D3D12_BLEND_DESC BlendPreMultiplied;\r\n    D3D12_BLEND_DESC BlendTraditional;\r\n    D3D12_BLEND_DESC BlendAdditive;\r\n    D3D12_BLEND_DESC BlendTraditionalAdditive;\r\n\r\n    D3D12_DEPTH_STENCIL_DESC DepthStateDisabled;\r\n    D3D12_DEPTH_STENCIL_DESC DepthStateReadWrite;\r\n    D3D12_DEPTH_STENCIL_DESC DepthStateReadOnly;\r\n    D3D12_DEPTH_STENCIL_DESC DepthStateReadOnlyReversed;\r\n    D3D12_DEPTH_STENCIL_DESC DepthStateTestEqual;\r\n\r\n    CommandSignature DispatchIndirectCommandSignature(1);\r\n    CommandSignature DrawIndirectCommandSignature(1);\r\n}\r\n\r\nnamespace BitonicSort\r\n{\r\n    void Initialize(void);\r\n    void Shutdown(void);\r\n}\r\n\r\nvoid Graphics::InitializeCommonState(void)\r\n{\r\n    SamplerLinearWrapDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;\r\n    SamplerLinearWrap = SamplerLinearWrapDesc.CreateDescriptor();\r\n\r\n    SamplerAnisoWrapDesc.MaxAnisotropy = 4;\r\n    SamplerAnisoWrap = SamplerAnisoWrapDesc.CreateDescriptor();\r\n\r\n    SamplerShadowDesc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;\r\n    SamplerShadowDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;\r\n    SamplerShadowDesc.SetTextureAddressMode(D3D12_TEXTURE_ADDRESS_MODE_CLAMP);\r\n    SamplerShadow = SamplerShadowDesc.CreateDescriptor();\r\n\r\n    SamplerLinearClampDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;\r\n    SamplerLinearClampDesc.SetTextureAddressMode(D3D12_TEXTURE_ADDRESS_MODE_CLAMP);\r\n    SamplerLinearClamp = SamplerLinearClampDesc.CreateDescriptor();\r\n\r\n    SamplerVolumeWrapDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;\r\n    SamplerVolumeWrap = SamplerVolumeWrapDesc.CreateDescriptor();\r\n\r\n    SamplerPointClampDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;\r\n    SamplerPointClampDesc.SetTextureAddressMode(D3D12_TEXTURE_ADDRESS_MODE_CLAMP);\r\n    SamplerPointClamp = SamplerPointClampDesc.CreateDescriptor();\r\n\r\n    SamplerLinearBorderDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;\r\n    SamplerLinearBorderDesc.SetTextureAddressMode(D3D12_TEXTURE_ADDRESS_MODE_BORDER);\r\n    SamplerLinearBorderDesc.SetBorderColor(Color(0.0f, 0.0f, 0.0f, 0.0f));\r\n    SamplerLinearBorder = SamplerLinearBorderDesc.CreateDescriptor();\r\n\r\n    SamplerPointBorderDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;\r\n    SamplerPointBorderDesc.SetTextureAddressMode(D3D12_TEXTURE_ADDRESS_MODE_BORDER);\r\n    SamplerPointBorderDesc.SetBorderColor(Color(0.0f, 0.0f, 0.0f, 0.0f));\r\n    SamplerPointBorder = SamplerPointBorderDesc.CreateDescriptor();\r\n\r\n    // Default rasterizer states\r\n    RasterizerDefault.FillMode = D3D12_FILL_MODE_SOLID;\r\n    RasterizerDefault.CullMode = D3D12_CULL_MODE_BACK;\r\n    RasterizerDefault.FrontCounterClockwise = TRUE;\r\n    RasterizerDefault.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;\r\n    RasterizerDefault.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;\r\n    RasterizerDefault.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;\r\n    RasterizerDefault.DepthClipEnable = TRUE;\r\n    RasterizerDefault.MultisampleEnable = FALSE;\r\n    RasterizerDefault.AntialiasedLineEnable = FALSE;\r\n    RasterizerDefault.ForcedSampleCount = 0;\r\n    RasterizerDefault.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;\r\n\r\n    RasterizerDefaultMsaa = RasterizerDefault;\r\n    RasterizerDefaultMsaa.MultisampleEnable = TRUE;\r\n\r\n    RasterizerDefaultCw = RasterizerDefault;\r\n    RasterizerDefaultCw.FrontCounterClockwise = FALSE;\r\n\r\n    RasterizerDefaultCwMsaa = RasterizerDefaultCw;\r\n    RasterizerDefaultCwMsaa.MultisampleEnable = TRUE;\r\n\r\n    RasterizerTwoSided = RasterizerDefault;\r\n    RasterizerTwoSided.CullMode = D3D12_CULL_MODE_NONE;\r\n\r\n    RasterizerTwoSidedMsaa = RasterizerTwoSided;\r\n    RasterizerTwoSidedMsaa.MultisampleEnable = TRUE;\r\n\r\n    // Shadows need their own rasterizer state so we can reverse the winding of faces\r\n    RasterizerShadow = RasterizerDefault;\r\n    //RasterizerShadow.CullMode = D3D12_CULL_FRONT;  // Hacked here rather than fixing the content\r\n    RasterizerShadow.SlopeScaledDepthBias = -1.5f;\r\n    RasterizerShadow.DepthBias = -100;\r\n\r\n    RasterizerShadowTwoSided = RasterizerShadow;\r\n    RasterizerShadowTwoSided.CullMode = D3D12_CULL_MODE_NONE;\r\n\r\n    RasterizerShadowCW = RasterizerShadow;\r\n    RasterizerShadowCW.FrontCounterClockwise = FALSE;\r\n\r\n    DepthStateDisabled.DepthEnable = FALSE;\r\n    DepthStateDisabled.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;\r\n    DepthStateDisabled.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;\r\n    DepthStateDisabled.StencilEnable = FALSE;\r\n    DepthStateDisabled.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n    DepthStateDisabled.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n    DepthStateDisabled.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;\r\n    DepthStateDisabled.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;\r\n    DepthStateDisabled.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;\r\n    DepthStateDisabled.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;\r\n    DepthStateDisabled.BackFace = DepthStateDisabled.FrontFace;\r\n\r\n    DepthStateReadWrite = DepthStateDisabled;\r\n    DepthStateReadWrite.DepthEnable = TRUE;\r\n    DepthStateReadWrite.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n    DepthStateReadWrite.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;\r\n\r\n    DepthStateReadOnly = DepthStateReadWrite;\r\n    DepthStateReadOnly.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;\r\n\r\n    DepthStateReadOnlyReversed = DepthStateReadOnly;\r\n    DepthStateReadOnlyReversed.DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n\r\n    DepthStateTestEqual = DepthStateReadOnly;\r\n    DepthStateTestEqual.DepthFunc = D3D12_COMPARISON_FUNC_EQUAL;\r\n\r\n    D3D12_BLEND_DESC alphaBlend = {};\r\n    alphaBlend.IndependentBlendEnable = FALSE;\r\n    alphaBlend.RenderTarget[0].BlendEnable = FALSE;\r\n    alphaBlend.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;\r\n    alphaBlend.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;\r\n    alphaBlend.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;\r\n    alphaBlend.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;\r\n    alphaBlend.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;\r\n    alphaBlend.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;\r\n    alphaBlend.RenderTarget[0].RenderTargetWriteMask = 0;\r\n    BlendNoColorWrite = alphaBlend;\r\n\r\n    alphaBlend.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;\r\n    BlendDisable = alphaBlend;\r\n\r\n    alphaBlend.RenderTarget[0].BlendEnable = TRUE;\r\n    BlendTraditional = alphaBlend;\r\n\r\n    alphaBlend.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE;\r\n    BlendPreMultiplied = alphaBlend;\r\n\r\n    alphaBlend.RenderTarget[0].DestBlend = D3D12_BLEND_ONE;\r\n    BlendAdditive = alphaBlend;\r\n\r\n    alphaBlend.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;\r\n    BlendTraditionalAdditive = alphaBlend;\r\n\r\n    DispatchIndirectCommandSignature[0].Dispatch();\r\n    DispatchIndirectCommandSignature.Finalize();\r\n\r\n    DrawIndirectCommandSignature[0].Draw();\r\n    DrawIndirectCommandSignature.Finalize();\r\n\r\n    BitonicSort::Initialize();\r\n}\r\n\r\nvoid Graphics::DestroyCommonState(void)\r\n{\r\n    DispatchIndirectCommandSignature.Destroy();\r\n    DrawIndirectCommandSignature.Destroy();\r\n    \r\n    BitonicSort::Shutdown();\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GraphicsCommon.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\nclass SamplerDesc;\r\nclass CommandSignature;\r\n\r\nnamespace Graphics\r\n{\r\n    extern SamplerDesc SamplerLinearWrapDesc;\r\n    extern SamplerDesc SamplerAnisoWrapDesc;\r\n    extern SamplerDesc SamplerShadowDesc;\r\n    extern SamplerDesc SamplerLinearClampDesc;\r\n    extern SamplerDesc SamplerVolumeWrapDesc;\r\n    extern SamplerDesc SamplerPointClampDesc;\r\n    extern SamplerDesc SamplerPointBorderDesc;\r\n    extern SamplerDesc SamplerLinearBorderDesc;\r\n\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerLinearWrap;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerAnisoWrap;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerShadow;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerLinearClamp;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerVolumeWrap;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerPointClamp;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerPointBorder;\r\n    extern D3D12_CPU_DESCRIPTOR_HANDLE SamplerLinearBorder;\r\n\r\n    extern D3D12_RASTERIZER_DESC RasterizerDefault;\r\n    extern D3D12_RASTERIZER_DESC RasterizerDefaultMsaa;\r\n    extern D3D12_RASTERIZER_DESC RasterizerDefaultCw;\r\n    extern D3D12_RASTERIZER_DESC RasterizerDefaultCwMsaa;\r\n    extern D3D12_RASTERIZER_DESC RasterizerTwoSided;\r\n    extern D3D12_RASTERIZER_DESC RasterizerTwoSidedMsaa;\r\n    extern D3D12_RASTERIZER_DESC RasterizerShadow;\r\n    extern D3D12_RASTERIZER_DESC RasterizerShadowCW;\r\n    extern D3D12_RASTERIZER_DESC RasterizerShadowTwoSided;\r\n\r\n    extern D3D12_BLEND_DESC BlendNoColorWrite;\t\t// XXX\r\n    extern D3D12_BLEND_DESC BlendDisable;\t\t\t// 1, 0\r\n    extern D3D12_BLEND_DESC BlendPreMultiplied;\t\t// 1, 1-SrcA\r\n    extern D3D12_BLEND_DESC BlendTraditional;\t\t// SrcA, 1-SrcA\r\n    extern D3D12_BLEND_DESC BlendAdditive;\t\t\t// 1, 1\r\n    extern D3D12_BLEND_DESC BlendTraditionalAdditive;// SrcA, 1\r\n\r\n    extern D3D12_DEPTH_STENCIL_DESC DepthStateDisabled;\r\n    extern D3D12_DEPTH_STENCIL_DESC DepthStateReadWrite;\r\n    extern D3D12_DEPTH_STENCIL_DESC DepthStateReadOnly;\r\n    extern D3D12_DEPTH_STENCIL_DESC DepthStateReadOnlyReversed;\r\n    extern D3D12_DEPTH_STENCIL_DESC DepthStateTestEqual;\r\n\r\n    extern CommandSignature DispatchIndirectCommandSignature;\r\n    extern CommandSignature DrawIndirectCommandSignature;\r\n\r\n    void InitializeCommonState(void);\r\n    void DestroyCommonState(void);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GraphicsCore.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n// Modified 2018, Intel Corporation\r\n// Added checking for Intel GPU\r\n\r\n#include \"pch.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"GameCore.h\"\r\n#include \"BufferManager.h\"\r\n#include \"GpuCounterManager.h\"\r\n#include \"PostEffects.h\"\r\n#include \"SSAO.h\"\r\n#include \"TextRenderer.h\"\r\n#include \"ColorBuffer.h\"\r\n#include \"SystemTime.h\"\r\n#include \"SamplerManager.h\"\r\n#include \"DescriptorHeap.h\"\r\n#include \"CommandContext.h\"\r\n#include \"CommandListManager.h\"\r\n#include \"RootSignature.h\"\r\n#include \"CommandSignature.h\"\r\n#include \"ParticleEffectManager.h\"\r\n#include \"GraphRenderer.h\"\r\n#include \"TemporalEffects.h\"\r\n\r\n#include \"ART/GUI/GUICore.h\"\r\n\r\n// This macro determines whether to detect if there is an HDR display and enable HDR10 output.\r\n// Currently, with HDR display enabled, the pixel magnfication functionality is broken.\r\n#define CONDITIONALLY_ENABLE_HDR_OUTPUT 1\r\n\r\n// Uncomment this to enable experimental support for the new shader compiler, DXC.exe\r\n//#define DXIL\r\n\r\n#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    #include <agile.h>\r\n#endif\r\n\r\n#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2)\r\n    #include <dxgi1_6.h>\r\n#else\r\n    #include <dxgi1_4.h>\t// For WARP\r\n#endif\r\n#include <winreg.h>\t\t// To read the registry\r\n\r\n#include \"CompiledShaders/ScreenQuadVS.h\"\r\n#include \"CompiledShaders/BufferCopyPS.h\"\r\n#include \"CompiledShaders/PresentSDRPS.h\"\r\n#include \"CompiledShaders/PresentHDRPS.h\"\r\n#include \"CompiledShaders/MagnifyPixelsPS.h\"\r\n#include \"CompiledShaders/BilinearUpsamplePS.h\"\r\n#include \"CompiledShaders/BicubicHorizontalUpsamplePS.h\"\r\n#include \"CompiledShaders/BicubicVerticalUpsamplePS.h\"\r\n#include \"CompiledShaders/SharpeningUpsamplePS.h\"\r\n#include \"CompiledShaders/GenerateMipsLinearCS.h\"\r\n#include \"CompiledShaders/GenerateMipsLinearOddCS.h\"\r\n#include \"CompiledShaders/GenerateMipsLinearOddXCS.h\"\r\n#include \"CompiledShaders/GenerateMipsLinearOddYCS.h\"\r\n#include \"CompiledShaders/GenerateMipsGammaCS.h\"\r\n#include \"CompiledShaders/GenerateMipsGammaOddCS.h\"\r\n#include \"CompiledShaders/GenerateMipsGammaOddXCS.h\"\r\n#include \"CompiledShaders/GenerateMipsGammaOddYCS.h\"\r\n\r\n#define SWAP_CHAIN_BUFFER_COUNT 3\r\n\r\n// Temporary: The GUI seems to be  incompatible with 10-bit. Until we change the GUI to render to a separate texture target\r\n// we downgrade the bit depth to a compatible format\r\n#ifdef ART_ENABLE_GUI\r\n\tDXGI_FORMAT SwapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM;\r\n#else\r\n\tDXGI_FORMAT SwapChainFormat = DXGI_FORMAT_R10G10B10A2_UNORM;\r\n#endif\r\n\r\n#ifndef SAFE_RELEASE\r\n#define SAFE_RELEASE(x) if (x != nullptr) { x->Release(); x = nullptr; }\r\n#endif\r\n\r\nusing namespace Math;\r\n\r\nnamespace GameCore\r\n{\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    extern HWND g_hWnd;\r\n#else\r\n    extern Platform::Agile<Windows::UI::Core::CoreWindow>  g_window;\r\n#endif\r\n}\r\n\r\nnamespace\r\n{\r\n    float s_FrameTime = 0.0f;\r\n\tfloat s_OfflineTimeStep = 0.0f;\r\n    uint64_t s_FrameIndex = 0;\r\n    int64_t s_FrameStartTick = 0;\r\n\r\n    // DRR: TODO\r\n    BoolVar s_EnableVSync(\"Timing/VSync\", false /*true*/);\r\n    BoolVar s_LimitTo30Hz(\"Timing/Limit To 30Hz\", false);\r\n    BoolVar s_DropRandomFrames(\"Timing/Drop Random Frames\", false);\r\n}\r\n\r\nnamespace Graphics\r\n{\r\n    void PreparePresentLDR();\r\n    void PreparePresentHDR();\r\n    void CompositeOverlays( GraphicsContext& Context );\r\n\r\n#ifndef RELEASE\r\n    const GUID WKPDID_D3DDebugObjectName = { 0x429b8c22,0x9188,0x4b0c, { 0x87,0x42,0xac,0xb0,0xbf,0x85,0xc2,0x00 }};\r\n#endif\r\n\r\n    enum eResolution { k720p, k900p, k1080p, k1440p, k1800p, k2160p };\r\n\r\n    const uint32_t kMaxNativeWidth = 3840;\r\n    const uint32_t kMaxNativeHeight = 2160;\r\n    const uint32_t kNumPredefinedResolutions = 6;\r\n\r\n    const char* ResolutionLabels[] = { \"1280x720\", \"1600x900\", \"1920x1080\", \"2560x1440\", \"3200x1800\", \"3840x2160\" };\r\n    EnumVar TargetResolution(\"Graphics/Display/Native Resolution\", k1080p, kNumPredefinedResolutions, ResolutionLabels);\r\n\r\n    bool g_bTypedUAVLoadSupport_R11G11B10_FLOAT = false;\r\n    bool g_bTypedUAVLoadSupport_R16G16B16A16_FLOAT = false;\r\n    bool g_bEnableHDROutput = false;\r\n    NumVar g_HDRPaperWhite(\"Graphics/Display/Paper White (nits)\", 200.0f, 100.0f, 500.0f, 50.0f);\r\n    NumVar g_MaxDisplayLuminance(\"Graphics/Display/Peak Brightness (nits)\", 1000.0f, 500.0f, 10000.0f, 100.0f);\r\n    const char* HDRModeLabels[] = { \"HDR\", \"SDR\", \"Side-by-Side\" };\r\n    EnumVar HDRDebugMode(\"Graphics/Display/HDR Debug Mode\", 0, 3, HDRModeLabels);\r\n\r\n    float    g_ResolutionScale = 1.0f;\r\n    uint32_t g_NativeWidth = 0;\r\n    uint32_t g_NativeHeight = 0;\r\n    uint32_t g_DisplayWidth = 1920;\r\n    uint32_t g_DisplayHeight = 1080;\r\n    ColorBuffer g_PreDisplayBuffer;\r\n    bool g_IntelIsGPU;\r\n\r\n    void SetNativeResolution(void)\r\n    {\r\n        uint32_t NativeWidth, NativeHeight;\r\n\r\n        switch (eResolution((int)TargetResolution))\r\n        {\r\n        default:\r\n        case k720p:\r\n            NativeWidth = 1280;\r\n            NativeHeight = 720;\r\n            break;\r\n        case k900p:\r\n            NativeWidth = 1600;\r\n            NativeHeight = 900;\r\n            break;\r\n        case k1080p:\r\n            NativeWidth = 1920;\r\n            NativeHeight = 1080;\r\n            break;\r\n        case k1440p:\r\n            NativeWidth = 2560;\r\n            NativeHeight = 1440;\r\n            break;\r\n        case k1800p:\r\n            NativeWidth = 3200;\r\n            NativeHeight = 1800;\r\n            break;\r\n        case k2160p:\r\n            NativeWidth = 3840;\r\n            NativeHeight = 2160;\r\n            break;\r\n        }\r\n\r\n        if (g_NativeWidth == NativeWidth && g_NativeHeight == NativeHeight)\r\n            return;\r\n\r\n        DEBUGPRINT(\"Changing native resolution to %ux%u\", NativeWidth, NativeHeight);\r\n\r\n        g_NativeWidth = NativeWidth;\r\n        g_NativeHeight = NativeHeight;\r\n\r\n        g_CommandManager.IdleGPU();\r\n\r\n        InitializeRenderingBuffers(NativeWidth, NativeHeight);\r\n    }\r\n\r\n    DX12_DEVICE* g_Device = nullptr;\r\n\r\n    CommandListManager g_CommandManager;\r\n    ContextManager g_ContextManager;\r\n\r\n    D3D_FEATURE_LEVEL g_D3DFeatureLevel = D3D_FEATURE_LEVEL_11_0;\r\n\r\n    ColorBuffer g_DisplayPlane[SWAP_CHAIN_BUFFER_COUNT];\r\n    UINT g_CurrentBuffer = 0;\r\n\r\n    IDXGISwapChain1* s_SwapChain1 = nullptr;\r\n\r\n    DescriptorAllocator g_DescriptorAllocator[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES] =\r\n    {\r\n        D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,\r\n        D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,\r\n        D3D12_DESCRIPTOR_HEAP_TYPE_RTV,\r\n        D3D12_DESCRIPTOR_HEAP_TYPE_DSV,\r\n    };\r\n\r\n    RootSignature s_PresentRS;\r\n    GraphicsPSO s_BlendUIPSO;\r\n    GraphicsPSO PresentSDRPS;\r\n    GraphicsPSO PresentHDRPS;\r\n    GraphicsPSO MagnifyPixelsPS;\r\n    GraphicsPSO SharpeningUpsamplePS;\r\n    GraphicsPSO BicubicHorizontalUpsamplePS;\r\n    GraphicsPSO BicubicVerticalUpsamplePS;\r\n    GraphicsPSO BilinearUpsamplePS;\r\n\r\n    RootSignature g_GenerateMipsRS;\r\n    ComputePSO g_GenerateMipsLinearPSO[4];\r\n    ComputePSO g_GenerateMipsGammaPSO[4];\r\n\r\n    enum { kBilinear, kBicubic, kSharpening, kFilterCount };\r\n    const char* FilterLabels[] = { \"Bilinear\", \"Bicubic\", \"Sharpening\" };\r\n    EnumVar UpsampleFilter(\"Graphics/Display/Upsample Filter\", kFilterCount - 1, kFilterCount, FilterLabels);\r\n    NumVar BicubicUpsampleWeight(\"Graphics/Display/Bicubic Filter Weight\", -0.75f, -1.0f, -0.25f, 0.25f);\r\n    NumVar SharpeningSpread(\"Graphics/Display/Sharpness Sample Spread\", 1.0f, 0.7f, 2.0f, 0.1f);\r\n    NumVar SharpeningRotation(\"Graphics/Display/Sharpness Sample Rotation\", 45.0f, 0.0f, 90.0f, 15.0f);\r\n    NumVar SharpeningStrength(\"Graphics/Display/Sharpness Strength\", 0.10f, 0.0f, 1.0f, 0.01f);\r\n\r\n    enum DebugZoomLevel { kDebugZoomOff, kDebugZoom2x, kDebugZoom4x, kDebugZoom8x, kDebugZoom16x, kDebugZoomCount };\r\n    const char* DebugZoomLabels[] = { \"Off\", \"2x Zoom\", \"4x Zoom\", \"8x Zoom\", \"16x Zoom\" };\r\n    EnumVar DebugZoom(\"Graphics/Display/Magnify Pixels\", kDebugZoomOff, kDebugZoomCount, DebugZoomLabels);\r\n}\r\n\r\nvoid Graphics::Resize(uint32_t width, uint32_t height)\r\n{\r\n    ASSERT(s_SwapChain1 != nullptr);\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\tARTGUI::Finalize();\r\n#endif // ART_ENABLE_GUI\r\n\t\r\n\tg_CommandManager.IdleGPU();\r\n\r\n    g_DisplayWidth = width;\r\n    g_DisplayHeight = height;\r\n\r\n    DEBUGPRINT(\"Changing display resolution to %ux%u\", width, height);\r\n\r\n    g_PreDisplayBuffer.Create(L\"PreDisplay Buffer\", width, height, 1, SwapChainFormat);\r\n\r\n    for (uint32_t i = 0; i < SWAP_CHAIN_BUFFER_COUNT; ++i)\r\n        g_DisplayPlane[i].Destroy();\r\n\r\n    ASSERT_SUCCEEDED(s_SwapChain1->ResizeBuffers(SWAP_CHAIN_BUFFER_COUNT, width, height, SwapChainFormat, 0));\r\n\r\n    for (uint32_t i = 0; i < SWAP_CHAIN_BUFFER_COUNT; ++i)\r\n    {\r\n        ComPtr<ID3D12Resource> DisplayPlane;\r\n        ASSERT_SUCCEEDED(s_SwapChain1->GetBuffer(i, MY_IID_PPV_ARGS(&DisplayPlane)));\r\n        g_DisplayPlane[i].CreateFromSwapChain(L\"Primary SwapChain Buffer\", DisplayPlane.Detach());\r\n    }\r\n\r\n    g_CurrentBuffer = 0;\r\n\r\n    g_CommandManager.IdleGPU();\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\tARTGUI::Initialize();\r\n\tARTGUI::Resize(width, height);\r\n#endif // ART_ENABLE_GUI\r\n\r\n    ResizeDisplayDependentBuffers(g_NativeWidth, g_NativeHeight);\r\n}\r\n\r\n#ifdef DXIL\r\n// A more recent Windows SDK than currently required is needed for these.\r\ntypedef HRESULT(WINAPI *D3D12EnableExperimentalFeaturesFn)(\r\n    UINT                                    NumFeatures,\r\n    __in_ecount(NumFeatures) const IID*     pIIDs,\r\n    __in_ecount_opt(NumFeatures) void*      pConfigurationStructs,\r\n    __in_ecount_opt(NumFeatures) UINT*      pConfigurationStructSizes);\r\n\r\nstatic const GUID D3D12ExperimentalShaderModelsID = { /* 76f5573e-f13a-40f5-b297-81ce9e18933f */\r\n    0x76f5573e,\r\n    0xf13a,\r\n    0x40f5,\r\n    { 0xb2, 0x97, 0x81, 0xce, 0x9e, 0x18, 0x93, 0x3f }\r\n};\r\n\r\nusing namespace DirectX;\r\n\r\nstatic HRESULT EnableExperimentalShaderModels() {\r\n    HMODULE hRuntime = LoadLibraryW(L\"d3d12.dll\");\r\n    if (hRuntime == NULL) {\r\n        return HRESULT_FROM_WIN32(GetLastError());\r\n    }\r\n\r\n    D3D12EnableExperimentalFeaturesFn pD3D12EnableExperimentalFeatures =\r\n        (D3D12EnableExperimentalFeaturesFn)GetProcAddress(hRuntime, \"D3D12EnableExperimentalFeatures\");\r\n    if (pD3D12EnableExperimentalFeatures == nullptr) {\r\n        FreeLibrary(hRuntime);\r\n        return HRESULT_FROM_WIN32(GetLastError());\r\n    }\r\n\r\n    return pD3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModelsID, nullptr, nullptr);\r\n}\r\n#endif\r\n\r\n// Initialize the DirectX resources required to run.\r\nvoid Graphics::Initialize(void)\r\n{\r\n    ASSERT(s_SwapChain1 == nullptr, \"Graphics has already been initialized\");\r\n\r\n    Microsoft::WRL::ComPtr<DX12_DEVICE> pDevice;\r\n\r\n#if _DEBUG\r\n    Microsoft::WRL::ComPtr<ID3D12Debug1> debugInterface;\r\n    if (SUCCEEDED(D3D12GetDebugInterface(MY_IID_PPV_ARGS(&debugInterface))))\r\n    {\r\n        debugInterface->EnableDebugLayer();\r\n        //debugInterface->SetEnableGPUBasedValidation( TRUE );\r\n    }\r\n    else\r\n        Utility::Print(\"WARNING:  Unable to enable D3D12 debug validation layer\\n\");\r\n#endif\r\n\r\n#ifdef DXIL\r\n    EnableExperimentalShaderModels();\r\n#endif\r\n\r\n    // Obtain the DXGI factory\r\n    Microsoft::WRL::ComPtr<IDXGIFactory4> dxgiFactory;\r\n    ASSERT_SUCCEEDED(CreateDXGIFactory2(0, MY_IID_PPV_ARGS(&dxgiFactory)));\r\n\r\n    // Create the D3D graphics device\r\n    Microsoft::WRL::ComPtr<IDXGIAdapter1> pAdapter;\r\n\r\n    static const bool bUseWarpDriver = false;\r\n\r\n    if (!bUseWarpDriver)\r\n    {\r\n        SIZE_T MaxSize = 0;\r\n\r\n        for (uint32_t Idx = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(Idx, &pAdapter); ++Idx)\r\n        {\r\n            DXGI_ADAPTER_DESC1 desc;\r\n            pAdapter->GetDesc1(&desc);\r\n            if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)\r\n                continue;\r\n\r\n            if (desc.DedicatedVideoMemory > MaxSize && SUCCEEDED(D3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, MY_IID_PPV_ARGS(&pDevice))))\r\n            {\r\n                pAdapter->GetDesc1(&desc);\r\n                Utility::Printf(L\"D3D12-capable hardware found:  %s (%u MB)\\n\", desc.Description, desc.DedicatedVideoMemory >> 20);\r\n                \r\n                g_IntelIsGPU = (wcsstr(desc.Description, L\"Intel\") != 0);\r\n                MaxSize = desc.DedicatedVideoMemory;\r\n            }\r\n        }\r\n\r\n        if (MaxSize > 0)\r\n            g_Device = pDevice.Detach();\r\n    }\r\n\r\n    if (g_Device == nullptr)\r\n    {\r\n        if (bUseWarpDriver)\r\n            Utility::Print(\"WARP software adapter requested.  Initializing...\\n\");\r\n        else\r\n            Utility::Print(\"Failed to find a hardware adapter.  Falling back to WARP.\\n\");\r\n        ASSERT_SUCCEEDED(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&pAdapter)));\r\n        ASSERT_SUCCEEDED(D3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, MY_IID_PPV_ARGS(&pDevice)));\r\n        g_Device = pDevice.Detach();\r\n    }\r\n#ifndef RELEASE\r\n    else\r\n    {\r\n        bool DeveloperModeEnabled = false;\r\n\r\n        // Look in the Windows Registry to determine if Developer Mode is enabled\r\n        HKEY hKey;\r\n        LSTATUS result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L\"SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\AppModelUnlock\", 0, KEY_READ, &hKey);\r\n        if (result == ERROR_SUCCESS)\r\n        {\r\n            DWORD keyValue, keySize = sizeof(DWORD);\r\n            result = RegQueryValueEx(hKey, L\"AllowDevelopmentWithoutDevLicense\", 0, NULL, (byte*)&keyValue, &keySize);\r\n            if (result == ERROR_SUCCESS && keyValue == 1)\r\n                DeveloperModeEnabled = true;\r\n            RegCloseKey(hKey);\r\n        }\r\n\r\n        WARN_ONCE_IF_NOT(DeveloperModeEnabled, \"Enable Developer Mode on Windows 10 to get consistent profiling results\");\r\n\r\n        // Prevent the GPU from overclocking or underclocking to get consistent timings\r\n        if (DeveloperModeEnabled)\r\n            g_Device->SetStablePowerState(TRUE);\r\n    }\r\n#endif\t\r\n\r\n#if _DEBUG\r\n    ID3D12InfoQueue* pInfoQueue = nullptr;\r\n    if (SUCCEEDED(g_Device->QueryInterface(MY_IID_PPV_ARGS(&pInfoQueue))))\r\n    {\r\n        // Suppress whole categories of messages\r\n        //D3D12_MESSAGE_CATEGORY Categories[] = {};\r\n\r\n        // Suppress messages based on their severity level\r\n        D3D12_MESSAGE_SEVERITY Severities[] = \r\n        {\r\n            D3D12_MESSAGE_SEVERITY_INFO\r\n        };\r\n\r\n        // Suppress individual messages by their ID\r\n        D3D12_MESSAGE_ID DenyIds[] =\r\n        {\r\n            // This occurs when there are uninitialized descriptors in a descriptor table, even when a\r\n            // shader does not access the missing descriptors.  I find this is common when switching\r\n            // shader permutations and not wanting to change much code to reorder resources.\r\n            D3D12_MESSAGE_ID_INVALID_DESCRIPTOR_HANDLE,\r\n\r\n            // Triggered when a shader does not export all color components of a render target, such as\r\n            // when only writing RGB to an R10G10B10A2 buffer, ignoring alpha.\r\n            D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_PS_OUTPUT_RT_OUTPUT_MISMATCH,\r\n\r\n            // This occurs when a descriptor table is unbound even when a shader does not access the missing\r\n            // descriptors.  This is common with a root signature shared between disparate shaders that\r\n            // don't all need the same types of resources.\r\n            D3D12_MESSAGE_ID_COMMAND_LIST_DESCRIPTOR_TABLE_NOT_SET,\r\n\r\n            // RESOURCE_BARRIER_DUPLICATE_SUBRESOURCE_TRANSITIONS\r\n            (D3D12_MESSAGE_ID)1008,\r\n        };\r\n\r\n        D3D12_INFO_QUEUE_FILTER NewFilter = {};\r\n        //NewFilter.DenyList.NumCategories = _countof(Categories);\r\n        //NewFilter.DenyList.pCategoryList = Categories;\r\n        NewFilter.DenyList.NumSeverities = _countof(Severities);\r\n        NewFilter.DenyList.pSeverityList = Severities;\r\n        NewFilter.DenyList.NumIDs = _countof(DenyIds);\r\n        NewFilter.DenyList.pIDList = DenyIds;\r\n\r\n        pInfoQueue->PushStorageFilter(&NewFilter);\r\n        pInfoQueue->Release();\r\n    }\r\n#endif\r\n\r\n    // We like to do read-modify-write operations on UAVs during post processing.  To support that, we\r\n    // need to either have the hardware do typed UAV loads of R11G11B10_FLOAT or we need to manually\r\n    // decode an R32_UINT representation of the same buffer.  This code determines if we get the hardware\r\n    // load support.\r\n    D3D12_FEATURE_DATA_D3D12_OPTIONS FeatureData = {};\r\n    if (SUCCEEDED(g_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &FeatureData, sizeof(FeatureData))))\r\n    {\r\n        if (FeatureData.TypedUAVLoadAdditionalFormats)\r\n        {\r\n            D3D12_FEATURE_DATA_FORMAT_SUPPORT Support =\r\n            {\r\n                DXGI_FORMAT_R11G11B10_FLOAT, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE\r\n            };\r\n\r\n            if (SUCCEEDED(g_Device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &Support, sizeof(Support))) &&\r\n                (Support.Support2 & D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD) != 0)\r\n            {\r\n                g_bTypedUAVLoadSupport_R11G11B10_FLOAT = true;\r\n            }\r\n\r\n            Support.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;\r\n\r\n            if (SUCCEEDED(g_Device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &Support, sizeof(Support))) &&\r\n                (Support.Support2 & D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD) != 0)\r\n            {\r\n                g_bTypedUAVLoadSupport_R16G16B16A16_FLOAT = true;\r\n            }\r\n        }\r\n    }\r\n\r\n    g_CommandManager.Create(g_Device);\r\n\r\n    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};\r\n    swapChainDesc.Width = g_DisplayWidth;\r\n    swapChainDesc.Height = g_DisplayHeight;\r\n    swapChainDesc.Format = SwapChainFormat;\r\n    swapChainDesc.Scaling = DXGI_SCALING_NONE;\r\n    swapChainDesc.SampleDesc.Quality = 0;\r\n    swapChainDesc.SampleDesc.Count = 1;\r\n    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;\r\n    swapChainDesc.BufferCount = SWAP_CHAIN_BUFFER_COUNT;\r\n    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;\r\n    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;\r\n\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) // Win32\r\n    ASSERT_SUCCEEDED(dxgiFactory->CreateSwapChainForHwnd(g_CommandManager.GetCommandQueue(), GameCore::g_hWnd, &swapChainDesc, nullptr, nullptr, &s_SwapChain1));\r\n#else // UWP\r\n    ASSERT_SUCCEEDED(dxgiFactory->CreateSwapChainForCoreWindow(g_CommandManager.GetCommandQueue(), (IUnknown*)GameCore::g_window.Get(), &swapChainDesc, nullptr, &s_SwapChain1));\r\n#endif\r\n\r\n#if CONDITIONALLY_ENABLE_HDR_OUTPUT && defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2)\r\n    {\r\n        IDXGISwapChain4* swapChain = (IDXGISwapChain4*)s_SwapChain1;\r\n        ComPtr<IDXGIOutput> output;\r\n        ComPtr<IDXGIOutput6> output6;\r\n        DXGI_OUTPUT_DESC1 outputDesc;\r\n        UINT colorSpaceSupport;\r\n\r\n        // Query support for ST.2084 on the display and set the color space accordingly\r\n        if (SUCCEEDED(swapChain->GetContainingOutput(&output)) &&\r\n            SUCCEEDED(output.As(&output6)) &&\r\n            SUCCEEDED(output6->GetDesc1(&outputDesc)) &&\r\n            outputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 &&\r\n            SUCCEEDED(swapChain->CheckColorSpaceSupport(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, &colorSpaceSupport)) &&\r\n            (colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) &&\r\n            SUCCEEDED(swapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)))\r\n        {\r\n            g_bEnableHDROutput = true;\r\n        }\r\n    }\r\n#endif\r\n\r\n    for (uint32_t i = 0; i < SWAP_CHAIN_BUFFER_COUNT; ++i)\r\n    {\r\n        ComPtr<ID3D12Resource> DisplayPlane;\r\n        ASSERT_SUCCEEDED(s_SwapChain1->GetBuffer(i, MY_IID_PPV_ARGS(&DisplayPlane)));\r\n        g_DisplayPlane[i].CreateFromSwapChain(L\"Primary SwapChain Buffer\", DisplayPlane.Detach());\r\n    }\r\n\r\n    // Common state was moved to GraphicsCommon.*\r\n    InitializeCommonState();\r\n\r\n    s_PresentRS.Reset(4, 2);\r\n    s_PresentRS[0].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 2);\r\n    s_PresentRS[1].InitAsConstants(0, 6, D3D12_SHADER_VISIBILITY_ALL);\r\n    s_PresentRS[2].InitAsBufferSRV(2, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    s_PresentRS[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 1);\r\n    s_PresentRS.InitStaticSampler(0, SamplerLinearClampDesc);\r\n    s_PresentRS.InitStaticSampler(1, SamplerPointClampDesc);\r\n    s_PresentRS.Finalize(L\"Present\");\r\n\r\n    // Initialize PSOs\r\n    s_BlendUIPSO.SetRootSignature(s_PresentRS);\r\n    s_BlendUIPSO.SetRasterizerState( RasterizerTwoSided );\r\n    s_BlendUIPSO.SetBlendState( BlendPreMultiplied );\r\n    s_BlendUIPSO.SetDepthStencilState( DepthStateDisabled );\r\n    s_BlendUIPSO.SetSampleMask(0xFFFFFFFF);\r\n    s_BlendUIPSO.SetInputLayout(0, nullptr);\r\n    s_BlendUIPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);\r\n    s_BlendUIPSO.SetVertexShader( g_pScreenQuadVS, sizeof(g_pScreenQuadVS) );\r\n    s_BlendUIPSO.SetPixelShader( g_pBufferCopyPS, sizeof(g_pBufferCopyPS) );\r\n    s_BlendUIPSO.SetRenderTargetFormat(SwapChainFormat, DXGI_FORMAT_UNKNOWN);\r\n    s_BlendUIPSO.Finalize();\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName = s_BlendUIPSO; \\\r\n    ObjName.SetBlendState( BlendDisable ); \\\r\n    ObjName.SetPixelShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO(PresentSDRPS, g_pPresentSDRPS);\r\n    CreatePSO(MagnifyPixelsPS, g_pMagnifyPixelsPS);\r\n    CreatePSO(BilinearUpsamplePS, g_pBilinearUpsamplePS);\r\n    CreatePSO(BicubicHorizontalUpsamplePS, g_pBicubicHorizontalUpsamplePS);\r\n    CreatePSO(BicubicVerticalUpsamplePS, g_pBicubicVerticalUpsamplePS);\r\n    CreatePSO(SharpeningUpsamplePS, g_pSharpeningUpsamplePS);\r\n\r\n#undef CreatePSO\r\n\r\n    BicubicHorizontalUpsamplePS = s_BlendUIPSO;\r\n    BicubicHorizontalUpsamplePS.SetBlendState( BlendDisable );\r\n    BicubicHorizontalUpsamplePS.SetPixelShader(g_pBicubicHorizontalUpsamplePS, sizeof(g_pBicubicHorizontalUpsamplePS) );\r\n    BicubicHorizontalUpsamplePS.SetRenderTargetFormat(DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN);\r\n    BicubicHorizontalUpsamplePS.Finalize();\r\n\r\n    PresentHDRPS = PresentSDRPS;\r\n    PresentHDRPS.SetPixelShader(g_pPresentHDRPS, sizeof(g_pPresentHDRPS));\r\n    DXGI_FORMAT SwapChainFormats[2] = { DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM };\r\n    PresentHDRPS.SetRenderTargetFormats(2, SwapChainFormats, DXGI_FORMAT_UNKNOWN );\r\n    PresentHDRPS.Finalize();\r\n\r\n    g_GenerateMipsRS.Reset(3, 1);\r\n    g_GenerateMipsRS[0].InitAsConstants(0, 4);\r\n    g_GenerateMipsRS[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1);\r\n    g_GenerateMipsRS[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 4);\r\n    g_GenerateMipsRS.InitStaticSampler(0, SamplerLinearClampDesc);\r\n    g_GenerateMipsRS.Finalize(L\"Generate Mips\");\r\n    \r\n#define CreatePSO(ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(g_GenerateMipsRS); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO(g_GenerateMipsLinearPSO[0], g_pGenerateMipsLinearCS);\r\n    CreatePSO(g_GenerateMipsLinearPSO[1], g_pGenerateMipsLinearOddXCS);\r\n    CreatePSO(g_GenerateMipsLinearPSO[2], g_pGenerateMipsLinearOddYCS);\r\n    CreatePSO(g_GenerateMipsLinearPSO[3], g_pGenerateMipsLinearOddCS);\r\n    CreatePSO(g_GenerateMipsGammaPSO[0], g_pGenerateMipsGammaCS);\r\n    CreatePSO(g_GenerateMipsGammaPSO[1], g_pGenerateMipsGammaOddXCS);\r\n    CreatePSO(g_GenerateMipsGammaPSO[2], g_pGenerateMipsGammaOddYCS);\r\n    CreatePSO(g_GenerateMipsGammaPSO[3], g_pGenerateMipsGammaOddCS);\r\n\r\n    g_PreDisplayBuffer.Create(L\"PreDisplay Buffer\", g_DisplayWidth, g_DisplayHeight, 1, SwapChainFormat);\r\n\r\n    GpuCounterManager::Initialize(4096);\r\n    SetNativeResolution();\r\n    TemporalEffects::Initialize();\r\n    PostEffects::Initialize();\r\n    SSAO::Initialize();\r\n    TextRenderer::Initialize();\r\n    GraphRenderer::Initialize();\r\n    ParticleEffects::Initialize(kMaxNativeWidth, kMaxNativeHeight);\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\tARTGUI::Initialize();\r\n#endif // ART_ENABLE_GUI\r\n}\r\n\r\nvoid Graphics::Terminate( void )\r\n{\r\n    g_CommandManager.IdleGPU();\r\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\r\n    s_SwapChain1->SetFullscreenState(FALSE, nullptr);\r\n#endif\r\n}\r\n\r\nvoid Graphics::Shutdown( void )\r\n{\r\n    CommandContext::DestroyAllContexts();\r\n    g_CommandManager.Shutdown();\r\n    GpuCounterManager::Shutdown();\r\n    s_SwapChain1->Release();\r\n    PSO::DestroyAll();\r\n    RootSignature::DestroyAll();\r\n    DescriptorAllocator::DestroyAll();\r\n\r\n    DestroyCommonState();\r\n    DestroyRenderingBuffers();\r\n    TemporalEffects::Shutdown();\r\n    PostEffects::Shutdown();\r\n    SSAO::Shutdown();\r\n    TextRenderer::Shutdown();\r\n    GraphRenderer::Shutdown();\r\n    ParticleEffects::Shutdown();\r\n    TextureManager::Shutdown();\r\n\r\n    for (UINT i = 0; i < SWAP_CHAIN_BUFFER_COUNT; ++i)\r\n        g_DisplayPlane[i].Destroy();\r\n\r\n    g_PreDisplayBuffer.Destroy();\r\n\r\n#if defined(_DEBUG)\r\n    ID3D12DebugDevice* debugInterface;\r\n    if (SUCCEEDED(g_Device->QueryInterface(&debugInterface)))\r\n    {\r\n        debugInterface->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL | D3D12_RLDO_IGNORE_INTERNAL);\r\n        debugInterface->Release();\r\n    }\r\n#endif\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\tARTGUI::Finalize();\r\n#endif //ART_ENABLE_GUI\r\n\r\n    SAFE_RELEASE(g_Device);\r\n}\r\n\r\nvoid Graphics::PreparePresentHDR(void)\r\n{\r\n    GraphicsContext& Context = GraphicsContext::Begin(L\"Present\");\r\n\r\n    // We're going to be reading these buffers to write to the swap chain buffer(s)\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_OverlayBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DisplayPlane[g_CurrentBuffer], D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n\r\n    Context.SetRootSignature(s_PresentRS);\r\n    Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\r\n\r\n    Context.SetDynamicDescriptor(0, 0, g_pSceneColorBuffer->GetSRV());\r\n    Context.SetDynamicDescriptor(0, 1, g_OverlayBuffer.GetSRV());\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE RTVs[] =\r\n    {\r\n        g_DisplayPlane[g_CurrentBuffer].GetRTV()\r\n    };\r\n\r\n    Context.SetPipelineState(PresentHDRPS);\r\n    Context.SetRenderTargets(_countof(RTVs), RTVs);\r\n    Context.SetViewportAndScissor(0, 0, g_NativeWidth, g_NativeHeight);\r\n    struct Constants\r\n    {\r\n        float RcpDstWidth;\r\n        float RcpDstHeight;\r\n        float PaperWhite;\r\n        float MaxBrightness;\r\n        int32_t DebugMode;\r\n    };\r\n    Constants consts = { 1.0f / g_NativeWidth, 1.0f / g_NativeHeight,\r\n        (float)g_HDRPaperWhite, (float)g_MaxDisplayLuminance, (int32_t)HDRDebugMode };\r\n    Context.SetConstantArray(1, sizeof(Constants) / 4, (float*)&consts);\r\n    Context.Draw(3);\r\n\r\n    Context.TransitionResource(g_DisplayPlane[g_CurrentBuffer], D3D12_RESOURCE_STATE_PRESENT);\r\n\r\n    // Close the final context to be executed before frame present.\r\n    Context.Finish();\r\n}\r\n\r\nvoid Graphics::CompositeOverlays( GraphicsContext& Context )\r\n{\t\r\n\t// Blend (or write) the UI overlay\r\n    Context.TransitionResource(g_OverlayBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n    Context.SetDynamicDescriptor(0, 0, g_OverlayBuffer.GetSRV());\r\n    Context.SetPipelineState(s_BlendUIPSO);\r\n    Context.SetConstants(1, 1.0f / g_NativeWidth, 1.0f / g_NativeHeight);\r\n    Context.Draw(3);\r\n}\r\n\r\nvoid Graphics::PreparePresentLDR(void)\r\n{\r\n    GraphicsContext& Context = GraphicsContext::Begin(L\"Present\");\r\n\r\n    // We're going to be reading these buffers to write to the swap chain buffer(s)\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n\r\n    Context.SetRootSignature(s_PresentRS);\r\n    Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\r\n\r\n    // Copy (and convert) the LDR buffer to the back buffer\r\n\t\t\r\n    Context.SetDynamicDescriptor(0, 0, g_pSceneColorBuffer->GetSRV());\r\n\r\n    ColorBuffer& UpsampleDest = (DebugZoom == kDebugZoomOff ? g_DisplayPlane[g_CurrentBuffer] : g_PreDisplayBuffer);\r\n\r\n    // DRR Upscale\r\n    if (g_ResolutionScale != 1.0f && \r\n        ((g_pSceneColorBuffer->GetWidth()  != g_NativeWidth) ||\r\n         (g_pSceneColorBuffer->GetHeight() != g_NativeHeight)) )\r\n    {\r\n        Context.SetPipelineState(BilinearUpsamplePS);\r\n        Context.TransitionResource(UpsampleDest, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(UpsampleDest.GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n        Context.Draw(3);\r\n    }\r\n    else if (g_NativeWidth == g_DisplayWidth && g_NativeHeight == g_DisplayHeight)\r\n    {\r\n        Context.SetPipelineState(PresentSDRPS);\r\n        Context.TransitionResource(UpsampleDest, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(UpsampleDest.GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_NativeWidth, g_NativeHeight);\r\n        Context.Draw(3);\r\n    }\r\n    else if (UpsampleFilter == kBicubic)\r\n    {\r\n        Context.TransitionResource(g_HorizontalBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(g_HorizontalBuffer.GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_DisplayWidth, g_NativeHeight);\r\n        Context.SetPipelineState(BicubicHorizontalUpsamplePS);\r\n        Context.SetConstants(1, g_NativeWidth, g_NativeHeight, (float)BicubicUpsampleWeight);\r\n        Context.Draw(3);\r\n\r\n        Context.TransitionResource(g_HorizontalBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(UpsampleDest, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(UpsampleDest.GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n        Context.SetPipelineState(BicubicVerticalUpsamplePS);\r\n        Context.SetConstants(1, g_DisplayWidth, g_NativeHeight, (float)BicubicUpsampleWeight);\r\n        Context.SetDynamicDescriptor(0, 0, g_HorizontalBuffer.GetSRV());\r\n        Context.Draw(3);\r\n    }\r\n    else if (UpsampleFilter == kSharpening)\r\n    {\r\n        Context.SetPipelineState(SharpeningUpsamplePS);\r\n        Context.TransitionResource(UpsampleDest, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(UpsampleDest.GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n        float TexelWidth = 1.0f / g_NativeWidth;\r\n        float TexelHeight = 1.0f / g_NativeHeight;\r\n        float X = Math::Cos((float)SharpeningRotation / 180.0f * 3.14159f) * (float)SharpeningSpread;\r\n        float Y = Math::Sin((float)SharpeningRotation / 180.0f * 3.14159f) * (float)SharpeningSpread;\r\n        const float WA = (float)SharpeningStrength;\r\n        const float WB = 1.0f + 4.0f * WA;\r\n        float Constants[] = { X * TexelWidth, Y * TexelHeight, Y * TexelWidth, -X * TexelHeight, WA, WB };\r\n        Context.SetConstantArray(1, _countof(Constants), Constants);\r\n        Context.Draw(3);\r\n    }\r\n    else if (UpsampleFilter == kBilinear)\r\n    {\r\n        Context.SetPipelineState(BilinearUpsamplePS);\r\n        Context.TransitionResource(UpsampleDest, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(UpsampleDest.GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n        Context.Draw(3);\r\n    }\r\n\r\n    if (DebugZoom != kDebugZoomOff)\r\n    {\r\n        Context.TransitionResource(g_PreDisplayBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        Context.SetPipelineState(MagnifyPixelsPS);\r\n        Context.TransitionResource(g_DisplayPlane[g_CurrentBuffer], D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        Context.SetRenderTarget(g_DisplayPlane[g_CurrentBuffer].GetRTV());\r\n        Context.SetViewportAndScissor(0, 0, g_DisplayWidth, g_DisplayHeight);\r\n        Context.SetConstants(1, 1.0f / ((int)DebugZoom + 1.0f));\r\n        Context.SetDynamicDescriptor(0, 0, g_PreDisplayBuffer.GetSRV());\r\n        Context.Draw(3);\r\n    }\r\n\r\n    CompositeOverlays(Context);\r\n\r\n#ifdef ART_ENABLE_GUI\r\n\tARTGUI::Display(Context);\r\n#endif // ART_ENABLE_GUI\r\n\r\n\tContext.TransitionResource(g_DisplayPlane[g_CurrentBuffer], D3D12_RESOURCE_STATE_PRESENT);\r\n\r\n    // Close the final context to be executed before frame present.\r\n    Context.Finish();\r\n}\r\n\r\nvoid Graphics::Present(void)\r\n{\r\n    if (g_bEnableHDROutput)\r\n        PreparePresentHDR();\r\n    else\r\n        PreparePresentLDR();\r\n\r\n    g_CurrentBuffer = (g_CurrentBuffer + 1) % SWAP_CHAIN_BUFFER_COUNT;\r\n\r\n    UINT PresentInterval = s_EnableVSync ? std::min(4, (int)Round(s_FrameTime * 60.0f)) : 0;\r\n\r\n    s_SwapChain1->Present(PresentInterval, 0);\r\n\r\n    // Test robustness to handle spikes in CPU time\r\n    //if (s_DropRandomFrames)\r\n    //{\r\n    //\tif (std::rand() % 25 == 0)\r\n    //\t\tBusyLoopSleep(0.010);\r\n    //}\r\n\r\n    int64_t CurrentTick = SystemTime::GetCurrentTick();\r\n\r\n    if (s_EnableVSync)\r\n    {\r\n        // With VSync enabled, the time step between frames becomes a multiple of 16.666 ms.  We need\r\n        // to add logic to vary between 1 and 2 (or 3 fields).  This delta time also determines how\r\n        // long the previous frame should be displayed (i.e. the present interval.)\r\n        s_FrameTime = (s_LimitTo30Hz ? 2.0f : 1.0f) / 60.0f;\r\n        if (s_DropRandomFrames)\r\n        {\r\n            if (std::rand() % 50 == 0)\r\n                s_FrameTime += (1.0f / 60.0f);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        // When running free, keep the most recent total frame time as the time step for\r\n        // the next frame simulation.  This is not super-accurate, but assuming a frame\r\n        // time varies smoothly, it should be close enough.\r\n        s_FrameTime = (float)SystemTime::TimeBetweenTicks(s_FrameStartTick, CurrentTick);\r\n    }\r\n\r\n    s_FrameStartTick = CurrentTick;\r\n\r\n    ++s_FrameIndex;\r\n    TemporalEffects::Update((uint32_t)s_FrameIndex);\r\n\r\n    SetNativeResolution();\r\n}\r\n\r\nuint64_t Graphics::GetFrameCount(void)\r\n{\r\n    return s_FrameIndex;\r\n}\r\n\r\nuint32_t Graphics::GetNumBackbuffers(void) {\r\n\treturn SWAP_CHAIN_BUFFER_COUNT;\r\n}\r\n\r\nuint32_t Graphics::GetActiveFramebufferIdx() {\r\n\treturn g_CurrentBuffer;\r\n}\r\n\r\nColorBuffer& Graphics::GetFramebufferByIdx(uint32_t idx) {\r\n\tASSERT(idx < SWAP_CHAIN_BUFFER_COUNT);\r\n\r\n\treturn g_DisplayPlane[idx];\r\n}\r\n\r\nColorBuffer& Graphics::GetOverlayBuffer() {\r\n\treturn g_OverlayBuffer;\r\n}\r\n\r\nfloat Graphics::GetFrameTime(void)\r\n{\r\n    return (s_OfflineTimeStep > 0) ? s_OfflineTimeStep : s_FrameTime;\r\n}\r\n\r\nfloat Graphics::GetFrameRate(void)\r\n{\r\n    return s_FrameTime == 0.0f ? 0.0f : 1.0f / s_FrameTime;\r\n}\r\n\r\nvoid Graphics::SetOfflineTimestep(float spf) {\r\n\ts_OfflineTimeStep = spf;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/GraphicsCore.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n// Modified 2018, Intel Corporation\r\n// Added checking for Intel GPU\r\n\r\n#pragma once\r\n\r\n#include \"PipelineState.h\"\r\n#include \"DescriptorHeap.h\"\r\n#include \"RootSignature.h\"\r\n#include \"SamplerManager.h\"\r\n#include \"GraphicsCommon.h\"\r\n\r\nclass ColorBuffer;\r\nclass DepthBuffer;\r\nclass GraphicsPSO;\r\nclass CommandContext;\r\nclass CommandListManager;\r\nclass CommandSignature;\r\nclass ContextManager;\r\n\r\nnamespace Graphics\r\n{\r\n#ifndef RELEASE\r\n    extern const GUID WKPDID_D3DDebugObjectName;\r\n#endif\r\n\r\n    using namespace Microsoft::WRL;\r\n\r\n    void Initialize(void);\r\n    void Resize(uint32_t width, uint32_t height);\r\n    void Terminate(void);\r\n    void Shutdown(void);\r\n    void Present(void);\r\n\r\n    extern uint32_t g_DisplayWidth;\r\n    extern uint32_t g_DisplayHeight;\r\n    extern float g_ResolutionScale;\r\n\r\n    // Returns the number of elapsed frames since application start\r\n    uint64_t GetFrameCount(void);\r\n\r\n\tuint32_t GetNumBackbuffers(void);\r\n\t\r\n\t// for multi-buffered rendering, returns the index of the currently active backbuffer\r\n\tuint32_t GetActiveFramebufferIdx(void);\r\n\r\n\tColorBuffer& GetFramebufferByIdx(uint32_t idx);\r\n\r\n\tColorBuffer& GetOverlayBuffer();\r\n\r\n    // The amount of time elapsed during the last completed frame.  The CPU and/or\r\n    // GPU may be idle during parts of the frame.  The frame time measures the time\r\n    // between calls to present each frame.\r\n    float GetFrameTime(void);\r\n\r\n    // The total number of frames per second\r\n    float GetFrameRate(void);\r\n\r\n\t// if greater  than zero, the app will update the time with a constant rate\r\n\t// if zero, it will render interactively, based on the system time\r\n\t// The meaning of the time is \"seconds per frame\"\r\n\tvoid SetOfflineTimestep(float spf);\r\n\t\r\n\textern DX12_DEVICE* g_Device;\r\n    extern CommandListManager g_CommandManager;\r\n    extern ContextManager g_ContextManager;\r\n\r\n    extern D3D_FEATURE_LEVEL g_D3DFeatureLevel;\r\n    extern bool g_bTypedUAVLoadSupport_R11G11B10_FLOAT;\r\n    extern bool g_bEnableHDROutput;\r\n\r\n    extern DescriptorAllocator g_DescriptorAllocator[];\r\n    inline D3D12_CPU_DESCRIPTOR_HANDLE AllocateDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 )\r\n    {\r\n        return g_DescriptorAllocator[Type].Allocate(Count);\r\n    }\r\n\r\n    extern bool g_IntelIsGPU;\r\n    extern RootSignature g_GenerateMipsRS;\r\n    extern ComputePSO g_GenerateMipsLinearPSO[4];\r\n    extern ComputePSO g_GenerateMipsGammaPSO[4];\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Hash.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#pragma once\r\n\r\n#include \"Math/Common.h\"\r\n\r\n// This requires SSE4.2 which is present on Intel Nehalem (Nov. 2008)\r\n// and AMD Bulldozer (Oct. 2011) processors.  I could put a runtime\r\n// check for this, but I'm just going to assume people playing with\r\n// DirectX 12 on Windows 10 have fairly recent machines.\r\n#ifdef _M_X64\r\n#define ENABLE_SSE_CRC32 1\r\n#else\r\n#define ENABLE_SSE_CRC32 0\r\n#endif\r\n\r\n#if ENABLE_SSE_CRC32\r\n#pragma intrinsic(_mm_crc32_u32)\r\n#pragma intrinsic(_mm_crc32_u64)\r\n#endif\r\n\r\nnamespace Utility\r\n{\r\n    inline size_t HashRange(const uint32_t* const Begin, const uint32_t* const End, size_t Hash)\r\n    {\r\n#if ENABLE_SSE_CRC32\r\n        const uint64_t* Iter64 = (const uint64_t*)Math::AlignUp(Begin, 8);\r\n        const uint64_t* const End64 = (const uint64_t* const)Math::AlignDown(End, 8);\r\n\r\n        // If not 64-bit aligned, start with a single u32\r\n        if ((uint32_t*)Iter64 > Begin)\r\n            Hash = _mm_crc32_u32((uint32_t)Hash, *Begin);\r\n\r\n        // Iterate over consecutive u64 values\r\n        while (Iter64 < End64)\r\n            Hash = _mm_crc32_u64((uint64_t)Hash, *Iter64++);\r\n\r\n        // If there is a 32-bit remainder, accumulate that\r\n        if ((uint32_t*)Iter64 < End)\r\n            Hash = _mm_crc32_u32((uint32_t)Hash, *(uint32_t*)Iter64);\r\n#else\r\n        // An inexpensive hash for CPUs lacking SSE4.2\r\n        for (const uint32_t* Iter = Begin; Iter < End; ++Iter)\r\n            Hash = 16777619U * Hash ^ *Iter;\r\n#endif\r\n\r\n        return Hash;\r\n    }\r\n\r\n    template <typename T> inline size_t HashState( const T* StateDesc, size_t Count = 1, size_t Hash = 2166136261U )\r\n    {\r\n        static_assert((sizeof(T) & 3) == 0 && alignof(T) >= 4, \"State object is not word-aligned\");\r\n        return HashRange((uint32_t*)StateDesc, (uint32_t*)(StateDesc + Count), Hash);\r\n    }\r\n\r\n} // namespace Utility\r\n"
  },
  {
    "path": "MiniEngine/Core/LinearAllocator.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//             Alex Nankervis\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"LinearAllocator.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandListManager.h\"\r\n#include <thread>\r\n\r\nusing namespace Graphics;\r\nusing namespace std;\r\n\r\nLinearAllocatorType LinearAllocatorPageManager::sm_AutoType = kGpuExclusive;\r\n\r\nLinearAllocatorPageManager::LinearAllocatorPageManager()\r\n{\r\n    m_AllocationType = sm_AutoType;\r\n    sm_AutoType = (LinearAllocatorType)(sm_AutoType + 1);\r\n    ASSERT(sm_AutoType <= kNumAllocatorTypes);\r\n}\r\n\r\nLinearAllocatorPageManager LinearAllocator::sm_PageManager[2];\r\n\r\nLinearAllocationPage* LinearAllocatorPageManager::RequestPage()\r\n{\r\n    lock_guard<mutex> LockGuard(m_Mutex);\r\n\r\n    while (!m_RetiredPages.empty() && g_CommandManager.IsFenceComplete(m_RetiredPages.front().first))\r\n    {\r\n        m_AvailablePages.push(m_RetiredPages.front().second);\r\n        m_RetiredPages.pop();\r\n    }\r\n\r\n    LinearAllocationPage* PagePtr = nullptr;\r\n\r\n    if (!m_AvailablePages.empty())\r\n    {\r\n        PagePtr = m_AvailablePages.front();\r\n        m_AvailablePages.pop();\r\n    }\r\n    else\r\n    {\r\n        PagePtr = CreateNewPage();\r\n        m_PagePool.emplace_back(PagePtr);\r\n    }\r\n\r\n    return PagePtr;\r\n}\r\n\r\nvoid LinearAllocatorPageManager::DiscardPages( uint64_t FenceValue, const vector<LinearAllocationPage*>& UsedPages )\r\n{\r\n    lock_guard<mutex> LockGuard(m_Mutex);\r\n    for (auto iter = UsedPages.begin(); iter != UsedPages.end(); ++iter)\r\n        m_RetiredPages.push(make_pair(FenceValue, *iter));\r\n}\r\n\r\nvoid LinearAllocatorPageManager::FreeLargePages( uint64_t FenceValue, const vector<LinearAllocationPage*>& LargePages )\r\n{\r\n    lock_guard<mutex> LockGuard(m_Mutex);\r\n\r\n    while (!m_DeletionQueue.empty() && g_CommandManager.IsFenceComplete(m_DeletionQueue.front().first))\r\n    {\r\n        delete m_DeletionQueue.front().second;\r\n        m_DeletionQueue.pop();\r\n    }\r\n\r\n    for (auto iter = LargePages.begin(); iter != LargePages.end(); ++iter)\r\n    {\r\n        (*iter)->Unmap();\r\n        m_DeletionQueue.push(make_pair(FenceValue, *iter));\r\n    }\r\n}\r\n\r\nLinearAllocationPage* LinearAllocatorPageManager::CreateNewPage( size_t PageSize  )\r\n{\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    D3D12_RESOURCE_DESC ResourceDesc;\r\n    ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;\r\n    ResourceDesc.Alignment = 0;\r\n    ResourceDesc.Height = 1;\r\n    ResourceDesc.DepthOrArraySize = 1;\r\n    ResourceDesc.MipLevels = 1;\r\n    ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;\r\n    ResourceDesc.SampleDesc.Count = 1;\r\n    ResourceDesc.SampleDesc.Quality = 0;\r\n    ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;\r\n\r\n    D3D12_RESOURCE_STATES DefaultUsage;\r\n\r\n    if (m_AllocationType == kGpuExclusive)\r\n    {\r\n        HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;\r\n        ResourceDesc.Width = PageSize == 0 ? kGpuAllocatorPageSize : PageSize;\r\n        ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;\r\n        DefaultUsage = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;\r\n    }\r\n    else\r\n    {\r\n        HeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;\r\n        ResourceDesc.Width = PageSize == 0 ? kCpuAllocatorPageSize : PageSize;\r\n        ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;\r\n        DefaultUsage = D3D12_RESOURCE_STATE_GENERIC_READ;\r\n    }\r\n\r\n    ID3D12Resource* pBuffer;\r\n    ASSERT_SUCCEEDED( g_Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE,\r\n        &ResourceDesc, DefaultUsage, nullptr, MY_IID_PPV_ARGS(&pBuffer)) );\r\n\r\n    pBuffer->SetName(L\"LinearAllocator Page\");\r\n\r\n    return new LinearAllocationPage(pBuffer, DefaultUsage);\r\n}\r\n\r\nvoid LinearAllocator::CleanupUsedPages( uint64_t FenceID )\r\n{\r\n    if (m_CurPage == nullptr)\r\n        return;\r\n\r\n    m_RetiredPages.push_back(m_CurPage);\r\n    m_CurPage = nullptr;\r\n    m_CurOffset = 0;\r\n\r\n    sm_PageManager[m_AllocationType].DiscardPages(FenceID, m_RetiredPages);\r\n    m_RetiredPages.clear();\r\n\r\n    sm_PageManager[m_AllocationType].FreeLargePages(FenceID, m_LargePageList);\r\n    m_LargePageList.clear();\r\n}\r\n\r\nDynAlloc LinearAllocator::AllocateLargePage(size_t SizeInBytes)\r\n{\r\n    LinearAllocationPage* OneOff = sm_PageManager[m_AllocationType].CreateNewPage(SizeInBytes);\r\n    m_LargePageList.push_back(OneOff);\r\n\r\n    DynAlloc ret(*OneOff, 0, SizeInBytes);\r\n    ret.DataPtr = OneOff->m_CpuVirtualAddress;\r\n    ret.GpuAddress = OneOff->m_GpuVirtualAddress;\r\n\r\n    return ret;\r\n}\r\n\r\nDynAlloc LinearAllocator::Allocate(size_t SizeInBytes, size_t Alignment)\r\n{\r\n    const size_t AlignmentMask = Alignment - 1;\r\n\r\n    // Assert that it's a power of two.\r\n    ASSERT((AlignmentMask & Alignment) == 0);\r\n\r\n    // Align the allocation\r\n    const size_t AlignedSize = Math::AlignUpWithMask(SizeInBytes, AlignmentMask);\r\n\r\n    if (AlignedSize > m_PageSize)\r\n        return AllocateLargePage(AlignedSize);\r\n\r\n    m_CurOffset = Math::AlignUp(m_CurOffset, Alignment);\r\n\r\n    if (m_CurOffset + AlignedSize > m_PageSize)\r\n    {\r\n        ASSERT(m_CurPage != nullptr);\r\n        m_RetiredPages.push_back(m_CurPage);\r\n        m_CurPage = nullptr;\r\n    }\r\n\r\n    if (m_CurPage == nullptr)\r\n    {\r\n        m_CurPage = sm_PageManager[m_AllocationType].RequestPage();\r\n        m_CurOffset = 0;\r\n    }\r\n\r\n    DynAlloc ret(*m_CurPage, m_CurOffset, AlignedSize);\r\n    ret.DataPtr = (uint8_t*)m_CurPage->m_CpuVirtualAddress + m_CurOffset;\r\n    ret.GpuAddress = m_CurPage->m_GpuVirtualAddress + m_CurOffset;\r\n\r\n    m_CurOffset += AlignedSize;\r\n\r\n    return ret;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/LinearAllocator.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// Description:  This is a dynamic graphics memory allocator for DX12.  It's designed to work in concert\r\n// with the CommandContext class and to do so in a thread-safe manner.  There may be many command contexts,\r\n// each with its own linear allocators.  They act as windows into a global memory pool by reserving a\r\n// context-local memory page.  Requesting a new page is done in a thread-safe manner by guarding accesses\r\n// with a mutex lock.\r\n//\r\n// When a command context is finished, it will receive a fence ID that indicates when it's safe to reclaim\r\n// used resources.  The CleanupUsedPages() method must be invoked at this time so that the used pages can be\r\n// scheduled for reuse after the fence has cleared.\r\n\r\n#pragma once\r\n\r\n#include \"GpuResource.h\"\r\n#include <vector>\r\n#include <queue>\r\n#include <mutex>\r\n\r\n// Constant blocks must be multiples of 16 constants @ 16 bytes each\r\n#define DEFAULT_ALIGN 256\r\n\r\n// Various types of allocations may contain NULL pointers.  Check before dereferencing if you are unsure.\r\nstruct DynAlloc\r\n{\r\n    DynAlloc(GpuResource& BaseResource, size_t ThisOffset, size_t ThisSize)\r\n        : Buffer(BaseResource), Offset(ThisOffset), Size(ThisSize) {}\r\n\r\n    GpuResource& Buffer;\t// The D3D buffer associated with this memory.\r\n    size_t Offset;\t\t\t// Offset from start of buffer resource\r\n    size_t Size;\t\t\t// Reserved size of this allocation\r\n    void* DataPtr;\t\t\t// The CPU-writeable address\r\n    D3D12_GPU_VIRTUAL_ADDRESS GpuAddress;\t// The GPU-visible address\r\n};\r\n\r\nclass LinearAllocationPage : public GpuResource\r\n{\r\npublic:\r\n    LinearAllocationPage(ID3D12Resource* pResource, D3D12_RESOURCE_STATES Usage) : GpuResource()\r\n    {\r\n        m_pResource.Attach(pResource);\r\n        m_UsageState = Usage;\r\n        m_GpuVirtualAddress = m_pResource->GetGPUVirtualAddress();\r\n        m_pResource->Map(0, nullptr, &m_CpuVirtualAddress);\r\n    }\r\n\r\n    ~LinearAllocationPage()\r\n    {\r\n        Unmap();\r\n    }\r\n\r\n    void Map(void)\r\n    {\r\n        if (m_CpuVirtualAddress == nullptr)\r\n        {\r\n            m_pResource->Map(0, nullptr, &m_CpuVirtualAddress);\r\n        }\r\n    }\r\n\r\n    void Unmap(void)\r\n    {\r\n        if (m_CpuVirtualAddress != nullptr)\r\n        {\r\n            m_pResource->Unmap(0, nullptr);\r\n            m_CpuVirtualAddress = nullptr;\r\n        }\r\n    }\r\n\r\n    void* m_CpuVirtualAddress;\r\n    D3D12_GPU_VIRTUAL_ADDRESS m_GpuVirtualAddress;\r\n};\r\n\r\nenum LinearAllocatorType\r\n{\r\n    kInvalidAllocator = -1,\r\n\r\n    kGpuExclusive = 0,\t\t// DEFAULT   GPU-writeable (via UAV)\r\n    kCpuWritable = 1,\t\t// UPLOAD CPU-writeable (but write combined)\r\n\r\n    kNumAllocatorTypes\r\n};\r\n\r\nenum\r\n{\r\n    kGpuAllocatorPageSize = 0x10000,\t// 64K\r\n    kCpuAllocatorPageSize = 0x200000\t// 2MB\r\n};\r\n\r\nclass LinearAllocatorPageManager\r\n{\r\npublic:\r\n\r\n    LinearAllocatorPageManager();\r\n    LinearAllocationPage* RequestPage( void );\r\n    LinearAllocationPage* CreateNewPage( size_t PageSize = 0 );\r\n\r\n    // Discarded pages will get recycled.  This is for fixed size pages.\r\n    void DiscardPages( uint64_t FenceID, const std::vector<LinearAllocationPage*>& Pages );\r\n\r\n    // Freed pages will be destroyed once their fence has passed.  This is for single-use,\r\n    // \"large\" pages.\r\n    void FreeLargePages( uint64_t FenceID, const std::vector<LinearAllocationPage*>& Pages );\r\n\r\n    void Destroy( void ) { m_PagePool.clear(); }\r\n\r\nprivate:\r\n\r\n    static LinearAllocatorType sm_AutoType;\r\n\r\n    LinearAllocatorType m_AllocationType;\r\n    std::vector<std::unique_ptr<LinearAllocationPage> > m_PagePool;\r\n    std::queue<std::pair<uint64_t, LinearAllocationPage*> > m_RetiredPages;\r\n    std::queue<std::pair<uint64_t, LinearAllocationPage*> > m_DeletionQueue;\r\n    std::queue<LinearAllocationPage*> m_AvailablePages;\r\n    std::mutex m_Mutex;\r\n};\r\n\r\nclass LinearAllocator\r\n{\r\npublic:\r\n\r\n    LinearAllocator(LinearAllocatorType Type) : m_AllocationType(Type), m_PageSize(0), m_CurOffset(~(size_t)0), m_CurPage(nullptr)\r\n    {\r\n        ASSERT(Type > kInvalidAllocator && Type < kNumAllocatorTypes);\r\n        m_PageSize = (Type == kGpuExclusive ? kGpuAllocatorPageSize : kCpuAllocatorPageSize);\r\n    }\r\n\r\n    DynAlloc Allocate( size_t SizeInBytes, size_t Alignment = DEFAULT_ALIGN );\r\n\r\n    void CleanupUsedPages( uint64_t FenceID );\r\n\r\n    static void DestroyAll( void )\r\n    {\r\n        sm_PageManager[0].Destroy();\r\n        sm_PageManager[1].Destroy();\r\n    }\r\n\r\nprivate:\r\n\r\n    DynAlloc AllocateLargePage( size_t SizeInBytes );\r\n\r\n    static LinearAllocatorPageManager sm_PageManager[2];\r\n\r\n    LinearAllocatorType m_AllocationType;\r\n    size_t m_PageSize;\r\n    size_t m_CurOffset;\r\n    LinearAllocationPage* m_CurPage;\r\n    std::vector<LinearAllocationPage*> m_RetiredPages;\r\n    std::vector<LinearAllocationPage*> m_LargePageList;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/BoundingPlane.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"VectorMath.h\"\r\n\r\nnamespace Math\r\n{\r\n    class BoundingPlane\r\n    {\r\n    public:\r\n\r\n        BoundingPlane() {}\r\n        BoundingPlane( Vector3 normalToPlane, float distanceFromOrigin ) : m_repr(normalToPlane, distanceFromOrigin) {}\r\n        BoundingPlane( Vector3 pointOnPlane, Vector3 normalToPlane );\r\n        BoundingPlane( float A, float B, float C, float D ) : m_repr(A, B, C, D) {}\r\n        BoundingPlane( const BoundingPlane& plane ) : m_repr(plane.m_repr) {}\r\n        explicit BoundingPlane( Vector4 plane ) : m_repr(plane) {}\r\n\r\n        INLINE operator Vector4() const { return m_repr; }\r\n\r\n        // Returns the direction the plane is facing.  (Warning:  might not be normalized.)\r\n        Vector3 GetNormal( void ) const { return Vector3(XMVECTOR(m_repr)); }\r\n\r\n        // Returns the point on the plane closest to the origin\r\n        Vector3 GetPointOnPlane( void ) const { return -GetNormal() * m_repr.GetW(); }\r\n\r\n        // Distance from 3D point\r\n        Scalar DistanceFromPoint( Vector3 point ) const\r\n        {\r\n            return Dot(point, GetNormal()) + m_repr.GetW();\r\n        }\r\n\r\n        // Distance from homogeneous point\r\n        Scalar DistanceFromPoint(Vector4 point) const\r\n        {\r\n            return Dot(point, m_repr);\r\n        }\r\n\r\n        // Most efficient way to transform a plane.  (Involves one quaternion-vector rotation and one dot product.)\r\n        friend BoundingPlane operator* ( const OrthogonalTransform& xform, BoundingPlane plane )\r\n        {\r\n            Vector3 normalToPlane = xform.GetRotation() * plane.GetNormal();\r\n            float distanceFromOrigin = plane.m_repr.GetW() - Dot(normalToPlane, xform.GetTranslation());\r\n            return BoundingPlane(normalToPlane, distanceFromOrigin);\r\n        }\r\n\r\n        // Less efficient way to transform a plane (but handles affine transformations.)\r\n        friend BoundingPlane operator* ( const Matrix4& mat, BoundingPlane plane )\r\n        {\r\n            return BoundingPlane( Transpose(Invert(mat)) * plane.m_repr );\r\n        }\r\n\r\n    private:\r\n\r\n        Vector4 m_repr;\r\n    };\r\n\r\n    //=======================================================================================================\r\n    // Inline implementations\r\n    //\r\n    inline BoundingPlane::BoundingPlane( Vector3 pointOnPlane, Vector3 normalToPlane )\r\n    {\r\n        // Guarantee a normal.  This constructor isn't meant to be called frequently, but if it is, we can change this.\r\n        normalToPlane = Normalize(normalToPlane);\t\r\n        m_repr = Vector4(normalToPlane, -Dot(pointOnPlane, normalToPlane));\r\n    }\r\n\r\n    //=======================================================================================================\r\n    // Functions operating on planes\r\n    //\r\n    inline BoundingPlane PlaneFromPointsCCW( Vector3 A, Vector3 B, Vector3 C )\r\n    {\r\n        return BoundingPlane( A, Cross(B - A, C - A) );\r\n    }\r\n\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/BoundingSphere.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"VectorMath.h\"\r\n\r\nnamespace Math\r\n{\r\n    class BoundingSphere\r\n    {\r\n    public:\r\n        BoundingSphere() {}\r\n        BoundingSphere( Vector3 center, Scalar radius );\r\n        explicit BoundingSphere( Vector4 sphere );\r\n\r\n        Vector3 GetCenter( void ) const;\r\n        Scalar GetRadius( void ) const;\r\n\r\n    private:\r\n\r\n        Vector4 m_repr;\r\n    };\r\n\r\n    //=======================================================================================================\r\n    // Inline implementations\r\n    //\r\n\r\n    inline BoundingSphere::BoundingSphere( Vector3 center, Scalar radius )\r\n    {\r\n        m_repr = Vector4(center);\r\n        m_repr.SetW(radius);\r\n    }\r\n\r\n    inline BoundingSphere::BoundingSphere( Vector4 sphere )\r\n        : m_repr(sphere)\r\n    {\r\n    }\r\n\r\n    inline Vector3 BoundingSphere::GetCenter( void ) const\r\n    {\r\n        return Vector3(m_repr);\r\n    }\r\n\r\n    inline Scalar BoundingSphere::GetRadius( void ) const\r\n    {\r\n        return m_repr.GetW();\r\n    }\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Common.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include <DirectXMath.h>\r\n#include <intrin.h>\r\n\r\n#define INLINE __forceinline\r\n\r\nnamespace Math\r\n{\r\n    template <typename T> __forceinline T AlignUpWithMask( T value, size_t mask )\r\n    {\r\n        return (T)(((size_t)value + mask) & ~mask);\r\n    }\r\n\r\n    template <typename T> __forceinline T AlignDownWithMask( T value, size_t mask )\r\n    {\r\n        return (T)((size_t)value & ~mask);\r\n    }\r\n\r\n    template <typename T> __forceinline T AlignUp( T value, size_t alignment )\r\n    {\r\n        return AlignUpWithMask(value, alignment - 1);\r\n    }\r\n\r\n    template <typename T> __forceinline T AlignDown( T value, size_t alignment )\r\n    {\r\n        return AlignDownWithMask(value, alignment - 1);\r\n    }\r\n\r\n    template <typename T> __forceinline bool IsAligned( T value, size_t alignment )\r\n    {\r\n        return 0 == ((size_t)value & (alignment - 1));\r\n    }\r\n\r\n    template <typename T> __forceinline T DivideByMultiple( T value, size_t alignment )\r\n    {\r\n        return (T)((value + alignment - 1) / alignment);\r\n    }\r\n\r\n    template <typename T> __forceinline bool IsPowerOfTwo(T value)\r\n    {\r\n        return 0 == (value & (value - 1));\r\n    }\r\n\r\n    template <typename T> __forceinline bool IsDivisible(T value, T divisor)\r\n    {\r\n        return (value / divisor) * divisor == value;\r\n    }\r\n\r\n    __forceinline uint8_t Log2(uint64_t value)\r\n    {\r\n        unsigned long mssb; // most significant set bit\r\n        unsigned long lssb; // least significant set bit\r\n\r\n        // If perfect power of two (only one set bit), return index of bit.  Otherwise round up\r\n        // fractional log by adding 1 to most signicant set bit's index.\r\n        if (_BitScanReverse64(&mssb, value) > 0 && _BitScanForward64(&lssb, value) > 0)\r\n            return uint8_t(mssb + (mssb == lssb ? 0 : 1));\r\n        else\r\n            return 0;\r\n    }\r\n\r\n    template <typename T> __forceinline T AlignPowerOfTwo(T value)\r\n    {\r\n        return value == 0 ? 0 : 1 << Log2(value);\r\n    }\r\n\r\n    using namespace DirectX;\r\n\r\n    INLINE XMVECTOR SplatZero()\r\n    {\r\n        return XMVectorZero();\r\n    }\r\n\r\n#if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_)\r\n\r\n    INLINE XMVECTOR SplatOne( XMVECTOR zero = SplatZero() )\r\n    {\r\n        __m128i AllBits = _mm_castps_si128(_mm_cmpeq_ps(zero, zero));\r\n        return _mm_castsi128_ps(_mm_slli_epi32(_mm_srli_epi32(AllBits, 25), 23));\t// return 0x3F800000\r\n        //return _mm_cvtepi32_ps(_mm_srli_epi32(SetAllBits(zero), 31));\t\t\t\t// return (float)1;  (alternate method)\r\n    }\r\n\r\n#if defined(_XM_SSE4_INTRINSICS_)\r\n    INLINE XMVECTOR CreateXUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        return _mm_insert_ps(one, one, 0x0E);\r\n    }\r\n    INLINE XMVECTOR CreateYUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        return _mm_insert_ps(one, one, 0x0D);\r\n    }\r\n    INLINE XMVECTOR CreateZUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        return _mm_insert_ps(one, one, 0x0B);\r\n    }\r\n    INLINE XMVECTOR CreateWUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        return _mm_insert_ps(one, one, 0x07);\r\n    }\r\n    INLINE XMVECTOR SetWToZero( FXMVECTOR vec )\r\n    {\r\n        return _mm_insert_ps(vec, vec, 0x08);\r\n    }\r\n    INLINE XMVECTOR SetWToOne( FXMVECTOR vec )\r\n    {\r\n        return _mm_blend_ps(vec, SplatOne(), 0x8);\r\n    }\r\n#else\r\n    INLINE XMVECTOR CreateXUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        return _mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(one), 12));\r\n    }\r\n    INLINE XMVECTOR CreateYUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        XMVECTOR unitx = CreateXUnitVector(one);\r\n        return _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(unitx), 4));\r\n    }\r\n    INLINE XMVECTOR CreateZUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        XMVECTOR unitx = CreateXUnitVector(one);\r\n        return _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(unitx), 8));\r\n    }\r\n    INLINE XMVECTOR CreateWUnitVector( XMVECTOR one = SplatOne() )\r\n    {\r\n        return _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(one), 12));\r\n    }\r\n    INLINE XMVECTOR SetWToZero( FXMVECTOR vec )\r\n    {\r\n        __m128i MaskOffW = _mm_srli_si128(_mm_castps_si128(_mm_cmpeq_ps(vec, vec)), 4);\r\n        return _mm_and_ps(vec, _mm_castsi128_ps(MaskOffW));\r\n    }\r\n    INLINE XMVECTOR SetWToOne( FXMVECTOR vec )\r\n    {\r\n        return _mm_movelh_ps(vec, _mm_unpackhi_ps(vec, SplatOne()));\r\n    }\r\n#endif\r\n\r\n#else // !_XM_SSE_INTRINSICS_\r\n\r\n    INLINE XMVECTOR SplatOne() { return XMVectorSplatOne(); }\r\n    INLINE XMVECTOR CreateXUnitVector() { return g_XMIdentityR0; }\r\n    INLINE XMVECTOR CreateYUnitVector() { return g_XMIdentityR1; }\r\n    INLINE XMVECTOR CreateZUnitVector() { return g_XMIdentityR2; }\r\n    INLINE XMVECTOR CreateWUnitVector() { return g_XMIdentityR3; }\r\n    INLINE XMVECTOR SetWToZero( FXMVECTOR vec ) { return XMVectorAndInt( vec, g_XMMask3 ); }\r\n    INLINE XMVECTOR SetWToOne( FXMVECTOR vec ) { return XMVectorSelect( g_XMIdentityR3, vec, g_XMMask3 ); }\r\n\r\n#endif\r\n\r\n    enum EZeroTag { kZero, kOrigin };\r\n    enum EIdentityTag { kOne, kIdentity };\r\n    enum EXUnitVector { kXUnitVector };\r\n    enum EYUnitVector { kYUnitVector };\r\n    enum EZUnitVector { kZUnitVector };\r\n    enum EWUnitVector { kWUnitVector };\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Frustum.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"Frustum.h\"\r\n#include \"Camera.h\"\r\n\r\nusing namespace Math;\r\n\r\nvoid Frustum::ConstructPerspectiveFrustum( float HTan, float VTan, float NearClip, float FarClip )\r\n{\r\n    const float NearX = HTan * NearClip;\r\n    const float NearY = VTan * NearClip;\r\n    const float FarX = HTan * FarClip;\r\n    const float FarY = VTan * FarClip;\r\n\r\n    // Define the frustum corners\r\n    m_FrustumCorners[ kNearLowerLeft  ] = Vector3(-NearX, -NearY, -NearClip);\t// Near lower left\r\n    m_FrustumCorners[ kNearUpperLeft  ] = Vector3(-NearX,  NearY, -NearClip);\t// Near upper left\r\n    m_FrustumCorners[ kNearLowerRight ] = Vector3( NearX, -NearY, -NearClip);\t// Near lower right\r\n    m_FrustumCorners[ kNearUpperRight ] = Vector3( NearX,  NearY, -NearClip);\t// Near upper right\r\n    m_FrustumCorners[ kFarLowerLeft   ] = Vector3( -FarX,  -FarY,  -FarClip);\t// Far lower left\r\n    m_FrustumCorners[ kFarUpperLeft   ] = Vector3( -FarX,   FarY,  -FarClip);\t// Far upper left\r\n    m_FrustumCorners[ kFarLowerRight  ] = Vector3(  FarX,  -FarY,  -FarClip);\t// Far lower right\r\n    m_FrustumCorners[ kFarUpperRight  ] = Vector3(  FarX,   FarY,  -FarClip);\t// Far upper right\r\n\r\n    const float NHx = RecipSqrt( 1.0f + HTan * HTan );\r\n    const float NHz = -NHx * HTan;\r\n    const float NVy = RecipSqrt( 1.0f + VTan * VTan );\r\n    const float NVz = -NVy * VTan;\r\n\r\n    // Define the bounding planes\r\n    m_FrustumPlanes[kNearPlane]\t\t= BoundingPlane( 0.0f, 0.0f, -1.0f, -NearClip );\r\n    m_FrustumPlanes[kFarPlane]\t\t= BoundingPlane( 0.0f, 0.0f,  1.0f,   FarClip );\r\n    m_FrustumPlanes[kLeftPlane]\t\t= BoundingPlane(  NHx, 0.0f,   NHz,      0.0f );\r\n    m_FrustumPlanes[kRightPlane]\t= BoundingPlane( -NHx, 0.0f,   NHz,      0.0f );\r\n    m_FrustumPlanes[kTopPlane]\t\t= BoundingPlane( 0.0f, -NVy,   NVz,      0.0f );\r\n    m_FrustumPlanes[kBottomPlane]\t= BoundingPlane( 0.0f,  NVy,   NVz,      0.0f );\r\n}\r\n\r\nvoid Frustum::ConstructOrthographicFrustum( float Left, float Right, float Top, float Bottom, float Front, float Back )\r\n{\r\n    // Define the frustum corners\r\n    m_FrustumCorners[ kNearLowerLeft  ] = Vector3(Left,   Bottom,\t-Front);\t// Near lower left\r\n    m_FrustumCorners[ kNearUpperLeft  ] = Vector3(Left,   Top,\t\t-Front);\t// Near upper left\r\n    m_FrustumCorners[ kNearLowerRight ] = Vector3(Right,  Bottom,\t-Front);\t// Near lower right\r\n    m_FrustumCorners[ kNearUpperRight ] = Vector3(Right,  Top,\t\t-Front);\t// Near upper right\r\n    m_FrustumCorners[ kFarLowerLeft   ] = Vector3(Left,   Bottom,\t -Back);\t// Far lower left\r\n    m_FrustumCorners[ kFarUpperLeft   ] = Vector3(Left,   Top,\t\t -Back);\t// Far upper left\r\n    m_FrustumCorners[ kFarLowerRight  ] = Vector3(Right,  Bottom,\t -Back);\t// Far lower right\r\n    m_FrustumCorners[ kFarUpperRight  ] = Vector3(Right,  Top,\t\t -Back);\t// Far upper right\r\n\r\n    // Define the bounding planes\r\n    m_FrustumPlanes[kNearPlane]\t\t= BoundingPlane(  0.0f,  0.0f, -1.0f, -Front );\r\n    m_FrustumPlanes[kFarPlane]\t\t= BoundingPlane(  0.0f,  0.0f,  1.0f,   Back );\r\n    m_FrustumPlanes[kLeftPlane]\t\t= BoundingPlane(  1.0f,  0.0f,  0.0f,  -Left );\r\n    m_FrustumPlanes[kRightPlane]\t= BoundingPlane( -1.0f,  0.0f,  0.0f,  Right );\r\n    m_FrustumPlanes[kTopPlane]\t\t= BoundingPlane(  0.0f, -1.0f,  0.0f, Bottom );\r\n    m_FrustumPlanes[kBottomPlane]\t= BoundingPlane(  0.0f,  1.0f,  0.0f,   -Top );\r\n}\r\n\r\n\r\nFrustum::Frustum( const Matrix4& ProjMat )\r\n{\r\n    const float* ProjMatF = (const float*)&ProjMat;\r\n\r\n    const float RcpXX = 1.0f / ProjMatF[ 0];\r\n    const float RcpYY = 1.0f / ProjMatF[ 5];\r\n    const float RcpZZ = 1.0f / ProjMatF[10];\r\n\r\n    // Identify if the projection is perspective or orthographic by looking at the 4th row.\r\n    if (ProjMatF[3] == 0.0f && ProjMatF[7] == 0.0f && ProjMatF[11] == 0.0f && ProjMatF[15] == 1.0f)\r\n    {\r\n        // Orthographic\r\n        float Left\t = (-1.0f - ProjMatF[12]) * RcpXX;\r\n        float Right\t = ( 1.0f - ProjMatF[12]) * RcpXX;\r\n        float Top\t = ( 1.0f - ProjMatF[13]) * RcpYY;\r\n        float Bottom = (-1.0f - ProjMatF[13]) * RcpYY;\r\n        float Front\t = ( 0.0f - ProjMatF[14]) * RcpZZ;\r\n        float Back   = ( 1.0f - ProjMatF[14]) * RcpZZ;\r\n\r\n        // Check for reverse Z here.  The bounding planes need to point into the frustum.\r\n        if (Front < Back)\r\n            ConstructOrthographicFrustum( Left, Right, Top, Bottom, Front, Back );\r\n        else\r\n            ConstructOrthographicFrustum( Left, Right, Top, Bottom, Back, Front );\r\n    }\r\n    else\r\n    {\r\n        // Perspective\r\n        float NearClip, FarClip;\r\n\r\n        if (RcpZZ > 0.0f)\t// Reverse Z\r\n        {\r\n            FarClip = ProjMatF[14] * RcpZZ;\r\n            NearClip = FarClip / (RcpZZ + 1.0f);\r\n        }\r\n        else\r\n        {\r\n            NearClip = ProjMatF[14] * RcpZZ;\r\n            FarClip = NearClip / (RcpZZ + 1.0f);\r\n        }\r\n\r\n        ConstructPerspectiveFrustum( RcpXX, RcpYY, NearClip, FarClip );\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Frustum.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"BoundingPlane.h\"\r\n#include \"BoundingSphere.h\"\r\n\r\nnamespace Math\r\n{\r\n    class Frustum\r\n    {\r\n    public:\r\n        Frustum() {}\r\n\r\n        Frustum( const Matrix4& ProjectionMatrix );\r\n\r\n        enum CornerID\r\n        {\r\n            kNearLowerLeft, kNearUpperLeft, kNearLowerRight, kNearUpperRight,\r\n            kFarLowerLeft,  kFarUpperLeft,  kFarLowerRight,  kFarUpperRight\r\n        };\r\n\r\n        enum PlaneID\r\n        {\r\n            kNearPlane, kFarPlane, kLeftPlane, kRightPlane, kTopPlane, kBottomPlane\r\n        };\r\n\r\n        Vector3         GetFrustumCorner( CornerID id ) const   { return m_FrustumCorners[id]; }\r\n        BoundingPlane   GetFrustumPlane( PlaneID id ) const     { return m_FrustumPlanes[id]; }\r\n\r\n        // Test whether the bounding sphere intersects the frustum.  Intersection is defined as either being\r\n        // fully contained in the frustum, or by intersecting one or more of the planes.\r\n        bool IntersectSphere( BoundingSphere sphere ) const;\r\n\r\n        // We don't officially have a BoundingBox class yet, but let's assume it's forthcoming.  (There is a\r\n        // simple struct in the Model project.)\r\n        bool IntersectBoundingBox(const Vector3 minBound, const Vector3 maxBound) const;\r\n\r\n        friend Frustum  operator* ( const OrthogonalTransform& xform, const Frustum& frustum );\t// Fast\r\n        friend Frustum  operator* ( const AffineTransform& xform, const Frustum& frustum );\t\t// Slow\r\n        friend Frustum  operator* ( const Matrix4& xform, const Frustum& frustum );\t\t\t\t// Slowest (and most general)\r\n\r\n    private:\r\n\r\n        // Perspective frustum constructor (for pyramid-shaped frusta)\r\n        void ConstructPerspectiveFrustum( float HTan, float VTan, float NearClip, float FarClip );\r\n\r\n        // Orthographic frustum constructor (for box-shaped frusta)\r\n        void ConstructOrthographicFrustum( float Left, float Right, float Top, float Bottom, float NearClip, float FarClip );\r\n\r\n        Vector3 m_FrustumCorners[8];\t\t// the corners of the frustum\r\n        BoundingPlane m_FrustumPlanes[6];\t\t\t// the bounding planes\r\n    };\r\n\r\n    //=======================================================================================================\r\n    // Inline implementations\r\n    //\r\n\r\n    inline bool Frustum::IntersectSphere( BoundingSphere sphere ) const\r\n    {\r\n        float radius = sphere.GetRadius();\r\n        for (int i = 0; i < 6; ++i)\r\n        {\r\n            if (m_FrustumPlanes[i].DistanceFromPoint(sphere.GetCenter()) + radius < 0.0f)\r\n                return false;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    inline bool Frustum::IntersectBoundingBox(const Vector3 minBound, const Vector3 maxBound) const\r\n    {\r\n        for (int i = 0; i < 6; ++i)\r\n        {\r\n            BoundingPlane p = m_FrustumPlanes[i];\r\n            Vector3 farCorner = Select(minBound, maxBound, p.GetNormal() > Vector3(kZero));\r\n            if (p.DistanceFromPoint(farCorner) < 0.0f)\r\n                return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    inline Frustum operator* ( const OrthogonalTransform& xform, const Frustum& frustum )\r\n    {\r\n        Frustum result;\r\n\r\n        for (int i = 0; i < 8; ++i)\r\n            result.m_FrustumCorners[i] = xform * frustum.m_FrustumCorners[i];\r\n\r\n        for (int i = 0; i < 6; ++i)\r\n            result.m_FrustumPlanes[i] = xform * frustum.m_FrustumPlanes[i];\r\n\r\n        return result;\r\n    }\r\n\r\n    inline Frustum operator* ( const AffineTransform& xform, const Frustum& frustum )\r\n    {\r\n        Frustum result;\r\n\r\n        for (int i = 0; i < 8; ++i)\r\n            result.m_FrustumCorners[i] = xform * frustum.m_FrustumCorners[i];\r\n\r\n        Matrix4 XForm = Transpose(Invert(Matrix4(xform)));\r\n\r\n        for (int i = 0; i < 6; ++i)\r\n            result.m_FrustumPlanes[i] = BoundingPlane(XForm * Vector4(frustum.m_FrustumPlanes[i]));\r\n\r\n        return result;\r\n    }\r\n\r\n    inline Frustum operator* ( const Matrix4& mtx, const Frustum& frustum )\r\n    {\r\n        Frustum result;\r\n\r\n        for (int i = 0; i < 8; ++i)\r\n            result.m_FrustumCorners[i] = Vector3( mtx * frustum.m_FrustumCorners[i] );\r\n\r\n        Matrix4 XForm = Transpose(Invert(mtx));\r\n\r\n        for (int i = 0; i < 6; ++i)\r\n            result.m_FrustumPlanes[i] = BoundingPlane(XForm * Vector4(frustum.m_FrustumPlanes[i]));\r\n\r\n        return result;\r\n    }\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Functions.inl",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#pragma once\n\nnamespace Math\n{\n\t// To allow floats to implicitly construct Scalars, we need to clarify these operators and suppress\n\t// upconversion.\n\tINLINE bool operator<  ( Scalar lhs, float rhs ) { return (float)lhs <  rhs; }\n\tINLINE bool operator<= ( Scalar lhs, float rhs ) { return (float)lhs <= rhs; }\n\tINLINE bool operator>  ( Scalar lhs, float rhs ) { return (float)lhs >  rhs; }\n\tINLINE bool operator>= ( Scalar lhs, float rhs ) { return (float)lhs >= rhs; }\n\tINLINE bool operator== ( Scalar lhs, float rhs ) { return (float)lhs == rhs; }\n\tINLINE bool operator<  ( float lhs, Scalar rhs ) { return lhs <  (float)rhs; }\n\tINLINE bool operator<= ( float lhs, Scalar rhs ) { return lhs <= (float)rhs; }\n\tINLINE bool operator>  ( float lhs, Scalar rhs ) { return lhs >  (float)rhs; }\n\tINLINE bool operator>= ( float lhs, Scalar rhs ) { return lhs >= (float)rhs; }\n\tINLINE bool operator== ( float lhs, Scalar rhs ) { return lhs == (float)rhs; }\n\n#define CREATE_SIMD_FUNCTIONS( TYPE ) \\\n\tINLINE TYPE Sqrt( TYPE s ) { return TYPE(XMVectorSqrt(s)); } \\\n\tINLINE TYPE Recip( TYPE s ) { return TYPE(XMVectorReciprocal(s)); } \\\n\tINLINE TYPE RecipSqrt( TYPE s ) { return TYPE(XMVectorReciprocalSqrt(s)); } \\\n\tINLINE TYPE Floor( TYPE s ) { return TYPE(XMVectorFloor(s)); } \\\n\tINLINE TYPE Ceiling( TYPE s ) { return TYPE(XMVectorCeiling(s)); } \\\n\tINLINE TYPE Round( TYPE s ) { return TYPE(XMVectorRound(s)); } \\\n\tINLINE TYPE Abs( TYPE s ) { return TYPE(XMVectorAbs(s)); } \\\n\tINLINE TYPE Exp( TYPE s ) { return TYPE(XMVectorExp(s)); } \\\n\tINLINE TYPE Pow( TYPE b, TYPE e ) { return TYPE(XMVectorPow(b, e)); } \\\n\tINLINE TYPE Log( TYPE s ) { return TYPE(XMVectorLog(s)); } \\\n\tINLINE TYPE Sin( TYPE s ) { return TYPE(XMVectorSin(s)); } \\\n\tINLINE TYPE Cos( TYPE s ) { return TYPE(XMVectorCos(s)); } \\\n\tINLINE TYPE Tan( TYPE s ) { return TYPE(XMVectorTan(s)); } \\\n\tINLINE TYPE ASin( TYPE s ) { return TYPE(XMVectorASin(s)); } \\\n\tINLINE TYPE ACos( TYPE s ) { return TYPE(XMVectorACos(s)); } \\\n\tINLINE TYPE ATan( TYPE s ) { return TYPE(XMVectorATan(s)); } \\\n\tINLINE TYPE ATan2( TYPE y, TYPE x ) { return TYPE(XMVectorATan2(y, x)); } \\\n\tINLINE TYPE Lerp( TYPE a, TYPE b, TYPE t ) { return TYPE(XMVectorLerpV(a, b, t)); } \\\n\tINLINE TYPE Max( TYPE a, TYPE b ) { return TYPE(XMVectorMax(a, b)); } \\\n\tINLINE TYPE Min( TYPE a, TYPE b ) { return TYPE(XMVectorMin(a, b)); } \\\n\tINLINE TYPE Clamp( TYPE v, TYPE a, TYPE b ) { return Min(Max(v, a), b); } \\\n\tINLINE BoolVector operator<  ( TYPE lhs, TYPE rhs ) { return XMVectorLess(lhs, rhs); } \\\n\tINLINE BoolVector operator<= ( TYPE lhs, TYPE rhs ) { return XMVectorLessOrEqual(lhs, rhs); } \\\n\tINLINE BoolVector operator>  ( TYPE lhs, TYPE rhs ) { return XMVectorGreater(lhs, rhs); } \\\n\tINLINE BoolVector operator>= ( TYPE lhs, TYPE rhs ) { return XMVectorGreaterOrEqual(lhs, rhs); } \\\n\tINLINE BoolVector operator== ( TYPE lhs, TYPE rhs ) { return XMVectorEqual(lhs, rhs); } \\\n\tINLINE TYPE Select( TYPE lhs, TYPE rhs, BoolVector mask ) { return TYPE(XMVectorSelect(lhs, rhs, mask)); }\n\n\n\tCREATE_SIMD_FUNCTIONS(Scalar)\n\tCREATE_SIMD_FUNCTIONS(Vector3)\n\tCREATE_SIMD_FUNCTIONS(Vector4)\n\n#undef CREATE_SIMD_FUNCTIONS\n\n\tINLINE float Sqrt( float s ) { return Sqrt(Scalar(s)); }\n\tINLINE float Recip( float s ) { return Recip(Scalar(s)); }\n\tINLINE float RecipSqrt( float s ) { return RecipSqrt(Scalar(s)); }\n\tINLINE float Floor( float s ) { return Floor(Scalar(s)); }\n\tINLINE float Ceiling( float s ) { return Ceiling(Scalar(s)); }\n\tINLINE float Round( float s ) { return Round(Scalar(s)); }\n\tINLINE float Abs( float s ) { return s < 0.0f ? -s : s; }\n\tINLINE float Exp( float s ) { return Exp(Scalar(s)); }\n\tINLINE float Pow( float b, float e ) { return Pow(Scalar(b), Scalar(e)); }\n\tINLINE float Log( float s ) { return Log(Scalar(s)); }\n\tINLINE float Sin( float s ) { return Sin(Scalar(s)); }\n\tINLINE float Cos( float s ) { return Cos(Scalar(s)); }\n\tINLINE float Tan( float s ) { return Tan(Scalar(s)); }\n\tINLINE float ASin( float s ) { return ASin(Scalar(s)); }\n\tINLINE float ACos( float s ) { return ACos(Scalar(s)); }\n\tINLINE float ATan( float s ) { return ATan(Scalar(s)); }\n\tINLINE float ATan2( float y, float x ) { return ATan2(Scalar(y), Scalar(x)); }\n\tINLINE float Lerp( float a, float b, float t ) { return a + (b - a) * t; }\n\tINLINE float Max( float a, float b ) { return a > b ? a : b; }\n\tINLINE float Min( float a, float b ) { return a < b ? a : b; }\n\tINLINE float Clamp( float v, float a, float b ) { return Min(Max(v, a), b); }\n\n\tINLINE Scalar Length( Vector3 v ) { return Scalar(XMVector3Length(v)); }\n\tINLINE Scalar LengthSquare( Vector3 v ) { return Scalar(XMVector3LengthSq(v)); }\n\tINLINE Scalar LengthRecip( Vector3 v ) { return Scalar(XMVector3ReciprocalLength(v)); }\n\tINLINE Scalar Dot( Vector3 v1, Vector3 v2 ) { return Scalar(XMVector3Dot(v1, v2)); }\n\tINLINE Scalar Dot( Vector4 v1, Vector4 v2 ) { return Scalar(XMVector4Dot(v1, v2)); }\n\tINLINE Vector3 Cross( Vector3 v1, Vector3 v2 ) { return Vector3(XMVector3Cross(v1, v2)); }\n\tINLINE Vector3 Normalize( Vector3 v ) { return Vector3(XMVector3Normalize(v)); }\n\tINLINE Vector4 Normalize( Vector4 v ) { return Vector4(XMVector4Normalize(v)); }\n\tINLINE Quaternion Normalize( Quaternion q ) { return Quaternion(XMQuaternionNormalize(q)); }\n\n\tINLINE Matrix3 Transpose( const Matrix3& mat ) { return Matrix3(XMMatrixTranspose(mat)); }\n\n\t// inline Matrix3 Inverse( const Matrix3& mat ) { TBD }\n\t// inline Transform Inverse( const Transform& mat ) { TBD }\n\n\t// This specialized matrix invert assumes that the 3x3 matrix is orthogonal (and normalized).\n\tINLINE AffineTransform OrthoInvert( const AffineTransform& xform )\n\t{\n\t\tMatrix3 basis = Transpose(xform.GetBasis());\n\t\treturn AffineTransform( basis, basis * -xform.GetTranslation() );\n\t}\n\n\tINLINE OrthogonalTransform Invert( const OrthogonalTransform& xform )\t { return ~xform; }\n\n\tINLINE Matrix4 Transpose( const Matrix4& mat ) { return Matrix4(XMMatrixTranspose(mat)); }\n\tINLINE Matrix4 Invert( const Matrix4& mat ) { return Matrix4(XMMatrixInverse(nullptr, mat)); }\n\n\tINLINE Matrix4 OrthoInvert( const Matrix4& xform )\n\t{\n\t\tMatrix3 basis = Transpose(xform.Get3x3());\n\t\tVector3 translate = basis * -Vector3(xform.GetW());\n\t\treturn Matrix4( basis, translate );\n\t}\n\n}"
  },
  {
    "path": "MiniEngine/Core/Math/Matrix3.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Quaternion.h\"\r\n\r\nnamespace Math\r\n{\r\n    // Represents a 3x3 matrix while occuping a 4x4 memory footprint.  The unused row and column are undefined but implicitly\r\n    // (0, 0, 0, 1).  Constructing a Matrix4 will make those values explicit.\r\n    __declspec(align(16)) class Matrix3\r\n    {\r\n    public:\r\n        INLINE Matrix3() {}\r\n        INLINE Matrix3( Vector3 x, Vector3 y, Vector3 z ) { m_mat[0] = x; m_mat[1] = y; m_mat[2] = z; }\r\n        INLINE Matrix3( const Matrix3& m ) { m_mat[0] = m.m_mat[0]; m_mat[1] = m.m_mat[1]; m_mat[2] = m.m_mat[2]; }\r\n        INLINE Matrix3( Quaternion q ) { *this = Matrix3(XMMatrixRotationQuaternion(q)); }\r\n        INLINE explicit Matrix3( const XMMATRIX& m ) { m_mat[0] = Vector3(m.r[0]); m_mat[1] = Vector3(m.r[1]); m_mat[2] = Vector3(m.r[2]); }\r\n        INLINE explicit Matrix3( EIdentityTag ) { m_mat[0] = Vector3(kXUnitVector); m_mat[1] = Vector3(kYUnitVector); m_mat[2] = Vector3(kZUnitVector);  }\r\n        INLINE explicit Matrix3( EZeroTag ) { m_mat[0] = m_mat[1] = m_mat[2] = Vector3(kZero); }\r\n\r\n        INLINE void SetX(Vector3 x) { m_mat[0] = x; }\r\n        INLINE void SetY(Vector3 y) { m_mat[1] = y; }\r\n        INLINE void SetZ(Vector3 z) { m_mat[2] = z; }\r\n\r\n        INLINE Vector3 GetX() const { return m_mat[0]; }\r\n        INLINE Vector3 GetY() const { return m_mat[1]; }\r\n        INLINE Vector3 GetZ() const { return m_mat[2]; }\r\n\r\n        static INLINE Matrix3 MakeXRotation( float angle ) { return Matrix3(XMMatrixRotationX(angle)); }\r\n        static INLINE Matrix3 MakeYRotation( float angle ) { return Matrix3(XMMatrixRotationY(angle)); }\r\n        static INLINE Matrix3 MakeZRotation( float angle ) { return Matrix3(XMMatrixRotationZ(angle)); }\r\n        static INLINE Matrix3 MakeScale( float scale ) { return Matrix3(XMMatrixScaling(scale, scale, scale)); }\r\n        static INLINE Matrix3 MakeScale( float sx, float sy, float sz ) { return Matrix3(XMMatrixScaling(sx, sy, sz)); }\r\n        static INLINE Matrix3 MakeScale( Vector3 scale ) { return Matrix3(XMMatrixScalingFromVector(scale)); }\r\n\r\n        INLINE operator XMMATRIX() const { return (const XMMATRIX&)m_mat; }\r\n\r\n        INLINE Vector3 operator* ( Vector3 vec ) const { return Vector3( XMVector3TransformNormal(vec, *this) ); }\r\n        INLINE Matrix3 operator* ( const Matrix3& mat ) const { return Matrix3( *this * mat.GetX(), *this * mat.GetY(), *this * mat.GetZ() ); }\r\n\r\n    private:\r\n        Vector3 m_mat[3];\r\n    };\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Matrix4.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Transform.h\"\r\n\r\nnamespace Math\r\n{\r\n    __declspec(align(16)) class Matrix4\r\n    {\r\n    public:\r\n        INLINE Matrix4() {}\r\n        INLINE Matrix4( Vector3 x, Vector3 y, Vector3 z, Vector3 w )\r\n        {\r\n            m_mat.r[0] = SetWToZero(x); m_mat.r[1] = SetWToZero(y);\r\n            m_mat.r[2] = SetWToZero(z); m_mat.r[3] = SetWToOne(w);\r\n        }\r\n        INLINE Matrix4( Vector4 x, Vector4 y, Vector4 z, Vector4 w ) { m_mat.r[0] = x; m_mat.r[1] = y; m_mat.r[2] = z; m_mat.r[3] = w; }\r\n        INLINE Matrix4( const Matrix4& mat ) { m_mat = mat.m_mat; }\r\n        INLINE Matrix4( const Matrix3& mat )\r\n        {\r\n            m_mat.r[0] = SetWToZero(mat.GetX());\r\n            m_mat.r[1] = SetWToZero(mat.GetY());\r\n            m_mat.r[2] = SetWToZero(mat.GetZ());\r\n            m_mat.r[3] = CreateWUnitVector();\r\n        }\r\n        INLINE Matrix4( const Matrix3& xyz, Vector3 w )\r\n        {\r\n            m_mat.r[0] = SetWToZero(xyz.GetX());\r\n            m_mat.r[1] = SetWToZero(xyz.GetY());\r\n            m_mat.r[2] = SetWToZero(xyz.GetZ());\r\n            m_mat.r[3] = SetWToOne(w);\r\n        }\r\n        INLINE Matrix4( const AffineTransform& xform ) { *this = Matrix4( xform.GetBasis(), xform.GetTranslation()); }\r\n        INLINE Matrix4( const OrthogonalTransform& xform ) { *this = Matrix4( Matrix3(xform.GetRotation()), xform.GetTranslation() ); }\r\n        INLINE explicit Matrix4( const XMMATRIX& mat ) { m_mat = mat; }\r\n        INLINE explicit Matrix4( EIdentityTag ) { m_mat = XMMatrixIdentity(); }\r\n        INLINE explicit Matrix4( EZeroTag ) { m_mat.r[0] = m_mat.r[1] = m_mat.r[2] = m_mat.r[3] = SplatZero(); }\r\n\r\n        INLINE const Matrix3& Get3x3() const { return (const Matrix3&)*this; }\r\n\r\n        INLINE Vector4 GetX() const { return Vector4(m_mat.r[0]); }\r\n        INLINE Vector4 GetY() const { return Vector4(m_mat.r[1]); }\r\n        INLINE Vector4 GetZ() const { return Vector4(m_mat.r[2]); }\r\n        INLINE Vector4 GetW() const { return Vector4(m_mat.r[3]); }\r\n\r\n        INLINE void SetX(Vector4 x) { m_mat.r[0] = x; }\r\n        INLINE void SetY(Vector4 y) { m_mat.r[1] = y; }\r\n        INLINE void SetZ(Vector4 z) { m_mat.r[2] = z; }\r\n        INLINE void SetW(Vector4 w) { m_mat.r[3] = w; }\r\n\r\n        INLINE operator XMMATRIX() const { return m_mat; }\r\n\r\n        INLINE Vector4 operator* ( Vector3 vec ) const { return Vector4(XMVector3Transform(vec, m_mat)); }\r\n        INLINE Vector4 operator* ( Vector4 vec ) const { return Vector4(XMVector4Transform(vec, m_mat)); }\r\n        INLINE Matrix4 operator* ( const Matrix4& mat ) const { return Matrix4(XMMatrixMultiply(mat, m_mat)); }\r\n\r\n        static INLINE Matrix4 MakeScale( float scale ) { return Matrix4(XMMatrixScaling(scale, scale, scale)); }\r\n        static INLINE Matrix4 MakeScale( Vector3 scale ) { return Matrix4(XMMatrixScalingFromVector(scale)); }\r\n\r\n\r\n    private:\r\n        XMMATRIX m_mat;\r\n    };\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Quaternion.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Vector.h\"\r\n\r\nnamespace Math\r\n{\r\n    class Quaternion\r\n    {\r\n    public:\r\n        INLINE Quaternion() { m_vec = XMQuaternionIdentity(); }\r\n        INLINE Quaternion( const Vector3& axis, const Scalar& angle ) { m_vec = XMQuaternionRotationAxis( axis, angle ); }\r\n        INLINE Quaternion( float pitch, float yaw, float roll) { m_vec = XMQuaternionRotationRollPitchYaw(pitch, yaw, roll); }\r\n        INLINE explicit Quaternion( const XMMATRIX& matrix ) { m_vec = XMQuaternionRotationMatrix( matrix ); }\t\r\n        INLINE explicit Quaternion( FXMVECTOR vec ) { m_vec = vec; }\r\n        INLINE explicit Quaternion( EIdentityTag ) { m_vec = XMQuaternionIdentity(); }\r\n\r\n        INLINE operator XMVECTOR() const { return m_vec; }\r\n\r\n        INLINE Quaternion operator~ ( void ) const { return Quaternion(XMQuaternionConjugate(m_vec)); }\r\n        INLINE Quaternion operator- ( void ) const { return Quaternion(XMVectorNegate(m_vec)); }\r\n\r\n        INLINE Quaternion operator* ( Quaternion rhs ) const { return Quaternion(XMQuaternionMultiply(rhs, m_vec)); }\r\n        INLINE Vector3 operator* ( Vector3 rhs ) const { return Vector3(XMVector3Rotate(rhs, m_vec)); }\r\n\r\n        INLINE Quaternion& operator= ( Quaternion rhs ) { m_vec = rhs; return *this; }\r\n        INLINE Quaternion& operator*= ( Quaternion rhs ) { *this = *this * rhs; return *this; }\r\n\r\n    protected:\r\n        XMVECTOR m_vec;\r\n    };\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Random.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"Random.h\"\r\n\r\nnamespace Math\r\n{\r\n    RandomNumberGenerator g_RNG;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Random.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Common.h\"\r\n#include <random>\r\n\r\nnamespace Math\r\n{\r\n    class RandomNumberGenerator\r\n    {\r\n    public:\r\n        RandomNumberGenerator() : m_gen(m_rd())\r\n        {\r\n        }\r\n\r\n        // Default int range is [MIN_INT, MAX_INT].  Max value is included.\r\n        int32_t NextInt( void )\r\n        {\r\n            return std::uniform_int_distribution<int32_t>(0x80000000, 0x7FFFFFFF)(m_gen);\r\n        }\r\n\r\n        int32_t NextInt( int32_t MaxVal )\r\n        {\r\n            return std::uniform_int_distribution<int32_t>(0, MaxVal)(m_gen);\r\n        }\r\n\r\n        int32_t NextInt( int32_t MinVal, int32_t MaxVal )\r\n        {\r\n            return std::uniform_int_distribution<int32_t>(MinVal, MaxVal)(m_gen);\r\n        }\r\n\r\n        // Default float range is [0.0f, 1.0f).  Max value is excluded.\r\n        float NextFloat( float MaxVal = 1.0f )\r\n        {\r\n            return std::uniform_real_distribution<float>(0.0f, MaxVal)(m_gen);\r\n        }\r\n\r\n        float NextFloat( float MinVal, float MaxVal )\r\n        {\r\n            return std::uniform_real_distribution<float>(MinVal, MaxVal)(m_gen);\r\n        }\r\n\r\n        void SetSeed( UINT s )\r\n        {\r\n            m_gen.seed(s);\r\n        }\r\n\r\n    private:\r\n\r\n        std::random_device m_rd;\r\n        std::minstd_rand m_gen;\r\n    };\r\n\r\n    extern RandomNumberGenerator g_RNG;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Scalar.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Common.h\"\r\n\r\nnamespace Math\r\n{\r\n    class Scalar\r\n    {\r\n    public:\r\n        INLINE Scalar() {}\r\n        INLINE Scalar( const Scalar& s ) { m_vec = s; }\r\n        INLINE Scalar( float f ) { m_vec = XMVectorReplicate(f); }\r\n        INLINE explicit Scalar( FXMVECTOR vec ) { m_vec = vec; }\r\n        INLINE explicit Scalar( EZeroTag ) { m_vec = SplatZero(); }\r\n        INLINE explicit Scalar( EIdentityTag ) { m_vec = SplatOne(); }\r\n\r\n        INLINE operator XMVECTOR() const { return m_vec; }\r\n        INLINE operator float() const { return XMVectorGetX(m_vec); }\r\n\r\n    private:\r\n        XMVECTOR m_vec;\r\n    };\r\n\r\n    INLINE Scalar operator- ( Scalar s ) { return Scalar(XMVectorNegate(s)); }\r\n    INLINE Scalar operator+ ( Scalar s1, Scalar s2 ) { return Scalar(XMVectorAdd(s1, s2)); }\r\n    INLINE Scalar operator- ( Scalar s1, Scalar s2 ) { return Scalar(XMVectorSubtract(s1, s2)); }\r\n    INLINE Scalar operator* ( Scalar s1, Scalar s2 ) { return Scalar(XMVectorMultiply(s1, s2)); }\r\n    INLINE Scalar operator/ ( Scalar s1, Scalar s2 ) { return Scalar(XMVectorDivide(s1, s2)); }\r\n    INLINE Scalar operator+ ( Scalar s1, float s2 ) { return s1 + Scalar(s2); }\r\n    INLINE Scalar operator- ( Scalar s1, float s2 ) { return s1 - Scalar(s2); }\r\n    INLINE Scalar operator* ( Scalar s1, float s2 ) { return s1 * Scalar(s2); }\r\n    INLINE Scalar operator/ ( Scalar s1, float s2 ) { return s1 / Scalar(s2); }\r\n    INLINE Scalar operator+ ( float s1, Scalar s2 ) { return Scalar(s1) + s2; }\r\n    INLINE Scalar operator- ( float s1, Scalar s2 ) { return Scalar(s1) - s2; }\r\n    INLINE Scalar operator* ( float s1, Scalar s2 ) { return Scalar(s1) * s2; }\r\n    INLINE Scalar operator/ ( float s1, Scalar s2 ) { return Scalar(s1) / s2; }\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Transform.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Matrix3.h\"\r\n\r\nnamespace Math\r\n{\r\n    // This transform strictly prohibits non-uniform scale.  Scale itself is barely tolerated.\r\n    __declspec(align(16)) class OrthogonalTransform\r\n    {\r\n    public:\r\n        INLINE OrthogonalTransform() : m_rotation(kIdentity), m_translation(kZero) {}\r\n        INLINE OrthogonalTransform( Quaternion rotate ) : m_rotation(rotate), m_translation(kZero) {}\r\n        INLINE OrthogonalTransform( Vector3 translate ) : m_rotation(kIdentity), m_translation(translate) {}\r\n        INLINE OrthogonalTransform( Quaternion rotate, Vector3 translate ) : m_rotation(rotate), m_translation(translate) {}\r\n        INLINE OrthogonalTransform( const Matrix3& mat ) : m_rotation(mat), m_translation(kZero) {}\r\n        INLINE OrthogonalTransform( const Matrix3& mat, Vector3 translate ) : m_rotation(mat), m_translation(translate) {}\r\n        INLINE OrthogonalTransform( EIdentityTag ) : m_rotation(kIdentity), m_translation(kZero) {}\r\n        INLINE explicit OrthogonalTransform( const XMMATRIX& mat ) { *this = OrthogonalTransform( Matrix3(mat), Vector3(mat.r[3]) ); }\r\n\r\n        INLINE void SetRotation( Quaternion q ) { m_rotation = q; }\r\n        INLINE void SetTranslation( Vector3 v ) { m_translation = v; }\r\n\r\n        INLINE Quaternion GetRotation() const { return m_rotation; }\r\n        INLINE Vector3 GetTranslation() const { return m_translation; }\r\n\r\n        static INLINE OrthogonalTransform MakeXRotation( float angle ) { return OrthogonalTransform(Quaternion(Vector3(kXUnitVector), angle)); }\r\n        static INLINE OrthogonalTransform MakeYRotation( float angle ) { return OrthogonalTransform(Quaternion(Vector3(kYUnitVector), angle)); }\r\n        static INLINE OrthogonalTransform MakeZRotation( float angle ) { return OrthogonalTransform(Quaternion(Vector3(kZUnitVector), angle)); }\r\n        static INLINE OrthogonalTransform MakeTranslation( Vector3 translate ) { return OrthogonalTransform(translate); }\r\n\r\n        INLINE Vector3 operator* ( Vector3 vec ) const { return m_rotation * vec + m_translation; }\r\n        INLINE Vector4 operator* ( Vector4 vec ) const { return\r\n            Vector4(SetWToZero(m_rotation * Vector3((XMVECTOR)vec))) +\r\n            Vector4(SetWToOne(m_translation)) * vec.GetW();\r\n        }\r\n        INLINE OrthogonalTransform operator* ( const OrthogonalTransform& xform ) const {\r\n            return OrthogonalTransform( m_rotation * xform.m_rotation, m_rotation * xform.m_translation + m_translation );\r\n        }\r\n\r\n        INLINE OrthogonalTransform operator~ () const { Quaternion invertedRotation = ~m_rotation;\r\n            return OrthogonalTransform( invertedRotation, invertedRotation * -m_translation );\r\n        }\r\n\r\n    private:\r\n\r\n        Quaternion m_rotation;\r\n        Vector3 m_translation;\r\n    };\r\n\r\n    // A AffineTransform is a 3x4 matrix with an implicit 4th row = [0,0,0,1].  This is used to perform a change of\r\n    // basis on 3D points.  An affine transformation does not have to have orthonormal basis vectors.\r\n    __declspec(align(64)) class AffineTransform\r\n    {\r\n    public:\r\n        INLINE AffineTransform()\r\n            {}\r\n        INLINE AffineTransform( Vector3 x, Vector3 y, Vector3 z, Vector3 w )\r\n            : m_basis(x, y, z), m_translation(w) {}\r\n        INLINE AffineTransform( Vector3 translate )\r\n            : m_basis(kIdentity), m_translation(translate) {}\r\n        INLINE AffineTransform( const Matrix3& mat, Vector3 translate = Vector3(kZero) )\r\n            : m_basis(mat), m_translation(translate) {}\r\n        INLINE AffineTransform( Quaternion rot, Vector3 translate = Vector3(kZero) )\r\n            : m_basis(rot), m_translation(translate) {}\r\n        INLINE AffineTransform( const OrthogonalTransform& xform )\r\n            : m_basis(xform.GetRotation()), m_translation(xform.GetTranslation()) {}\r\n        INLINE AffineTransform( EIdentityTag )\r\n            : m_basis(kIdentity), m_translation(kZero) {}\r\n        INLINE explicit AffineTransform( const XMMATRIX& mat )\r\n            : m_basis(mat), m_translation(mat.r[3]) {}\r\n\r\n        INLINE operator XMMATRIX() const { return (XMMATRIX&)*this; }\r\n\r\n        INLINE void SetX(Vector3 x) { m_basis.SetX(x); }\r\n        INLINE void SetY(Vector3 y) { m_basis.SetY(y); }\r\n        INLINE void SetZ(Vector3 z) { m_basis.SetZ(z); }\r\n        INLINE void SetTranslation(Vector3 w) { m_translation = w; }\r\n\r\n        INLINE Vector3 GetX() const { return m_basis.GetX(); }\r\n        INLINE Vector3 GetY() const { return m_basis.GetY(); }\r\n        INLINE Vector3 GetZ() const { return m_basis.GetZ(); }\r\n        INLINE Vector3 GetTranslation() const { return m_translation; }\r\n        INLINE const Matrix3& GetBasis() const { return (const Matrix3&)*this; }\r\n\r\n        static INLINE AffineTransform MakeXRotation( float angle ) { return AffineTransform(Matrix3::MakeXRotation(angle)); }\r\n        static INLINE AffineTransform MakeYRotation( float angle ) { return AffineTransform(Matrix3::MakeYRotation(angle)); }\r\n        static INLINE AffineTransform MakeZRotation( float angle ) { return AffineTransform(Matrix3::MakeZRotation(angle)); }\r\n        static INLINE AffineTransform MakeScale( float scale ) { return AffineTransform(Matrix3::MakeScale(scale)); }\r\n        static INLINE AffineTransform MakeScale( Vector3 scale ) { return AffineTransform(Matrix3::MakeScale(scale)); }\r\n        static INLINE AffineTransform MakeTranslation( Vector3 translate ) { return AffineTransform(translate); }\r\n\r\n        INLINE Vector3 operator* ( Vector3 vec ) const { return m_basis * vec + m_translation; }\r\n        INLINE AffineTransform operator* ( const AffineTransform& mat ) const {\r\n            return AffineTransform( m_basis * mat.m_basis, *this * mat.GetTranslation() );\r\n        }\r\n\r\n    private:\r\n        Matrix3 m_basis;\r\n        Vector3 m_translation;\r\n    };\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Math/Vector.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Scalar.h\"\r\n\r\nnamespace Math\r\n{\r\n    class Vector4;\r\n\r\n    // A 3-vector with an unspecified fourth component.  Depending on the context, the W can be 0 or 1, but both are implicit.\r\n    // The actual value of the fourth component is undefined for performance reasons.\r\n    class Vector3\r\n    {\r\n    public:\r\n\r\n        INLINE Vector3() {}\r\n        INLINE Vector3( float x, float y, float z ) { m_vec = XMVectorSet(x, y, z, z); }\r\n        INLINE Vector3( const XMFLOAT3& v ) { m_vec = XMLoadFloat3(&v); }\r\n        INLINE Vector3( const Vector3& v ) { m_vec = v; }\r\n        INLINE Vector3( Scalar s ) { m_vec = s; }\r\n        INLINE explicit Vector3( Vector4 v );\r\n        INLINE explicit Vector3( FXMVECTOR vec ) { m_vec = vec; }\r\n        INLINE explicit Vector3( EZeroTag ) { m_vec = SplatZero(); }\r\n        INLINE explicit Vector3( EIdentityTag ) { m_vec = SplatOne(); }\r\n        INLINE explicit Vector3( EXUnitVector ) { m_vec = CreateXUnitVector(); }\r\n        INLINE explicit Vector3( EYUnitVector ) { m_vec = CreateYUnitVector(); }\r\n        INLINE explicit Vector3( EZUnitVector ) { m_vec = CreateZUnitVector(); }\r\n\r\n        INLINE operator XMVECTOR() const { return m_vec; }\r\n\r\n        INLINE Scalar GetX() const { return Scalar(XMVectorSplatX(m_vec)); }\r\n        INLINE Scalar GetY() const { return Scalar(XMVectorSplatY(m_vec)); }\r\n        INLINE Scalar GetZ() const { return Scalar(XMVectorSplatZ(m_vec)); }\r\n        INLINE void SetX( Scalar x ) { m_vec = XMVectorPermute<4,1,2,3>(m_vec, x); }\r\n        INLINE void SetY( Scalar y ) { m_vec = XMVectorPermute<0,5,2,3>(m_vec, y); }\r\n        INLINE void SetZ( Scalar z ) { m_vec = XMVectorPermute<0,1,6,3>(m_vec, z); }\r\n\r\n        INLINE Vector3 operator- () const { return Vector3(XMVectorNegate(m_vec)); }\r\n        INLINE Vector3 operator+ ( Vector3 v2 ) const { return Vector3(XMVectorAdd(m_vec, v2)); }\r\n        INLINE Vector3 operator- ( Vector3 v2 ) const { return Vector3(XMVectorSubtract(m_vec, v2)); }\r\n        INLINE Vector3 operator* ( Vector3 v2 ) const { return Vector3(XMVectorMultiply(m_vec, v2)); }\r\n        INLINE Vector3 operator/ ( Vector3 v2 ) const { return Vector3(XMVectorDivide(m_vec, v2)); }\r\n        INLINE Vector3 operator* ( Scalar  v2 ) const { return *this * Vector3(v2); }\r\n        INLINE Vector3 operator/ ( Scalar  v2 ) const { return *this / Vector3(v2); }\r\n        INLINE Vector3 operator* ( float  v2 ) const { return *this * Scalar(v2); }\r\n        INLINE Vector3 operator/ ( float  v2 ) const { return *this / Scalar(v2); }\r\n\r\n        INLINE Vector3& operator += ( Vector3 v ) { *this = *this + v; return *this; }\r\n        INLINE Vector3& operator -= ( Vector3 v ) { *this = *this - v; return *this; }\r\n        INLINE Vector3& operator *= ( Vector3 v ) { *this = *this * v; return *this; }\r\n        INLINE Vector3& operator /= ( Vector3 v ) { *this = *this / v; return *this; }\r\n\r\n        INLINE friend Vector3 operator* ( Scalar  v1, Vector3 v2 ) { return Vector3(v1) * v2; }\r\n        INLINE friend Vector3 operator/ ( Scalar  v1, Vector3 v2 ) \t{ return Vector3(v1) / v2; }\r\n        INLINE friend Vector3 operator* ( float   v1, Vector3 v2 ) { return Scalar(v1) * v2; }\r\n        INLINE friend Vector3 operator/ ( float   v1, Vector3 v2 ) \t{ return Scalar(v1) / v2; }\r\n\r\n    protected:\r\n        XMVECTOR m_vec;\r\n    };\r\n\r\n    // A 4-vector, completely defined.\r\n    class Vector4\r\n    {\r\n    public:\r\n        INLINE Vector4() {}\r\n        INLINE Vector4( float x, float y, float z, float w ) { m_vec = XMVectorSet(x, y, z, w); }\r\n        INLINE Vector4( Vector3 xyz, float w ) { m_vec = XMVectorSetW(xyz, w); }\r\n        INLINE Vector4( const Vector4& v ) { m_vec = v; }\r\n        INLINE Vector4( const Scalar& s ) { m_vec = s; }\r\n        INLINE explicit Vector4( Vector3 xyz ) { m_vec = SetWToOne(xyz); }\r\n        INLINE explicit Vector4( FXMVECTOR vec ) { m_vec = vec; }\r\n        INLINE explicit Vector4( EZeroTag ) { m_vec = SplatZero(); }\r\n        INLINE explicit Vector4( EIdentityTag ) { m_vec = SplatOne(); }\r\n        INLINE explicit Vector4( EXUnitVector\t) { m_vec = CreateXUnitVector(); }\r\n        INLINE explicit Vector4( EYUnitVector ) { m_vec = CreateYUnitVector(); }\r\n        INLINE explicit Vector4( EZUnitVector ) { m_vec = CreateZUnitVector(); }\r\n        INLINE explicit Vector4( EWUnitVector ) { m_vec = CreateWUnitVector(); }\r\n\r\n        INLINE operator XMVECTOR() const { return m_vec; }\r\n\r\n        INLINE Scalar GetX() const { return Scalar(XMVectorSplatX(m_vec)); }\r\n        INLINE Scalar GetY() const { return Scalar(XMVectorSplatY(m_vec)); }\r\n        INLINE Scalar GetZ() const { return Scalar(XMVectorSplatZ(m_vec)); }\r\n        INLINE Scalar GetW() const { return Scalar(XMVectorSplatW(m_vec)); }\r\n        INLINE void SetX( Scalar x ) { m_vec = XMVectorPermute<4,1,2,3>(m_vec, x); }\r\n        INLINE void SetY( Scalar y ) { m_vec = XMVectorPermute<0,5,2,3>(m_vec, y); }\r\n        INLINE void SetZ( Scalar z ) { m_vec = XMVectorPermute<0,1,6,3>(m_vec, z); }\r\n        INLINE void SetW( Scalar w ) { m_vec = XMVectorPermute<0,1,2,7>(m_vec, w); }\r\n\r\n        INLINE Vector4 operator- () const { return Vector4(XMVectorNegate(m_vec)); }\r\n        INLINE Vector4 operator+ ( Vector4 v2 ) const { return Vector4(XMVectorAdd(m_vec, v2)); }\r\n        INLINE Vector4 operator- ( Vector4 v2 ) const { return Vector4(XMVectorSubtract(m_vec, v2)); }\r\n        INLINE Vector4 operator* ( Vector4 v2 ) const { return Vector4(XMVectorMultiply(m_vec, v2)); }\r\n        INLINE Vector4 operator/ ( Vector4 v2 ) const { return Vector4(XMVectorDivide(m_vec, v2)); }\r\n        INLINE Vector4 operator* ( Scalar  v2 ) const { return *this * Vector4(v2); }\r\n        INLINE Vector4 operator/ ( Scalar  v2 ) const { return *this / Vector4(v2); }\r\n        INLINE Vector4 operator* ( float   v2 ) const { return *this * Scalar(v2); }\r\n        INLINE Vector4 operator/ ( float   v2 ) const { return *this / Scalar(v2); }\r\n\r\n        INLINE void operator*= ( float   v2 ) { *this = *this * Scalar(v2); }\r\n        INLINE void operator/= ( float   v2 ) { *this = *this / Scalar(v2); }\r\n\r\n        INLINE friend Vector4 operator* ( Scalar  v1, Vector4 v2 ) { return Vector4(v1) * v2; }\r\n        INLINE friend Vector4 operator/ ( Scalar  v1, Vector4 v2 ) \t{ return Vector4(v1) / v2; }\r\n        INLINE friend Vector4 operator* ( float   v1, Vector4 v2 ) { return Scalar(v1) * v2; }\r\n        INLINE friend Vector4 operator/ ( float   v1, Vector4 v2 ) \t{ return Scalar(v1) / v2; }\r\n\r\n    protected:\r\n        XMVECTOR m_vec;\r\n    };\r\n\r\n    INLINE Vector3::Vector3( Vector4 v )\r\n    {\r\n        Scalar W = v.GetW();\r\n        m_vec = XMVectorSelect( XMVectorDivide(v, W), v, XMVectorEqual(W, SplatZero()) );\r\n    }\r\n\r\n    class BoolVector\r\n    {\r\n    public:\r\n        INLINE BoolVector( FXMVECTOR vec ) { m_vec = vec; }\r\n        INLINE operator XMVECTOR() const { return m_vec; }\r\n    protected:\r\n        XMVECTOR m_vec;\r\n    };\r\n\r\n} // namespace Math\r\n"
  },
  {
    "path": "MiniEngine/Core/MotionBlur.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"MotionBlur.h\"\r\n#include \"Camera.h\"\r\n#include \"BufferManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"Camera.h\"\r\n#include \"PostEffects.h\"\r\n#include \"SystemTime.h\"\r\n\r\n#include \"CompiledShaders/ScreenQuadVS.h\"\r\n#include \"CompiledShaders/CameraMotionBlurPrePassCS.h\"\r\n#include \"CompiledShaders/CameraMotionBlurPrePassLinearZCS.h\"\r\n#include \"CompiledShaders/MotionBlurPrePassCS.h\"\r\n#include \"CompiledShaders/MotionBlurFinalPassCS.h\"\r\n#include \"CompiledShaders/MotionBlurFinalPassPS.h\"\r\n#include \"CompiledShaders/CameraVelocityCS.h\"\r\n#include \"CompiledShaders/TemporalBlendCS.h\"\r\n#include \"CompiledShaders/BoundNeighborhoodCS.h\"\r\n\r\nusing namespace Graphics;\r\nusing namespace Math;\r\n\r\nnamespace MotionBlur\r\n{\r\n    BoolVar Enable(\"Graphics/Motion Blur/Enable\", false);\r\n\r\n    RootSignature s_RootSignature;\r\n    ComputePSO s_CameraMotionBlurPrePassCS[2];\r\n    ComputePSO s_MotionBlurPrePassCS;\r\n    ComputePSO s_MotionBlurFinalPassCS;\r\n    GraphicsPSO s_MotionBlurFinalPassPS;\r\n    ComputePSO s_CameraVelocityCS[2];\r\n}\r\n\r\nvoid MotionBlur::Initialize( void )\r\n{\r\n    s_RootSignature.Reset(4, 1);\r\n    s_RootSignature.InitStaticSampler(0, SamplerLinearBorderDesc);\r\n    s_RootSignature[0].InitAsConstants(0, 4);\r\n    s_RootSignature[1].InitAsConstantBuffer(1);\r\n    s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 8);\r\n    s_RootSignature[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 8);\r\n    s_RootSignature.Finalize(L\"Motion Blur\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(s_RootSignature); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        CreatePSO(s_MotionBlurFinalPassCS, g_pMotionBlurFinalPassCS);\r\n    }\r\n    else\r\n    {\r\n        s_MotionBlurFinalPassPS.SetRootSignature(s_RootSignature);\r\n        s_MotionBlurFinalPassPS.SetRasterizerState( RasterizerTwoSided );\r\n        s_MotionBlurFinalPassPS.SetBlendState( BlendPreMultiplied );\r\n        s_MotionBlurFinalPassPS.SetDepthStencilState( DepthStateDisabled );\r\n        s_MotionBlurFinalPassPS.SetSampleMask(0xFFFFFFFF);\r\n        s_MotionBlurFinalPassPS.SetInputLayout(0, nullptr);\r\n        s_MotionBlurFinalPassPS.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);\r\n        s_MotionBlurFinalPassPS.SetVertexShader( g_pScreenQuadVS, sizeof(g_pScreenQuadVS) );\r\n        s_MotionBlurFinalPassPS.SetPixelShader( g_pMotionBlurFinalPassPS, sizeof(g_pMotionBlurFinalPassPS) );\r\n        s_MotionBlurFinalPassPS.SetRenderTargetFormat(g_pSceneColorBuffer->GetFormat(), DXGI_FORMAT_UNKNOWN);\r\n        s_MotionBlurFinalPassPS.Finalize();\r\n\r\n    }\r\n    CreatePSO( s_CameraMotionBlurPrePassCS[0], g_pCameraMotionBlurPrePassCS );\r\n    CreatePSO( s_CameraMotionBlurPrePassCS[1], g_pCameraMotionBlurPrePassLinearZCS );\r\n    CreatePSO( s_MotionBlurPrePassCS, g_pMotionBlurPrePassCS );\r\n    CreatePSO( s_CameraVelocityCS[0], g_pCameraVelocityCS );\r\n    CreatePSO( s_CameraVelocityCS[1], g_pCameraVelocityCS );\r\n\r\n#undef CreatePSO\r\n}\r\n\r\nvoid MotionBlur::Shutdown( void )\r\n{\r\n}\r\n\r\n// Linear Z ends up being faster since we haven't officially decompressed the depth buffer.  You \r\n// would think that it might be slower to use linear Z because we have to convert it back to\r\n// hyperbolic Z for the reprojection.  Nevertheless, the reduced bandwidth and decompress eliminate\r\n// make Linear Z the better choice.  (The choice also lets you evict the depth buffer from ESRAM.)\r\n\r\nvoid MotionBlur::GenerateCameraVelocityBuffer( CommandContext& BaseContext, const Camera& camera, bool UseLinearZ )\r\n{\r\n    GenerateCameraVelocityBuffer(BaseContext, camera.GetReprojectionMatrix(), camera.GetNearClip(), camera.GetFarClip(), UseLinearZ);\r\n}\r\n\r\nvoid MotionBlur::GenerateCameraVelocityBuffer( CommandContext& BaseContext, const Matrix4& reprojectionMatrix, float nearClip, float farClip, bool UseLinearZ)\r\n{\r\n    ScopedTimer _prof(L\"Generate Camera Velocity\", BaseContext);\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n    ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];\r\n\r\n    Context.SetRootSignature(s_RootSignature);\r\n\r\n    uint32_t Width = LinearDepth.GetWidth();\r\n    uint32_t Height = LinearDepth.GetHeight();\r\n\r\n    float RcpHalfDimX = 2.0f / Width;\r\n    float RcpHalfDimY = 2.0f / Height;\r\n    float RcpZMagic = nearClip / (farClip - nearClip);\r\n\r\n    Matrix4 preMult = Matrix4(\r\n        Vector4( RcpHalfDimX, 0.0f, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, -RcpHalfDimY, 0.0f, 0.0f),\r\n        Vector4( 0.0f, 0.0f, UseLinearZ ? RcpZMagic : 1.0f, 0.0f ),\r\n        Vector4( -1.0f, 1.0f, UseLinearZ ? -RcpZMagic : 0.0f, 1.0f )\r\n    );\r\n\r\n    Matrix4 postMult = Matrix4(\r\n        Vector4( 1.0f / RcpHalfDimX, 0.0f, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, -1.0f / RcpHalfDimY, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),\r\n        Vector4( 1.0f / RcpHalfDimX, 1.0f / RcpHalfDimY, 0.0f, 1.0f ) );\r\n\r\n\r\n    Matrix4 CurToPrevXForm = postMult * reprojectionMatrix * preMult;\r\n\r\n    Context.SetDynamicConstantBufferView(1, sizeof(CurToPrevXForm), &CurToPrevXForm);\r\n    Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n    if (UseLinearZ)\r\n        Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    else\r\n        Context.TransitionResource(*g_pSceneDepthBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    Context.SetPipelineState(s_CameraVelocityCS[UseLinearZ ? 1 : 0]);\r\n    Context.SetDynamicDescriptor(3, 0, UseLinearZ ? LinearDepth.GetSRV() : g_pSceneDepthBuffer->GetDepthSRV());\r\n    Context.SetDynamicDescriptor(2, 0, g_VelocityBuffer.GetUAV());\r\n    Context.Dispatch2D(Width, Height);\r\n}\r\n\r\n\r\nvoid MotionBlur::RenderCameraBlur( CommandContext& BaseContext, const Camera& camera, bool UseLinearZ )\r\n{\r\n    RenderCameraBlur(BaseContext, camera.GetReprojectionMatrix(), camera.GetNearClip(), camera.GetFarClip(), UseLinearZ);\r\n}\r\n\r\nvoid MotionBlur::RenderCameraBlur( CommandContext& BaseContext, const Matrix4& reprojectionMatrix, float nearClip, float farClip, bool UseLinearZ)\r\n{\r\n    ScopedTimer _prof(L\"MotionBlur\", BaseContext);\r\n\r\n    if (!Enable)\r\n        return;\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n\r\n    Context.SetRootSignature(s_RootSignature);\r\n\r\n    ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];\r\n\r\n    uint32_t Width = LinearDepth.GetWidth();\r\n    uint32_t Height = LinearDepth.GetHeight();\r\n\r\n    float RcpHalfDimX = 2.0f / Width;\r\n    float RcpHalfDimY = 2.0f / Height;\r\n    float RcpZMagic = nearClip / (farClip - nearClip);\r\n\r\n    Matrix4 preMult = Matrix4(\r\n        Vector4( RcpHalfDimX, 0.0f, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, -RcpHalfDimY, 0.0f, 0.0f),\r\n        Vector4( 0.0f, 0.0f, UseLinearZ ? RcpZMagic : 1.0f, 0.0f ),\r\n        Vector4( -1.0f, 1.0f, UseLinearZ ? -RcpZMagic : 0.0f, 1.0f )\r\n    );\r\n\r\n    Matrix4 postMult = Matrix4(\r\n        Vector4( 1.0f / RcpHalfDimX, 0.0f, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, -1.0f / RcpHalfDimY, 0.0f, 0.0f ),\r\n        Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),\r\n        Vector4( 1.0f / RcpHalfDimX, 1.0f / RcpHalfDimY, 0.0f, 1.0f ) );\r\n\r\n    Matrix4 CurToPrevXForm = postMult * reprojectionMatrix * preMult;\r\n\r\n    Context.SetDynamicConstantBufferView(1, sizeof(CurToPrevXForm), &CurToPrevXForm);\r\n\r\n    if (UseLinearZ)\r\n        Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    else\r\n        Context.TransitionResource(*g_pSceneDepthBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    if (Enable)\r\n    {\r\n        Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n        Context.SetPipelineState(s_CameraMotionBlurPrePassCS[UseLinearZ ? 1 : 0]);\r\n        Context.SetDynamicDescriptor(3, 0, g_pSceneColorBuffer->GetSRV());\r\n        Context.SetDynamicDescriptor(3, 1, UseLinearZ ? LinearDepth.GetSRV() : g_pSceneDepthBuffer->GetDepthSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_MotionPrepBuffer.GetUAV());\r\n        Context.SetDynamicDescriptor(2, 1, g_VelocityBuffer.GetUAV());\r\n        Context.Dispatch2D(g_MotionPrepBuffer.GetWidth(), g_MotionPrepBuffer.GetHeight());\r\n\r\n        if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n        {\r\n            Context.SetPipelineState(s_MotionBlurFinalPassCS);\r\n            Context.SetConstants(0, 1.0f / Width, 1.0f / Height);\r\n\r\n            Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n            Context.SetDynamicDescriptor(3, 0, g_VelocityBuffer.GetSRV());\r\n            Context.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());\r\n\r\n            Context.Dispatch2D(Width, Height);\r\n\r\n            Context.InsertUAVBarrier(*g_pSceneColorBuffer);\r\n        }\r\n        else\r\n        {\r\n            GraphicsContext& GrContext = BaseContext.GetGraphicsContext();\r\n            GrContext.SetRootSignature(s_RootSignature);\r\n            GrContext.SetPipelineState(s_MotionBlurFinalPassPS);\r\n            GrContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n            GrContext.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n            GrContext.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n            GrContext.SetDynamicDescriptor(3, 0, g_VelocityBuffer.GetSRV());\r\n            GrContext.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());\r\n            GrContext.SetConstants(0, 1.0f / Width, 1.0f / Height);\r\n            GrContext.SetRenderTarget(g_pSceneColorBuffer->GetRTV());\r\n            GrContext.SetViewportAndScissor(0, 0, Width, Height);\r\n            GrContext.Draw(3);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        Context.SetPipelineState(s_CameraVelocityCS[UseLinearZ ? 1 : 0]);\r\n        Context.SetDynamicDescriptor(3, 0, UseLinearZ ? LinearDepth.GetSRV() : g_pSceneDepthBuffer->GetDepthSRV());\r\n        Context.SetDynamicDescriptor(2, 0, g_VelocityBuffer.GetUAV());\r\n        Context.Dispatch2D(Width, Height);\r\n    }\r\n}\r\n\r\nvoid MotionBlur::RenderObjectBlur( CommandContext& BaseContext, ColorBuffer& velocityBuffer )\r\n{\r\n    ScopedTimer _prof(L\"MotionBlur\", BaseContext);\r\n\r\n    if (!Enable)\r\n        return;\r\n\r\n    ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];\r\n\r\n    uint32_t Width = LinearDepth.GetWidth();\r\n    uint32_t Height = LinearDepth.GetHeight();\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n\r\n    Context.SetRootSignature(s_RootSignature);\r\n\r\n    Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(velocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    Context.SetDynamicDescriptor(2, 0, g_MotionPrepBuffer.GetUAV());\r\n    Context.SetDynamicDescriptor(3, 0, g_pSceneColorBuffer->GetSRV());\r\n    Context.SetDynamicDescriptor(3, 1, velocityBuffer.GetSRV());\r\n\r\n    Context.SetPipelineState(s_MotionBlurPrePassCS);\r\n    Context.Dispatch2D(g_MotionPrepBuffer.GetWidth(), g_MotionPrepBuffer.GetHeight());\r\n\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        Context.SetPipelineState(s_MotionBlurFinalPassCS);\r\n\r\n        Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(velocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n        Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n        Context.SetDynamicDescriptor(3, 0, velocityBuffer.GetSRV());\r\n        Context.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());\r\n        Context.SetConstants(0, 1.0f / Width, 1.0f / Height);\r\n\r\n        Context.Dispatch2D(Width, Height);\r\n\r\n        Context.InsertUAVBarrier(*g_pSceneColorBuffer);\r\n    }\r\n    else\r\n    {\r\n        GraphicsContext& GrContext = BaseContext.GetGraphicsContext();\r\n        GrContext.SetRootSignature(s_RootSignature);\r\n        GrContext.SetPipelineState(s_MotionBlurFinalPassPS);\r\n\r\n        GrContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        GrContext.TransitionResource(velocityBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        GrContext.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n\r\n        GrContext.SetDynamicDescriptor(3, 0, velocityBuffer.GetSRV());\r\n        GrContext.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());\r\n        GrContext.SetConstants(0, 1.0f / Width, 1.0f / Height);\r\n        GrContext.SetRenderTarget(g_pSceneColorBuffer->GetRTV());\r\n        GrContext.SetViewportAndScissor(0, 0, Width, Height);\r\n\r\n        GrContext.Draw(3);\r\n    }\r\n}\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/MotionBlur.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"EngineTuning.h\"\r\n\r\n// Forward declarations\r\nnamespace Math { class Matrix4; class Camera; }\r\nclass ColorBuffer;\r\nclass CommandContext;\r\n\r\nnamespace MotionBlur\r\n{\r\n    extern BoolVar Enable;\r\n\r\n    void Initialize( void );\r\n    void Shutdown( void );\r\n\r\n    void GenerateCameraVelocityBuffer( CommandContext& Context, const Math::Camera& camera, bool UseLinearZ = true );\r\n    void GenerateCameraVelocityBuffer( CommandContext& Context, const Math::Matrix4& reprojectionMatrix, float nearClip, float farClip, bool UseLinearZ = true);\r\n\r\n    // Generate motion blur only associated with the camera.  Does not handle fast-moving objects well, but\r\n    // does not require a full screen velocity buffer.\r\n    void RenderCameraBlur( CommandContext& Context, const Math::Camera& camera, bool UseLinearZ = true );\r\n    void RenderCameraBlur( CommandContext& Context, const Math::Matrix4& reprojectionMatrix, float nearClip, float farClip, bool UseLinearZ = true);\r\n\r\n    // Generate proper motion blur that takes into account the velocity of each pixel.  Requires a pre-generated\r\n    // velocity buffer (R16G16_FLOAT preferred.)\r\n    void RenderObjectBlur( CommandContext& Context, ColorBuffer& velocityBuffer );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleEffect.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Julia Careaga\r\n//             James Stanard\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"ParticleEffect.h\"\r\n#include \"CommandContext.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"BufferManager.h\"\r\n#include \"ParticleEffectManager.h\"\r\n#include \"GameInput.h\"\r\n#include \"Math/Random.h\"\r\n\r\nusing namespace Math;\r\nusing namespace ParticleEffects;\r\n\r\nnamespace ParticleEffects\r\n{\r\n    extern ComputePSO s_ParticleSpawnCS;\r\n    extern ComputePSO s_ParticleUpdateCS;\r\n    extern ComputePSO s_ParticleDispatchIndirectArgsCS;\r\n    extern StructuredBuffer SpriteVertexBuffer;\r\n    extern RandomNumberGenerator s_RNG;\r\n}\r\n\r\nParticleEffect::ParticleEffect(ParticleEffectProperties& effectProperties)\r\n{\r\n    m_ElapsedTime = 0.0;\r\n    m_EffectProperties = effectProperties;\r\n}\r\n\r\ninline static Color RandColor( Color c0, Color c1 )\r\n{\r\n    // We might want to find min and max of each channel rather than assuming c0 <= c1\r\n    return Color(\r\n        s_RNG.NextFloat( c0.R(), c1.R()),\r\n        s_RNG.NextFloat( c0.G(), c1.G()),\r\n        s_RNG.NextFloat( c0.B(), c1.B()),\r\n        s_RNG.NextFloat( c0.A(), c1.A())\r\n        );\r\n}\r\n\r\ninline static XMFLOAT3 RandSpread( const XMFLOAT3& s )\r\n{\r\n    // We might want to find min and max of each channel rather than assuming c0 <= c1\r\n    return XMFLOAT3(\r\n        s_RNG.NextFloat(-s.x, s.x),\r\n        s_RNG.NextFloat(-s.y, s.y), \r\n        s_RNG.NextFloat(-s.z, s.z)\r\n        );\r\n}\r\n\r\nvoid ParticleEffect::LoadDeviceResources(DX12_DEVICE* device)\r\n{\r\n    (device); // Currently unused.  May be useful with multi-adapter support.\r\n\r\n    m_OriginalEffectProperties = m_EffectProperties; //In case we want to reset\r\n    \r\n    //Fill particle spawn data buffer\r\n    ParticleSpawnData* pSpawnData = (ParticleSpawnData*)_malloca(m_EffectProperties.EmitProperties.MaxParticles * sizeof(ParticleSpawnData));\r\n    \r\n    for (UINT i = 0; i < m_EffectProperties.EmitProperties.MaxParticles; i++)\r\n    {\r\n        ParticleSpawnData& SpawnData = pSpawnData[i];\r\n        SpawnData.AgeRate = 1.0f / s_RNG.NextFloat( m_EffectProperties.LifeMinMax.x, m_EffectProperties.LifeMinMax.y );\r\n        float horizontalAngle = s_RNG.NextFloat(XM_2PI);\r\n        float horizontalVelocity = s_RNG.NextFloat( m_EffectProperties.Velocity.GetX(), m_EffectProperties.Velocity.GetY() );\r\n        SpawnData.Velocity.x = horizontalVelocity * cos(horizontalAngle);\r\n        SpawnData.Velocity.y = s_RNG.NextFloat( m_EffectProperties.Velocity.GetZ(), m_EffectProperties.Velocity.GetW() );\r\n        SpawnData.Velocity.z = horizontalVelocity * sin(horizontalAngle);\r\n\r\n        SpawnData.SpreadOffset = RandSpread(m_EffectProperties.Spread ) ;\r\n\r\n        SpawnData.StartSize = s_RNG.NextFloat( m_EffectProperties.Size.GetX(), m_EffectProperties.Size.GetY() );\r\n        SpawnData.EndSize = s_RNG.NextFloat( m_EffectProperties.Size.GetZ(), m_EffectProperties.Size.GetW() );\r\n        SpawnData.StartColor = RandColor( m_EffectProperties.MinStartColor, m_EffectProperties.MaxStartColor );\r\n        SpawnData.EndColor = RandColor( m_EffectProperties.MinEndColor, m_EffectProperties.MaxEndColor );\r\n        SpawnData.Mass = s_RNG.NextFloat( m_EffectProperties.MassMinMax.x, m_EffectProperties.MassMinMax.y );\r\n        SpawnData.RotationSpeed = s_RNG.NextFloat(); //todo\r\n        SpawnData.Random = s_RNG.NextFloat();\r\n    }\r\n    \r\n    m_RandomStateBuffer.Create(L\"ParticleSystem::SpawnDataBuffer\", m_EffectProperties.EmitProperties.MaxParticles, sizeof(ParticleSpawnData), pSpawnData);\r\n    _freea(pSpawnData);\r\n\r\n    m_StateBuffers[0].Create(L\"ParticleSystem::Buffer0\", m_EffectProperties.EmitProperties.MaxParticles, sizeof(ParticleMotion));\r\n    m_StateBuffers[1].Create(L\"ParticleSystem::Buffer1\", m_EffectProperties.EmitProperties.MaxParticles, sizeof(ParticleMotion));\r\n    m_CurrentStateBuffer = 0;\r\n\r\n    //DispatchIndirect args buffer / number of thread groups\r\n    __declspec(align(16)) UINT DispatchIndirectData[3] = { 0, 1, 1 };\r\n    m_DispatchIndirectArgs.Create(L\"ParticleSystem::DispatchIndirectArgs\", 1, sizeof(D3D12_DISPATCH_ARGUMENTS), DispatchIndirectData);\r\n\r\n}\r\n\r\nvoid ParticleEffect::Update(ComputeContext& CompContext,  float timeDelta)\r\n{\r\n\r\n    m_ElapsedTime += timeDelta;\r\n    m_EffectProperties.EmitProperties.LastEmitPosW = m_EffectProperties.EmitProperties.EmitPosW;\r\n    \r\n    //m_EffectProperties.EmitProperties.EmitPosW = XMFLOAT3(ComputeConstants.EmitPosW.x + 1.0f * float(GameInput::IsPressed(GameInput::kBButton)), ComputeConstants.EmitPosW.y + 1.0f * float(GameInput::IsPressed(GameInput::kYButton)), ComputeConstants.EmitPosW.z - 1.0f * float(GameInput::IsPressed(GameInput::kAButton)));//\r\n    //m_EffectProperties.EmitProperties.EmitPosW.x += m_EffectProperties.DirectionIncrement.x;\r\n    //m_EffectProperties.EmitProperties.EmitPosW.y += m_EffectProperties.DirectionIncrement.y;\r\n    //m_EffectProperties.EmitProperties.EmitPosW.z += m_EffectProperties.DirectionIncrement.z;\r\n\r\n\r\n    //CPU side random num gen\r\n    for (uint32_t i = 0; i < 64; i++)\r\n    {\r\n        UINT random = (UINT)s_RNG.NextInt(m_EffectProperties.EmitProperties.MaxParticles - 1);\r\n        m_EffectProperties.EmitProperties.RandIndex[i].x = random;\r\n    }\r\n    CompContext.SetDynamicConstantBufferView(2, sizeof(EmissionProperties), &m_EffectProperties.EmitProperties);\t\r\n\r\n    CompContext.TransitionResource(m_StateBuffers[m_CurrentStateBuffer], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    CompContext.SetDynamicDescriptor(4, 0, m_RandomStateBuffer.GetSRV());\r\n    CompContext.SetDynamicDescriptor(4, 1, m_StateBuffers[m_CurrentStateBuffer].GetSRV());\r\n\r\n    m_CurrentStateBuffer ^= 1;\r\n\r\n    CompContext.ResetCounter(m_StateBuffers[m_CurrentStateBuffer]);\r\n\r\n    CompContext.SetPipelineState(s_ParticleUpdateCS);\r\n    CompContext.TransitionResource(m_StateBuffers[m_CurrentStateBuffer], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    CompContext.TransitionResource(m_DispatchIndirectArgs, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n    CompContext.SetDynamicDescriptor(3, 2, m_StateBuffers[m_CurrentStateBuffer].GetUAV());\r\n    CompContext.DispatchIndirect(m_DispatchIndirectArgs, 0);\r\n\r\n    // Why need a barrier here so long as we are artificially clamping particle count.  This allows living\r\n    // particles to take precedence over new particles.  The current system always spawns a multiple of 64\r\n    // particles (To Be Fixed) until the total particle count reaches maximum.\r\n    CompContext.InsertUAVBarrier(m_StateBuffers[m_CurrentStateBuffer]);\r\n    \r\n    // Spawn to replace dead ones \r\n    CompContext.SetPipelineState(s_ParticleSpawnCS);\r\n    CompContext.SetDynamicDescriptor(4, 0, m_RandomStateBuffer.GetSRV());\r\n    UINT NumSpawnThreads = (UINT)(m_EffectProperties.EmitRate * timeDelta);\r\n    CompContext.Dispatch((NumSpawnThreads + 63) / 64, 1, 1);\r\n\r\n    // Output number of thread groups into m_DispatchIndirectArgs\t\r\n    CompContext.SetPipelineState(s_ParticleDispatchIndirectArgsCS);\r\n    CompContext.TransitionResource(m_DispatchIndirectArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    CompContext.TransitionResource(m_StateBuffers[m_CurrentStateBuffer], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    CompContext.SetDynamicDescriptor(4, 0, m_StateBuffers[m_CurrentStateBuffer].GetCounterSRV(CompContext));\r\n    CompContext.SetDynamicDescriptor(3, 1, m_DispatchIndirectArgs.GetUAV());\r\n    CompContext.Dispatch(1, 1, 1);\r\n}\r\n\r\n\r\nvoid ParticleEffect::Reset()\r\n{\r\n    m_EffectProperties = m_OriginalEffectProperties;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleEffect.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Julia Careaga\r\n//             James Stanard\r\n\r\n#pragma once\r\n#include \"pch.h\"\r\n#include \"GpuBuffer.h\"\r\n#include \"ParticleEffectProperties.h\"\r\n#include \"ParticleShaderStructs.h\"\r\n\r\nclass ParticleEffect \r\n{\r\npublic:\r\n    ParticleEffect(ParticleEffectProperties& effectProperties);\r\n    void LoadDeviceResources(DX12_DEVICE* device);\r\n    void Update(ComputeContext& CompContext, float timeDelta);\r\n    float GetLifetime(){ return m_EffectProperties.TotalActiveLifetime; }\r\n    float GetElapsedTime(){ return m_ElapsedTime; }\r\n    void Reset();\r\n\r\nprivate:\r\n\r\n    StructuredBuffer m_StateBuffers[2];\r\n    uint32_t m_CurrentStateBuffer;\r\n    StructuredBuffer m_RandomStateBuffer; \r\n    IndirectArgsBuffer m_DispatchIndirectArgs;\r\n    IndirectArgsBuffer m_DrawIndirectArgs;\r\n\r\n    ParticleEffectProperties m_EffectProperties;\r\n    ParticleEffectProperties m_OriginalEffectProperties;\r\n    float m_ElapsedTime;\r\n    UINT m_effectID;\r\n    \r\n\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleEffectManager.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Julia Careaga\r\n//             James Stanard\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"BufferManager.h\"\r\n#include \"BitonicSort.h\"\r\n#include \"Camera.h\"\r\n#include \"ColorBuffer.h\"\r\n#include \"CommandContext.h\"\r\n#include \"GameCore.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"Math/Random.h\"\r\n#include \"ParticleEffectManager.h\"\r\n#include \"ParticleEffect.h\"\r\n#include \"ParticleEffectProperties.h\"\r\n#include \"TextureManager.h\"\r\n#include <mutex>\r\n\r\n#include \"CompiledShaders/ParticleSpawnCS.h\"\r\n#include \"CompiledShaders/ParticleUpdateCS.h\"\r\n#include \"CompiledShaders/ParticleDispatchIndirectArgsCS.h\"\r\n#include \"CompiledShaders/ParticleFinalDispatchIndirectArgsCS.h\"\r\n#include \"CompiledShaders/ParticleLargeBinCullingCS.h\"\r\n#include \"CompiledShaders/ParticleBinCullingCS.h\"\r\n\r\n#include \"CompiledShaders/ParticleTileRenderCS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderFastCS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderSlowDynamicCS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderFastDynamicCS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderSlowLowResCS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderFastLowResCS.h\"\r\n\r\n#include \"CompiledShaders/ParticleTileRender2CS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderFast2CS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderSlowDynamic2CS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderFastDynamic2CS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderSlowLowRes2CS.h\"\r\n#include \"CompiledShaders/ParticleTileRenderFastLowRes2CS.h\"\r\n\r\n#include \"CompiledShaders/ParticleTileCullingCS.h\"\r\n#include \"CompiledShaders/ParticleDepthBoundsCS.h\"\r\n\r\n#include \"CompiledShaders/ParticleSortIndirectArgsCS.h\"\r\n#include \"CompiledShaders/ParticlePreSortCS.h\"\r\n#include \"CompiledShaders/ParticlePS.h\"\r\n#include \"CompiledShaders/ParticleVS.h\"\r\n#include \"CompiledShaders/ParticleNoSortVS.h\"\r\n\r\n#define EFFECTS_ERROR uint32_t(0xFFFFFFFF)\r\n\r\n#define MAX_TOTAL_PARTICLES 0x40000\t\t// 256k (18-bit indices)\r\n#define MAX_PARTICLES_PER_BIN 1024\r\n#define BIN_SIZE_X 128\r\n#define BIN_SIZE_Y 64\r\n#define TILE_SIZE 16\r\n\r\n// It's good to have 32 tiles per bin to maximize the tile culling phase\r\n#define TILES_PER_BIN_X (BIN_SIZE_X / TILE_SIZE)\r\n#define TILES_PER_BIN_Y (BIN_SIZE_Y / TILE_SIZE)\r\n#define TILES_PER_BIN (TILES_PER_BIN_X * TILES_PER_BIN_Y)\r\n\r\nusing namespace Graphics;\r\nusing namespace Math;\r\nusing namespace ParticleEffects;\r\n\r\nnamespace ParticleEffects\r\n{\r\n\t// Disable all particle effects for simplicity\r\n    BoolVar Enable(\"Graphics/Particle Effects/Enable\", false);\r\n    BoolVar EnableSpriteSort(\"Graphics/Particle Effects/Sort Sprites\", true);\r\n    BoolVar EnableTiledRendering(\"Graphics/Particle Effects/Tiled Rendering\", true);\r\n    BoolVar PauseSim(\"Graphics/Particle Effects/Pause Simulation\", false);\r\n    const char* ResolutionLabels[] = { \"High-Res\", \"Low-Res\", \"Dynamic\" };\r\n    EnumVar TiledRes(\"Graphics/Particle Effects/Tiled Sample Rate\", 2, 3, ResolutionLabels);\r\n    NumVar DynamicResLevel(\"Graphics/Particle Effects/Dynamic Resolution Cutoff\", 0.0f, -4.0f, 4.0f, 0.5f);\r\n    NumVar MipBias(\"Graphics/Particle Effects/Mip Bias\", 0.0f, -4.0f, 4.0f, 0.5f);\r\n    \r\n    ComputePSO s_ParticleSpawnCS;\r\n    ComputePSO s_ParticleUpdateCS;\r\n    ComputePSO s_ParticleDispatchIndirectArgsCS;\r\n\r\n    StructuredBuffer SpriteVertexBuffer;\r\n    \r\n    UINT s_ReproFrame = 0;//201;\r\n    RandomNumberGenerator s_RNG;\r\n}\r\n\r\nstruct CBChangesPerView\r\n{\r\n    Matrix4 gInvView;\r\n    Matrix4 gViewProj;\r\n\r\n    float gVertCotangent;\r\n    float gAspectRatio;\r\n    float gRcpFarZ;\r\n    float gInvertZ;\r\n\r\n    float gBufferWidth;\r\n    float gBufferHeight;\r\n    float gRcpBufferWidth;\r\n    float gRcpBufferHeight;\r\n\r\n    uint32_t gBinsPerRow;\r\n    uint32_t gTileRowPitch;\r\n    uint32_t gTilesPerRow;\r\n    uint32_t gTilesPerCol;\r\n};\r\n\r\nnamespace\r\n{\r\n    ComputePSO s_ParticleFinalDispatchIndirectArgsCS;\r\n    ComputePSO s_ParticleLargeBinCullingCS; \r\n    ComputePSO s_ParticleBinCullingCS; \r\n    ComputePSO s_ParticleTileCullingCS; \r\n    ComputePSO s_ParticleTileRenderSlowCS[3];\t// High-Res, Low-Res, Dynamic-Res\r\n    ComputePSO s_ParticleTileRenderFastCS[3]; \t// High-Res, Low-Res, Dynamic-Res (disable depth tests)\r\n    ComputePSO s_ParticleDepthBoundsCS;\r\n    GraphicsPSO s_NoTileRasterizationPSO[2];\r\n    ComputePSO s_ParticleSortIndirectArgsCS;\r\n    ComputePSO s_ParticlePreSortCS;\r\n\r\n    RootSignature RootSig;\r\n\r\n    StructuredBuffer SpriteIndexBuffer;\r\n    IndirectArgsBuffer SortIndirectArgs;\r\n\r\n    IndirectArgsBuffer DrawIndirectArgs;\r\n    IndirectArgsBuffer FinalDispatchIndirectArgs;\r\n    StructuredBuffer VisibleParticleBuffer;\r\n    StructuredBuffer BinParticles[2];\r\n    StructuredBuffer BinCounters[2];\r\n    StructuredBuffer TileCounters;\r\n    ByteAddressBuffer TileHitMasks;\r\n\r\n    StructuredBuffer TileDrawPackets;\r\n    StructuredBuffer TileFastDrawPackets;\r\n    IndirectArgsBuffer TileDrawDispatchIndirectArgs;\r\n\r\n    CBChangesPerView s_ChangesPerView;\r\n\r\n    GpuResource TextureArray;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE TextureArraySRV;\r\n    std::vector<std::wstring> TextureNameArray;\r\n\r\n    std::vector<std::unique_ptr<ParticleEffect>> ParticleEffectsPool;\r\n    std::vector<ParticleEffect*> ParticleEffectsActive;\r\n\r\n    static bool s_InitComplete = false; \r\n    UINT TotalElapsedFrames;\r\n\r\n    void SetFinalBuffers(ComputeContext& CompContext)\r\n    {\r\n        CompContext.SetPipelineState(s_ParticleFinalDispatchIndirectArgsCS);\r\n\r\n        CompContext.TransitionResource(SpriteVertexBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);\r\n        CompContext.TransitionResource(FinalDispatchIndirectArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        CompContext.TransitionResource(DrawIndirectArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        CompContext.SetDynamicDescriptor(3, 0, FinalDispatchIndirectArgs.GetUAV());\r\n        CompContext.SetDynamicDescriptor(3, 1, DrawIndirectArgs.GetUAV());\r\n        CompContext.SetDynamicDescriptor(4, 0, SpriteVertexBuffer.GetCounterSRV(CompContext));\r\n\r\n        CompContext.Dispatch( 1, 1, 1 );\r\n    }\r\n\r\n    void MaintainTextureList(ParticleEffectProperties& effectProperties)\r\n    {\r\n        std::wstring name = effectProperties.TexturePath;\r\n\r\n        for (uint32_t i = 0; i < TextureNameArray.size(); i++)\r\n        {\r\n            if (name.compare(TextureNameArray[i]) == 0)\r\n            {\r\n                effectProperties.EmitProperties.TextureID = i;\r\n                return;\r\n            }\r\n        }\r\n    \r\n        TextureNameArray.push_back(name);\r\n        UINT TextureID = (UINT)(TextureNameArray.size() - 1);\r\n        effectProperties.EmitProperties.TextureID = TextureID;\r\n\r\n        const ManagedTexture* managedTex = TextureManager::LoadDDSFromFile(name.c_str(), true);\r\n        managedTex->WaitForLoad();\r\n\r\n        GpuResource& ParticleTexture = *const_cast<ManagedTexture*>(managedTex);\r\n        CommandContext::InitializeTextureArraySlice(TextureArray, TextureID, ParticleTexture);\r\n    }\r\n\r\n\r\n    void RenderTiles(ComputeContext& CompContext, ColorBuffer& ColorTarget, ColorBuffer& LinearDepth)\r\n    {\t\r\n        size_t ScreenWidth = ColorTarget.GetWidth();\r\n        size_t ScreenHeight = ColorTarget.GetHeight();\r\n\r\n        ASSERT(ColorTarget.GetFormat() == DXGI_FORMAT_R32_UINT || g_bTypedUAVLoadSupport_R11G11B10_FLOAT,\r\n            \"Without typed UAV loads, tiled particles must render to a R32_UINT buffer\");\r\n\r\n        {\r\n            ScopedTimer _p(L\"Compute Depth Bounds\", CompContext);\r\n\r\n            CompContext.SetPipelineState(s_ParticleDepthBoundsCS);\r\n\r\n            CompContext.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(g_MinMaxDepth8, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(g_MinMaxDepth16, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(g_MinMaxDepth32, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.SetDynamicDescriptor(3, 0, g_MinMaxDepth8.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 1, g_MinMaxDepth16.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 2, g_MinMaxDepth32.GetUAV());\r\n            CompContext.SetDynamicDescriptor(4, 0, LinearDepth.GetSRV());\r\n\r\n            CompContext.Dispatch2D(ScreenWidth, ScreenHeight, 32, 32);\r\n        }\r\n\r\n        {\r\n            ScopedTimer _p(L\"Culling & Sorting\", CompContext);\r\n\r\n            CompContext.ResetCounter(VisibleParticleBuffer);\r\n\r\n            // The first step inserts each particle into all of the large bins it intersects.  Large bins\r\n            // are 512x256.\r\n            CompContext.SetPipelineState(s_ParticleLargeBinCullingCS);\r\n            CompContext.SetConstants(0, 5, 4);\r\n\r\n            CompContext.TransitionResource(SpriteVertexBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(FinalDispatchIndirectArgs, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n            CompContext.TransitionResource(BinParticles[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(BinCounters[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(VisibleParticleBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n            CompContext.SetDynamicDescriptor(3, 0, BinParticles[0].GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 1, BinCounters[0].GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 2, VisibleParticleBuffer.GetUAV());\r\n            CompContext.SetDynamicDescriptor(4, 0, SpriteVertexBuffer.GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 1, SpriteVertexBuffer.GetCounterSRV(CompContext));\r\n\r\n            CompContext.DispatchIndirect(FinalDispatchIndirectArgs);\r\n\r\n            // The second step refines the binning by inserting particles into the appropriate small bins.\r\n            // Small bins are 128x64.\r\n            CompContext.SetPipelineState(s_ParticleBinCullingCS);\r\n            CompContext.SetConstants(0, 3, 2);\r\n\r\n            CompContext.TransitionResource(VisibleParticleBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(BinParticles[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(BinCounters[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(BinParticles[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(BinCounters[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n            CompContext.SetDynamicDescriptor(3, 0, BinParticles[1].GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 1, BinCounters[1].GetUAV());\r\n            CompContext.SetDynamicDescriptor(4, 0, VisibleParticleBuffer.GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 1, BinParticles[0].GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 2, BinCounters[0].GetSRV());\r\n\r\n            CompContext.Dispatch2D(ScreenWidth, ScreenHeight, 4 * BIN_SIZE_X, 4 * BIN_SIZE_Y);\r\n\r\n            // The final sorting step will perform a bitonic sort on each bin's particles (front to\r\n            // back).  Afterward, it will generate a bitmap for each tile indicating which of the bin's\r\n            // particles occupy the tile.  This allows each tile to iterate over a sorted list of particles\r\n            // ignoring the ones that do not intersect.\r\n            CompContext.SetPipelineState(s_ParticleTileCullingCS);\r\n\r\n            CompContext.FillBuffer(TileDrawDispatchIndirectArgs, 0, 0, sizeof(uint32_t));\r\n            CompContext.FillBuffer(TileDrawDispatchIndirectArgs, 12, 0, sizeof(uint32_t));\r\n\r\n            CompContext.TransitionResource(BinParticles[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(TileHitMasks, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(TileDrawPackets, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(TileFastDrawPackets, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(TileDrawDispatchIndirectArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(BinParticles[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(BinCounters[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(g_MinMaxDepth8, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(g_MinMaxDepth16, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(g_MinMaxDepth32, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n            CompContext.SetDynamicDescriptor(3, 0, BinParticles[0].GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 1, TileHitMasks.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 2, TileDrawPackets.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 3, TileFastDrawPackets.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 4, TileDrawDispatchIndirectArgs.GetUAV());\r\n\r\n            CompContext.SetDynamicDescriptor(4, 0, BinParticles[1].GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 1, BinCounters[1].GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 2, TILE_SIZE == 16 ? g_MinMaxDepth16.GetSRV() : g_MinMaxDepth32.GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 3, VisibleParticleBuffer.GetSRV());\r\n\r\n            CompContext.Dispatch2D(ScreenWidth, ScreenHeight, BIN_SIZE_X, BIN_SIZE_Y);\r\n        }\r\n\r\n        {\r\n            ScopedTimer _p(L\"Tiled Rendering\", CompContext);\r\n\r\n            CompContext.TransitionResource(TileDrawDispatchIndirectArgs, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n            CompContext.TransitionResource(ColorTarget, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(BinParticles[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(TileHitMasks, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(TileDrawPackets, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(TileFastDrawPackets, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(TextureArray, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n            CompContext.SetDynamicDescriptor(3, 0, ColorTarget.GetUAV());\r\n\r\n            D3D12_CPU_DESCRIPTOR_HANDLE SRVs[] =\r\n            {\r\n                VisibleParticleBuffer.GetSRV(),\r\n                TileHitMasks.GetSRV(),\r\n                TextureArraySRV,\r\n                LinearDepth.GetSRV(),\r\n                BinParticles[0].GetSRV(),\r\n                TileDrawPackets.GetSRV(),\r\n                TileFastDrawPackets.GetSRV(),\r\n                (TILE_SIZE == 16 ? g_MinMaxDepth16.GetSRV() : g_MinMaxDepth32.GetSRV()),\r\n            };\r\n            CompContext.SetDynamicDescriptors(4, 0, _countof(SRVs), SRVs);\r\n\r\n            CompContext.SetConstants(0, (float)DynamicResLevel, (float)MipBias);\r\n\r\n            CompContext.SetPipelineState(s_ParticleTileRenderSlowCS[TiledRes]);\r\n            CompContext.DispatchIndirect(TileDrawDispatchIndirectArgs, 0);\r\n\r\n            CompContext.SetPipelineState(s_ParticleTileRenderFastCS[TiledRes]);\r\n            CompContext.DispatchIndirect(TileDrawDispatchIndirectArgs, 12);\r\n        }\r\n    }\r\n    \r\n    void RenderSprites(GraphicsContext& GrContext, ColorBuffer& ColorTarget, DepthBuffer& DepthTarget, ColorBuffer& LinearDepth)\r\n    {\r\n        if (EnableSpriteSort)\r\n        {\r\n            ScopedTimer _p(L\"Sort Particles\", GrContext);\r\n            ComputeContext& CompContext = GrContext.GetComputeContext();\r\n            CompContext.SetRootSignature(RootSig);\r\n\r\n            CompContext.SetDynamicConstantBufferView(1, sizeof(CBChangesPerView), &s_ChangesPerView);\r\n\r\n            CompContext.SetPipelineState(s_ParticleSortIndirectArgsCS);\r\n            CompContext.TransitionResource(SpriteVertexBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            CompContext.TransitionResource(SortIndirectArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.TransitionResource(DrawIndirectArgs, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.InsertUAVBarrier(DrawIndirectArgs);\r\n            CompContext.SetDynamicDescriptor(3, 0, SortIndirectArgs.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 1, DrawIndirectArgs.GetUAV());\r\n            CompContext.Dispatch(1, 1, 1);\r\n\r\n            CompContext.SetPipelineState(s_ParticlePreSortCS);\r\n            CompContext.TransitionResource(SortIndirectArgs, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n            CompContext.TransitionResource(SpriteIndexBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            CompContext.InsertUAVBarrier(DrawIndirectArgs);\r\n            CompContext.SetDynamicDescriptor(3, 0, SpriteIndexBuffer.GetUAV());\r\n            CompContext.SetDynamicDescriptor(3, 1, DrawIndirectArgs.GetUAV());\r\n            CompContext.SetDynamicDescriptor(4, 0, SpriteVertexBuffer.GetSRV());\r\n            CompContext.SetDynamicDescriptor(4, 1, SpriteVertexBuffer.GetCounterSRV(CompContext));\r\n            CompContext.DispatchIndirect(SortIndirectArgs, 0);\r\n\r\n            CompContext.InsertUAVBarrier(SpriteIndexBuffer);\r\n\r\n            BitonicSort::Sort(CompContext, SpriteIndexBuffer, SpriteVertexBuffer.GetCounterBuffer(), 0, true, false);\r\n        }\r\n\r\n        D3D12_RECT scissor;\r\n        scissor.left = 0;\r\n        scissor.top = 0;\r\n        scissor.right = (LONG)ColorTarget.GetWidth();\r\n        scissor.bottom = (LONG)ColorTarget.GetHeight();\r\n\r\n        D3D12_VIEWPORT viewport;\r\n        viewport.TopLeftX = 0.0;\r\n        viewport.TopLeftY = 0.0;\r\n        viewport.Width = (float)ColorTarget.GetWidth();\r\n        viewport.Height = (float)ColorTarget.GetHeight();\r\n        viewport.MinDepth = 0.0;\r\n        viewport.MaxDepth = 1.0;\r\n\r\n        GrContext.SetRootSignature(RootSig);\r\n        GrContext.SetPipelineState(s_NoTileRasterizationPSO[EnableSpriteSort ? 0 : 1]);\r\n        GrContext.TransitionResource(SpriteVertexBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        GrContext.TransitionResource(DrawIndirectArgs, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);\r\n        GrContext.TransitionResource(TextureArray, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        GrContext.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        GrContext.TransitionResource(SpriteIndexBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n        GrContext.SetDynamicDescriptor(4, 0, SpriteVertexBuffer.GetSRV() );\r\n        GrContext.SetDynamicDescriptor(4, 1, TextureArraySRV);\r\n        GrContext.SetDynamicDescriptor(4, 2, LinearDepth.GetSRV());\r\n        GrContext.SetDynamicDescriptor(4, 3, SpriteIndexBuffer.GetSRV());\r\n        GrContext.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);\r\n        GrContext.TransitionResource(ColorTarget, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        GrContext.TransitionResource(DepthTarget, D3D12_RESOURCE_STATE_DEPTH_READ);\r\n        GrContext.SetRenderTarget(ColorTarget.GetRTV(), DepthTarget.GetDSV_DepthReadOnly());\r\n        GrContext.SetViewportAndScissor(viewport, scissor);\r\n        GrContext.DrawIndirect(DrawIndirectArgs);\r\n    }\r\n\r\n} // {anonymous} namespace\r\n\r\n//---------------------------------------------------------------------\r\n//\r\n//\tInitialize\r\n//\r\n//---------------------------------------------------------------------\r\n\r\nvoid ParticleEffects::Initialize( uint32_t MaxDisplayWidth, uint32_t MaxDisplayHeight )\r\n{\t\r\n    D3D12_SAMPLER_DESC SamplerBilinearBorderDesc = SamplerPointBorderDesc;\r\n    SamplerBilinearBorderDesc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;\r\n\r\n    RootSig.Reset(5, 3);\r\n    RootSig.InitStaticSampler(0, SamplerBilinearBorderDesc);\r\n    RootSig.InitStaticSampler(1, SamplerPointBorderDesc);\r\n    RootSig.InitStaticSampler(2, SamplerPointClampDesc);\r\n    RootSig[0].InitAsConstants(0, 3);\r\n    RootSig[1].InitAsConstantBuffer(1);\r\n    RootSig[2].InitAsConstantBuffer(2);\r\n    RootSig[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 8);\r\n    RootSig[4].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 10);\r\n    RootSig.Finalize(L\"Particle Effects\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(RootSig); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n    CreatePSO(s_ParticleSpawnCS, g_pParticleSpawnCS);\r\n    CreatePSO(s_ParticleUpdateCS, g_pParticleUpdateCS);\r\n    CreatePSO(s_ParticleDispatchIndirectArgsCS, g_pParticleDispatchIndirectArgsCS);\r\n    CreatePSO(s_ParticleFinalDispatchIndirectArgsCS, g_pParticleFinalDispatchIndirectArgsCS);\r\n\r\n    CreatePSO(s_ParticleLargeBinCullingCS, g_pParticleLargeBinCullingCS);\r\n    CreatePSO(s_ParticleBinCullingCS, g_pParticleBinCullingCS);\r\n    CreatePSO(s_ParticleTileCullingCS, g_pParticleTileCullingCS);\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        CreatePSO(s_ParticleTileRenderSlowCS[0], g_pParticleTileRender2CS);\r\n        CreatePSO(s_ParticleTileRenderFastCS[0], g_pParticleTileRenderFast2CS);\r\n        CreatePSO(s_ParticleTileRenderSlowCS[1], g_pParticleTileRenderSlowLowRes2CS);\r\n        CreatePSO(s_ParticleTileRenderFastCS[1], g_pParticleTileRenderFastLowRes2CS);\r\n        CreatePSO(s_ParticleTileRenderSlowCS[2], g_pParticleTileRenderSlowDynamic2CS);\r\n        CreatePSO(s_ParticleTileRenderFastCS[2], g_pParticleTileRenderFastDynamic2CS);\r\n    }\r\n    else\r\n    {\r\n        CreatePSO(s_ParticleTileRenderSlowCS[0], g_pParticleTileRenderCS);\r\n        CreatePSO(s_ParticleTileRenderFastCS[0], g_pParticleTileRenderFastCS);\r\n        CreatePSO(s_ParticleTileRenderSlowCS[1], g_pParticleTileRenderSlowLowResCS);\r\n        CreatePSO(s_ParticleTileRenderFastCS[1], g_pParticleTileRenderFastLowResCS);\r\n        CreatePSO(s_ParticleTileRenderSlowCS[2], g_pParticleTileRenderSlowDynamicCS);\r\n        CreatePSO(s_ParticleTileRenderFastCS[2], g_pParticleTileRenderFastDynamicCS);\r\n    }\r\n    CreatePSO(s_ParticleDepthBoundsCS, g_pParticleDepthBoundsCS);\r\n    CreatePSO(s_ParticleSortIndirectArgsCS, g_pParticleSortIndirectArgsCS);\r\n    CreatePSO(s_ParticlePreSortCS, g_pParticlePreSortCS);\r\n\r\n#undef CreatePSO\r\n\r\n    //VSPS Render, no tiles.\r\n    s_NoTileRasterizationPSO[0].SetRootSignature(RootSig);\r\n    s_NoTileRasterizationPSO[0].SetRasterizerState(RasterizerTwoSided);\r\n    s_NoTileRasterizationPSO[0].SetDepthStencilState(DepthStateReadOnly);\r\n    s_NoTileRasterizationPSO[0].SetBlendState(BlendPreMultiplied);\r\n    s_NoTileRasterizationPSO[0].SetInputLayout(0, nullptr);\r\n    s_NoTileRasterizationPSO[0].SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE); \r\n    s_NoTileRasterizationPSO[0].SetRenderTargetFormat(g_pSceneColorBuffer->GetFormat(), g_pSceneDepthBuffer->GetFormat());\r\n    s_NoTileRasterizationPSO[0].SetVertexShader(g_pParticleVS, sizeof(g_pParticleVS));\r\n    s_NoTileRasterizationPSO[0].SetPixelShader(g_pParticlePS, sizeof(g_pParticlePS));\r\n    s_NoTileRasterizationPSO[0].Finalize();\r\n\r\n    s_NoTileRasterizationPSO[1] = s_NoTileRasterizationPSO[0];\r\n    s_NoTileRasterizationPSO[1].SetVertexShader(g_pParticleNoSortVS, sizeof(g_pParticleNoSortVS));\r\n    s_NoTileRasterizationPSO[1].Finalize();\r\n\r\n    __declspec(align(16)) UINT InitialDrawIndirectArgs[4] = { 4, 0, 0, 0 };\r\n    DrawIndirectArgs.Create(L\"ParticleEffects::DrawIndirectArgs\", 1, sizeof(D3D12_DRAW_ARGUMENTS), InitialDrawIndirectArgs);\r\n    __declspec(align(16)) UINT InitialDispatchIndirectArgs[6] = { 0, 1, 1, 0, 1, 1 };\r\n    FinalDispatchIndirectArgs.Create(L\"ParticleEffects::FinalDispatchIndirectArgs\", 1, sizeof(D3D12_DISPATCH_ARGUMENTS), InitialDispatchIndirectArgs);\r\n    SpriteVertexBuffer.Create(L\"ParticleEffects::SpriteVertexBuffer\", MAX_TOTAL_PARTICLES, sizeof(ParticleVertex));\r\n    VisibleParticleBuffer.Create(L\"ParticleEffects::VisibleParticleBuffer\", MAX_TOTAL_PARTICLES, sizeof(ParticleScreenData));\r\n    SpriteIndexBuffer.Create(L\"ParticleEffects::SpriteIndexBuffer\", MAX_TOTAL_PARTICLES, sizeof(UINT));\t\r\n    SortIndirectArgs.Create(L\"ParticleEffects::SortIndirectArgs\", 1, sizeof(D3D12_DISPATCH_ARGUMENTS));\r\n    TileDrawDispatchIndirectArgs.Create(L\"ParticleEffects::DrawPackets_IArgs\", 2, sizeof(D3D12_DISPATCH_ARGUMENTS), InitialDispatchIndirectArgs);\r\n\r\n    const uint32_t LargeBinsPerRow = DivideByMultiple(MaxDisplayWidth, 4 * BIN_SIZE_X);\r\n    const uint32_t LargeBinsPerCol = DivideByMultiple(MaxDisplayHeight, 4 * BIN_SIZE_Y);\r\n    const uint32_t BinsPerRow = LargeBinsPerRow * 4;\r\n    const uint32_t BinsPerCol = LargeBinsPerCol * 4;\r\n    const uint32_t MaxParticlesPerLargeBin = MAX_PARTICLES_PER_BIN * 16;\r\n    const uint32_t ParticleBinCapacity = LargeBinsPerRow * LargeBinsPerCol * MaxParticlesPerLargeBin;\r\n    const uint32_t TilesPerRow = DivideByMultiple(MaxDisplayWidth, TILE_SIZE);\r\n    const uint32_t TilesPerCol = DivideByMultiple(MaxDisplayHeight, TILE_SIZE);\r\n\r\n    // Padding is necessary to eliminate bounds checking when outputting data to bins or tiles.\r\n    const uint32_t PaddedTilesPerRow = AlignUp(TilesPerRow, TILES_PER_BIN_X * 4);\r\n    const uint32_t PaddedTilesPerCol = AlignUp(TilesPerCol, TILES_PER_BIN_Y * 4);\r\n\r\n    BinParticles[0].Create(L\"ParticleEffects::BinParticles[0]\", ParticleBinCapacity, sizeof(UINT));\r\n    BinParticles[1].Create(L\"ParticleEffects::BinParticles[1]\", ParticleBinCapacity, sizeof(UINT));\r\n    BinCounters[0].Create(L\"ParticleEffects::LargeBinCounters\", LargeBinsPerRow * LargeBinsPerCol, sizeof(UINT));\r\n    BinCounters[1].Create(L\"ParticleEffects::BinCounters\", BinsPerRow * BinsPerCol, sizeof(UINT));\r\n    TileCounters.Create(L\"ParticleEffects::TileCounters\", PaddedTilesPerRow * PaddedTilesPerCol, sizeof(UINT));\r\n    TileHitMasks.Create(L\"ParticleEffects::TileHitMasks\", PaddedTilesPerRow * PaddedTilesPerCol, MAX_PARTICLES_PER_BIN / 8);\r\n    TileDrawPackets.Create(L\"ParticleEffects::DrawPackets\", TilesPerRow * TilesPerCol, sizeof(UINT));\r\n    TileFastDrawPackets.Create(L\"ParticleEffects::FastDrawPackets\", TilesPerRow * TilesPerCol, sizeof(UINT));\r\n\r\n    D3D12_RESOURCE_DESC TexDesc = {};\r\n    TexDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\r\n    TexDesc.Format = DXGI_FORMAT_BC3_UNORM_SRGB;\r\n    TexDesc.Width = 64;\r\n    TexDesc.Height = 64;\r\n    TexDesc.DepthOrArraySize = 16;\r\n    TexDesc.MipLevels = 4;\r\n    TexDesc.SampleDesc.Count = 1;\r\n    TexDesc.Alignment = 0x10000;\r\n\r\n    D3D12_HEAP_PROPERTIES HeapProps = {};\r\n    HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    ID3D12Resource* tex = nullptr;\r\n    ASSERT_SUCCEEDED( g_Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE,\r\n        &TexDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&tex)) );\r\n    tex->SetName(L\"Particle TexArray\");\r\n    TextureArray = GpuResource(tex, D3D12_RESOURCE_STATE_COPY_DEST);\r\n    tex->Release();\r\n\r\n    D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {};\r\n    SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n    SRVDesc.Format = DXGI_FORMAT_BC3_UNORM_SRGB;\r\n    SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;\r\n    SRVDesc.Texture2DArray.MipLevels = 4;\r\n    SRVDesc.Texture2DArray.ArraySize = 16;\r\n    \r\n    TextureArraySRV = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateShaderResourceView(TextureArray.GetResource(), &SRVDesc, TextureArraySRV);\r\n\r\n    if (s_ReproFrame > 0)\r\n        s_RNG.SetSeed(1);\r\n    \r\n    TotalElapsedFrames = 0;\r\n    s_InitComplete = true;\r\n}\r\n\r\nvoid ParticleEffects::Shutdown( void )\r\n{\r\n    ClearAll();\r\n\r\n    SpriteVertexBuffer.Destroy();\r\n    DrawIndirectArgs.Destroy();\r\n    FinalDispatchIndirectArgs.Destroy();\r\n    SpriteVertexBuffer.Destroy();\r\n    VisibleParticleBuffer.Destroy();\r\n    SpriteIndexBuffer.Destroy();\r\n    SortIndirectArgs.Destroy();\r\n    TileDrawDispatchIndirectArgs.Destroy();\r\n\r\n    BinParticles[0].Destroy();\r\n    BinParticles[1].Destroy();\r\n    BinCounters[0].Destroy();\r\n    BinCounters[1].Destroy();\r\n    TileCounters.Destroy();\r\n    TileHitMasks.Destroy();\r\n    TileDrawPackets.Destroy();\r\n    TileFastDrawPackets.Destroy();\r\n    TextureArray.Destroy();\r\n}\r\n\r\n//Returns index into Pool\r\nEffectHandle ParticleEffects::PreLoadEffectResources( ParticleEffectProperties& effectProperties )\r\n{\r\n    if (!s_InitComplete)\r\n        return EFFECTS_ERROR;\r\n\r\n    static std::mutex s_TextureMutex;\r\n    s_TextureMutex.lock();\r\n    MaintainTextureList(effectProperties);\r\n    ParticleEffectsPool.emplace_back(new ParticleEffect(effectProperties));\r\n    s_TextureMutex.unlock();\r\n\r\n    EffectHandle index = (EffectHandle)ParticleEffectsPool.size() - 1;\r\n    ParticleEffectsPool[index]->LoadDeviceResources(Graphics::g_Device);\r\n    return index;\r\n}\r\n\r\n//Returns index into Active\r\nEffectHandle ParticleEffects::InstantiateEffect( EffectHandle effectHandle )\r\n{\r\n    if (!s_InitComplete || effectHandle >= ParticleEffectsPool.size() || effectHandle < 0)\r\n        return EFFECTS_ERROR;\r\n    \r\n    ParticleEffect* effect = ParticleEffectsPool[effectHandle].get();\r\n    if (effect != NULL)\r\n    {\r\n        static std::mutex s_InstantiateEffectFromPoolMutex;\r\n        s_InstantiateEffectFromPoolMutex.lock();\r\n        ParticleEffectsActive.push_back(effect);\r\n        s_InstantiateEffectFromPoolMutex.unlock();\r\n    }\r\n    else\r\n        return EFFECTS_ERROR;\r\n\r\n    EffectHandle index = (EffectHandle)ParticleEffectsActive.size() - 1;\r\n    return index;\r\n    \r\n}\r\n\r\n//Returns index into Active\r\nEffectHandle ParticleEffects::InstantiateEffect( ParticleEffectProperties& effectProperties )\r\n{\r\n    if (!s_InitComplete)\r\n        return EFFECTS_ERROR;\r\n\r\n    static std::mutex s_InstantiateNewEffectMutex;\r\n    s_InstantiateNewEffectMutex.lock();\r\n    MaintainTextureList(effectProperties);\r\n    ParticleEffect* newEffect = new ParticleEffect(effectProperties);\r\n    ParticleEffectsPool.emplace_back(newEffect);\r\n    ParticleEffectsActive.push_back(newEffect);\r\n    s_InstantiateNewEffectMutex.unlock();\r\n\r\n    EffectHandle index = (EffectHandle)ParticleEffectsActive.size() - 1;\r\n    ParticleEffectsActive[index]->LoadDeviceResources(Graphics::g_Device);\r\n    return index;\t\r\n}\r\n\r\n//---------------------------------------------------------------------\r\n//\r\n//\tUpdate\r\n//\r\n//---------------------------------------------------------------------\r\n\r\nvoid ParticleEffects::Update(ComputeContext& Context, float timeDelta )\r\n{\r\n    if (!Enable || !s_InitComplete || ParticleEffectsActive.size() == 0)\r\n        return;\r\n\r\n    ScopedTimer _prof(L\"Particle Update\", Context);\r\n\r\n    if (++TotalElapsedFrames == s_ReproFrame)\r\n        PauseSim = true;\r\n\r\n    if (PauseSim)\r\n        return;\r\n\r\n    Context.ResetCounter(SpriteVertexBuffer);\r\n\r\n    if (ParticleEffectsActive.size() == 0)\r\n        return;\r\n\r\n    Context.SetRootSignature(RootSig);\r\n    Context.SetConstants(0, timeDelta);\r\n    Context.TransitionResource(SpriteVertexBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.SetDynamicDescriptor(3, 0, SpriteVertexBuffer.GetUAV());\r\n\r\n    for (UINT i = 0; i < ParticleEffectsActive.size(); ++i)\r\n    {\t\r\n        ParticleEffectsActive[i]->Update(Context, timeDelta);\r\n\r\n        if (ParticleEffectsActive[i]->GetLifetime() <= ParticleEffectsActive[i]->GetElapsedTime())\r\n        {\r\n            //Erase from vector\r\n            auto iter = ParticleEffectsActive.begin() + i;\r\n            static std::mutex s_EraseEffectMutex;\r\n            s_EraseEffectMutex.lock();\r\n            ParticleEffectsActive.erase(iter);\r\n            s_EraseEffectMutex.unlock();\r\n        }\r\n    }\r\n\r\n    SetFinalBuffers(Context);\r\n}\r\n\r\n\r\n//---------------------------------------------------------------------\r\n//\r\n//\tRender\r\n//\r\n//---------------------------------------------------------------------\r\n\r\nvoid ParticleEffects::Render( CommandContext& Context, const Camera& Camera, ColorBuffer& ColorTarget, DepthBuffer& DepthTarget, ColorBuffer& LinearDepth)\r\n{\r\n    if (!Enable || !s_InitComplete || ParticleEffectsActive.size() == 0)\r\n        return;\r\n\r\n    uint32_t Width = (uint32_t)ColorTarget.GetWidth();\r\n    uint32_t Height = (uint32_t)ColorTarget.GetHeight();\r\n\r\n    ASSERT(\r\n        Width == DepthTarget.GetWidth() &&\r\n        Height == DepthTarget.GetHeight() &&\r\n        Width == LinearDepth.GetWidth() &&\r\n        Height == LinearDepth.GetHeight(),\r\n        \"There is a mismatch in buffer dimensions for rendering particles\"\r\n    );\r\n\r\n    ScopedTimer _prof(L\"Particle Render\", Context);\r\n\r\n    uint32_t BinsPerRow = 4 * DivideByMultiple(Width, 4 * BIN_SIZE_X);\r\n\r\n    s_ChangesPerView.gViewProj = Camera.GetViewProjMatrix();  \r\n    s_ChangesPerView.gInvView = Invert(Camera.GetViewMatrix());\r\n    float HCot = Camera.GetProjMatrix().GetX().GetX();\r\n    float VCot = Camera.GetProjMatrix().GetY().GetY();\r\n    s_ChangesPerView.gVertCotangent = VCot;\r\n    s_ChangesPerView.gAspectRatio = HCot / VCot;\r\n    s_ChangesPerView.gRcpFarZ = 1.0f / Camera.GetFarClip();\r\n    s_ChangesPerView.gInvertZ = Camera.GetNearClip() / (Camera.GetFarClip() - Camera.GetNearClip());\r\n    s_ChangesPerView.gBufferWidth = (float)Width;\r\n    s_ChangesPerView.gBufferHeight = (float)Height;\r\n    s_ChangesPerView.gRcpBufferWidth = 1.0f / Width;\r\n    s_ChangesPerView.gRcpBufferHeight = 1.0f / Height;\r\n    s_ChangesPerView.gBinsPerRow = BinsPerRow;\r\n    s_ChangesPerView.gTileRowPitch = BinsPerRow * TILES_PER_BIN_X;\r\n    s_ChangesPerView.gTilesPerRow = DivideByMultiple(Width, TILE_SIZE);\r\n    s_ChangesPerView.gTilesPerCol = DivideByMultiple(Height, TILE_SIZE);\r\n\r\n    // For now, UAV load support for R11G11B10 is required to read-modify-write the color buffer, but\r\n    // the compositing could be deferred.\r\n    WARN_ONCE_IF(EnableTiledRendering && !g_bTypedUAVLoadSupport_R11G11B10_FLOAT,\r\n        \"Unable to composite tiled particles without support for R11G11B10F UAV loads\");\r\n    EnableTiledRendering = EnableTiledRendering && g_bTypedUAVLoadSupport_R11G11B10_FLOAT;\r\n\r\n    if (EnableTiledRendering)\r\n    {\r\n        ComputeContext& CompContext = Context.GetComputeContext();\r\n        CompContext.TransitionResource(ColorTarget, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        CompContext.TransitionResource(BinCounters[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        CompContext.TransitionResource(BinCounters[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);\r\n\r\n        CompContext.ClearUAV(BinCounters[0]);\r\n        CompContext.ClearUAV(BinCounters[1]);\r\n        CompContext.SetRootSignature(RootSig);\r\n        CompContext.SetDynamicConstantBufferView(1, sizeof(CBChangesPerView), &s_ChangesPerView);\r\n\r\n        RenderTiles(CompContext, ColorTarget, LinearDepth);\r\n\r\n        CompContext.InsertUAVBarrier(ColorTarget);\r\n    }\r\n    else\r\n    {\r\n        GraphicsContext& GrContext = Context.GetGraphicsContext();\r\n        GrContext.SetRootSignature(RootSig);\r\n        GrContext.SetDynamicConstantBufferView(1, sizeof(CBChangesPerView), &s_ChangesPerView);\t\r\n        RenderSprites(GrContext, ColorTarget, DepthTarget, LinearDepth);\r\n    }\r\n\r\n}\r\n\r\n\r\n\r\n//---------------------------------------------------------------------\r\n//\r\n//\tClean up\r\n//\r\n//---------------------------------------------------------------------\r\n\r\nvoid ParticleEffects::ClearAll()\r\n{\r\n    ParticleEffectsActive.clear();\r\n    ParticleEffectsPool.clear();\r\n    TextureNameArray.clear();\r\n}\r\n\r\nvoid ParticleEffects::ResetEffect(EffectHandle EffectID)\r\n{\r\n    if (!s_InitComplete || ParticleEffectsActive.size() == 0 || PauseSim || EffectID >= ParticleEffectsActive.size())\r\n        return;\r\n    \r\n    ParticleEffectsActive[EffectID]->Reset();\r\n}\r\n\r\n\r\nfloat ParticleEffects::GetCurrentLife(EffectHandle EffectID)\r\n{\r\n    if (!s_InitComplete || ParticleEffectsActive.size() == 0 || PauseSim || EffectID >= ParticleEffectsActive.size())\r\n        return -1.0;\r\n    \r\n    return ParticleEffectsActive[EffectID]->GetElapsedTime();\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleEffectManager.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Julia Careaga\r\n//             James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\n#include \"ParticleEffectProperties.h\"\r\n#include \"ParticleEffect.h\"\r\n#include \"CommandContext.h\"\r\n#include \"Math/Random.h\"\r\n\r\nnamespace Math\r\n{\r\n    class Camera;\r\n}\r\n\r\nnamespace ParticleEffects\r\n{\r\n    void Initialize( uint32_t MaxDisplayWidth, uint32_t MaxDisplayHeight );\r\n    void Shutdown();\r\n    void ClearAll();\r\n    typedef uint32_t EffectHandle;\r\n    EffectHandle PreLoadEffectResources( ParticleEffectProperties& effectProperties );\r\n    EffectHandle InstantiateEffect( EffectHandle effectHandle );\r\n    EffectHandle InstantiateEffect( ParticleEffectProperties& effectProperties );\r\n    void Update(ComputeContext& Context, float timeDelta );\r\n    void Render(CommandContext& Context, const Camera& Camera, ColorBuffer& ColorTarget, DepthBuffer& DepthTarget, ColorBuffer& LinearDepth);\r\n    void ResetEffect(EffectHandle EffectID);\r\n    float GetCurrentLife(EffectHandle EffectID);\r\n\r\n    extern BoolVar Enable;\r\n    extern BoolVar PauseSim;\r\n    extern BoolVar EnableTiledRendering;\r\n    extern bool Reproducible; //If you want to repro set to true. When true, effect uses the same set of random numbers each run\r\n    extern UINT ReproFrame;\r\n} // namespace ParticleEffects\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleEffectProperties.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Julia Careaga\r\n//             James Stanard\r\n//\r\n\r\n#pragma once\r\n#include \"ParticleShaderStructs.h\"\r\n#include \"Color.h\"\r\n\r\nstruct ParticleEffectProperties\r\n{\t\r\n    ParticleEffectProperties() \r\n    { \r\n        ZeroMemory(this, sizeof(*this));\r\n        MinStartColor = Color(0.8f, 0.8f, 1.0f);\r\n        MaxStartColor = Color(0.9f, 0.9f, 1.0f);\r\n        MinEndColor = Color(1.0f, 1.0f, 1.0f);\r\n        MaxEndColor = Color(1.0f, 1.0f, 1.0f);\r\n        EmitProperties = *CreateEmissionProperties(); //Properties passed to the shader\r\n        EmitRate = 200;\r\n        LifeMinMax = XMFLOAT2(1.0f, 2.0f);\r\n        MassMinMax = XMFLOAT2(0.5f, 1.0f);\r\n        Size = Vector4(0.07f, 0.7f, 0.8f, 0.8f); // (Start size min, Start size max, End size min, End size max) \t\t\r\n        Spread = XMFLOAT3(0.5f, 1.5f, 0.1f);\r\n        TexturePath = L\"Resources/Textures/sparkTex.dds\"; \t\r\n        TotalActiveLifetime = 20.0;\r\n        Velocity = Vector4(0.5, 3.0, -0.5, 3.0 ); // (X velocity min, X velocity max, Y velocity min, Y velocity max)\r\n    };\r\n\r\n    \r\n    Color MinStartColor;\r\n    Color MaxStartColor;\r\n    Color MinEndColor;\r\n    Color MaxEndColor;\r\n    EmissionProperties  EmitProperties; \r\n    float EmitRate;\r\n    XMFLOAT2 LifeMinMax;   \r\n    XMFLOAT2 MassMinMax;\r\n    Vector4 Size;\r\n    XMFLOAT3 Spread;\r\n    std::wstring TexturePath;\r\n    float TotalActiveLifetime;\t \r\n    Vector4 Velocity;\r\n\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleEmissionProperties.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n\r\n#pragma once\r\n#include \"pch.h\"\r\n#include \"ParticleShaderStructs.h\"\r\n\r\nEmissionProperties* CreateEmissionProperties()\r\n{\r\n    EmissionProperties* emitProps = new EmissionProperties;\t\r\n    ZeroMemory(emitProps, sizeof(*emitProps));\r\n    emitProps->EmitPosW = emitProps->LastEmitPosW = XMFLOAT3(0.0,0.0,0.0);\r\n    emitProps->EmitDirW = XMFLOAT3(0.0,0.0,1.0); \r\n    emitProps->EmitRightW = XMFLOAT3(1.0,0.0,0.0); \r\n    emitProps->EmitUpW = XMFLOAT3(0.0,1.0,0.0);\r\n    emitProps->Restitution = 0.6;\r\n    emitProps->FloorHeight = -0.7;\r\n    emitProps->EmitSpeed = 1.0;\r\n    emitProps->Gravity = XMFLOAT3(0, -5, 0);\r\n    emitProps->MaxParticles = 500;\r\n    return emitProps;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/ParticleShaderStructs.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Julia Careaga\r\n//             James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\nusing namespace Math;\r\n//Emission Properties and other particle structs\r\n\r\n__declspec(align(16)) struct EmissionProperties\r\n{\r\n    XMFLOAT3 LastEmitPosW;\r\n    float EmitSpeed;\r\n    XMFLOAT3 EmitPosW;\r\n    float FloorHeight;\r\n    XMFLOAT3 EmitDirW;\r\n    float Restitution;\r\n    XMFLOAT3 EmitRightW;\r\n    float EmitterVelocitySensitivity;\r\n    XMFLOAT3 EmitUpW;\r\n    UINT MaxParticles;\r\n    XMFLOAT3 Gravity;\r\n    UINT TextureID;\r\n    XMFLOAT3 EmissiveColor;\r\n    float pad1;\t\r\n    XMUINT4 RandIndex[64];\r\n};\r\n\r\nEmissionProperties* CreateEmissionProperties();\r\n\r\nstruct ParticleSpawnData\r\n{\r\n    float AgeRate;\r\n    float RotationSpeed;\r\n    float StartSize;\r\n    float EndSize;\r\n    XMFLOAT3 Velocity; float Mass;\r\n    XMFLOAT3 SpreadOffset; float Random;\r\n    Color StartColor;\r\n    Color EndColor;\r\n};\r\n\r\n\r\nstruct ParticleMotion\r\n{\r\n    XMFLOAT3 Position;\r\n    float Mass;\t\r\n    XMFLOAT3 Velocity;\r\n    float Age;\r\n    float Rotation;\r\n    UINT ResetDataIndex;\r\n};\r\n\r\nstruct ParticleVertex\r\n{\r\n    XMFLOAT3 Position;\r\n    XMFLOAT4 Color;\r\n    float Size;\r\n    UINT TextureID;\r\n};\r\n\r\nstruct ParticleScreenData\r\n{\r\n    float Corner[2];\r\n    float RcpSize[2];\r\n    float Color[4];\r\n    float Depth;\r\n    float TextureIndex;\r\n    float TextureLevel;\r\n    uint32_t Bounds;\r\n};\r\n\r\n\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/PipelineState.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n\r\n#include \"pch.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"PipelineState.h\"\r\n#include \"RootSignature.h\"\r\n#include \"Hash.h\"\r\n#include <map>\r\n#include <thread>\r\n#include <mutex>\r\n\r\nusing Math::IsAligned;\r\nusing namespace Graphics;\r\nusing Microsoft::WRL::ComPtr;\r\nusing namespace std;\r\n\r\nstatic map< size_t, ComPtr<ID3D12PipelineState> > s_GraphicsPSOHashMap;\r\nstatic map< size_t, ComPtr<ID3D12PipelineState> > s_ComputePSOHashMap;\r\n\r\nvoid PSO::DestroyAll(void)\r\n{\r\n    s_GraphicsPSOHashMap.clear();\r\n    s_ComputePSOHashMap.clear();\r\n}\r\n\r\n\r\nGraphicsPSO::GraphicsPSO()\r\n{\r\n    ZeroMemory(&m_PSODesc, sizeof(m_PSODesc));\r\n    m_PSODesc.NodeMask = 1;\r\n    m_PSODesc.SampleMask = 0xFFFFFFFFu;\r\n    m_PSODesc.SampleDesc.Count = 1;\r\n    m_PSODesc.InputLayout.NumElements = 0;\r\n}\r\n\r\nvoid GraphicsPSO::SetBlendState( const D3D12_BLEND_DESC& BlendDesc )\r\n{\r\n    m_PSODesc.BlendState = BlendDesc;\r\n}\r\n\r\nvoid GraphicsPSO::SetRasterizerState( const D3D12_RASTERIZER_DESC& RasterizerDesc )\r\n{\r\n    m_PSODesc.RasterizerState = RasterizerDesc;\r\n}\r\n\r\nvoid GraphicsPSO::SetDepthStencilState( const D3D12_DEPTH_STENCIL_DESC& DepthStencilDesc )\r\n{\r\n    m_PSODesc.DepthStencilState = DepthStencilDesc;\r\n}\r\n\r\nvoid GraphicsPSO::SetSampleMask( UINT SampleMask )\r\n{\r\n    m_PSODesc.SampleMask = SampleMask;\r\n}\r\n\r\nvoid GraphicsPSO::SetPrimitiveTopologyType( D3D12_PRIMITIVE_TOPOLOGY_TYPE TopologyType )\r\n{\r\n    ASSERT(TopologyType != D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED, \"Can't draw with undefined topology\");\r\n    m_PSODesc.PrimitiveTopologyType = TopologyType;\r\n}\r\n\r\nvoid GraphicsPSO::SetPrimitiveRestart( D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBProps )\r\n{\r\n    m_PSODesc.IBStripCutValue = IBProps;\r\n}\r\n\r\nvoid GraphicsPSO::SetRenderTargetFormat( DXGI_FORMAT RTVFormat, DXGI_FORMAT DSVFormat, UINT MsaaCount, UINT MsaaQuality )\r\n{\r\n    SetRenderTargetFormats(1, &RTVFormat, DSVFormat, MsaaCount, MsaaQuality );\r\n}\r\n\r\nvoid GraphicsPSO::SetRenderTargetFormats( UINT NumRTVs, const DXGI_FORMAT* RTVFormats, DXGI_FORMAT DSVFormat, UINT MsaaCount, UINT MsaaQuality )\r\n{\r\n    ASSERT(NumRTVs == 0 || RTVFormats != nullptr, \"Null format array conflicts with non-zero length\");\r\n    for (UINT i = 0; i < NumRTVs; ++i)\r\n        m_PSODesc.RTVFormats[i] = RTVFormats[i];\r\n    for (UINT i = NumRTVs; i < m_PSODesc.NumRenderTargets; ++i)\r\n        m_PSODesc.RTVFormats[i] = DXGI_FORMAT_UNKNOWN;\r\n    m_PSODesc.NumRenderTargets = NumRTVs;\r\n    m_PSODesc.DSVFormat = DSVFormat;\r\n    m_PSODesc.SampleDesc.Count = MsaaCount;\r\n    m_PSODesc.SampleDesc.Quality = MsaaQuality;\r\n}\r\n\r\nvoid GraphicsPSO::SetInputLayout( UINT NumElements, const D3D12_INPUT_ELEMENT_DESC* pInputElementDescs )\r\n{\r\n    m_PSODesc.InputLayout.NumElements = NumElements;\r\n\r\n    if (NumElements > 0)\r\n    {\r\n        D3D12_INPUT_ELEMENT_DESC* NewElements = (D3D12_INPUT_ELEMENT_DESC*)malloc(sizeof(D3D12_INPUT_ELEMENT_DESC) * NumElements);\r\n        memcpy(NewElements, pInputElementDescs, NumElements * sizeof(D3D12_INPUT_ELEMENT_DESC));\r\n        m_InputLayouts.reset((const D3D12_INPUT_ELEMENT_DESC*)NewElements);\r\n    }\r\n    else\r\n        m_InputLayouts = nullptr;\r\n}\r\n\r\nvoid GraphicsPSO::Finalize()\r\n{\r\n    // Make sure the root signature is finalized first\r\n    m_PSODesc.pRootSignature = m_RootSignature->GetSignature();\r\n    ASSERT(m_PSODesc.pRootSignature != nullptr);\r\n\r\n    m_PSODesc.InputLayout.pInputElementDescs = nullptr;\r\n    size_t HashCode = Utility::HashState(&m_PSODesc);\r\n    HashCode = Utility::HashState(m_InputLayouts.get(), m_PSODesc.InputLayout.NumElements, HashCode);\r\n    m_PSODesc.InputLayout.pInputElementDescs = m_InputLayouts.get();\r\n\r\n    ID3D12PipelineState** PSORef = nullptr;\r\n    bool firstCompile = false;\r\n    {\r\n        static mutex s_HashMapMutex;\r\n        lock_guard<mutex> CS(s_HashMapMutex);\r\n        auto iter = s_GraphicsPSOHashMap.find(HashCode);\r\n\r\n        // Reserve space so the next inquiry will find that someone got here first.\r\n        if (iter == s_GraphicsPSOHashMap.end())\r\n        {\r\n            firstCompile = true;\r\n            PSORef = s_GraphicsPSOHashMap[HashCode].GetAddressOf();\r\n        }\r\n        else\r\n            PSORef = iter->second.GetAddressOf();\r\n    }\r\n\r\n    if (firstCompile)\r\n    {\r\n        ASSERT_SUCCEEDED( g_Device->CreateGraphicsPipelineState(&m_PSODesc, MY_IID_PPV_ARGS(&m_PSO)) );\r\n        s_GraphicsPSOHashMap[HashCode].Attach(m_PSO);\r\n    }\r\n    else\r\n    {\r\n        while (*PSORef == nullptr)\r\n            this_thread::yield();\r\n        m_PSO = *PSORef;\r\n    }\r\n}\r\n\r\nvoid ComputePSO::Finalize()\r\n{\r\n    // Make sure the root signature is finalized first\r\n    m_PSODesc.pRootSignature = m_RootSignature->GetSignature();\r\n    ASSERT(m_PSODesc.pRootSignature != nullptr);\r\n\r\n    size_t HashCode = Utility::HashState(&m_PSODesc);\r\n\r\n    ID3D12PipelineState** PSORef = nullptr;\r\n    bool firstCompile = false;\r\n    {\r\n        static mutex s_HashMapMutex;\r\n        lock_guard<mutex> CS(s_HashMapMutex);\r\n        auto iter = s_ComputePSOHashMap.find(HashCode);\r\n\r\n        // Reserve space so the next inquiry will find that someone got here first.\r\n        if (iter == s_ComputePSOHashMap.end())\r\n        {\r\n            firstCompile = true;\r\n            PSORef = s_ComputePSOHashMap[HashCode].GetAddressOf();\r\n        }\r\n        else\r\n            PSORef = iter->second.GetAddressOf();\r\n    }\r\n\r\n    if (firstCompile)\r\n    {\r\n        ASSERT_SUCCEEDED( g_Device->CreateComputePipelineState(&m_PSODesc, MY_IID_PPV_ARGS(&m_PSO)) );\r\n        s_ComputePSOHashMap[HashCode].Attach(m_PSO);\r\n    }\r\n    else\r\n    {\r\n        while (*PSORef == nullptr)\r\n            this_thread::yield();\r\n        m_PSO = *PSORef;\r\n    }\r\n}\r\n\r\nComputePSO::ComputePSO()\r\n{\r\n    ZeroMemory(&m_PSODesc, sizeof(m_PSODesc));\r\n    m_PSODesc.NodeMask = 1;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/PipelineState.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\nclass CommandContext;\r\nclass RootSignature;\r\nclass VertexShader;\r\nclass GeometryShader;\r\nclass HullShader;\r\nclass DomainShader;\r\nclass PixelShader;\r\nclass ComputeShader;\r\n\r\nclass PSO\r\n{\r\npublic:\r\n\r\n    PSO() : m_RootSignature(nullptr) {}\r\n\r\n    static void DestroyAll( void );\r\n\r\n    void SetRootSignature( const RootSignature& BindMappings )\r\n    {\r\n        m_RootSignature = &BindMappings;\r\n    }\r\n\r\n    const RootSignature&  GetRootSignature( void ) const\r\n    {\r\n        ASSERT(m_RootSignature != nullptr);\r\n        return *m_RootSignature;\r\n    }\r\n\r\n    ID3D12PipelineState* GetPipelineStateObject( void ) const { return m_PSO; }\r\n\r\nprotected:\r\n\r\n    const RootSignature* m_RootSignature;\r\n\r\n    ID3D12PipelineState* m_PSO;\r\n};\r\n\r\nclass GraphicsPSO : public PSO\r\n{\r\n    friend class CommandContext;\r\n\r\npublic:\r\n\r\n    // Start with empty state\r\n    GraphicsPSO();\r\n\r\n    void SetBlendState( const D3D12_BLEND_DESC& BlendDesc );\r\n    void SetRasterizerState( const D3D12_RASTERIZER_DESC& RasterizerDesc );\r\n    void SetDepthStencilState( const D3D12_DEPTH_STENCIL_DESC& DepthStencilDesc );\r\n    void SetSampleMask( UINT SampleMask );\r\n    void SetPrimitiveTopologyType( D3D12_PRIMITIVE_TOPOLOGY_TYPE TopologyType );\r\n    void SetRenderTargetFormat( DXGI_FORMAT RTVFormat, DXGI_FORMAT DSVFormat, UINT MsaaCount = 1, UINT MsaaQuality = 0 );\r\n    void SetRenderTargetFormats( UINT NumRTVs, const DXGI_FORMAT* RTVFormats, DXGI_FORMAT DSVFormat, UINT MsaaCount = 1, UINT MsaaQuality = 0 );\r\n    void SetInputLayout( UINT NumElements, const D3D12_INPUT_ELEMENT_DESC* pInputElementDescs );\r\n    void SetPrimitiveRestart( D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBProps );\r\n\r\n    // These const_casts shouldn't be necessary, but we need to fix the API to accept \"const void* pShaderBytecode\"\r\n    void SetVertexShader( const void* Binary, size_t Size ) { m_PSODesc.VS = CD3DX12_SHADER_BYTECODE(const_cast<void*>(Binary), Size); }\r\n    void SetPixelShader( const void* Binary, size_t Size ) { m_PSODesc.PS = CD3DX12_SHADER_BYTECODE(const_cast<void*>(Binary), Size); }\r\n    void SetGeometryShader( const void* Binary, size_t Size ) { m_PSODesc.GS = CD3DX12_SHADER_BYTECODE(const_cast<void*>(Binary), Size); }\r\n    void SetHullShader( const void* Binary, size_t Size ) { m_PSODesc.HS = CD3DX12_SHADER_BYTECODE(const_cast<void*>(Binary), Size); }\r\n    void SetDomainShader( const void* Binary, size_t Size ) { m_PSODesc.DS = CD3DX12_SHADER_BYTECODE(const_cast<void*>(Binary), Size); }\r\n\r\n    void SetVertexShader( const D3D12_SHADER_BYTECODE& Binary ) { m_PSODesc.VS = Binary; }\r\n    void SetPixelShader( const D3D12_SHADER_BYTECODE& Binary ) { m_PSODesc.PS = Binary; }\r\n    void SetGeometryShader( const D3D12_SHADER_BYTECODE& Binary ) { m_PSODesc.GS = Binary; }\r\n    void SetHullShader( const D3D12_SHADER_BYTECODE& Binary ) { m_PSODesc.HS = Binary; }\r\n    void SetDomainShader( const D3D12_SHADER_BYTECODE& Binary ) { m_PSODesc.DS = Binary; }\r\n\r\n\tvoid SetMsaaCount(UINT SampleCount) { m_PSODesc.SampleDesc.Count = SampleCount; }\r\n\r\n    // Perform validation and compute a hash value for fast state block comparisons\r\n    void Finalize();\r\n\r\nprivate:\r\n\r\n    D3D12_GRAPHICS_PIPELINE_STATE_DESC m_PSODesc;\r\n    std::shared_ptr<const D3D12_INPUT_ELEMENT_DESC> m_InputLayouts;\r\n};\r\n\r\n\r\nclass ComputePSO : public PSO\r\n{\r\n    friend class CommandContext;\r\n\r\npublic:\r\n    ComputePSO();\r\n\r\n    void SetComputeShader( const void* Binary, size_t Size ) { m_PSODesc.CS = CD3DX12_SHADER_BYTECODE(const_cast<void*>(Binary), Size); }\r\n    void SetComputeShader( const D3D12_SHADER_BYTECODE& Binary ) { m_PSODesc.CS = Binary; }\r\n\r\n    void Finalize();\r\n\r\nprivate:\r\n\r\n    D3D12_COMPUTE_PIPELINE_STATE_DESC m_PSODesc;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/PixelBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"PixelBuffer.h\"\r\n#include \"EsramAllocator.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"BufferManager.h\"\r\n#include \"CommandContext.h\"\r\n#include \"ReadbackBuffer.h\"\r\n#include <fstream>\r\n\r\n#include <DirectXPackedVector.h>\r\n\r\nusing namespace Graphics;\r\nusing namespace PackedVector;\r\n\r\nDXGI_FORMAT PixelBuffer::GetBaseFormat( DXGI_FORMAT defaultFormat )\r\n{\r\n    switch (defaultFormat)\r\n    {\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:\r\n        return DXGI_FORMAT_R8G8B8A8_TYPELESS;\r\n\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:\r\n        return DXGI_FORMAT_B8G8R8A8_TYPELESS;\r\n\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:\r\n        return DXGI_FORMAT_B8G8R8X8_TYPELESS;\r\n\r\n    // 32-bit Z w/ Stencil\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n        return DXGI_FORMAT_R32G8X24_TYPELESS;\r\n\r\n    // No Stencil\r\n    case DXGI_FORMAT_R32_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT:\r\n    case DXGI_FORMAT_R32_FLOAT:\r\n        return DXGI_FORMAT_R32_TYPELESS;\r\n\r\n    // 24-bit Z\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n        return DXGI_FORMAT_R24G8_TYPELESS;\r\n\r\n    // 16-bit Z w/o Stencil\r\n    case DXGI_FORMAT_R16_TYPELESS:\r\n    case DXGI_FORMAT_D16_UNORM:\r\n    case DXGI_FORMAT_R16_UNORM:\r\n        return DXGI_FORMAT_R16_TYPELESS;\r\n\r\n    default:\r\n        return defaultFormat;\r\n    }\r\n}\r\n\r\nDXGI_FORMAT PixelBuffer::GetUAVFormat( DXGI_FORMAT defaultFormat )\r\n{\r\n    switch (defaultFormat)\r\n    {\r\n    case DXGI_FORMAT_R8G8B8A8_TYPELESS:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:\r\n        return DXGI_FORMAT_R8G8B8A8_UNORM;\r\n\r\n    case DXGI_FORMAT_B8G8R8A8_TYPELESS:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:\r\n        return DXGI_FORMAT_B8G8R8A8_UNORM;\r\n\r\n    case DXGI_FORMAT_B8G8R8X8_TYPELESS:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:\r\n        return DXGI_FORMAT_B8G8R8X8_UNORM;\r\n\r\n    case DXGI_FORMAT_R32_TYPELESS:\r\n    case DXGI_FORMAT_R32_FLOAT:\r\n        return DXGI_FORMAT_R32_FLOAT;\r\n\r\n#ifdef _DEBUG\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n    case DXGI_FORMAT_D32_FLOAT:\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n    case DXGI_FORMAT_D16_UNORM:\r\n\r\n    ASSERT(false, \"Requested a UAV format for a depth stencil format.\");\r\n#endif\r\n\r\n    default:\r\n        return defaultFormat;\r\n    }\r\n}\r\n\r\nDXGI_FORMAT PixelBuffer::GetDSVFormat( DXGI_FORMAT defaultFormat )\r\n{\r\n    switch (defaultFormat)\r\n    {\r\n    // 32-bit Z w/ Stencil\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n        return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;\r\n\r\n    // No Stencil\r\n    case DXGI_FORMAT_R32_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT:\r\n    case DXGI_FORMAT_R32_FLOAT:\r\n        return DXGI_FORMAT_D32_FLOAT;\r\n\r\n    // 24-bit Z\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n        return DXGI_FORMAT_D24_UNORM_S8_UINT;\r\n\r\n    // 16-bit Z w/o Stencil\r\n    case DXGI_FORMAT_R16_TYPELESS:\r\n    case DXGI_FORMAT_D16_UNORM:\r\n    case DXGI_FORMAT_R16_UNORM:\r\n        return DXGI_FORMAT_D16_UNORM;\r\n\r\n    default:\r\n        return defaultFormat;\r\n    }\r\n}\r\n\r\nDXGI_FORMAT PixelBuffer::GetDepthFormat( DXGI_FORMAT defaultFormat )\r\n{\r\n    switch (defaultFormat)\r\n    {\r\n    // 32-bit Z w/ Stencil\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n        return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;\r\n\r\n    // No Stencil\r\n    case DXGI_FORMAT_R32_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT:\r\n    case DXGI_FORMAT_R32_FLOAT:\r\n        return DXGI_FORMAT_R32_FLOAT;\r\n\r\n    // 24-bit Z\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n        return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;\r\n\r\n    // 16-bit Z w/o Stencil\r\n    case DXGI_FORMAT_R16_TYPELESS:\r\n    case DXGI_FORMAT_D16_UNORM:\r\n    case DXGI_FORMAT_R16_UNORM:\r\n        return DXGI_FORMAT_R16_UNORM;\r\n\r\n    default:\r\n        return DXGI_FORMAT_UNKNOWN;\r\n    }\r\n}\r\n\r\nDXGI_FORMAT PixelBuffer::GetStencilFormat( DXGI_FORMAT defaultFormat )\r\n{\r\n    switch (defaultFormat)\r\n    {\r\n    // 32-bit Z w/ Stencil\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n        return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;\r\n\r\n    // 24-bit Z\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n        return DXGI_FORMAT_X24_TYPELESS_G8_UINT;\r\n\r\n    default:\r\n        return DXGI_FORMAT_UNKNOWN;\r\n    }\r\n}\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Return the BPP for a particular format\r\n//--------------------------------------------------------------------------------------\r\nsize_t PixelBuffer::BytesPerPixel( DXGI_FORMAT Format )\r\n{\r\n    switch( Format )\r\n    {\r\n    case DXGI_FORMAT_R32G32B32A32_TYPELESS:\r\n    case DXGI_FORMAT_R32G32B32A32_FLOAT:\r\n    case DXGI_FORMAT_R32G32B32A32_UINT:\r\n    case DXGI_FORMAT_R32G32B32A32_SINT:\r\n        return 16;\r\n\r\n    case DXGI_FORMAT_R32G32B32_TYPELESS:\r\n    case DXGI_FORMAT_R32G32B32_FLOAT:\r\n    case DXGI_FORMAT_R32G32B32_UINT:\r\n    case DXGI_FORMAT_R32G32B32_SINT:\r\n        return 12;\r\n\r\n    case DXGI_FORMAT_R16G16B16A16_TYPELESS:\r\n    case DXGI_FORMAT_R16G16B16A16_FLOAT:\r\n    case DXGI_FORMAT_R16G16B16A16_UNORM:\r\n    case DXGI_FORMAT_R16G16B16A16_UINT:\r\n    case DXGI_FORMAT_R16G16B16A16_SNORM:\r\n    case DXGI_FORMAT_R16G16B16A16_SINT:\r\n    case DXGI_FORMAT_R32G32_TYPELESS:\r\n    case DXGI_FORMAT_R32G32_FLOAT:\r\n    case DXGI_FORMAT_R32G32_UINT:\r\n    case DXGI_FORMAT_R32G32_SINT:\r\n    case DXGI_FORMAT_R32G8X24_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:\r\n    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:\r\n    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:\r\n        return 8;\r\n\r\n    case DXGI_FORMAT_R10G10B10A2_TYPELESS:\r\n    case DXGI_FORMAT_R10G10B10A2_UNORM:\r\n    case DXGI_FORMAT_R10G10B10A2_UINT:\r\n    case DXGI_FORMAT_R11G11B10_FLOAT:\r\n    case DXGI_FORMAT_R8G8B8A8_TYPELESS:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM:\r\n    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:\r\n    case DXGI_FORMAT_R8G8B8A8_UINT:\r\n    case DXGI_FORMAT_R8G8B8A8_SNORM:\r\n    case DXGI_FORMAT_R8G8B8A8_SINT:\r\n    case DXGI_FORMAT_R16G16_TYPELESS:\r\n    case DXGI_FORMAT_R16G16_FLOAT:\r\n    case DXGI_FORMAT_R16G16_UNORM:\r\n    case DXGI_FORMAT_R16G16_UINT:\r\n    case DXGI_FORMAT_R16G16_SNORM:\r\n    case DXGI_FORMAT_R16G16_SINT:\r\n    case DXGI_FORMAT_R32_TYPELESS:\r\n    case DXGI_FORMAT_D32_FLOAT:\r\n    case DXGI_FORMAT_R32_FLOAT:\r\n    case DXGI_FORMAT_R32_UINT:\r\n    case DXGI_FORMAT_R32_SINT:\r\n    case DXGI_FORMAT_R24G8_TYPELESS:\r\n    case DXGI_FORMAT_D24_UNORM_S8_UINT:\r\n    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:\r\n    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:\r\n    case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:\r\n    case DXGI_FORMAT_R8G8_B8G8_UNORM:\r\n    case DXGI_FORMAT_G8R8_G8B8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM:\r\n    case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:\r\n    case DXGI_FORMAT_B8G8R8A8_TYPELESS:\r\n    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:\r\n    case DXGI_FORMAT_B8G8R8X8_TYPELESS:\r\n    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:\r\n        return 4;\r\n\r\n    case DXGI_FORMAT_R8G8_TYPELESS:\r\n    case DXGI_FORMAT_R8G8_UNORM:\r\n    case DXGI_FORMAT_R8G8_UINT:\r\n    case DXGI_FORMAT_R8G8_SNORM:\r\n    case DXGI_FORMAT_R8G8_SINT:\r\n    case DXGI_FORMAT_R16_TYPELESS:\r\n    case DXGI_FORMAT_R16_FLOAT:\r\n    case DXGI_FORMAT_D16_UNORM:\r\n    case DXGI_FORMAT_R16_UNORM:\r\n    case DXGI_FORMAT_R16_UINT:\r\n    case DXGI_FORMAT_R16_SNORM:\r\n    case DXGI_FORMAT_R16_SINT:\r\n    case DXGI_FORMAT_B5G6R5_UNORM:\r\n    case DXGI_FORMAT_B5G5R5A1_UNORM:\r\n    case DXGI_FORMAT_A8P8:\r\n    case DXGI_FORMAT_B4G4R4A4_UNORM:\r\n        return 2;\r\n\r\n    case DXGI_FORMAT_R8_TYPELESS:\r\n    case DXGI_FORMAT_R8_UNORM:\r\n    case DXGI_FORMAT_R8_UINT:\r\n    case DXGI_FORMAT_R8_SNORM:\r\n    case DXGI_FORMAT_R8_SINT:\r\n    case DXGI_FORMAT_A8_UNORM:\r\n    case DXGI_FORMAT_P8:\r\n        return 1;\r\n\r\n    default:\r\n        return 0;\r\n    }\r\n}\r\nvoid PixelBuffer::AssociateWithResource( DX12_DEVICE* Device, const std::wstring& Name, ID3D12Resource* Resource, D3D12_RESOURCE_STATES CurrentState )\r\n{\r\n    (Device); // Unused until we support multiple adapters\r\n\r\n    ASSERT(Resource != nullptr);\r\n    D3D12_RESOURCE_DESC ResourceDesc = Resource->GetDesc();\r\n\r\n    m_pResource.Attach(Resource);\r\n    m_UsageState = CurrentState;\r\n\r\n    m_Width = (uint32_t)ResourceDesc.Width;\t\t// We don't care about large virtual textures yet\r\n    m_Height = ResourceDesc.Height;\r\n    m_ArraySize = ResourceDesc.DepthOrArraySize;\r\n    m_Format = ResourceDesc.Format;\r\n\r\n#ifndef RELEASE\r\n    m_Name = Name;\r\n    m_pResource->SetName(Name.c_str());\r\n#else\r\n    (Name);\r\n#endif\r\n}\r\n\r\nD3D12_RESOURCE_DESC PixelBuffer::DescribeTex2D( uint32_t Width, uint32_t Height, uint32_t DepthOrArraySize,\r\n    uint32_t NumMips, DXGI_FORMAT Format, UINT Flags)\r\n{\r\n    m_Width = Width;\r\n    m_Height = Height;\r\n    m_ArraySize = DepthOrArraySize;\r\n    m_Format = Format;\r\n    \r\n    return PixelBuffer::CreateResourceDesc( Width, Height, DepthOrArraySize, NumMips, Format, Flags );\r\n}\r\n\r\nvoid PixelBuffer::CreateTextureResource( DX12_DEVICE* Device, const std::wstring& Name,\r\n    const D3D12_RESOURCE_DESC& ResourceDesc, D3D12_CLEAR_VALUE ClearValue, D3D12_GPU_VIRTUAL_ADDRESS /*VidMemPtr*/ )\r\n{\r\n    GpuResource::Destroy();\r\n\r\n    CD3DX12_HEAP_PROPERTIES HeapProps(D3D12_HEAP_TYPE_DEFAULT);\r\n    ASSERT_SUCCEEDED( Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE,\r\n        &ResourceDesc, D3D12_RESOURCE_STATE_COMMON, &ClearValue, MY_IID_PPV_ARGS(&m_pResource) ));\r\n\r\n    m_UsageState = D3D12_RESOURCE_STATE_COMMON;\r\n    m_GpuVirtualAddress = D3D12_GPU_VIRTUAL_ADDRESS_NULL;\r\n\r\n#ifndef RELEASE\r\n    m_Name = Name;\r\n    m_pResource->SetName(Name.c_str());\r\n#else\r\n    (Name);\r\n#endif\r\n}\r\n\r\nvoid PixelBuffer::CreateTextureResource( DX12_DEVICE* Device, const std::wstring& Name,\r\n    const D3D12_RESOURCE_DESC& ResourceDesc, D3D12_CLEAR_VALUE ClearValue, EsramAllocator& /*Allocator*/ )\r\n{\r\n    CreateTextureResource(Device, Name, ResourceDesc, ClearValue);\r\n}\r\n\r\nvoid PixelBuffer::CreatePlacedResource( DX12_DEVICE* Device, const std::wstring& Name,\r\n    const D3D12_RESOURCE_DESC& ResourceDesc, D3D12_CLEAR_VALUE ClearValue, ID3D12Heap *Heap, UINT64 HeapOffset )\r\n{\r\n    GpuResource::Destroy();\r\n\r\n    RecreatePlacedResource( Device, ResourceDesc, ClearValue, Heap, HeapOffset );\r\n\r\n    m_UsageState = D3D12_RESOURCE_STATE_COMMON;\r\n    m_GpuVirtualAddress = D3D12_GPU_VIRTUAL_ADDRESS_NULL;\r\n\r\n#ifndef RELEASE\r\n    m_Name = Name;\r\n    m_pResource->SetName(Name.c_str());\r\n#else\r\n    (Name);\r\n#endif\r\n}\r\n\r\nvoid PixelBuffer::RecreatePlacedResource( DX12_DEVICE* Device, const D3D12_RESOURCE_DESC& ResourceDesc, \r\n        D3D12_CLEAR_VALUE ClearValue, ID3D12Heap *Heap, UINT64 HeapOffset )\r\n{\r\n    ASSERT_SUCCEEDED( Device->CreatePlacedResource( Heap, HeapOffset,\r\n        &ResourceDesc, m_UsageState, &ClearValue, MY_IID_PPV_ARGS(&m_pResource) ));\r\n\r\n#ifndef RELEASE\r\n    m_pResource->SetName(m_Name.c_str());\r\n#endif\r\n}\r\n\r\nvoid PixelBuffer::ExportToFile( const std::wstring& FilePath )\r\n{\r\n    // Create the buffer.  We will release it after all is done.\r\n    ReadbackBuffer TempBuffer;\r\n    TempBuffer.Create(L\"Temporary Readback Buffer\", m_Width * m_Height, (uint32_t)BytesPerPixel(m_Format));\r\n\r\n    CommandContext::ReadbackTexture2D(TempBuffer, *this);\r\n\r\n    // Retrieve a CPU-visible pointer to the buffer memory.  Map the whole range for reading.\r\n    void* Memory = TempBuffer.Map();\r\n\r\n    // Open the file and write the header followed by the texel data.\r\n    std::ofstream OutFile(FilePath, std::ios::out | std::ios::binary);\r\n    OutFile.write((const char*)&m_Format, 4);\r\n    OutFile.write((const char*)&m_Width, 4); // Pitch\r\n    OutFile.write((const char*)&m_Width, 4);\r\n    OutFile.write((const char*)&m_Height, 4);\r\n    OutFile.write((const char*)Memory, TempBuffer.GetBufferSize());\r\n    OutFile.close();\r\n\r\n    // No values were written to the buffer, so use a null range when unmapping.\r\n    TempBuffer.Unmap();\r\n}\r\n\r\nfloat applySRGB(float x) {\r\n\treturn x < 0.0031308f ? 12.92f * x : 1.055f * pow(x, 1.0f / 2.4f) - 0.055f;\r\n}\r\n\r\nvoid PixelBuffer::ExportToTGA(const std::wstring& FilePath) {\r\n\r\n\t// check if pixel format is supported\r\n\tif (m_Format != DXGI_FORMAT_R11G11B10_FLOAT) {\r\n\t\tUtility::Print(\"Error: ExportToTGA() unsupported pixel format.\");\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Unlike ExportToFile we need to interpret the RGB channels and store them in the simple TGA format.\r\n\tReadbackBuffer TempBuffer;\r\n\tTempBuffer.Create(L\"Temporary Readback Buffer\", m_Width * m_Height, (uint32_t)BytesPerPixel(m_Format));\r\n\r\n\tCommandContext::ReadbackTexture2D(TempBuffer, *this);\r\n\r\n\t// Retrieve a CPU-visible pointer to the buffer memory.  Map the whole range for reading.\r\n\tvoid* Memory = TempBuffer.Map();\r\n\r\n\t// Open the file and write the header followed by the texel data.\r\n\tstd::ofstream OutFile(FilePath, std::ios::out | std::ios::binary);\r\n\r\n\t/////////////////////////////////////////////////////\r\n\t// header\r\n\r\n\tchar header[18];\r\n\tZeroMemory(header, 18);\r\n\theader[2] = 2; // uncompressed RGB\r\n\theader[12] = (m_Width & 0x00FF);\r\n\theader[13] = (m_Width & 0xFF00) / 256;\r\n\theader[14] = (m_Height & 0x00FF);\r\n\theader[15] = (m_Height & 0xFF00) / 256;\r\n\theader[16] = 24; // bpp\r\n\t\r\n\tOutFile.write((const char*)header, 18);\r\n\r\n\tstd::vector<uint8_t> body;\r\n\tbody.resize(m_Width * m_Height * 3);\r\n\r\n\t// We also just hardcode a possible LDR conversion, for the minimal effort to get acceptable images\r\n\r\n\r\n\t// pixel data in BGR format, row-major order\r\n\tXMFLOAT3PK* pixelData = (XMFLOAT3PK*)Memory;\r\n\tfor (uint32_t y = 0; y < m_Height; y++) {\r\n\t\tfor (uint32_t x = 0; x < m_Width; x++) {\r\n\r\n\t\t\t// extract channels from packed bits\r\n\t\t\tXMVECTOR unpackedData = XMLoadFloat3PK(pixelData);\r\n\t\t\tpixelData++;\r\n\r\n\t\t\tuint32_t pixLinIdx = 3 * ((m_Height - y - 1) * m_Width + x);\r\n\r\n\t\t\tbody[pixLinIdx]= (uint8_t)(std::min<float>(applySRGB(unpackedData.m128_f32[2]) * 255.0f, 255.0f));\r\n\t\t\tbody[pixLinIdx + 1] = (uint8_t)(std::min<float>(applySRGB(unpackedData.m128_f32[1]) * 255.0f, 255.0f));\r\n\t\t\tbody[pixLinIdx + 2] = (uint8_t)(std::min<float>(applySRGB(unpackedData.m128_f32[0]) * 255.0f, 255.0f));\r\n\t\t}\r\n\t}\r\n\r\n\tOutFile.write((const char*) &body[0], body.size());\r\n\r\n\tOutFile.close();\r\n\r\n\t// No values were written to the buffer, so use a null range when unmapping.\r\n\tTempBuffer.Unmap();\r\n}\r\n\r\nD3D12_RESOURCE_DESC PixelBuffer::CreateResourceDesc( uint32_t Width, uint32_t Height, uint32_t DepthOrArraySize,\r\n    uint32_t NumMips, DXGI_FORMAT Format, UINT Flags)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = {};\r\n    Desc.Alignment = 0;\r\n    Desc.DepthOrArraySize = (UINT16)DepthOrArraySize;\r\n    Desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\r\n    Desc.Flags = (D3D12_RESOURCE_FLAGS)Flags;\r\n    Desc.Format = GetBaseFormat(Format);\r\n    Desc.Height = (UINT)Height;\r\n    Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;\r\n    Desc.MipLevels = (UINT16)NumMips;\r\n    Desc.SampleDesc.Count = 1;\r\n    Desc.SampleDesc.Quality = 0;\r\n    Desc.Width = (UINT64)Width;\r\n    \r\n    return Desc;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/PixelBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"GpuResource.h\"\r\n\r\nclass EsramAllocator;\r\nclass ReadbackBuffer;\r\n\r\nclass PixelBuffer : public GpuResource\r\n{\r\npublic:\r\n    PixelBuffer() : m_Width(0), m_Height(0), m_ArraySize(0), m_Format(DXGI_FORMAT_UNKNOWN), m_BankRotation(0) {}\r\n\r\n    uint32_t GetWidth(void) const { return m_Width; }\r\n    uint32_t GetHeight(void) const { return m_Height; }\r\n    uint32_t GetDepth(void) const { return m_ArraySize; }\r\n    const DXGI_FORMAT& GetFormat(void) const { return m_Format; }\r\n\r\n    // Has no effect on Windows\r\n    void SetBankRotation( uint32_t RotationAmount ) { m_BankRotation = RotationAmount; }\r\n\r\n    // Write the raw pixel buffer contents to a file\r\n    // Note that data is preceded by a 16-byte header:  { DXGI_FORMAT, Pitch (in pixels), Width (in pixels), Height }\r\n    void ExportToFile( const std::wstring& FilePath );\r\n\r\n\t// Special-purpose image export method to RGB TGA file.\r\n\t// Currtently the type of pixel formats is extremely limited based on application demand\r\n\tvoid ExportToTGA(const std::wstring& FilePath);\r\n\r\nprotected:\r\n\r\n    D3D12_RESOURCE_DESC DescribeTex2D(uint32_t Width, uint32_t Height, uint32_t DepthOrArraySize, uint32_t NumMips, DXGI_FORMAT Format, UINT Flags);\r\n\r\n    void AssociateWithResource( DX12_DEVICE* Device, const std::wstring& Name, ID3D12Resource* Resource, D3D12_RESOURCE_STATES CurrentState );\r\n\r\n    void CreateTextureResource( DX12_DEVICE* Device, const std::wstring& Name, const D3D12_RESOURCE_DESC& ResourceDesc,\r\n        D3D12_CLEAR_VALUE ClearValue, D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN );\r\n\r\n    void CreateTextureResource( DX12_DEVICE* Device, const std::wstring& Name, const D3D12_RESOURCE_DESC& ResourceDesc,\r\n        D3D12_CLEAR_VALUE ClearValue, EsramAllocator& Allocator );\r\n\r\n    void CreatePlacedResource( DX12_DEVICE* Device, const std::wstring& Name, const D3D12_RESOURCE_DESC& ResourceDesc, \r\n        D3D12_CLEAR_VALUE ClearValue, ID3D12Heap *Heap, UINT64 HeapOffset );\r\n\r\n    void RecreatePlacedResource( DX12_DEVICE* Device, const D3D12_RESOURCE_DESC& ResourceDesc, \r\n        D3D12_CLEAR_VALUE ClearValue, ID3D12Heap *Heap, UINT64 HeapOffset );\r\n\r\n    static DXGI_FORMAT GetBaseFormat( DXGI_FORMAT Format );\r\n    static DXGI_FORMAT GetUAVFormat( DXGI_FORMAT Format );\r\n    static DXGI_FORMAT GetDSVFormat( DXGI_FORMAT Format );\r\n    static DXGI_FORMAT GetDepthFormat( DXGI_FORMAT Format );\r\n    static DXGI_FORMAT GetStencilFormat( DXGI_FORMAT Format );\r\n    static size_t BytesPerPixel( DXGI_FORMAT Format );\r\n\r\n    uint32_t m_Width;\r\n    uint32_t m_Height;\r\n    uint32_t m_ArraySize;\r\n    DXGI_FORMAT m_Format;\r\n    uint32_t m_BankRotation;\r\n\r\n#ifndef RELEASE\r\n    std::wstring m_Name;\r\n#endif\r\n\r\npublic:\r\n    static D3D12_RESOURCE_DESC CreateResourceDesc(uint32_t Width, uint32_t Height, uint32_t DepthOrArraySize, uint32_t NumMips, DXGI_FORMAT Format, UINT Flags);\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/PostEffects.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n\r\n#include \"PostEffects.h\"\r\n#include \"GameCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"RootSignature.h\"\r\n#include \"PipelineState.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"BufferManager.h\"\r\n#include \"MotionBlur.h\"\r\n#include \"DepthOfField.h\"\r\n#include \"FXAA.h\"\r\n\r\n#include \"CompiledShaders/ToneMapCS.h\"\r\n#include \"CompiledShaders/ToneMap2CS.h\"\r\n#include \"CompiledShaders/ToneMapHDRCS.h\"\r\n#include \"CompiledShaders/ToneMapHDR2CS.h\"\r\n#include \"CompiledShaders/ApplyBloomCS.h\"\r\n#include \"CompiledShaders/ApplyBloom2CS.h\"\r\n#include \"CompiledShaders/DebugLuminanceHdrCS.h\"\r\n#include \"CompiledShaders/DebugLuminanceHdr2CS.h\"\r\n#include \"CompiledShaders/DebugLuminanceLdrCS.h\"\r\n#include \"CompiledShaders/DebugLuminanceLdr2CS.h\"\r\n#include \"CompiledShaders/GenerateHistogramCS.h\"\r\n#include \"CompiledShaders/DebugDrawHistogramCS.h\"\r\n#include \"CompiledShaders/AdaptExposureCS.h\"\r\n#include \"CompiledShaders/DownsampleBloomCS.h\"\r\n#include \"CompiledShaders/DownsampleBloomAllCS.h\"\r\n#include \"CompiledShaders/UpsampleAndBlurCS.h\"\r\n#include \"CompiledShaders/BlurCS.h\"\r\n#include \"CompiledShaders/BloomExtractAndDownsampleHdrCS.h\"\r\n#include \"CompiledShaders/BloomExtractAndDownsampleLdrCS.h\"\r\n#include \"CompiledShaders/ExtractLumaCS.h\"\r\n#include \"CompiledShaders/AverageLumaCS.h\"\r\n#include \"CompiledShaders/CopyBackPostBufferCS.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nnamespace SSAO\r\n{\r\n    extern BoolVar DebugDraw;\r\n}\r\n\r\nnamespace FXAA\r\n{\r\n    extern BoolVar DebugDraw;\r\n}\r\n\r\nnamespace DepthOfField\r\n{\r\n    extern BoolVar Enable;\r\n    extern EnumVar DebugMode;\r\n}\r\n\r\nnamespace PostEffects\r\n{\r\n    const float kInitialMinLog = -12.0f;\r\n    const float kInitialMaxLog = 4.0f;\r\n\r\n    BoolVar EnableHDR(\"Graphics/HDR/Enable\", true);\r\n    BoolVar EnableAdaptation(\"Graphics/HDR/Adaptive Exposure\", true);\r\n    ExpVar MinExposure(\"Graphics/HDR/Min Exposure\", 1.0f / 64.0f, -8.0f, 0.0f, 0.25f);\r\n    ExpVar MaxExposure(\"Graphics/HDR/Max Exposure\", 64.0f, 0.0f, 8.0f, 0.25f);\r\n    NumVar TargetLuminance(\"Graphics/HDR/Key\", 0.08f, 0.01f, 0.99f, 0.01f);\r\n    NumVar AdaptationRate(\"Graphics/HDR/Adaptation Rate\", 0.05f, 0.01f, 1.0f, 0.01f);\r\n    ExpVar Exposure(\"Graphics/HDR/Exposure\", 2.0f, -8.0f, 8.0f, 0.25f);\r\n    BoolVar DrawHistogram(\"Graphics/HDR/Draw Histogram\", false);\r\n\r\n\t// KX: turn off Bloom by default for better TAA evaluation (also turn off \"High Quality\" by default);\r\n    BoolVar BloomEnable(\"Graphics/Bloom/Enable\", false);\r\n    NumVar BloomThreshold(\"Graphics/Bloom/Threshold\", 4.0f, 0.0f, 8.0f, 0.1f);\t\t// The threshold luminance above which a pixel will start to bloom\r\n    NumVar BloomStrength(\"Graphics/Bloom/Strength\", 0.1f, 0.0f, 2.0f, 0.05f);\t\t// A modulator controlling how much bloom is added back into the image\r\n    NumVar BloomUpsampleFactor(\"Graphics/Bloom/Scatter\", 0.65f, 0.0f, 1.0f, 0.05f);\t// Controls the \"focus\" of the blur.  High values spread out more causing a haze.\r\n    BoolVar HighQualityBloom(\"Graphics/Bloom/High Quality\", false);\t\t\t\t\t// High quality blurs 5 octaves of bloom; low quality only blurs 3.\r\n\r\n    RootSignature PostEffectsRS;\r\n    ComputePSO ToneMapCS;\r\n    ComputePSO ToneMapHDRCS;\r\n    ComputePSO ApplyBloomCS;\r\n    ComputePSO DebugLuminanceHdrCS;\r\n    ComputePSO DebugLuminanceLdrCS;\r\n    ComputePSO GenerateHistogramCS;\r\n    ComputePSO DrawHistogramCS;\r\n    ComputePSO AdaptExposureCS;\r\n    ComputePSO DownsampleBloom2CS;\r\n    ComputePSO DownsampleBloom4CS;\r\n    ComputePSO UpsampleAndBlurCS;\r\n    ComputePSO BlurCS;\r\n    ComputePSO BloomExtractAndDownsampleHdrCS;\r\n    ComputePSO BloomExtractAndDownsampleLdrCS;\r\n    ComputePSO ExtractLumaCS;\r\n    ComputePSO AverageLumaCS;\r\n    ComputePSO CopyBackPostBufferCS;\r\n\r\n    StructuredBuffer g_Exposure;\r\n\r\n    void UpdateExposure(ComputeContext&);\r\n    void BlurBuffer(ComputeContext&, ColorBuffer buffer[2], const ColorBuffer& lowerResBuf, float upsampleBlendFactor );\r\n    void GenerateBloom(ComputeContext&);\r\n    void ExtractLuma(ComputeContext&);\r\n    void ProcessHDR(ComputeContext&);\r\n    void ProcessLDR(CommandContext&);\r\n}\r\n\r\nvoid PostEffects::Initialize( void )\r\n{\r\n    PostEffectsRS.Reset(4, 2);\r\n    PostEffectsRS.InitStaticSampler(0, SamplerLinearClampDesc);\r\n    PostEffectsRS.InitStaticSampler(1, SamplerLinearBorderDesc);\r\n    PostEffectsRS[0].InitAsConstants(0, 4);\r\n    PostEffectsRS[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 4);\r\n    PostEffectsRS[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 4);\r\n    PostEffectsRS[3].InitAsConstantBuffer(1);\r\n    PostEffectsRS.Finalize(L\"Post Effects\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(PostEffectsRS); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        CreatePSO(ToneMapCS, g_pToneMap2CS);\r\n        CreatePSO(ToneMapHDRCS, g_pToneMapHDR2CS);\r\n        CreatePSO(ApplyBloomCS, g_pApplyBloom2CS);\r\n        CreatePSO(DebugLuminanceHdrCS, g_pDebugLuminanceHdr2CS);\r\n        CreatePSO(DebugLuminanceLdrCS, g_pDebugLuminanceLdr2CS);\r\n    }\r\n    else\r\n    {\r\n        CreatePSO(ToneMapCS, g_pToneMapCS);\r\n        CreatePSO(ToneMapHDRCS, g_pToneMapHDRCS);\r\n        CreatePSO(ApplyBloomCS, g_pApplyBloomCS);\r\n        CreatePSO(DebugLuminanceHdrCS, g_pDebugLuminanceHdrCS);\r\n        CreatePSO(DebugLuminanceLdrCS, g_pDebugLuminanceLdrCS);\r\n    }\r\n    CreatePSO( GenerateHistogramCS, g_pGenerateHistogramCS );\r\n    CreatePSO( DrawHistogramCS, g_pDebugDrawHistogramCS );\r\n    CreatePSO( AdaptExposureCS, g_pAdaptExposureCS );\r\n    CreatePSO( DownsampleBloom2CS, g_pDownsampleBloomCS );\r\n    CreatePSO( DownsampleBloom4CS, g_pDownsampleBloomAllCS );\r\n    CreatePSO( UpsampleAndBlurCS, g_pUpsampleAndBlurCS );\r\n    CreatePSO( BlurCS, g_pBlurCS );\r\n    CreatePSO( BloomExtractAndDownsampleHdrCS, g_pBloomExtractAndDownsampleHdrCS );\r\n    CreatePSO( BloomExtractAndDownsampleLdrCS, g_pBloomExtractAndDownsampleLdrCS );\r\n    CreatePSO( ExtractLumaCS, g_pExtractLumaCS );\r\n    CreatePSO( AverageLumaCS, g_pAverageLumaCS );\r\n    CreatePSO( CopyBackPostBufferCS, g_pCopyBackPostBufferCS );\r\n\r\n\r\n#undef CreatePSO\r\n\r\n    __declspec(align(16)) float initExposure[] =\r\n    {\r\n        Exposure, 1.0f / Exposure, Exposure, 0.0f,\r\n        kInitialMinLog, kInitialMaxLog, kInitialMaxLog - kInitialMinLog, 1.0f / (kInitialMaxLog - kInitialMinLog)\r\n    };\r\n    g_Exposure.Create(L\"Exposure\", 8, 4, initExposure);\r\n\r\n    FXAA::Initialize();\r\n    MotionBlur::Initialize();\r\n    DepthOfField::Initialize();\r\n}\r\n\r\nvoid PostEffects::Shutdown( void )\r\n{\r\n    g_Exposure.Destroy();\r\n\r\n    FXAA::Shutdown();\r\n    MotionBlur::Shutdown();\r\n    DepthOfField::Shutdown();\r\n}\r\n\r\nvoid PostEffects::BlurBuffer( ComputeContext& Context, ColorBuffer buffer[2], const ColorBuffer& lowerResBuf, float upsampleBlendFactor )\r\n{\r\n    // Set the shader constants\r\n    uint32_t bufferWidth = buffer[0].GetWidth();\r\n    uint32_t bufferHeight = buffer[0].GetHeight();\r\n    Context.SetConstants(0, 1.0f / bufferWidth, 1.0f / bufferHeight, upsampleBlendFactor);\r\n\r\n    // Set the input textures and output UAV\r\n    Context.TransitionResource( buffer[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.SetDynamicDescriptor(1, 0, buffer[1].GetUAV());\r\n    D3D12_CPU_DESCRIPTOR_HANDLE SRVs[2] = { buffer[0].GetSRV(), lowerResBuf.GetSRV() };\r\n    Context.SetDynamicDescriptors(2, 0, 2, SRVs);\r\n\r\n    // Set the shader:  upsample and blur or just blur\r\n    Context.SetPipelineState(&buffer[0] == &lowerResBuf ? BlurCS : UpsampleAndBlurCS);\r\n\r\n    // Dispatch the compute shader with default 8x8 thread groups\r\n    Context.Dispatch2D(bufferWidth, bufferHeight);\r\n\r\n    Context.TransitionResource( buffer[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n}\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Bloom effect in CS path\r\n//--------------------------------------------------------------------------------------\r\nvoid PostEffects::GenerateBloom( ComputeContext& Context )\r\n{\r\n    ScopedTimer _prof(L\"Generate Bloom\", Context);\r\n\r\n    // We can generate a bloom buffer up to 1/4 smaller in each dimension without undersampling.  If only downsizing by 1/2 or less, a faster\r\n    // shader can be used which only does one bilinear sample.\r\n\r\n    uint32_t kBloomWidth = g_LumaLR.GetWidth();\r\n    uint32_t kBloomHeight = g_LumaLR.GetHeight();\r\n\r\n    // These bloom buffer dimensions were chosen for their impressive divisibility by 128 and because they are roughly 16:9.\r\n    // The blurring algorithm is exactly 9 pixels by 9 pixels, so if the aspect ratio of each pixel is not square, the blur\r\n    // will be oval in appearance rather than circular.  Coincidentally, they are close to 1/2 of a 720p buffer and 1/3 of\r\n    // 1080p.  This is a common size for a bloom buffer on consoles.\r\n    ASSERT(kBloomWidth % 16 == 0 && kBloomHeight % 16 == 0, \"Bloom buffer dimensions must be multiples of 16\");\r\n\r\n\r\n    Context.SetConstants(0, 1.0f / kBloomWidth, 1.0f / kBloomHeight, (float)BloomThreshold );\r\n    Context.TransitionResource(g_aBloomUAV1[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_LumaLR, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    {\r\n\r\n        Context.SetDynamicDescriptor(1, 0, g_aBloomUAV1[0].GetUAV());\r\n        Context.SetDynamicDescriptor(1, 1, g_LumaLR.GetUAV());\r\n        Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetSRV());\r\n        Context.SetDynamicDescriptor(2, 1, g_Exposure.GetSRV());\r\n\r\n        Context.SetPipelineState(EnableHDR ? BloomExtractAndDownsampleHdrCS : BloomExtractAndDownsampleLdrCS);\r\n        Context.Dispatch2D(kBloomWidth, kBloomHeight);\r\n    }\r\n\r\n    Context.TransitionResource(g_aBloomUAV1[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.SetDynamicDescriptor(2, 0, g_aBloomUAV1[0].GetSRV());\r\n\r\n    // The difference between high and low quality bloom is that high quality sums 5 octaves with a 2x frequency scale, and the low quality\r\n    // sums 3 octaves with a 4x frequency scale.\r\n    if (HighQualityBloom)\r\n    {\r\n        Context.TransitionResource(g_aBloomUAV2[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_aBloomUAV3[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_aBloomUAV4[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_aBloomUAV5[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n        // Set the UAVs\r\n        D3D12_CPU_DESCRIPTOR_HANDLE UAVs[4] = {\r\n            g_aBloomUAV2[0].GetUAV(), g_aBloomUAV3[0].GetUAV(), g_aBloomUAV4[0].GetUAV(), g_aBloomUAV5[0].GetUAV() };\r\n        Context.SetDynamicDescriptors(1, 0, 4, UAVs);\r\n\r\n        // Each dispatch group is 8x8 threads, but each thread reads in 2x2 source texels (bilinear filter).\r\n        Context.SetPipelineState(DownsampleBloom4CS);\r\n        Context.Dispatch2D(kBloomWidth / 2, kBloomHeight / 2);\r\n\r\n        Context.TransitionResource(g_aBloomUAV2[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_aBloomUAV3[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_aBloomUAV4[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_aBloomUAV5[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n        float upsampleBlendFactor = BloomUpsampleFactor;\r\n\r\n        // Blur then upsample and blur four times\r\n        BlurBuffer( Context, g_aBloomUAV5, g_aBloomUAV5[0], 1.0f );\r\n        BlurBuffer( Context, g_aBloomUAV4, g_aBloomUAV5[1], upsampleBlendFactor  );\r\n        BlurBuffer( Context, g_aBloomUAV3, g_aBloomUAV4[1], upsampleBlendFactor  );\r\n        BlurBuffer( Context, g_aBloomUAV2, g_aBloomUAV3[1], upsampleBlendFactor  );\r\n        BlurBuffer( Context, g_aBloomUAV1, g_aBloomUAV2[1], upsampleBlendFactor  );\r\n    }\r\n    else\r\n    {\r\n        // Set the UAVs\r\n        D3D12_CPU_DESCRIPTOR_HANDLE UAVs[2] = { g_aBloomUAV3[0].GetUAV(), g_aBloomUAV5[0].GetUAV() };\r\n        Context.SetDynamicDescriptors(1, 0, 2, UAVs);\r\n\r\n        Context.TransitionResource(g_aBloomUAV3[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_aBloomUAV5[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n        // Each dispatch group is 8x8 threads, but each thread reads in 2x2 source texels (bilinear filter).\r\n        Context.SetPipelineState(DownsampleBloom2CS);\r\n        Context.Dispatch2D(kBloomWidth / 2, kBloomHeight / 2);\r\n\r\n        Context.TransitionResource(g_aBloomUAV3[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_aBloomUAV5[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n        float upsampleBlendFactor = BloomUpsampleFactor * 2.0f / 3.0f;\r\n\r\n        // Blur then upsample and blur two times\r\n        BlurBuffer( Context, g_aBloomUAV5, g_aBloomUAV5[0], 1.0f );\r\n        BlurBuffer( Context, g_aBloomUAV3, g_aBloomUAV5[1], upsampleBlendFactor );\r\n        BlurBuffer( Context, g_aBloomUAV1, g_aBloomUAV3[1], upsampleBlendFactor );\r\n    }\r\n}\r\n\r\nvoid PostEffects::ExtractLuma( ComputeContext& Context )\r\n{\r\n    ScopedTimer _prof(L\"Extract Luma\", Context);\r\n\r\n    Context.TransitionResource(g_LumaLR, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.SetConstants(0, 1.0f / g_LumaLR.GetWidth(), 1.0f / g_LumaLR.GetHeight());\r\n    Context.SetDynamicDescriptor(1, 0, g_LumaLR.GetUAV());\r\n    Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetSRV());\r\n    Context.SetDynamicDescriptor(2, 1, g_Exposure.GetSRV());\r\n    Context.SetPipelineState(ExtractLumaCS);\r\n    Context.Dispatch2D(g_LumaLR.GetWidth(), g_LumaLR.GetHeight());\r\n}\r\n\r\nvoid PostEffects::UpdateExposure( ComputeContext& Context )\r\n{\r\n    ScopedTimer _prof(L\"Update Exposure\", Context);\r\n\r\n    if (!EnableAdaptation)\r\n    {\r\n        __declspec(align(16)) float initExposure[] =\r\n        {\r\n            Exposure, 1.0f / Exposure, Exposure, 0.0f,\r\n            kInitialMinLog, kInitialMaxLog, kInitialMaxLog - kInitialMinLog, 1.0f / (kInitialMaxLog - kInitialMinLog)\r\n        };\r\n        Context.WriteBuffer(g_Exposure, 0, initExposure, sizeof(initExposure));\r\n        Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n        return;\r\n    }\r\n    \r\n    // Generate an HDR histogram\r\n    Context.TransitionResource(g_Histogram, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);\r\n    Context.ClearUAV(g_Histogram);\r\n    Context.TransitionResource(g_LumaLR, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.SetDynamicDescriptor(1, 0, g_Histogram.GetUAV() );\r\n    Context.SetDynamicDescriptor(2, 0, g_LumaLR.GetSRV() );\r\n    Context.SetPipelineState(GenerateHistogramCS);\r\n    Context.Dispatch2D(g_LumaLR.GetWidth(), g_LumaLR.GetHeight(), 16, 384);\r\n\r\n    __declspec(align(16)) struct\r\n    {\r\n        float TargetLuminance;\r\n        float AdaptationRate;\r\n        float MinExposure;\r\n        float MaxExposure;\r\n        uint32_t PixelCount; \r\n    } constants =\r\n    {\r\n        TargetLuminance, AdaptationRate, MinExposure, MaxExposure,\r\n        g_LumaLR.GetWidth() * g_LumaLR.GetHeight()\r\n    };\r\n    Context.TransitionResource(g_Histogram, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.SetDynamicDescriptor(1, 0, g_Exposure.GetUAV());\r\n    Context.SetDynamicDescriptor(2, 0, g_Histogram.GetSRV());\r\n    Context.SetDynamicConstantBufferView(3, sizeof(constants), &constants);\r\n    Context.SetPipelineState(AdaptExposureCS);\r\n    Context.Dispatch();\r\n    Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n}\r\n\r\nvoid PostEffects::ProcessHDR( ComputeContext& Context )\r\n{\r\n    ScopedTimer _prof(L\"HDR Tone Mapping\", Context);\r\n\r\n    if (BloomEnable)\r\n    {\r\n        GenerateBloom(Context);\r\n        Context.TransitionResource(g_aBloomUAV1[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    }\r\n    else if (EnableAdaptation)\r\n        ExtractLuma(Context);\r\n\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n        Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    else\r\n        Context.TransitionResource(g_PostEffectsBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n    Context.TransitionResource(g_LumaBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    Context.SetPipelineState(FXAA::DebugDraw ? DebugLuminanceHdrCS : (g_bEnableHDROutput ? ToneMapHDRCS : ToneMapCS));\r\n\r\n    // Set constants\r\n    Context.SetConstants(0, 1.0f / g_pSceneColorBuffer->GetWidth(), 1.0f / g_pSceneColorBuffer->GetHeight(),\r\n        (float)BloomStrength);\r\n\r\n    // Separate out SDR result from its perceived luminance\r\n    if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n        Context.SetDynamicDescriptor(1, 0, g_pSceneColorBuffer->GetUAV());\r\n    else\r\n    {\r\n        Context.SetDynamicDescriptor(1, 0, g_PostEffectsBuffer.GetUAV());\r\n        Context.SetDynamicDescriptor(2, 2, g_pSceneColorBuffer->GetSRV());\r\n    }\r\n    Context.SetDynamicDescriptor(1, 1, g_LumaBuffer.GetUAV());\r\n\r\n    // Read in original HDR value and blurred bloom buffer\r\n    Context.SetDynamicDescriptor(2, 0, g_Exposure.GetSRV());\r\n    Context.SetDynamicDescriptor(2, 1, BloomEnable ? g_aBloomUAV1[1].GetSRV() : TextureManager::GetBlackTex2D().GetSRV());\r\n    \r\n    Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n\r\n    // Do this last so that the bright pass uses the same exposure as tone mapping\r\n    UpdateExposure(Context);\r\n}\r\n\r\nvoid PostEffects::ProcessLDR(CommandContext& BaseContext)\r\n{\r\n    ScopedTimer _prof(L\"SDR Processing\", BaseContext);\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n\r\n    bool bGenerateBloom = BloomEnable && !SSAO::DebugDraw;\r\n    if (bGenerateBloom)\r\n        GenerateBloom(Context);\r\n\r\n    if (bGenerateBloom || FXAA::DebugDraw || SSAO::DebugDraw || !g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n    {\r\n        if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n            Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        else\r\n            Context.TransitionResource(g_PostEffectsBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n        Context.TransitionResource(g_aBloomUAV1[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_LumaBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n        // Set constants\r\n        Context.SetConstants(0, 1.0f / g_pSceneColorBuffer->GetWidth(), 1.0f / g_pSceneColorBuffer->GetHeight(),\r\n            (float)BloomStrength);\r\n\r\n        // Separate out SDR result from its perceived luminance\r\n        if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n            Context.SetDynamicDescriptor(1, 0, g_pSceneColorBuffer->GetUAV());\r\n        else\r\n        {\r\n            Context.SetDynamicDescriptor(1, 0, g_PostEffectsBuffer.GetUAV());\r\n            Context.SetDynamicDescriptor(2, 2, g_pSceneColorBuffer->GetSRV());\r\n        }\r\n        Context.SetDynamicDescriptor(1, 1, g_LumaBuffer.GetUAV());\r\n\r\n        // Read in original SDR value and blurred bloom buffer\r\n        Context.SetDynamicDescriptor(2, 0, bGenerateBloom ? g_aBloomUAV1[1].GetSRV() : TextureManager::GetBlackTex2D().GetSRV());\r\n\r\n        Context.SetPipelineState(FXAA::DebugDraw ? DebugLuminanceLdrCS : ApplyBloomCS);\r\n        Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n\r\n        Context.TransitionResource(g_LumaBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    }\r\n}\r\n\r\nvoid PostEffects::CopyBackPostBuffer( ComputeContext& Context )\r\n{\r\n    ScopedTimer _prof(L\"Copy Post back to Scene\", Context);\r\n    Context.SetRootSignature(PostEffectsRS);\r\n    Context.SetPipelineState(CopyBackPostBufferCS);\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_PostEffectsBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.SetDynamicDescriptor(1, 0, g_pSceneColorBuffer->GetUAV());\r\n    Context.SetDynamicDescriptor(2, 0, g_PostEffectsBuffer.GetSRV());\r\n    Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n}\r\n\r\nvoid PostEffects::Render( void )\r\n{\r\n    ComputeContext& Context = ComputeContext::Begin(L\"Post Effects\");\r\n\r\n    Context.SetRootSignature(PostEffectsRS);\r\n\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n\r\n    if (EnableHDR && !SSAO::DebugDraw && !(DepthOfField::Enable && DepthOfField::DebugMode >= 3))\r\n        ProcessHDR(Context);\r\n    else\r\n        ProcessLDR(Context);\r\n\r\n    bool bGeneratedLumaBuffer = EnableHDR || FXAA::DebugDraw || BloomEnable;\r\n    if (FXAA::Enable)\r\n        FXAA::Render(Context, bGeneratedLumaBuffer);\r\n\r\n    // In the case where we've been doing post processing in a separate buffer, we need to copy it\r\n    // back to the original buffer.  It is possible to skip this step if the next shader knows to\r\n    // do the manual format decode from UINT, but there are several code paths that need to be\r\n    // changed, and some of them rely on texture filtering, which won't work with UINT.  Since this\r\n    // is only to support legacy hardware and a single buffer copy isn't that big of a deal, this\r\n    // is the most economical solution.\r\n    if (!g_bTypedUAVLoadSupport_R11G11B10_FLOAT)\r\n        CopyBackPostBuffer(Context);\r\n\r\n    if (DrawHistogram)\r\n    {\r\n        ScopedTimer _prof(L\"Draw Debug Histogram\", Context);\r\n        Context.SetRootSignature(PostEffectsRS);\r\n        Context.SetPipelineState(DrawHistogramCS);\r\n        Context.InsertUAVBarrier(*g_pSceneColorBuffer);\r\n        Context.TransitionResource(g_Histogram, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_Exposure, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.SetDynamicDescriptor(1, 0, g_pSceneColorBuffer->GetUAV());\r\n        D3D12_CPU_DESCRIPTOR_HANDLE SRVs[2] = { g_Histogram.GetSRV(), g_Exposure.GetSRV() };\r\n        Context.SetDynamicDescriptors(2, 0, 2, SRVs);\r\n        Context.Dispatch(1, 32);\r\n        Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    }\r\n\r\n    Context.Finish();\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/PostEffects.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n#include \"EngineTuning.h\"\r\n\r\nclass ComputeContext;\r\n\r\nnamespace PostEffects\r\n{\r\n    extern BoolVar EnableHDR;\t\t\t// Turn on tone mapping features\r\n\r\n    // Tone mapping parameters\r\n    extern ExpVar Exposure;\t\t\t\t// Brightness scaler when adapative exposure is disabled\r\n    extern BoolVar EnableAdaptation;\t// Automatically adjust brightness based on perceived luminance\r\n\r\n    // Adapation parameters\r\n    extern ExpVar MinExposure;\r\n    extern ExpVar MaxExposure;\r\n    extern NumVar TargetLuminance;\r\n    extern NumVar AdaptationRate;\r\n\r\n    // Bloom parameters\r\n    extern BoolVar BloomEnable;\r\n    extern NumVar BloomThreshold;\r\n    extern NumVar BloomStrength;\r\n\r\n    extern BoolVar EnableFXAA;\r\n\r\n    void Initialize( void );\r\n    void Shutdown( void );\r\n    void Render( void );\r\n\r\n    // Copy the contents of the post effects buffer onto the main scene buffer\r\n    void CopyBackPostBuffer( ComputeContext& Context );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ReadbackBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"ReadbackBuffer.h\"\r\n#include \"GraphicsCore.h\"\r\n\r\nusing namespace Graphics;\r\n\r\nvoid ReadbackBuffer::Create( const std::wstring& name, uint32_t NumElements, uint32_t ElementSize )\r\n{\r\n    GpuResource::Destroy();\r\n\r\n    m_ElementCount = NumElements;\r\n    m_ElementSize = ElementSize;\r\n    m_BufferSize = NumElements * ElementSize;\r\n    m_UsageState = D3D12_RESOURCE_STATE_COPY_DEST;\r\n\r\n    // Create a readback buffer large enough to hold all texel data\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.Type = D3D12_HEAP_TYPE_READBACK;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    // Readback buffers must be 1-dimensional, i.e. \"buffer\" not \"texture2d\"\r\n    D3D12_RESOURCE_DESC ResourceDesc = {};\r\n    ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;\r\n    ResourceDesc.Width = m_BufferSize;\r\n    ResourceDesc.Height = 1;\r\n    ResourceDesc.DepthOrArraySize = 1;\r\n    ResourceDesc.MipLevels = 1;\r\n    ResourceDesc.Format = DXGI_FORMAT_UNKNOWN;\r\n    ResourceDesc.SampleDesc.Count = 1;\r\n    ResourceDesc.SampleDesc.Quality = 0;\r\n    ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;\r\n    ResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;\r\n\r\n    ASSERT_SUCCEEDED( g_Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &ResourceDesc,\r\n        D3D12_RESOURCE_STATE_COPY_DEST, nullptr, MY_IID_PPV_ARGS(&m_pResource)) );\r\n\r\n    m_GpuVirtualAddress = m_pResource->GetGPUVirtualAddress();\r\n\r\n#ifdef RELEASE\r\n    (name);\r\n#else\r\n    m_pResource->SetName(name.c_str());\r\n#endif\r\n}\r\n\r\n\r\nvoid* ReadbackBuffer::Map(void)\r\n{\r\n    void* Memory;\r\n    m_pResource->Map(0, &CD3DX12_RANGE(0, m_BufferSize), &Memory);\r\n    return Memory;\r\n}\r\n\r\nvoid ReadbackBuffer::Unmap(void)\r\n{\r\n    m_pResource->Unmap(0, &CD3DX12_RANGE(0, 0));\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ReadbackBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"GpuBuffer.h\"\r\n\r\nclass ReadbackBuffer : public GpuBuffer\r\n{\r\npublic:\r\n    virtual ~ReadbackBuffer() { Destroy(); }\r\n\r\n    void Create( const std::wstring& name, uint32_t NumElements, uint32_t ElementSize );\r\n\r\n    void* Map(void);\r\n    void Unmap(void);\r\n\r\nprotected:\r\n\r\n    void CreateDerivedViews(void) {}\r\n\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/RootSignature.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"RootSignature.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"Hash.h\"\r\n#include <map>\r\n#include <thread>\r\n#include <mutex>\r\n\r\nusing namespace Graphics;\r\nusing namespace std;\r\nusing Microsoft::WRL::ComPtr;\r\n\r\nstatic std::map< size_t, ComPtr<ID3D12RootSignature> > s_RootSignatureHashMap;\r\n\r\nvoid RootSignature::DestroyAll(void)\r\n{\r\n    s_RootSignatureHashMap.clear();\r\n}\r\n\r\nvoid RootSignature::InitStaticSampler(\r\n    UINT Register,\r\n    const D3D12_SAMPLER_DESC& NonStaticSamplerDesc,\r\n    D3D12_SHADER_VISIBILITY Visibility )\r\n{\r\n    ASSERT(m_NumInitializedStaticSamplers < m_NumSamplers);\r\n    D3D12_STATIC_SAMPLER_DESC& StaticSamplerDesc = m_SamplerArray[m_NumInitializedStaticSamplers++];\r\n\r\n    StaticSamplerDesc.Filter = NonStaticSamplerDesc.Filter;\r\n    StaticSamplerDesc.AddressU = NonStaticSamplerDesc.AddressU;\r\n    StaticSamplerDesc.AddressV = NonStaticSamplerDesc.AddressV;\r\n    StaticSamplerDesc.AddressW = NonStaticSamplerDesc.AddressW;\r\n    StaticSamplerDesc.MipLODBias = NonStaticSamplerDesc.MipLODBias;\r\n    StaticSamplerDesc.MaxAnisotropy = NonStaticSamplerDesc.MaxAnisotropy;\r\n    StaticSamplerDesc.ComparisonFunc = NonStaticSamplerDesc.ComparisonFunc;\r\n    StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;\r\n    StaticSamplerDesc.MinLOD = NonStaticSamplerDesc.MinLOD;\r\n    StaticSamplerDesc.MaxLOD = NonStaticSamplerDesc.MaxLOD;\r\n    StaticSamplerDesc.ShaderRegister = Register;\r\n    StaticSamplerDesc.RegisterSpace = 0;\r\n    StaticSamplerDesc.ShaderVisibility = Visibility;\r\n\r\n    if (StaticSamplerDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER ||\r\n        StaticSamplerDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER ||\r\n        StaticSamplerDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)\r\n    {\r\n        WARN_ONCE_IF_NOT(\r\n            // Transparent Black\r\n            NonStaticSamplerDesc.BorderColor[0] == 0.0f &&\r\n            NonStaticSamplerDesc.BorderColor[1] == 0.0f &&\r\n            NonStaticSamplerDesc.BorderColor[2] == 0.0f &&\r\n            NonStaticSamplerDesc.BorderColor[3] == 0.0f ||\r\n            // Opaque Black\r\n            NonStaticSamplerDesc.BorderColor[0] == 0.0f &&\r\n            NonStaticSamplerDesc.BorderColor[1] == 0.0f &&\r\n            NonStaticSamplerDesc.BorderColor[2] == 0.0f &&\r\n            NonStaticSamplerDesc.BorderColor[3] == 1.0f ||\r\n            // Opaque White\r\n            NonStaticSamplerDesc.BorderColor[0] == 1.0f &&\r\n            NonStaticSamplerDesc.BorderColor[1] == 1.0f &&\r\n            NonStaticSamplerDesc.BorderColor[2] == 1.0f &&\r\n            NonStaticSamplerDesc.BorderColor[3] == 1.0f,\r\n            \"Sampler border color does not match static sampler limitations\");\r\n\r\n        if (NonStaticSamplerDesc.BorderColor[3] == 1.0f)\r\n        {\r\n            if (NonStaticSamplerDesc.BorderColor[0] == 1.0f)\r\n                StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;\r\n            else\r\n                StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;\r\n        }\r\n        else\r\n            StaticSamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;\r\n    }\r\n}\r\n\r\nvoid RootSignature::Finalize(const std::wstring& name, D3D12_ROOT_SIGNATURE_FLAGS Flags)\r\n{\r\n    if (m_Finalized)\r\n        return;\r\n\r\n    ASSERT(m_NumInitializedStaticSamplers == m_NumSamplers);\r\n\r\n    D3D12_ROOT_SIGNATURE_DESC RootDesc;\r\n    RootDesc.NumParameters = m_NumParameters;\r\n    RootDesc.pParameters = (const D3D12_ROOT_PARAMETER*)m_ParamArray.get();\r\n    RootDesc.NumStaticSamplers = m_NumSamplers;\r\n    RootDesc.pStaticSamplers = (const D3D12_STATIC_SAMPLER_DESC*)m_SamplerArray.get();\r\n    RootDesc.Flags = Flags;\r\n\r\n    m_DescriptorTableBitMap = 0;\r\n    m_SamplerTableBitMap = 0;\r\n\r\n    size_t HashCode = Utility::HashState(&RootDesc.Flags);\r\n    HashCode = Utility::HashState( RootDesc.pStaticSamplers, m_NumSamplers, HashCode );\r\n\r\n    for (UINT Param = 0; Param < m_NumParameters; ++Param)\r\n    {\r\n        const D3D12_ROOT_PARAMETER& RootParam = RootDesc.pParameters[Param];\r\n        m_DescriptorTableSize[Param] = 0;\r\n\r\n        if (RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n        {\r\n            ASSERT(RootParam.DescriptorTable.pDescriptorRanges != nullptr);\r\n\r\n            HashCode = Utility::HashState( RootParam.DescriptorTable.pDescriptorRanges,\r\n                RootParam.DescriptorTable.NumDescriptorRanges, HashCode );\r\n\r\n            // We keep track of sampler descriptor tables separately from CBV_SRV_UAV descriptor tables\r\n            if (RootParam.DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)\r\n                m_SamplerTableBitMap |= (1 << Param);\r\n            else\r\n                m_DescriptorTableBitMap |= (1 << Param);\r\n\r\n            for (UINT TableRange = 0; TableRange < RootParam.DescriptorTable.NumDescriptorRanges; ++TableRange)\r\n                m_DescriptorTableSize[Param] += RootParam.DescriptorTable.pDescriptorRanges[TableRange].NumDescriptors;\r\n        }\r\n        else\r\n            HashCode = Utility::HashState( &RootParam, 1, HashCode );\r\n    }\r\n\r\n    ID3D12RootSignature** RSRef = nullptr;\r\n    bool firstCompile = false;\r\n    {\r\n        static mutex s_HashMapMutex;\r\n        lock_guard<mutex> CS(s_HashMapMutex);\r\n        auto iter = s_RootSignatureHashMap.find(HashCode);\r\n\r\n        // Reserve space so the next inquiry will find that someone got here first.\r\n        if (iter == s_RootSignatureHashMap.end())\r\n        {\r\n            RSRef = s_RootSignatureHashMap[HashCode].GetAddressOf();\r\n            firstCompile = true;\r\n        }\r\n        else\r\n            RSRef = iter->second.GetAddressOf();\r\n    }\r\n\r\n    if (firstCompile)\r\n    {\r\n        ComPtr<ID3DBlob> pOutBlob, pErrorBlob;\r\n\r\n        ASSERT_SUCCEEDED( D3D12SerializeRootSignature(&RootDesc, D3D_ROOT_SIGNATURE_VERSION_1,\r\n            pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf()));\r\n\r\n        ASSERT_SUCCEEDED( g_Device->CreateRootSignature(1, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(),\r\n            MY_IID_PPV_ARGS(&m_Signature)) );\r\n\r\n        m_Signature->SetName(name.c_str());\r\n\r\n        s_RootSignatureHashMap[HashCode].Attach(m_Signature);\r\n        ASSERT(*RSRef == m_Signature);\r\n    }\r\n    else\r\n    {\r\n        while (*RSRef == nullptr)\r\n            this_thread::yield();\r\n        m_Signature = *RSRef;\r\n    }\r\n\r\n    m_Finalized = TRUE;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/RootSignature.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\nclass DescriptorCache;\r\n\r\nclass RootParameter\r\n{\r\n    friend class RootSignature;\r\npublic:\r\n\r\n    RootParameter() \r\n    {\r\n        m_RootParam.ParameterType = (D3D12_ROOT_PARAMETER_TYPE)0xFFFFFFFF;\r\n    }\r\n\r\n    ~RootParameter()\r\n    {\r\n        Clear();\r\n    }\r\n\r\n    void Clear()\r\n    {\r\n        if (m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n            delete [] m_RootParam.DescriptorTable.pDescriptorRanges;\r\n\r\n        m_RootParam.ParameterType = (D3D12_ROOT_PARAMETER_TYPE)0xFFFFFFFF;\r\n    }\r\n\r\n    void InitAsConstants( UINT Register, UINT NumDwords, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL )\r\n    {\r\n        m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        m_RootParam.ShaderVisibility = Visibility;\r\n        m_RootParam.Constants.Num32BitValues = NumDwords;\r\n        m_RootParam.Constants.ShaderRegister = Register;\r\n        m_RootParam.Constants.RegisterSpace = 0;\r\n    }\r\n\r\n    void InitAsConstantBuffer( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL )\r\n    {\r\n        m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        m_RootParam.ShaderVisibility = Visibility;\r\n        m_RootParam.Descriptor.ShaderRegister = Register;\r\n        m_RootParam.Descriptor.RegisterSpace = 0;\r\n    }\r\n\r\n    void InitAsBufferSRV( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL )\r\n    {\r\n        m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        m_RootParam.ShaderVisibility = Visibility;\r\n        m_RootParam.Descriptor.ShaderRegister = Register;\r\n        m_RootParam.Descriptor.RegisterSpace = 0;\r\n    }\r\n\r\n    void InitAsBufferUAV( UINT Register, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL )\r\n    {\r\n        m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        m_RootParam.ShaderVisibility = Visibility;\r\n        m_RootParam.Descriptor.ShaderRegister = Register;\r\n        m_RootParam.Descriptor.RegisterSpace = 0;\r\n    }\r\n\r\n    void InitAsDescriptorRange( D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL )\r\n    {\r\n        InitAsDescriptorTable(1, Visibility);\r\n        SetTableRange(0, Type, Register, Count);\r\n    }\r\n\r\n    void InitAsDescriptorTable( UINT RangeCount, D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL )\r\n    {\r\n        m_RootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        m_RootParam.ShaderVisibility = Visibility;\r\n        m_RootParam.DescriptorTable.NumDescriptorRanges = RangeCount;\r\n        m_RootParam.DescriptorTable.pDescriptorRanges = new D3D12_DESCRIPTOR_RANGE[RangeCount];\r\n    }\r\n\r\n    void SetTableRange( UINT RangeIndex, D3D12_DESCRIPTOR_RANGE_TYPE Type, UINT Register, UINT Count, UINT Space = 0 )\r\n    {\r\n        D3D12_DESCRIPTOR_RANGE* range = const_cast<D3D12_DESCRIPTOR_RANGE*>(m_RootParam.DescriptorTable.pDescriptorRanges + RangeIndex);\r\n        range->RangeType = Type;\r\n        range->NumDescriptors = Count;\r\n        range->BaseShaderRegister = Register;\r\n        range->RegisterSpace = Space;\r\n        range->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;\r\n    }\r\n\r\n    const D3D12_ROOT_PARAMETER& operator() ( void ) const { return m_RootParam; }\r\n        \r\n\r\nprotected:\r\n\r\n    D3D12_ROOT_PARAMETER m_RootParam;\r\n};\r\n\r\n// Maximum 64 DWORDS divied up amongst all root parameters.\r\n// Root constants = 1 DWORD * NumConstants\r\n// Root descriptor (CBV, SRV, or UAV) = 2 DWORDs each\r\n// Descriptor table pointer = 1 DWORD\r\n// Static samplers = 0 DWORDS (compiled into shader)\r\nclass RootSignature\r\n{\r\n    friend class DynamicDescriptorHeap;\r\n\r\npublic:\r\n\r\n    RootSignature( UINT NumRootParams = 0, UINT NumStaticSamplers = 0 ) : m_Finalized(FALSE), m_NumParameters(NumRootParams)\r\n    {\r\n        Reset(NumRootParams, NumStaticSamplers);\r\n    }\r\n\r\n    ~RootSignature()\r\n    {\r\n    }\r\n\r\n    static void DestroyAll(void);\r\n\r\n    void Reset( UINT NumRootParams, UINT NumStaticSamplers = 0 )\r\n    {\r\n        if (NumRootParams > 0)\r\n            m_ParamArray.reset(new RootParameter[NumRootParams]);\r\n        else\r\n            m_ParamArray = nullptr;\r\n        m_NumParameters = NumRootParams;\r\n\r\n        if (NumStaticSamplers > 0)\r\n            m_SamplerArray.reset(new D3D12_STATIC_SAMPLER_DESC[NumStaticSamplers]);\r\n        else\r\n            m_SamplerArray = nullptr;\r\n        m_NumSamplers = NumStaticSamplers;\r\n        m_NumInitializedStaticSamplers = 0;\r\n    }\r\n\r\n    RootParameter& operator[] ( size_t EntryIndex )\r\n    {\r\n        ASSERT(EntryIndex < m_NumParameters);\r\n        return m_ParamArray.get()[EntryIndex];\r\n    }\r\n\r\n    const RootParameter& operator[] ( size_t EntryIndex ) const\r\n    {\r\n        ASSERT(EntryIndex < m_NumParameters);\r\n        return m_ParamArray.get()[EntryIndex];\r\n    }\r\n\r\n    void InitStaticSampler( UINT Register, const D3D12_SAMPLER_DESC& NonStaticSamplerDesc,\r\n        D3D12_SHADER_VISIBILITY Visibility = D3D12_SHADER_VISIBILITY_ALL );\r\n\r\n    void Finalize(const std::wstring& name, D3D12_ROOT_SIGNATURE_FLAGS Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n\r\n    ID3D12RootSignature* GetSignature() const { return m_Signature; }\r\n\r\nprotected:\r\n\r\n    BOOL m_Finalized;\r\n    UINT m_NumParameters;\r\n    UINT m_NumSamplers;\r\n    UINT m_NumInitializedStaticSamplers;\r\n    uint32_t m_DescriptorTableBitMap;\t\t// One bit is set for root parameters that are non-sampler descriptor tables\r\n    uint32_t m_SamplerTableBitMap;\t\t\t// One bit is set for root parameters that are sampler descriptor tables\r\n    uint32_t m_DescriptorTableSize[16];\t\t// Non-sampler descriptor tables need to know their descriptor count\r\n    std::unique_ptr<RootParameter[]> m_ParamArray;\r\n    std::unique_ptr<D3D12_STATIC_SAMPLER_DESC[]> m_SamplerArray;\r\n    ID3D12RootSignature* m_Signature;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/SSAO.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"SSAO.h\"\r\n#include \"BufferManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"Camera.h\"\r\n#include \"TemporalEffects.h\"\r\n\r\n#include \"CompiledShaders/AoPrepareDepthBuffers1CS.h\"\r\n#include \"CompiledShaders/AoPrepareDepthBuffers2CS.h\"\r\n#include \"CompiledShaders/LinearizeDepthCS.h\"\r\n#include \"CompiledShaders/DebugSSAOCS.h\"\r\n#include \"CompiledShaders/AoRender1CS.h\"\r\n#include \"CompiledShaders/AoRender2CS.h\"\r\n#include \"CompiledShaders/AoBlurUpsampleBlendOutCS.h\"\r\n#include \"CompiledShaders/AoBlurUpsamplePreMinBlendOutCS.h\"\r\n#include \"CompiledShaders/AoBlurUpsampleCS.h\"\r\n#include \"CompiledShaders/AoBlurUpsamplePreMinCS.h\"\r\n\r\nusing namespace Graphics;\r\nusing namespace Math;\r\n\r\nnamespace SSAO\r\n{\r\n\t// turn off SSAO by default\r\n    BoolVar Enable(\"Graphics/SSAO/Enable\", false);\r\n    BoolVar DebugDraw(\"Graphics/SSAO/Debug Draw\", false);\r\n    BoolVar AsyncCompute(\"Graphics/SSAO/Async Compute\", false);\r\n    BoolVar ComputeLinearZ(\"Graphics/SSAO/Always Linearize Z\", false);\r\n\r\n    // High quality (and better) is barely a noticeable improvement when modulated properly with ambient light.\r\n    // However, in the debug view the quality improvement is very apparent.\r\n    enum QualityLevel { kSsaoQualityVeryLow, kSsaoQualityLow, kSsaoQualityMedium, kSsaoQualityHigh, kSsaoQualityVeryHigh, kNumSsaoQualitySettings };\r\n    const char* QualityLabels[kNumSsaoQualitySettings] = { \"Very Low\", \"Low\", \"Medium\", \"High\", \"Very High\" };\r\n    EnumVar g_QualityLevel(\"Graphics/SSAO/Quality Level\", kSsaoQualityHigh, kNumSsaoQualitySettings, QualityLabels);\r\n\r\n    // This is necessary to filter out pixel shimmer due to bilateral upsampling with too much lost resolution.  High\r\n    // frequency detail can sometimes not be reconstructed, and the noise filter fills in the missing pixels with the\r\n    // result of the higher resolution SSAO.\r\n    NumVar g_NoiseFilterTolerance(\"Graphics/SSAO/Noise Filter Threshold (log10)\", -3.0f, -8.0f, 0.0f, 0.25f);\r\n    NumVar g_BlurTolerance(\"Graphics/SSAO/Blur Tolerance (log10)\", -5.0f, -8.0f, -1.0f, 0.25f);\r\n    NumVar g_UpsampleTolerance(\"Graphics/SSAO/Upsample Tolerance (log10)\", -7.0f, -12.0f, -1.0f, 0.5f);\r\n\r\n    // Controls how aggressive to fade off samples that occlude spheres but by so much as to be unreliable.\r\n    // This is what gives objects a dark halo around them when placed in front of a wall.  If you want to\r\n    // fade off the halo, boost your rejection falloff.  The tradeoff is that it reduces overall AO.\r\n    NumVar RejectionFalloff(\"Graphics/SSAO/Rejection Falloff (rcp)\", 2.5f, 1.0f, 10.0f, 0.5f);\r\n\r\n    // The effect normally marks anything that's 50% occluded or less as \"fully unoccluded\".  This throws away\r\n    // half of our result.  Accentuation gives more range to the effect, but it will darken all AO values in the\r\n    // process.  It will also cause \"under occluded\" geometry to appear to be highlighted.  If your ambient light\r\n    // is determined by the surface normal (such as with IBL), you might not want this side effect.\r\n    NumVar Accentuation(\"Graphics/SSAO/Accentuation\", 0.1f, 0.0f, 1.0f, 0.1f);\r\n\r\n    IntVar HierarchyDepth(\"Graphics/SSAO/Hierarchy Depth\", 3, 1, 4);\r\n}\r\n\r\nnamespace\r\n{\r\n    RootSignature s_RootSignature;\r\n    ComputePSO s_DepthPrepare1CS;\r\n    ComputePSO s_DepthPrepare2CS;\r\n    ComputePSO s_Render1CS;\r\n    ComputePSO s_Render2CS;\r\n    ComputePSO s_BlurUpsampleBlend[2];\t// Blend the upsampled result with the next higher resolution\r\n    ComputePSO s_BlurUpsampleFinal[2];\t// Don't blend the result, just upsample it\r\n    ComputePSO s_LinearizeDepthCS;\r\n    ComputePSO s_DebugSSAOCS;\r\n\r\n    float SampleThickness[12];\t// Pre-computed sample thicknesses\r\n}\r\n\r\nvoid SSAO::Initialize( void )\r\n{\r\n    s_RootSignature.Reset(5, 2);\r\n    s_RootSignature.InitStaticSampler(0, SamplerLinearClampDesc);\r\n    s_RootSignature.InitStaticSampler(1, SamplerLinearBorderDesc);\r\n    s_RootSignature[0].InitAsConstants(0, 4);\r\n    s_RootSignature[1].InitAsConstantBuffer(1);\r\n    s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 5);\r\n    s_RootSignature[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 5);\r\n    s_RootSignature[4].InitAsBufferSRV(5);\r\n    s_RootSignature.Finalize(L\"SSAO\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(s_RootSignature); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO( s_DepthPrepare1CS, g_pAoPrepareDepthBuffers1CS );\r\n    CreatePSO( s_DepthPrepare2CS, g_pAoPrepareDepthBuffers2CS );\r\n    CreatePSO( s_LinearizeDepthCS,  g_pLinearizeDepthCS );\r\n    CreatePSO( s_DebugSSAOCS, g_pDebugSSAOCS );\r\n    CreatePSO( s_Render1CS, g_pAoRender1CS );\r\n    CreatePSO( s_Render2CS, g_pAoRender2CS );\r\n\r\n    CreatePSO( s_BlurUpsampleBlend[0], g_pAoBlurUpsampleBlendOutCS );\r\n    CreatePSO( s_BlurUpsampleBlend[1], g_pAoBlurUpsamplePreMinBlendOutCS );\r\n    CreatePSO( s_BlurUpsampleFinal[0], g_pAoBlurUpsampleCS );\r\n    CreatePSO( s_BlurUpsampleFinal[1], g_pAoBlurUpsamplePreMinCS );\r\n\r\n    SampleThickness[ 0] = sqrt(1.0f - 0.2f * 0.2f);\r\n    SampleThickness[ 1] = sqrt(1.0f - 0.4f * 0.4f);\r\n    SampleThickness[ 2] = sqrt(1.0f - 0.6f * 0.6f);\r\n    SampleThickness[ 3] = sqrt(1.0f - 0.8f * 0.8f);\r\n    SampleThickness[ 4] = sqrt(1.0f - 0.2f * 0.2f - 0.2f * 0.2f);\r\n    SampleThickness[ 5] = sqrt(1.0f - 0.2f * 0.2f - 0.4f * 0.4f);\r\n    SampleThickness[ 6] = sqrt(1.0f - 0.2f * 0.2f - 0.6f * 0.6f);\r\n    SampleThickness[ 7] = sqrt(1.0f - 0.2f * 0.2f - 0.8f * 0.8f);\r\n    SampleThickness[ 8] = sqrt(1.0f - 0.4f * 0.4f - 0.4f * 0.4f);\r\n    SampleThickness[ 9] = sqrt(1.0f - 0.4f * 0.4f - 0.6f * 0.6f);\r\n    SampleThickness[10] = sqrt(1.0f - 0.4f * 0.4f - 0.8f * 0.8f);\r\n    SampleThickness[11] = sqrt(1.0f - 0.6f * 0.6f - 0.6f * 0.6f);\r\n}\r\n\r\nvoid SSAO::Shutdown(void)\r\n{\r\n}\r\n\r\nnamespace SSAO\r\n{\r\n    void ComputeAO( ComputeContext& Context, ColorBuffer& Destination, ColorBuffer& DepthBuffer, const float TanHalfFovH )\r\n    {\r\n        size_t BufferWidth = DepthBuffer.GetWidth();\r\n        size_t BufferHeight = DepthBuffer.GetHeight();\r\n        size_t ArrayCount = DepthBuffer.GetDepth();\r\n\r\n        // Here we compute multipliers that convert the center depth value into (the reciprocal of)\r\n        // sphere thicknesses at each sample location.  This assumes a maximum sample radius of 5\r\n        // units, but since a sphere has no thickness at its extent, we don't need to sample that far\r\n        // out.  Only samples whole integer offsets with distance less than 25 are used.  This means\r\n        // that there is no sample at (3, 4) because its distance is exactly 25 (and has a thickness of 0.)\r\n\r\n        // The shaders are set up to sample a circular region within a 5-pixel radius.\r\n        const float ScreenspaceDiameter = 10.0f;\r\n\r\n        // SphereDiameter = CenterDepth * ThicknessMultiplier.  This will compute the thickness of a sphere centered\r\n        // at a specific depth.  The ellipsoid scale can stretch a sphere into an ellipsoid, which changes the\r\n        // characteristics of the AO.\r\n        // TanHalfFovH:  Radius of sphere in depth units if its center lies at Z = 1\r\n        // ScreenspaceDiameter:  Diameter of sample sphere in pixel units\r\n        // ScreenspaceDiameter / BufferWidth:  Ratio of the screen width that the sphere actually covers\r\n        // Note about the \"2.0f * \":  Diameter = 2 * Radius\r\n        float ThicknessMultiplier = 2.0f * TanHalfFovH * ScreenspaceDiameter / BufferWidth;\r\n\r\n        if (ArrayCount == 1)\r\n            ThicknessMultiplier *= 2.0f;\r\n\r\n        // This will transform a depth value from [0, thickness] to [0, 1].\r\n        float InverseRangeFactor = 1.0f / ThicknessMultiplier;\r\n\r\n        __declspec(align(16)) float SsaoCB[28];\r\n\r\n        // The thicknesses are smaller for all off-center samples of the sphere.  Compute thicknesses relative\r\n        // to the center sample.\r\n        SsaoCB[ 0] = InverseRangeFactor / SampleThickness[ 0];\r\n        SsaoCB[ 1] = InverseRangeFactor / SampleThickness[ 1];\r\n        SsaoCB[ 2] = InverseRangeFactor / SampleThickness[ 2];\r\n        SsaoCB[ 3] = InverseRangeFactor / SampleThickness[ 3];\r\n        SsaoCB[ 4] = InverseRangeFactor / SampleThickness[ 4];\r\n        SsaoCB[ 5] = InverseRangeFactor / SampleThickness[ 5];\r\n        SsaoCB[ 6] = InverseRangeFactor / SampleThickness[ 6];\r\n        SsaoCB[ 7] = InverseRangeFactor / SampleThickness[ 7];\r\n        SsaoCB[ 8] = InverseRangeFactor / SampleThickness[ 8];\r\n        SsaoCB[ 9] = InverseRangeFactor / SampleThickness[ 9];\r\n        SsaoCB[10] = InverseRangeFactor / SampleThickness[10];\r\n        SsaoCB[11] = InverseRangeFactor / SampleThickness[11];\r\n\r\n        // These are the weights that are multiplied against the samples because not all samples are\r\n        // equally important.  The farther the sample is from the center location, the less they matter.\r\n        // We use the thickness of the sphere to determine the weight.  The scalars in front are the number\r\n        // of samples with this weight because we sum the samples together before multiplying by the weight,\r\n        // so as an aggregate all of those samples matter more.  After generating this table, the weights\r\n        // are normalized.\r\n        SsaoCB[12] = 4.0f * SampleThickness[ 0];\t// Axial\r\n        SsaoCB[13] = 4.0f * SampleThickness[ 1];\t// Axial\r\n        SsaoCB[14] = 4.0f * SampleThickness[ 2];\t// Axial\r\n        SsaoCB[15] = 4.0f * SampleThickness[ 3];\t// Axial\r\n        SsaoCB[16] = 4.0f * SampleThickness[ 4];\t// Diagonal\r\n        SsaoCB[17] = 8.0f * SampleThickness[ 5];\t// L-shaped\r\n        SsaoCB[18] = 8.0f * SampleThickness[ 6];\t// L-shaped\r\n        SsaoCB[19] = 8.0f * SampleThickness[ 7];\t// L-shaped\r\n        SsaoCB[20] = 4.0f * SampleThickness[ 8];\t// Diagonal\r\n        SsaoCB[21] = 8.0f * SampleThickness[ 9];\t// L-shaped\r\n        SsaoCB[22] = 8.0f * SampleThickness[10];\t// L-shaped\r\n        SsaoCB[23] = 4.0f * SampleThickness[11];\t// Diagonal\r\n\r\n//#define SAMPLE_EXHAUSTIVELY\r\n\r\n        // If we aren't using all of the samples, delete their weights before we normalize.\r\n    #ifndef SAMPLE_EXHAUSTIVELY\r\n        SsaoCB[12] = 0.0f;\r\n        SsaoCB[14] = 0.0f;\r\n        SsaoCB[17] = 0.0f;\r\n        SsaoCB[19] = 0.0f;\r\n        SsaoCB[21] = 0.0f;\r\n    #endif\r\n\r\n        // Normalize the weights by dividing by the sum of all weights\r\n        float totalWeight = 0.0f;\r\n        for (int i = 12; i < 24; ++i)\r\n            totalWeight += SsaoCB[i];\r\n        for (int i = 12; i < 24; ++i)\r\n            SsaoCB[i] /= totalWeight;\r\n\r\n        SsaoCB[24] = 1.0f / BufferWidth;\r\n        SsaoCB[25] = 1.0f / BufferHeight;\r\n        SsaoCB[26] = 1.0f / -RejectionFalloff;\r\n        SsaoCB[27] = 1.0f / (1.0f + Accentuation);\r\n\r\n        Context.SetDynamicConstantBufferView(1, sizeof(SsaoCB), SsaoCB);\r\n        Context.SetDynamicDescriptor(2, 0, Destination.GetUAV());\r\n        Context.SetDynamicDescriptor(3, 0, DepthBuffer.GetSRV() );\r\n\r\n        if (ArrayCount == 1)\r\n            Context.Dispatch2D(BufferWidth, BufferHeight, 16, 16);\r\n        else\r\n            Context.Dispatch3D(BufferWidth, BufferHeight, ArrayCount, 8, 8, 1);\r\n    }\r\n    \r\n    void BlurAndUpsample( ComputeContext& Context,\r\n        ColorBuffer& Destination, ColorBuffer& HiResDepth, ColorBuffer& LoResDepth,\r\n        ColorBuffer* InterleavedAO, ColorBuffer* HighQualityAO, ColorBuffer* HiResAO\r\n    )\r\n    {\r\n        size_t LoWidth  = LoResDepth.GetWidth();\r\n        size_t LoHeight = LoResDepth.GetHeight();\r\n        size_t HiWidth  = HiResDepth.GetWidth();\r\n        size_t HiHeight = HiResDepth.GetHeight();\r\n\r\n        ComputePSO* shader = nullptr;\r\n        if (HiResAO == nullptr)\r\n        {\r\n            shader = &s_BlurUpsampleFinal[HighQualityAO == nullptr ? 0 : 1];\r\n        }\r\n        else\r\n        {\r\n            shader = &s_BlurUpsampleBlend[HighQualityAO == nullptr ? 0 : 1];\r\n        }\r\n        Context.SetPipelineState(*shader);\r\n\r\n        float kBlurTolerance = 1.0f - powf(10.0f, g_BlurTolerance) * 1920.0f / (float)LoWidth;\r\n        kBlurTolerance *= kBlurTolerance;\r\n        float kUpsampleTolerance = powf(10.0f, g_UpsampleTolerance);\r\n        float kNoiseFilterWeight = 1.0f / (powf(10.0f, g_NoiseFilterTolerance) + kUpsampleTolerance);\r\n\r\n        __declspec(align(16)) float cbData[] = {\r\n            1.0f / LoWidth, 1.0f / LoHeight, 1.0f / HiWidth, 1.0f / HiHeight, \r\n            kNoiseFilterWeight, 1920.0f / (float)LoWidth, kBlurTolerance, kUpsampleTolerance\r\n        };\r\n        Context.SetDynamicConstantBufferView(1, sizeof(cbData), cbData);\r\n\r\n        Context.TransitionResource(Destination, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(LoResDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(HiResDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.SetDynamicDescriptor(2, 0, Destination.GetUAV());\r\n        Context.SetDynamicDescriptor(3, 0, LoResDepth.GetSRV());\r\n        Context.SetDynamicDescriptor(3, 1, HiResDepth.GetSRV());\r\n        if (InterleavedAO != nullptr)\r\n        {\r\n            Context.TransitionResource(*InterleavedAO, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.SetDynamicDescriptor(3, 2, InterleavedAO->GetSRV());\r\n        }\r\n        if (HighQualityAO != nullptr)\r\n        {\r\n            Context.TransitionResource(*HighQualityAO, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.SetDynamicDescriptor(3, 3, HighQualityAO->GetSRV());\r\n        }\r\n        if (HiResAO != nullptr)\r\n        {\r\n            Context.TransitionResource(*HiResAO, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.SetDynamicDescriptor(3, 4, HiResAO->GetSRV());\r\n        }\r\n\r\n        Context.Dispatch2D(HiWidth+2, HiHeight+2, 16, 16);\r\n    }\r\n}\r\n\r\nvoid SSAO::Render( GraphicsContext& GfxContext, const Camera& camera )\r\n{\r\n    const float* pProjMat = reinterpret_cast<const float*>(&camera.GetProjMatrix());\r\n    Render(GfxContext, pProjMat, camera.GetNearClip(), camera.GetFarClip() );\r\n}\r\n\r\nvoid SSAO::Render( GraphicsContext& GfxContext, const float* ProjMat, float NearClipDist, float FarClipDist )\r\n{\r\n    uint32_t FrameIndex = TemporalEffects::GetFrameIndexMod2();\r\n\r\n    ColorBuffer& LinearDepth = g_LinearDepth[FrameIndex];\r\n\r\n    const float zMagic = (FarClipDist - NearClipDist) / NearClipDist;\r\n\r\n    if (!Enable)\r\n    {\r\n        ScopedTimer _prof(L\"Generate SSAO\", GfxContext);\r\n\r\n        GfxContext.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_RENDER_TARGET, true);\r\n        GfxContext.ClearColor(g_SSAOFullScreen);\r\n        GfxContext.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n\r\n        if (!ComputeLinearZ)\r\n            return;\r\n\r\n        ComputeContext& Context = GfxContext.GetComputeContext();\r\n        Context.SetRootSignature(s_RootSignature);\r\n\r\n        Context.TransitionResource(*g_pSceneDepthBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.SetConstants(0, zMagic);\r\n        Context.SetDynamicDescriptor(3, 0, g_pSceneDepthBuffer->GetDepthSRV());\r\n\r\n        Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.SetDynamicDescriptors(2, 0, 1, &LinearDepth.GetUAV());\r\n        Context.SetPipelineState(s_LinearizeDepthCS);\r\n        Context.Dispatch2D(LinearDepth.GetWidth(), LinearDepth.GetHeight(), 16, 16);\r\n\r\n        if (DebugDraw)\r\n        {\r\n            Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n            Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n            Context.SetDynamicDescriptors(2, 0, 1, &g_pSceneColorBuffer->GetUAV());\r\n            Context.SetDynamicDescriptors(3, 0, 1, &LinearDepth.GetSRV() );\r\n            Context.SetPipelineState(s_DebugSSAOCS);\r\n            Context.Dispatch2D(g_SSAOFullScreen.GetWidth(), g_SSAOFullScreen.GetHeight());\r\n        }\r\n\r\n        return;\r\n    }\r\n\r\n    // if this is not available LinearZ will already have been computed through a cbr or msaa resolve\r\n    if ( g_pSceneDepthBuffer )\r\n        GfxContext.TransitionResource(*g_pSceneDepthBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    \r\n    GfxContext.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n    if (AsyncCompute)\r\n    {\r\n        // Flush the ZPrePass and wait for it on the compute queue\r\n        g_CommandManager.GetComputeQueue().StallForFence(GfxContext.Flush());\r\n    }\r\n    else\r\n    {\r\n        EngineProfiling::BeginBlock(L\"Generate SSAO\", &GfxContext);\r\n    }\r\n\r\n    ComputeContext& Context = AsyncCompute ? ComputeContext::Begin(L\"Async SSAO\", true) : GfxContext.GetComputeContext();\r\n    Context.SetRootSignature(s_RootSignature);\r\n\r\n    { ScopedTimer _prof(L\"Decompress and downsample\", Context);\r\n\r\n    // Phase 1:  Decompress, linearize, downsample, and deinterleave the depth buffer\r\n    Context.SetConstants(0, zMagic, (int)ComputeLinearZ);\r\n\r\n    // if this is not available LinearZ will already have been computed through a cbr or msaa resolve\r\n    if ( g_pSceneDepthBuffer )\r\n        Context.SetDynamicDescriptor(3, 0, g_pSceneDepthBuffer->GetDepthSRV() );\r\n\r\n\tif (ComputeLinearZ)\r\n\t\tContext.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\telse\r\n\t{\r\n\t\tContext.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\t\tContext.SetDynamicDescriptor(3, 1, LinearDepth.GetSRV());\r\n\t}\r\n    Context.TransitionResource(g_DepthDownsize1, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_DepthTiled1, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_DepthDownsize2, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_DepthTiled2, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE DownsizeUAVs[5] = { LinearDepth.GetUAV(), g_DepthDownsize1.GetUAV(), g_DepthTiled1.GetUAV(),\r\n        g_DepthDownsize2.GetUAV(), g_DepthTiled2.GetUAV() };\r\n    Context.SetDynamicDescriptors(2, 0, 5, DownsizeUAVs);\r\n\r\n    Context.SetPipelineState(s_DepthPrepare1CS);\r\n    Context.Dispatch2D(g_DepthTiled2.GetWidth() * 8, g_DepthTiled2.GetHeight() * 8);\r\n\r\n    if (HierarchyDepth > 2)\r\n    {\r\n        Context.SetConstants(0, 1.0f / g_DepthDownsize2.GetWidth(), 1.0f / g_DepthDownsize2.GetHeight());\r\n        Context.TransitionResource(g_DepthDownsize2, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        Context.TransitionResource(g_DepthDownsize3, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DepthTiled3, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DepthDownsize4, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        Context.TransitionResource(g_DepthTiled4, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        D3D12_CPU_DESCRIPTOR_HANDLE DownsizeAgainUAVs[4] = { g_DepthDownsize3.GetUAV(), g_DepthTiled3.GetUAV(), g_DepthDownsize4.GetUAV(), g_DepthTiled4.GetUAV() };\r\n        Context.SetDynamicDescriptors(2, 0, 4, DownsizeAgainUAVs);\r\n        Context.SetDynamicDescriptors(3, 0, 1, &g_DepthDownsize2.GetSRV() );\r\n        Context.SetPipelineState(s_DepthPrepare2CS);\r\n        Context.Dispatch2D(g_DepthTiled4.GetWidth() * 8, g_DepthTiled4.GetHeight() * 8);\r\n    }\r\n\r\n    } // End decompress\r\n    { ScopedTimer _prof(L\"Analyze depth volumes\", Context);\r\n\r\n    // Load first element of projection matrix which is the cotangent of the horizontal FOV divided by 2.\r\n    const float FovTangent = 1.0f / ProjMat[0];\r\n\r\n    Context.TransitionResource(g_AOMerged1, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOMerged2, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOMerged3, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOMerged4, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOHighQuality1, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOHighQuality2, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOHighQuality3, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_AOHighQuality4, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_DepthTiled1, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthTiled2, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthTiled3, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthTiled4, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthDownsize1, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthDownsize2, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthDownsize3, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_DepthDownsize4, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    // Phase 2:  Render SSAO for each sub-tile\r\n    if (HierarchyDepth > 3)\r\n    {\r\n        Context.SetPipelineState( s_Render1CS );\r\n        ComputeAO( Context, g_AOMerged4, g_DepthTiled4, FovTangent );\r\n        if (g_QualityLevel >= kSsaoQualityLow)\r\n        {\r\n            Context.SetPipelineState( s_Render2CS );\r\n            ComputeAO( Context, g_AOHighQuality4, g_DepthDownsize4, FovTangent );\r\n        }\r\n    }\r\n    if (HierarchyDepth > 2)\r\n    {\r\n        Context.SetPipelineState( s_Render1CS );\r\n        ComputeAO( Context, g_AOMerged3, g_DepthTiled3, FovTangent );\r\n        if (g_QualityLevel >= kSsaoQualityMedium)  \r\n        {\r\n            Context.SetPipelineState( s_Render2CS );\r\n            ComputeAO( Context, g_AOHighQuality3, g_DepthDownsize3, FovTangent );\r\n        }\r\n    }\r\n    if (HierarchyDepth > 1)\r\n    {\r\n        Context.SetPipelineState( s_Render1CS );\r\n        ComputeAO( Context, g_AOMerged2, g_DepthTiled2, FovTangent );\r\n        if (g_QualityLevel >= kSsaoQualityHigh)\t   \r\n        {\r\n            Context.SetPipelineState( s_Render2CS );\r\n            ComputeAO( Context, g_AOHighQuality2, g_DepthDownsize2, FovTangent );\r\n        }\r\n    }\r\n    {\r\n        Context.SetPipelineState( s_Render1CS );\r\n        ComputeAO( Context, g_AOMerged1, g_DepthTiled1, FovTangent );\r\n        if (g_QualityLevel >= kSsaoQualityVeryHigh)\r\n        {\r\n            Context.SetPipelineState( s_Render2CS );\r\n            ComputeAO( Context, g_AOHighQuality1, g_DepthDownsize1, FovTangent );\r\n        }\r\n    }\r\n\r\n    } // End analyze\r\n    {  ScopedTimer _prof(L\"Blur and upsample\", Context);\r\n\r\n    // Phase 4:  Iteratively blur and upsample, combining each result\r\n\r\n    ColorBuffer* NextSRV = &g_AOMerged4;\r\n\r\n\r\n    // 120 x 68 -> 240 x 135\r\n    if (HierarchyDepth > 3)\r\n    {\r\n        BlurAndUpsample( Context, g_AOSmooth3, g_DepthDownsize3, g_DepthDownsize4, NextSRV,\r\n            g_QualityLevel >= kSsaoQualityLow ? &g_AOHighQuality4 : nullptr, &g_AOMerged3 );\r\n\r\n        NextSRV = &g_AOSmooth3;\r\n    }\r\n    else\r\n        NextSRV = &g_AOMerged3;\r\n\r\n\r\n    // 240 x 135 -> 480 x 270\r\n    if (HierarchyDepth > 2)\r\n    {\r\n        BlurAndUpsample( Context, g_AOSmooth2, g_DepthDownsize2, g_DepthDownsize3, NextSRV,\r\n            g_QualityLevel >= kSsaoQualityMedium ? &g_AOHighQuality3 : nullptr, &g_AOMerged2 );\r\n\r\n        NextSRV = &g_AOSmooth2;\r\n    }\r\n    else\r\n        NextSRV = &g_AOMerged2;\r\n\r\n    // 480 x 270 -> 960 x 540\r\n    if (HierarchyDepth > 1)\r\n    {\r\n        BlurAndUpsample( Context, g_AOSmooth1, g_DepthDownsize1, g_DepthDownsize2, NextSRV,\r\n            g_QualityLevel >= kSsaoQualityHigh ? &g_AOHighQuality2 : nullptr, &g_AOMerged1 );\r\n\r\n        NextSRV = &g_AOSmooth1;\r\n    }\r\n    else\r\n        NextSRV = &g_AOMerged1;\r\n\r\n    // 960 x 540 -> 1920 x 1080\r\n    BlurAndUpsample( Context, g_SSAOFullScreen, LinearDepth, g_DepthDownsize1, NextSRV,\r\n        g_QualityLevel >= kSsaoQualityVeryHigh ? &g_AOHighQuality1 : nullptr, nullptr );\r\n\r\n    } // End blur and upsample\r\n\r\n    if (AsyncCompute)\r\n        Context.Finish();\r\n    else\r\n        EngineProfiling::EndBlock(&GfxContext);\r\n\r\n    if (DebugDraw)\r\n    {\r\n        if (AsyncCompute)\r\n        {\r\n            g_CommandManager.GetGraphicsQueue().StallForProducer(\r\n                g_CommandManager.GetComputeQueue());\r\n        }\r\n\r\n        ComputeContext& CC = GfxContext.GetComputeContext();\r\n        CC.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n        CC.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n        CC.SetRootSignature(s_RootSignature);\r\n        CC.SetPipelineState(s_DebugSSAOCS);\r\n        CC.SetDynamicDescriptors(2, 0, 1, &g_pSceneColorBuffer->GetUAV());\r\n        CC.SetDynamicDescriptors(3, 0, 1, &g_SSAOFullScreen.GetSRV());\r\n        CC.Dispatch2D(g_SSAOFullScreen.GetWidth(), g_SSAOFullScreen.GetHeight());\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/SSAO.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\nnamespace Math { class Camera;  }\r\n\r\nnamespace SSAO\r\n{\r\n    void Initialize( void );\r\n    void Shutdown( void );\r\n    void Render(GraphicsContext& Context, const float* ProjMat, float NearClipDist, float FarClipDist );\r\n    void Render(GraphicsContext& Context, const Math::Camera& camera );\r\n\r\n    extern BoolVar Enable;\r\n    extern BoolVar DebugDraw;\r\n    extern BoolVar AsyncCompute;\r\n    extern BoolVar ComputeLinearZ;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/SamplerManager.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//             Alex Nankervis\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"SamplerManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"Hash.h\"\r\n#include <map>\r\n\r\nusing namespace std;\r\nusing namespace Graphics;\r\n\r\nnamespace\r\n{\r\n    map< size_t, D3D12_CPU_DESCRIPTOR_HANDLE > s_SamplerCache;\r\n}\r\n\r\nD3D12_CPU_DESCRIPTOR_HANDLE SamplerDesc::CreateDescriptor()\r\n{\r\n    size_t hashValue = Utility::HashState(this);\r\n    auto iter = s_SamplerCache.find(hashValue);\r\n    if (iter != s_SamplerCache.end())\r\n    {\r\n        return iter->second;\r\n    }\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE Handle = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);\r\n    g_Device->CreateSampler(this, Handle);\r\n    return Handle;\r\n}\r\n\r\nvoid SamplerDesc::CreateDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE& Handle )\r\n{\r\n    g_Device->CreateSampler(this, Handle);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/SamplerManager.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n#include \"Color.h\"\r\n\r\nclass SamplerDesc : public D3D12_SAMPLER_DESC\r\n{\r\npublic:\r\n    // These defaults match the default values for HLSL-defined root\r\n    // signature static samplers.  So not overriding them here means\r\n    // you can safely not define them in HLSL.\r\n    SamplerDesc()\r\n    {\r\n        Filter = D3D12_FILTER_ANISOTROPIC;\r\n\t\t//Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;\r\n\t\t//Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;\r\n        AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;\r\n        AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;\r\n        AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;\r\n        MipLODBias = 0.0f;\r\n        MaxAnisotropy = 16;\r\n        ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;\r\n        BorderColor[0] = 1.0f;\r\n        BorderColor[1] = 1.0f;\r\n        BorderColor[2] = 1.0f;\r\n        BorderColor[3] = 1.0f;\r\n        MinLOD = 0.0f;\r\n        MaxLOD = D3D12_FLOAT32_MAX;\r\n    }\r\n\r\n    void SetTextureAddressMode( D3D12_TEXTURE_ADDRESS_MODE AddressMode )\r\n    {\r\n        AddressU = AddressMode;\r\n        AddressV = AddressMode;\r\n        AddressW = AddressMode;\r\n    }\r\n\r\n    void SetBorderColor( Color Border )\r\n    {\r\n        BorderColor[0] = Border.R();\r\n        BorderColor[1] = Border.G();\r\n        BorderColor[2] = Border.B();\r\n        BorderColor[3] = Border.A();\r\n    }\r\n\r\n    // Allocate new descriptor as needed; return handle to existing descriptor when possible\r\n    D3D12_CPU_DESCRIPTOR_HANDLE CreateDescriptor( void );\r\n\r\n    // Create descriptor in place (no deduplication)\r\n    void CreateDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE& Handle );\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AdaptExposureCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The group size is 16x16, but one group iterates over an entire 16-wide column of pixels (384 pixels tall)\r\n// Assuming the total workspace is 640x384, there will be 40 thread groups computing the histogram in parallel.\r\n// The histogram measures logarithmic luminance ranging from 2^-12 up to 2^4.  This should provide a nice window\r\n// where the exposure would range from 2^-4 up to 2^4.\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n#include \"ShaderUtility.hlsli\"\r\n\r\nByteAddressBuffer Histogram : register(t0);\r\nRWStructuredBuffer<float> Exposure : register(u0);\r\n\r\ncbuffer cb0 : register(b1)\r\n{\r\n    float TargetLuminance;\r\n    float AdaptationRate;\r\n    float MinExposure;\r\n    float MaxExposure;\r\n    uint PixelCount; \r\n}\r\n\r\ngroupshared float gs_Accum[256];\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 256, 1, 1 )]\r\nvoid main( uint GI : SV_GroupIndex )\r\n{\r\n    float WeightedSum = (float)GI * (float)Histogram.Load(GI * 4);\r\n\r\n    [unroll]\r\n    for (uint i = 1; i < 256; i *= 2)\r\n    {\r\n        gs_Accum[GI] = WeightedSum;\t\t\t\t\t// Write\r\n        GroupMemoryBarrierWithGroupSync();\t\t\t// Sync\r\n        WeightedSum += gs_Accum[(GI + i) % 256];\t// Read\r\n        GroupMemoryBarrierWithGroupSync();\t\t\t// Sync\r\n    }\r\n\r\n    float MinLog = Exposure[4];\r\n    float MaxLog = Exposure[5];\r\n    float LogRange = Exposure[6];\r\n    float RcpLogRange = Exposure[7];\r\n\r\n    // Average histogram value is the weighted sum of all pixels divided by the total number of pixels\r\n    // minus those pixels which provided no weight (i.e. black pixels.)\r\n    float weightedHistAvg = WeightedSum / (max(1, PixelCount - Histogram.Load(0))) - 1.0;\r\n    float logAvgLuminance = exp2(weightedHistAvg / 254.0 * LogRange + MinLog);\r\n    float targetExposure = TargetLuminance / logAvgLuminance;\r\n    //float targetExposure = -log2(1 - TargetLuminance) / logAvgLuminance;\r\n\r\n    float exposure = Exposure[0];\r\n    exposure = lerp(exposure, targetExposure, AdaptationRate);\r\n    exposure = clamp(exposure, MinExposure, MaxExposure);\r\n\r\n    if (GI == 0)\r\n    {\r\n        Exposure[0] = exposure;\r\n        Exposure[1] = 1.0 / exposure;\r\n        Exposure[2] = exposure;\r\n        Exposure[3] = weightedHistAvg;\r\n\r\n        // First attempt to recenter our histogram around the log-average.\r\n        float biasToCenter = (floor(weightedHistAvg) - 128.0) / 255.0;\r\n        if (abs(biasToCenter) > 0.1)\r\n        {\r\n            MinLog += biasToCenter * RcpLogRange;\r\n            MaxLog += biasToCenter * RcpLogRange;\r\n        }\r\n\r\n        // TODO:  Increase or decrease the log range to better fit the range of values.\r\n        // (Idea) Look at intermediate log-weighted sums for under- or over-represented\r\n        // extreme bounds.  I.e. break the for loop into two pieces to compute the sum of\r\n        // groups of 16, check the groups on each end, then finish the recursive summation.\r\n\r\n        Exposure[4] = MinLog;\r\n        Exposure[5] = MaxLog;\r\n        Exposure[6] = LogRange;\r\n        Exposure[7] = 1.0 / LogRange;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoBlurAndUpsampleCS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#include \"SSAORS.hlsli\"\n\nTexture2D<float> LoResDB : register(t0);\nTexture2D<float> HiResDB : register(t1);\nTexture2D<float> LoResAO1 : register(t2);\n#ifdef COMBINE_LOWER_RESOLUTIONS\nTexture2D<float> LoResAO2 : register(t3);\n#endif\n#ifdef BLEND_WITH_HIGHER_RESOLUTION\nTexture2D<float> HiResAO : register(t4);\n#endif\n\nRWTexture2D<float> AoResult : register(u0);\n\nSamplerState LinearSampler : register(s0);\n\ncbuffer CB1 : register(b1)\n{\n    float2 InvLowResolution;\n    float2 InvHighResolution;\n    float NoiseFilterStrength;\n    float StepSize;\n    float kBlurTolerance;\n    float kUpsampleTolerance;\n}\n\ngroupshared float DepthCache[256];\ngroupshared float AOCache1[256];\ngroupshared float AOCache2[256];\n\nvoid PrefetchData( uint index, float2 uv )\n{\n    float4 AO1 = LoResAO1.Gather( LinearSampler, uv );\n\n#ifdef COMBINE_LOWER_RESOLUTIONS\n    AO1 = min(AO1, LoResAO2.Gather( LinearSampler, uv ));\n#endif\n\n    AOCache1[index   ] = AO1.w;\n    AOCache1[index+ 1] = AO1.z;\n    AOCache1[index+16] = AO1.x;\n    AOCache1[index+17] = AO1.y;\n\n    float4 ID = 1.0 / LoResDB.Gather( LinearSampler, uv );\n    DepthCache[index   ] = ID.w;\n    DepthCache[index+ 1] = ID.z;\n    DepthCache[index+16] = ID.x;\n    DepthCache[index+17] = ID.y;\n}\n\nfloat SmartBlur( float a, float b, float c, float d, float e, bool Left, bool Middle, bool Right )\n{\n    b = Left | Middle ? b : c;\n    a = Left ? a : b;\n    d = Right | Middle ? d : c;\n    e = Right ? e : d;\n    return ((a + e) / 2.0 + b + c + d) / 4.0;\n}\n\nbool CompareDeltas( float d1, float d2, float l1, float l2 )\n{\n    float temp = d1 * d2 + StepSize;\n    return temp * temp > l1 * l2 * kBlurTolerance;\n}\n\nvoid BlurHorizontally( uint leftMostIndex )\n{\n    float a0 = AOCache1[leftMostIndex  ];\n    float a1 = AOCache1[leftMostIndex+1];\n    float a2 = AOCache1[leftMostIndex+2];\n    float a3 = AOCache1[leftMostIndex+3];\n    float a4 = AOCache1[leftMostIndex+4];\n    float a5 = AOCache1[leftMostIndex+5];\n    float a6 = AOCache1[leftMostIndex+6];\n\n    float d0 = DepthCache[leftMostIndex  ];\n    float d1 = DepthCache[leftMostIndex+1];\n    float d2 = DepthCache[leftMostIndex+2];\n    float d3 = DepthCache[leftMostIndex+3];\n    float d4 = DepthCache[leftMostIndex+4];\n    float d5 = DepthCache[leftMostIndex+5];\n    float d6 = DepthCache[leftMostIndex+6];\n\n    float d01 = d1 - d0;\n    float d12 = d2 - d1;\n    float d23 = d3 - d2;\n    float d34 = d4 - d3;\n    float d45 = d5 - d4;\n    float d56 = d6 - d5;\n\n    float l01 = d01 * d01 + StepSize;\n    float l12 = d12 * d12 + StepSize;\n    float l23 = d23 * d23 + StepSize;\n    float l34 = d34 * d34 + StepSize;\n    float l45 = d45 * d45 + StepSize;\n    float l56 = d56 * d56 + StepSize;\n\n    bool c02 = CompareDeltas( d01, d12, l01, l12 );\n    bool c13 = CompareDeltas( d12, d23, l12, l23 );\n    bool c24 = CompareDeltas( d23, d34, l23, l34 );\n    bool c35 = CompareDeltas( d34, d45, l34, l45 );\n    bool c46 = CompareDeltas( d45, d56, l45, l56 );\n\n    AOCache2[leftMostIndex  ] = SmartBlur( a0, a1, a2, a3, a4, c02, c13, c24 );\n    AOCache2[leftMostIndex+1] = SmartBlur( a1, a2, a3, a4, a5, c13, c24, c35 );\n    AOCache2[leftMostIndex+2] = SmartBlur( a2, a3, a4, a5, a6, c24, c35, c46 );\n}\n\nvoid BlurVertically( uint topMostIndex )\n{\n    float a0 = AOCache2[topMostIndex   ];\n    float a1 = AOCache2[topMostIndex+16];\n    float a2 = AOCache2[topMostIndex+32];\n    float a3 = AOCache2[topMostIndex+48];\n    float a4 = AOCache2[topMostIndex+64];\n    float a5 = AOCache2[topMostIndex+80];\n\n    float d0 = DepthCache[topMostIndex+ 2];\n    float d1 = DepthCache[topMostIndex+18];\n    float d2 = DepthCache[topMostIndex+34];\n    float d3 = DepthCache[topMostIndex+50];\n    float d4 = DepthCache[topMostIndex+66];\n    float d5 = DepthCache[topMostIndex+82];\n\n    float d01 = d1 - d0;\n    float d12 = d2 - d1;\n    float d23 = d3 - d2;\n    float d34 = d4 - d3;\n    float d45 = d5 - d4;\n\n    float l01 = d01 * d01 + StepSize;\n    float l12 = d12 * d12 + StepSize;\n    float l23 = d23 * d23 + StepSize;\n    float l34 = d34 * d34 + StepSize;\n    float l45 = d45 * d45 + StepSize;\n\n    bool c02 = CompareDeltas( d01, d12, l01, l12 );\n    bool c13 = CompareDeltas( d12, d23, l12, l23 );\n    bool c24 = CompareDeltas( d23, d34, l23, l34 );\n    bool c35 = CompareDeltas( d34, d45, l34, l45 );\n\n    float aoResult1 = SmartBlur( a0, a1, a2, a3, a4, c02, c13, c24 );\n    float aoResult2 = SmartBlur( a1, a2, a3, a4, a5, c13, c24, c35 );\n\n    AOCache1[topMostIndex   ] = aoResult1;\n    AOCache1[topMostIndex+16] = aoResult2;\n}\n\n// We essentially want 5 weights:  4 for each low-res pixel and 1 to blend in when none of the 4 really\n// match.  The filter strength is 1 / DeltaZTolerance.  So a tolerance of 0.01 would yield a strength of 100.\n// Note that a perfect match of low to high depths would yield a weight of 10^6, completely superceding any\n// noise filtering.  The noise filter is intended to soften the effects of shimmering when the high-res depth\n// buffer has a lot of small holes in it causing the low-res depth buffer to inaccurately represent it.\nfloat BilateralUpsample( float HiDepth, float HiAO, float4 LowDepths, float4 LowAO )\n{\n    float4 weights = float4(9, 3, 1, 3) / ( abs(HiDepth - LowDepths) + kUpsampleTolerance );\n    float TotalWeight = dot(weights, 1) + NoiseFilterStrength;\n    float WeightedSum = dot(LowAO, weights) + NoiseFilterStrength;// * HiAO;\n    return HiAO * WeightedSum / TotalWeight;\n}\n\n[RootSignature(SSAO_RootSig)]\n[numthreads( 8, 8, 1 )]\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\n{\n    //\n    // Load 4 pixels per thread into LDS to fill the 16x16 LDS cache with depth and AO\n    //\n    PrefetchData( GTid.x << 1 | GTid.y << 5, int2(DTid.xy + GTid.xy - 2) * InvLowResolution );\n    GroupMemoryBarrierWithGroupSync();\n\n    // Goal:  End up with a 9x9 patch that is blurred so we can upsample.  Blur radius is 2 pixels, so start with 13x13 area.\n\n    //\n    // Horizontally blur the pixels.\t13x13 -> 9x13\n    //\n    if (GI < 39)\n        BlurHorizontally((GI / 3) * 16 + (GI % 3) * 3);\n    GroupMemoryBarrierWithGroupSync();\n\n    //\n    // Vertically blur the pixels.\t\t9x13 -> 9x9\n    //\n    if (GI < 45)\n        BlurVertically((GI / 9) * 32 + GI % 9);\n    GroupMemoryBarrierWithGroupSync();\n\n    //\n    // Bilateral upsample\n    //\n    uint Idx0 = GTid.x + GTid.y * 16;\n    float4 LoSSAOs = float4( AOCache1[Idx0+16], AOCache1[Idx0+17], AOCache1[Idx0+1], AOCache1[Idx0] );\n\n    // We work on a quad of pixels at once because then we can gather 4 each of high and low-res depth values\n    float2 UV0 = DTid.xy * InvLowResolution;\n    float2 UV1 = DTid.xy * 2 * InvHighResolution;\n\n#ifdef BLEND_WITH_HIGHER_RESOLUTION\n    float4 HiSSAOs  = HiResAO.Gather(LinearSampler, UV1);\n#else\n    float4 HiSSAOs = 1.0;\n#endif\n    float4 LoDepths = LoResDB.Gather(LinearSampler, UV0);\n    float4 HiDepths = HiResDB.Gather(LinearSampler, UV1);\n\n    int2 OutST = DTid.xy << 1;\n    AoResult[OutST + int2(-1,  0)] = BilateralUpsample( HiDepths.x, HiSSAOs.x, LoDepths.xyzw, LoSSAOs.xyzw );\n    AoResult[OutST + int2( 0,  0)] = BilateralUpsample( HiDepths.y, HiSSAOs.y, LoDepths.yzwx, LoSSAOs.yzwx );\n    AoResult[OutST + int2( 0, -1)] = BilateralUpsample( HiDepths.z, HiSSAOs.z, LoDepths.zwxy, LoSSAOs.zwxy );\n    AoResult[OutST + int2(-1, -1)] = BilateralUpsample( HiDepths.w, HiSSAOs.w, LoDepths.wxyz, LoSSAOs.wxyz );\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoBlurUpsampleBlendOutCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define BLEND_WITH_HIGHER_RESOLUTION\r\n\r\n#include \"AoBlurAndUpsampleCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoBlurUpsampleCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"AoBlurAndUpsampleCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoBlurUpsamplePreMinBlendOutCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define COMBINE_LOWER_RESOLUTIONS\r\n#define BLEND_WITH_HIGHER_RESOLUTION\r\n\r\n#include \"AoBlurAndUpsampleCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoBlurUpsamplePreMinCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define COMBINE_LOWER_RESOLUTIONS\r\n\r\n#include \"AoBlurAndUpsampleCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoPrepareDepthBuffers1CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"SSAORS.hlsli\"\r\n\r\nRWTexture2D<float> LinearZ : register(u0);\r\nRWTexture2D<float2> DS2x : register(u1);\r\nRWTexture2DArray<float> DS2xAtlas : register(u2);\r\nRWTexture2D<float2> DS4x : register(u3);\r\nRWTexture2DArray<float> DS4xAtlas : register(u4);\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float ZMagic;\r\n\tint   ComputeLinearZ;\r\n}\r\n\r\nTexture2D<float> Depth : register(t0);\r\nTexture2D<float> LinearZIn : register(t1);\r\n\r\nfloat Linearize( uint2 st )\r\n{\r\n    float depth = Depth[st];\r\n    float dist = 1.0 / (ZMagic * depth + 1.0);\r\n    LinearZ[st] = dist;\r\n    return dist;\r\n}\r\n\r\ngroupshared float g_CacheW[256];\r\n\r\n[RootSignature(SSAO_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint2 startST = Gid.xy << 4 | GTid.xy;\r\n    uint destIdx = GTid.y << 4 | GTid.x;\r\n\tif (ComputeLinearZ == 1) {\r\n\t\tg_CacheW[destIdx + 0] = Linearize(startST | uint2(0, 0));\r\n\t\tg_CacheW[destIdx + 8] = Linearize(startST | uint2(8, 0));\r\n\t\tg_CacheW[destIdx + 128] = Linearize(startST | uint2(0, 8));\r\n\t\tg_CacheW[destIdx + 136] = Linearize(startST | uint2(8, 8));\r\n\t}\r\n\telse {\r\n\t\tg_CacheW[destIdx + 0] = LinearZIn[startST | uint2(0, 0)];\r\n\t\tg_CacheW[destIdx + 8] = LinearZIn[startST | uint2(8, 0)];\r\n\t\tg_CacheW[destIdx + 128] = LinearZIn[startST | uint2(0, 8)];\r\n\t\tg_CacheW[destIdx + 136] = LinearZIn[startST | uint2(8, 8)];\r\n\t}\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint ldsIndex = (GTid.x << 1) | (GTid.y << 5);\r\n\r\n    float w1 = g_CacheW[ldsIndex];\r\n\r\n    uint2 st = DTid.xy;\r\n    uint slice = (st.x & 3) | ((st.y & 3) << 2);\r\n    DS2x[st] = w1;\r\n    DS2xAtlas[uint3(st >> 2, slice)] = w1;\r\n\r\n    if ((GI & 011) == 0)\r\n    {\r\n        st = DTid.xy >> 1;\r\n        slice = (st.x & 3) | ((st.y & 3) << 2);\r\n        DS4x[st] = w1;\r\n        DS4xAtlas[uint3(st >> 2, slice)] = w1;\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoPrepareDepthBuffers2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"SSAORS.hlsli\"\r\n\r\nTexture2D<float> DS4x : register(t0);\r\nRWTexture2D<float> DS8x : register(u0);\r\nRWTexture2DArray<float> DS8xAtlas : register(u1);\r\nRWTexture2D<float> DS16x : register(u2);\r\nRWTexture2DArray<float> DS16xAtlas : register(u3);\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float2 InvSourceDimension;\r\n}\r\n\r\n[RootSignature(SSAO_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float m1 = DS4x[DTid.xy << 1];\r\n\r\n    uint2 st = DTid.xy;\r\n    uint2 stAtlas = st >> 2;\r\n    uint stSlice = (st.x & 3) | ((st.y & 3) << 2);\r\n    DS8x[st] = m1;\r\n    DS8xAtlas[uint3(stAtlas, stSlice)] = m1;\r\n\r\n    if ((GI & 011) == 0)\r\n    {\r\n        uint2 st = DTid.xy >> 1;\r\n        uint2 stAtlas = st >> 2;\r\n        uint stSlice = (st.x & 3) | ((st.y & 3) << 2);\r\n        DS16x[st] = m1;\r\n        DS16xAtlas[uint3(stAtlas, stSlice)] = m1;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoRender1CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define INTERLEAVE_RESULT\r\n#include \"AoRenderCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoRender2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n\r\n#include \"AoRenderCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AoRenderCS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#include \"SSAORS.hlsli\"\n\n#ifndef INTERLEAVE_RESULT\n#define WIDE_SAMPLING 1\n#endif\n\n#ifdef INTERLEAVE_RESULT\nTexture2DArray<float> DepthTex : register(t0);\n#else\nTexture2D<float> DepthTex : register(t0);\n#endif\nRWTexture2D<float> Occlusion : register(u0);\nSamplerState LinearBorderSampler : register(s1);\ncbuffer CB1 : register(b1)\n{\n    float4 gInvThicknessTable[3];\n    float4 gSampleWeightTable[3];\n    float2 gInvSliceDimension;\n    float  gRejectFadeoff;\n    float  gRcpAccentuation;\n}\n\n#if WIDE_SAMPLING\n    // 32x32 cache size:  the 16x16 in the center forms the area of focus with the 8-pixel perimeter used for wide gathering.\n    #define TILE_DIM 32\n    #define THREAD_COUNT_X 16\n    #define THREAD_COUNT_Y 16\n#else\n    // 16x16 cache size:  the 8x8 in the center forms the area of focus with the 4-pixel perimeter used for gathering.\n    #define TILE_DIM 16\n    #define THREAD_COUNT_X 8\n    #define THREAD_COUNT_Y 8\n#endif\n\ngroupshared float DepthSamples[TILE_DIM * TILE_DIM];\n\nfloat TestSamplePair( float frontDepth, float invRange, uint base, int offset )\n{\n    // \"Disocclusion\" measures the penetration distance of the depth sample within the sphere.\n    // Disocclusion < 0 (full occlusion) -> the sample fell in front of the sphere\n    // Disocclusion > 1 (no occlusion) -> the sample fell behind the sphere\n    float disocclusion1 = DepthSamples[base + offset] * invRange - frontDepth;\n    float disocclusion2 = DepthSamples[base - offset] * invRange - frontDepth;\n\n    float pseudoDisocclusion1 = saturate(gRejectFadeoff * disocclusion1);\n    float pseudoDisocclusion2 = saturate(gRejectFadeoff * disocclusion2);\n\n    return\n        clamp(disocclusion1, pseudoDisocclusion2, 1.0) +\n        clamp(disocclusion2, pseudoDisocclusion1, 1.0) -\n        pseudoDisocclusion1 * pseudoDisocclusion2;\n}\n\nfloat TestSamples( uint centerIdx, uint x, uint y, float invDepth, float invThickness )\n{\n#if WIDE_SAMPLING\n    x <<= 1;\n    y <<= 1;\n#endif\n\n    float invRange = invThickness * invDepth;\n    float frontDepth = invThickness - 0.5;\n\n    if (y == 0)\n    {\n        // Axial\n        return 0.5 * (\n            TestSamplePair(frontDepth, invRange, centerIdx, x) +\n            TestSamplePair(frontDepth, invRange, centerIdx, x * TILE_DIM));\n    }\n    else if (x == y)\n    {\n        // Diagonal\n        return 0.5 * (\n            TestSamplePair(frontDepth, invRange, centerIdx, x * TILE_DIM - x) +\n            TestSamplePair(frontDepth, invRange, centerIdx, x * TILE_DIM + x));\n    }\n    else\n    {\n        // L-Shaped\n        return 0.25 * (\n            TestSamplePair(frontDepth, invRange, centerIdx, y * TILE_DIM + x) +\n            TestSamplePair(frontDepth, invRange, centerIdx, y * TILE_DIM - x) +\n            TestSamplePair(frontDepth, invRange, centerIdx, x * TILE_DIM + y) +\n            TestSamplePair(frontDepth, invRange, centerIdx, x * TILE_DIM - y));\n    }\n}\n\n[RootSignature(SSAO_RootSig)]\n#if WIDE_SAMPLING\n[numthreads( 16, 16, 1 )]\n#else\n[numthreads( 8, 8, 1 )]\n#endif\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\n{\n#if WIDE_SAMPLING\n    float2 QuadCenterUV = int2(DTid.xy + GTid.xy - 7) * gInvSliceDimension;\n#else\n    float2 QuadCenterUV = int2(DTid.xy + GTid.xy - 3) * gInvSliceDimension;\n#endif\n\n    // Fetch four depths and store them in LDS\n#ifdef INTERLEAVE_RESULT\n    float4 depths = DepthTex.Gather(LinearBorderSampler, float3(QuadCenterUV, DTid.z));\n#else\n    float4 depths = DepthTex.Gather(LinearBorderSampler, QuadCenterUV);\n#endif\n    int destIdx = GTid.x * 2 + GTid.y * 2 * TILE_DIM;\n    DepthSamples[destIdx] = depths.w;\n    DepthSamples[destIdx + 1] = depths.z;\n    DepthSamples[destIdx + TILE_DIM] = depths.x;\n    DepthSamples[destIdx + TILE_DIM + 1] = depths.y;\n\n    GroupMemoryBarrierWithGroupSync();\n\n#if WIDE_SAMPLING\n    uint thisIdx = GTid.x + GTid.y * TILE_DIM + 8 * TILE_DIM + 8;\n#else\n    uint thisIdx = GTid.x + GTid.y * TILE_DIM + 4 * TILE_DIM + 4;\n#endif\n    const float invThisDepth = 1.0 / DepthSamples[thisIdx];\n\n    float ao = 0.0;\n\n//#define SAMPLE_EXHAUSTIVELY\n\n#ifdef SAMPLE_EXHAUSTIVELY\n    // 68 samples:  sample all cells in *within* a circular radius of 5\n    ao += gSampleWeightTable[0].x * TestSamples(thisIdx, 1, 0, invThisDepth, gInvThicknessTable[0].x);\n    ao += gSampleWeightTable[0].y * TestSamples(thisIdx, 2, 0, invThisDepth, gInvThicknessTable[0].y);\n    ao += gSampleWeightTable[0].z * TestSamples(thisIdx, 3, 0, invThisDepth, gInvThicknessTable[0].z);\n    ao += gSampleWeightTable[0].w * TestSamples(thisIdx, 4, 0, invThisDepth, gInvThicknessTable[0].w);\n    ao += gSampleWeightTable[1].x * TestSamples(thisIdx, 1, 1, invThisDepth, gInvThicknessTable[1].x);\n    ao += gSampleWeightTable[2].x * TestSamples(thisIdx, 2, 2, invThisDepth, gInvThicknessTable[2].x);\n    ao += gSampleWeightTable[2].w * TestSamples(thisIdx, 3, 3, invThisDepth, gInvThicknessTable[2].w);\n    ao += gSampleWeightTable[1].y * TestSamples(thisIdx, 1, 2, invThisDepth, gInvThicknessTable[1].y);\n    ao += gSampleWeightTable[1].z * TestSamples(thisIdx, 1, 3, invThisDepth, gInvThicknessTable[1].z);\n    ao += gSampleWeightTable[1].w * TestSamples(thisIdx, 1, 4, invThisDepth, gInvThicknessTable[1].w);\n    ao += gSampleWeightTable[2].y * TestSamples(thisIdx, 2, 3, invThisDepth, gInvThicknessTable[2].y);\n    ao += gSampleWeightTable[2].z * TestSamples(thisIdx, 2, 4, invThisDepth, gInvThicknessTable[2].z);\n#else // SAMPLE_CHECKER\n    // 36 samples:  sample every-other cell in a checker board pattern\n    ao += gSampleWeightTable[0].y * TestSamples(thisIdx, 2, 0, invThisDepth, gInvThicknessTable[0].y);\n    ao += gSampleWeightTable[0].w * TestSamples(thisIdx, 4, 0, invThisDepth, gInvThicknessTable[0].w);\n    ao += gSampleWeightTable[1].x * TestSamples(thisIdx, 1, 1, invThisDepth, gInvThicknessTable[1].x);\n    ao += gSampleWeightTable[2].x * TestSamples(thisIdx, 2, 2, invThisDepth, gInvThicknessTable[2].x);\n    ao += gSampleWeightTable[2].w * TestSamples(thisIdx, 3, 3, invThisDepth, gInvThicknessTable[2].w);\n    ao += gSampleWeightTable[1].z * TestSamples(thisIdx, 1, 3, invThisDepth, gInvThicknessTable[1].z);\n    ao += gSampleWeightTable[2].z * TestSamples(thisIdx, 2, 4, invThisDepth, gInvThicknessTable[2].z);\n#endif\n\n#ifdef INTERLEAVE_RESULT\n    uint2 OutPixel = DTid.xy << 2 | uint2(DTid.z & 3, DTid.z >> 2);\n#else\n    uint2 OutPixel = DTid.xy;\n#endif\n    Occlusion[OutPixel] = ao * gRcpAccentuation;\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ApplyBloom2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ApplyBloomCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ApplyBloomCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nTexture2D<float3> Bloom : register( t0 );\r\n#if SUPPORT_TYPED_UAV_LOADS\r\nRWTexture2D<float3> SrcColor : register( u0 );\r\n#else\r\nRWTexture2D<uint> DstColor : register(u0);\r\nTexture2D<float3> SrcColor : register(t2);\r\n#endif\r\nRWTexture2D<float> OutLuma : register( u1 );\r\nSamplerState LinearSampler : register( s0 );\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float2 g_RcpBufferDim;\r\n    float g_BloomStrength;\r\n};\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float2 TexCoord = (DTid.xy + 0.5) * g_RcpBufferDim;\r\n\r\n    // Load LDR and bloom\r\n    float3 ldrColor = SrcColor[DTid.xy] + g_BloomStrength * Bloom.SampleLevel(LinearSampler, TexCoord, 0);\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    SrcColor[DTid.xy] = ldrColor;\r\n#else\r\n    DstColor[DTid.xy] = Pack_R11G11B10_FLOAT(ldrColor);\r\n#endif\r\n    OutLuma[DTid.xy] = RGBToLogLuminance(ldrColor);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/AverageLumaCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nTexture2D<float> InputBuf : register( t0 );\r\nRWStructuredBuffer<float> Result : register( u0 );\r\n\r\ngroupshared float buffer[64];\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float sumThisThread = InputBuf[DTid.xy];\r\n    buffer[GI] = sumThisThread;\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    sumThisThread += buffer[GI + 32];\r\n    buffer[GI] = sumThisThread;\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    sumThisThread += buffer[GI + 16];\r\n    buffer[GI] = sumThisThread;\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    sumThisThread += buffer[GI + 8];\r\n    buffer[GI] = sumThisThread;\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    sumThisThread += buffer[GI + 4];\r\n    buffer[GI] = sumThisThread;\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    sumThisThread += buffer[GI + 2];\r\n    buffer[GI] = sumThisThread;\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    sumThisThread += buffer[GI + 1];\r\n\r\n    if (GI == 0)\r\n        Result[Gid.x + Gid.y * 5] = sumThisThread / 64.0f;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BicubicHorizontalUpsamplePS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Simple bicubic filter\r\n//\r\n// http://en.wikipedia.org/wiki/Bicubic_interpolation\r\n// http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html\r\n//\r\n//--------------------------------------------------------------------------------------\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    uint2 TextureSize;\r\n    float A;\r\n}\r\n\r\nfloat W1(float x)\r\n{\r\n    return x * x * ((A + 2) * x - (A + 3)) + 1.0;\r\n}\r\n\r\nfloat W2(float x)\r\n{\r\n    return A * (x * (x * (x - 5) + 8) - 4);\r\n}\r\n\r\nfloat4 GetWeights(float d1)\r\n{\r\n    return float4(W2(1.0 + d1), W1(d1), W1(1.0 - d1), W2(2.0 - d1));\r\n}\r\n\r\nfloat3 GetColor(uint s, uint t)\r\n{\r\n#ifdef GAMMA_SPACE\r\n    return ApplyDisplayProfile(ColorTex[uint2(s, t)], DISPLAY_PLANE_FORMAT);\r\n#else\r\n    return ColorTex[uint2(s, t)];\r\n#endif\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main(float4 position : SV_Position, float2 uv : TexCoord0) : SV_Target0\r\n{\r\n    float2 t = uv * TextureSize + 0.5;\r\n    float2 f = frac(t);\r\n    int2 st = int2(t.x, position.y);\r\n\r\n    uint MaxWidth = TextureSize.x - 1;\r\n\r\n    uint s0 = max(st.x - 2, 0);\r\n    uint s1 = max(st.x - 1, 0);\r\n    uint s2 = min(st.x + 0, MaxWidth);\r\n    uint s3 = min(st.x + 1, MaxWidth);\r\n\r\n    float4 W = GetWeights(f.x);\r\n    float3 Color = \r\n        W.x * GetColor(s0, st.y) + \r\n        W.y * GetColor(s1, st.y) + \r\n        W.z * GetColor(s2, st.y) +\r\n        W.w * GetColor(s3, st.y);\r\n\r\n    return Color;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BicubicUpsampleGammaPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define GAMMA_SPACE\r\n#include \"BicubicUpsamplePS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BicubicUpsamplePS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Simple bicubic filter\r\n//\r\n// http://en.wikipedia.org/wiki/Bicubic_interpolation\r\n// http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html\r\n//\r\n//--------------------------------------------------------------------------------------\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\nSamplerState BilinearClamp : register(s0);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    uint2 TextureSize;\r\n    float A;\r\n}\r\n\r\nfloat W1(float x)\r\n{\r\n    return x * x * ((A + 2) * x - (A + 3)) + 1.0;\r\n}\r\n\r\nfloat W2(float x)\r\n{\r\n    return A * (x * (x * (x - 5) + 8) - 4);\r\n}\r\n\r\nfloat4 GetWeights(float d1)\r\n{\r\n    return float4(W2(1.0 + d1), W1(d1), W1(1.0 - d1), W2(2.0 - d1));\r\n}\r\n\r\nfloat3 Cubic(float4 w, float3 c0, float3 c1, float3 c2, float3 c3)\r\n{\r\n    return c0 * w.x + c1 * w.y + c2 * w.z + c3 * w.w;\r\n}\r\n\r\nfloat3 GetColor(uint s, uint t)\r\n{\r\n#ifdef GAMMA_SPACE\r\n    return ApplyDisplayProfile(ColorTex[uint2(s, t)], DISPLAY_PLANE_FORMAT);\r\n#else\r\n    return ColorTex[uint2(s, t)];\r\n#endif\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main(float4 position : SV_Position, float2 uv : TexCoord0) : SV_Target0\r\n{\r\n    float2 t = uv * TextureSize + 0.5;\r\n    float2 f = frac(t);\r\n    int2 st = int2(t);\r\n\r\n    uint MaxWidth = TextureSize.x - 1;\r\n    uint MaxHeight = TextureSize.y - 1;\r\n\r\n    uint s0 = max(st.x - 2, 0);\r\n    uint s1 = max(st.x - 1, 0);\r\n    uint s2 = min(st.x + 0, MaxWidth);\r\n    uint s3 = min(st.x + 1, MaxWidth);\r\n\r\n    uint t0 = max(st.y - 2, 0);\r\n    uint t1 = max(st.y - 1, 0);\r\n    uint t2 = min(st.y + 0, MaxHeight);\r\n    uint t3 = min(st.y + 1, MaxHeight);\r\n\r\n    float4 Weights = GetWeights(f.x);\r\n    float3 c0 = Cubic(Weights, GetColor(s0, t0), GetColor(s1, t0), GetColor(s2, t0), GetColor(s3, t0));\r\n    float3 c1 = Cubic(Weights, GetColor(s0, t1), GetColor(s1, t1), GetColor(s2, t1), GetColor(s3, t1));\r\n    float3 c2 = Cubic(Weights, GetColor(s0, t2), GetColor(s1, t2), GetColor(s2, t2), GetColor(s3, t2));\r\n    float3 c3 = Cubic(Weights, GetColor(s0, t3), GetColor(s1, t3), GetColor(s2, t3), GetColor(s3, t3));\r\n    float3 Color = Cubic(GetWeights(f.y), c0, c1, c2, c3);\r\n\r\n#ifdef GAMMA_SPACE\r\n    return Color;\r\n#else\r\n    return ApplyDisplayProfile(Color, DISPLAY_PLANE_FORMAT);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BicubicVerticalUpsamplePS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Simple bicubic filter\r\n//\r\n// http://en.wikipedia.org/wiki/Bicubic_interpolation\r\n// http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html\r\n//\r\n//--------------------------------------------------------------------------------------\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    uint2 TextureSize;\r\n    float A;\r\n}\r\n\r\nfloat W1(float x)\r\n{\r\n    return x * x * ((A + 2) * x - (A + 3)) + 1.0;\r\n}\r\n\r\nfloat W2(float x)\r\n{\r\n    return A * (x * (x * (x - 5) + 8) - 4);\r\n}\r\n\r\nfloat4 GetWeights(float d1)\r\n{\r\n    return float4(W2(1.0 + d1), W1(d1), W1(1.0 - d1), W2(2.0 - d1));\r\n}\r\n\r\nfloat3 GetColor(uint s, uint t)\r\n{\r\n    return ColorTex[uint2(s, t)];\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main(float4 position : SV_Position, float2 uv : TexCoord0) : SV_Target0\r\n{\r\n    float2 t = uv * TextureSize + 0.5;\r\n    float2 f = frac(t);\r\n    int2 st = int2(position.x, t.y);\r\n\r\n    uint MaxHeight = TextureSize.y - 1;\r\n\r\n    uint t0 = max(st.y - 2, 0);\r\n    uint t1 = max(st.y - 1, 0);\r\n    uint t2 = min(st.y + 0, MaxHeight);\r\n    uint t3 = min(st.y + 1, MaxHeight);\r\n\r\n    float4 W = GetWeights(f.y);\r\n    float3 Color =\r\n        W.x * GetColor(st.x, t0) +\r\n        W.y * GetColor(st.x, t1) +\r\n        W.z * GetColor(st.x, t2) +\r\n        W.w * GetColor(st.x, t3);\r\n\r\n#ifdef GAMMA_SPACE\r\n        return Color;\r\n#else\r\n        return ApplyDisplayProfile(Color, DISPLAY_PLANE_FORMAT);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BilinearUpsamplePS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\n\r\nSamplerState BilinearFilter : register(s0);\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main( float4 position : SV_Position, float2 uv : TexCoord0 ) : SV_Target0\r\n{\r\n    float3 LinearRGB = RemoveDisplayProfile(ColorTex.SampleLevel(BilinearFilter, uv, 0), LDR_COLOR_FORMAT);\r\n    return ApplyDisplayProfile(LinearRGB, DISPLAY_PLANE_FORMAT);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/Bitonic32InnerSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// Description:  The bitonic sort works by sorting groups of size k,\r\n// starting with k=2 and doubling until k>=NumItems.  To sort the\r\n// group, keys are compared with a distance of j, which starts at half\r\n// of k and continues halving down to 1.  When j is 1024 and less, the\r\n// compare and swap can happen in LDS, and these iterations form the\r\n// \"inner sort\".  Inner sorting happens in LDS and loops.  Outer sorting\r\n// happens in memory and does not loop.  (Looping happens on the CPU by\r\n// issuing sequential dispatches and barriers.)\r\n\r\n\r\n#include \"BitonicSortCommon.hlsli\"\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    uint k; // k >= 4096\r\n};\r\n\r\n#ifdef BITONICSORT_64BIT\r\n\r\nRWStructuredBuffer<uint2> g_SortBuffer : register(u0);\r\n\r\ngroupshared uint gs_SortKeys[2048];\r\ngroupshared uint gs_SortIndices[2048];\r\n\r\nvoid LoadKeyIndexPair( uint Element, uint ListCount )\r\n{\r\n    uint2 KeyIndex = Element < ListCount ? g_SortBuffer[Element] : NullItem;\r\n    gs_SortIndices[Element & 2047] = KeyIndex.x;\r\n    gs_SortKeys[Element & 2047] = KeyIndex.y;\r\n}\r\n\r\nvoid StoreKeyIndexPair( uint Element, uint ListCount )\r\n{\r\n    if (Element < ListCount)\r\n        g_SortBuffer[Element] = uint2(gs_SortIndices[Element & 2047], gs_SortKeys[Element & 2047]);\r\n}\r\n\r\n#else // 32-bit packed key/index pairs\r\n\r\nRWStructuredBuffer<uint> g_SortBuffer : register(u0);\r\n\r\ngroupshared uint gs_SortKeys[2048];\r\n\r\nvoid LoadKeyIndexPair( uint Element, uint ListCount )\r\n{\r\n    gs_SortKeys[Element & 2047] = Element < ListCount ? g_SortBuffer[Element] : NullItem;\r\n}\r\n\r\nvoid StoreKeyIndexPair( uint Element, uint ListCount )\r\n{\r\n    if (Element < ListCount)\r\n        g_SortBuffer[Element] = gs_SortKeys[Element & 2047];\r\n}\r\n\r\n#endif\r\n\r\n[RootSignature(BitonicSort_RootSig)]\r\n[numthreads(1024, 1, 1)]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex )\r\n{\r\n    const uint ListCount = g_CounterBuffer.Load(CounterOffset);\r\n\r\n    // Item index of the start of this group\r\n    const uint GroupStart = Gid.x * 2048;\r\n\r\n    // Load from memory into LDS to prepare sort\r\n    LoadKeyIndexPair(GroupStart + GI, ListCount);\r\n    LoadKeyIndexPair(GroupStart + GI + 1024, ListCount);\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // This is better unrolled because it reduces ALU and because some\r\n    // architectures can load/store two LDS items in a single instruction\r\n    // as long as their separation is a compile-time constant.\r\n    [unroll]\r\n    for (uint j = 1024; j > 0; j /= 2)\r\n    {\r\n        uint Index2 = InsertOneBit(GI, j);\r\n        uint Index1 = Index2 ^ j;\r\n\r\n        uint A = gs_SortKeys[Index1];\r\n        uint B = gs_SortKeys[Index2];\r\n\r\n        if (ShouldSwap(A, B))\r\n        {\r\n            // Swap the keys\r\n            gs_SortKeys[Index1] = B;\r\n            gs_SortKeys[Index2] = A;\r\n\r\n#ifdef BITONICSORT_64BIT\r\n            // Then swap the indices (for 64-bit sorts)\r\n            A = gs_SortIndices[Index1];\r\n            B = gs_SortIndices[Index2];\r\n            gs_SortIndices[Index1] = B;\r\n            gs_SortIndices[Index2] = A;\r\n#endif\r\n        }\r\n\r\n        GroupMemoryBarrierWithGroupSync();\r\n    }\r\n\r\n    StoreKeyIndexPair(GroupStart + GI, ListCount);\r\n    StoreKeyIndexPair(GroupStart + GI + 1024, ListCount);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/Bitonic32OuterSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"BitonicSortCommon.hlsli\"\r\n\r\n#ifdef BITONICSORT_64BIT\r\nRWStructuredBuffer<uint2> g_SortBuffer : register(u0);\r\n#else\r\nRWStructuredBuffer<uint> g_SortBuffer : register(u0);\r\n#endif\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    uint k;\t// k >= 4096\r\n    uint j;\t// j >= 2048 && j < k\r\n};\r\n\r\n[RootSignature(BitonicSort_RootSig)]\r\n[numthreads(1024, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID  )\r\n{\r\n    const uint ListCount = g_CounterBuffer.Load(CounterOffset);\r\n\r\n    // Form unique index pair from dispatch thread ID\r\n    uint Index2 = InsertOneBit(DTid.x, j);\r\n    uint Index1 = Index2 ^ (k == 2 * j ? k - 1 : j);\r\n\r\n    if (Index2 >= ListCount)\r\n        return;\r\n\r\n#ifdef BITONICSORT_64BIT\r\n    uint2 A = g_SortBuffer[Index1];\r\n    uint2 B = g_SortBuffer[Index2];\r\n#else\r\n    uint A = g_SortBuffer[Index1];\r\n    uint B = g_SortBuffer[Index2];\r\n#endif\r\n\r\n    if (ShouldSwap(A, B))\r\n    {\r\n        g_SortBuffer[Index1] = B;\r\n        g_SortBuffer[Index2] = A;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/Bitonic32PreSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// Description:  A bitonic sort must eventually sort the power-of-two\r\n// ceiling of items.  E.g. 391 items -> 512 items.  Because of this\r\n// \"null items\" must be used as padding at the end of the list so that\r\n// they can participate in the sort but remain at the end of the list.\r\n//\r\n// The pre-sort does two things.  It appends null items as need, and\r\n// it does the initial sort for k values up to 2048.  This is because\r\n// we can run 1024 threads, each of of which can compare and swap two\r\n// elements without contention.  And because we can always fit 2048\r\n// keys & indices in LDS with occupancy greater than one.  (A single\r\n// thread group can use as much as 32KB of LDS.)\r\n\r\n\r\n#include \"BitonicSortCommon.hlsli\"\r\n\r\n#ifdef BITONICSORT_64BIT\r\n\r\nRWStructuredBuffer<uint2> g_SortBuffer : register(u0);\r\n\r\ngroupshared uint gs_SortIndices[2048];\r\ngroupshared uint gs_SortKeys[2048];\r\n\r\nvoid FillSortKey( uint Element, uint ListCount )\r\n{\r\n    // Unused elements must sort to the end\r\n    if (Element < ListCount)\r\n    {\r\n        uint2 KeyIndexPair = g_SortBuffer[Element];\r\n        gs_SortKeys[Element & 2047] = KeyIndexPair.y;\r\n        gs_SortIndices[Element & 2047] = KeyIndexPair.x;\r\n    }\r\n    else\r\n    {\r\n        gs_SortKeys[Element & 2047] = NullItem;\r\n    }\r\n}\r\n\r\nvoid StoreKeyIndexPair( uint Element, uint ListCount)\r\n{\r\n    if (Element < ListCount)\r\n        g_SortBuffer[Element] = uint2(gs_SortIndices[Element & 2047], gs_SortKeys[Element & 2047]);\r\n}\r\n\r\n#else // 32-bit packed key/index pairs\r\n\r\nRWStructuredBuffer<uint> g_SortBuffer : register(u0);\r\n\r\ngroupshared uint gs_SortKeys[2048];\r\n\r\nvoid FillSortKey( uint Element, uint ListCount )\r\n{\r\n    // Unused elements must sort to the end\r\n    gs_SortKeys[Element & 2047] = (Element < ListCount ? g_SortBuffer[Element] : NullItem);\r\n}\r\n\r\nvoid StoreKeyIndexPair( uint Element, uint ListCount )\r\n{\r\n    if (Element < ListCount)\r\n        g_SortBuffer[Element] = gs_SortKeys[Element & 2047];\r\n}\r\n\r\n#endif\r\n\r\n[RootSignature(BitonicSort_RootSig)]\r\n[numthreads(1024, 1, 1)]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex )\r\n{\r\n    // Item index of the start of this group\r\n    const uint GroupStart = Gid.x * 2048;\r\n\r\n    // Actual number of items that need sorting\r\n    const uint ListCount = g_CounterBuffer.Load(CounterOffset);\r\n\r\n    FillSortKey(GroupStart + GI, ListCount);\r\n    FillSortKey(GroupStart + GI + 1024, ListCount);\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint k;\r\n\r\n    // This is better unrolled because it reduces ALU and because some\r\n    // architectures can load/store two LDS items in a single instruction\r\n    // as long as their separation is a compile-time constant.\r\n    [unroll]\r\n    for (k = 2; k <= 2048; k <<= 1)\r\n    {\r\n        [unroll]\r\n        for (uint j = k / 2; j > 0; j /= 2)\r\n        {\r\n            uint Index2 = InsertOneBit(GI, j);\r\n            uint Index1 = Index2 ^ (k == 2 * j ? k - 1 : j);\r\n\r\n            uint A = gs_SortKeys[Index1];\r\n            uint B = gs_SortKeys[Index2];\r\n\r\n            if (ShouldSwap(A, B))\r\n            {\r\n                // Swap the keys\r\n                gs_SortKeys[Index1] = B;\r\n                gs_SortKeys[Index2] = A;\r\n\r\n#ifdef BITONICSORT_64BIT\r\n                // Then swap the indices (for 64-bit sorts)\r\n                A = gs_SortIndices[Index1];\r\n                B = gs_SortIndices[Index2];\r\n                gs_SortIndices[Index1] = B;\r\n                gs_SortIndices[Index2] = A;\r\n#endif\r\n            }\r\n\r\n            GroupMemoryBarrierWithGroupSync();\r\n        }\r\n    }\r\n\r\n    // Write sorted results to memory\r\n    StoreKeyIndexPair(GroupStart + GI, ListCount);\r\n    StoreKeyIndexPair(GroupStart + GI + 1024, ListCount);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/Bitonic64InnerSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define BITONICSORT_64BIT\r\n#include \"Bitonic32InnerSortCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/Bitonic64OuterSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define BITONICSORT_64BIT\r\n#include \"Bitonic32OuterSortCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/Bitonic64PreSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define BITONICSORT_64BIT\r\n#include \"Bitonic32PreSortCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BitonicIndirectArgsCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"BitonicSortCommon.hlsli\"\r\n\r\nRWByteAddressBuffer g_IndirectArgsBuffer : register(u0);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    uint MaxIterations;\r\n}\r\n\r\nuint NextPow2( uint Val )\r\n{\r\n    uint Mask = (1 << firstbithigh(Val)) - 1;\r\n    return (Val + Mask) & ~Mask;\r\n}\r\n\r\n[RootSignature(BitonicSort_RootSig)]\r\n[numthreads(22, 1, 1)]\r\nvoid main( uint GI : SV_GroupIndex )\r\n{\r\n    if (GI >= MaxIterations)\r\n        return;\r\n\r\n    uint ListCount = g_CounterBuffer.Load(CounterOffset);\r\n    uint k = 2048 << GI;\r\n\r\n    // We need one more iteration every time the number of thread groups doubles\r\n    if (k > NextPow2((ListCount + 2047) & ~2047))\r\n        ListCount = 0;\r\n\r\n    uint PrevDispatches = GI * (GI + 1) / 2;\r\n    uint Offset = 12 * PrevDispatches;\r\n\r\n    // Generate outer sort dispatch arguments\r\n    for (uint j = k / 2; j > 1024; j /= 2)\r\n    {\r\n        // All of the groups of size 2j that are full\r\n        uint CompleteGroups = (ListCount & ~(2 * j - 1)) / 2048;\r\n\r\n        // Remaining items must only be sorted if there are more than j of them\r\n        uint PartialGroups = ((uint)max(int(ListCount - CompleteGroups * 2048 - j), 0) + 1023) / 1024;\r\n\r\n        g_IndirectArgsBuffer.Store3(Offset, uint3(CompleteGroups + PartialGroups, 1, 1));\r\n\r\n        Offset += 12;\r\n    }\r\n\r\n    // The inner sort always sorts all groups (rounded up to multiples of 2048)\r\n    g_IndirectArgsBuffer.Store3(Offset, uint3((ListCount + 2047) / 2048, 1, 1));\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BitonicSortCommon.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define BitonicSort_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 2),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 1)),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 1)),\" \\\n    \"RootConstants(b1, num32BitConstants = 2)\"\n\nByteAddressBuffer g_CounterBuffer : register(t0);\n\ncbuffer CB1 : register(b1)\n{\n    // Offset into counter buffer where this list's item count is stored\n    uint CounterOffset;\n\n    // A sort key that will end up at the end of the list; to be used to pad\n    // lists in LDS (always 2048 items).\n    //   Descending:  0x00000000\n    //   Ascending:   0xffffffff\n    // Also used by the ShouldSwap() function to invert ordering.\n    uint NullItem; \n}\n\n// Takes Value and widens it by one bit at the location of the bit\n// in the mask.  A one is inserted in the space.  OneBitMask must\n// have one and only one bit set.\nuint InsertOneBit( uint Value, uint OneBitMask )\n{\n    uint Mask = OneBitMask - 1;\n    return (Value & ~Mask) << 1 | (Value & Mask) | OneBitMask;\n}\n\n// Determines if two sort keys should be swapped in the list.  NullItem is\n// either 0 or 0xffffffff.  XOR with the NullItem will either invert the bits\n// (effectively a negation) or leave the bits alone.  When the the NullItem is\n// 0, we are sorting descending, so when A < B, they should swap.  For an\n// ascending sort, ~A < ~B should swap.\nbool ShouldSwap(uint A, uint B)\n{\n    return (A ^ NullItem) < (B ^ NullItem);\n}\n\n// Same as above, but only compares the upper 32-bit word.\nbool ShouldSwap(uint2 A, uint2 B)\n{\n    return (A.y ^ NullItem) < (B.y ^ NullItem);\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BloomExtractAndDownsampleHdrCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for extracting bright pixels and downsampling them to an unblurred bloom buffer.\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nSamplerState BiLinearClamp : register( s0 );\r\nTexture2D<float3> SourceTex : register( t0 );\r\nStructuredBuffer<float> Exposure : register( t1 );\r\nRWTexture2D<float3> BloomResult : register( u0 );\r\nRWTexture2D<uint> LumaResult : register( u1 );\r\n\r\ncbuffer cb0\r\n{\r\n    float2 g_inverseOutputSize;\r\n    float g_bloomThreshold;\r\n}\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    // We need the scale factor and the size of one pixel so that our four samples are right in the middle\r\n    // of the quadrant they are covering.\r\n    float2 uv = (DTid.xy + 0.5) * g_inverseOutputSize;\r\n    float2 offset = g_inverseOutputSize * 0.25;\r\n\r\n    // Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x\r\n    float3 color1 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x, -offset.y), 0 );\r\n    float3 color2 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x, -offset.y), 0 );\r\n    float3 color3 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x,  offset.y), 0 );\r\n    float3 color4 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x,  offset.y), 0 );\r\n\r\n    float luma1 = RGBToLuminance(color1);\r\n    float luma2 = RGBToLuminance(color2);\r\n    float luma3 = RGBToLuminance(color3);\r\n    float luma4 = RGBToLuminance(color4);\r\n\r\n    const float kSmallEpsilon = 0.0001;\r\n\r\n    float ScaledThreshold = g_bloomThreshold * Exposure[1];\t// BloomThreshold / Exposure\r\n\r\n    // We perform a brightness filter pass, where lone bright pixels will contribute less.\r\n    color1 *= max(kSmallEpsilon, luma1 - ScaledThreshold) / (luma1 + kSmallEpsilon);\r\n    color2 *= max(kSmallEpsilon, luma2 - ScaledThreshold) / (luma2 + kSmallEpsilon);\r\n    color3 *= max(kSmallEpsilon, luma3 - ScaledThreshold) / (luma3 + kSmallEpsilon);\r\n    color4 *= max(kSmallEpsilon, luma4 - ScaledThreshold) / (luma4 + kSmallEpsilon);\r\n\r\n    // The shimmer filter helps remove stray bright pixels from the bloom buffer by inversely weighting\r\n    // them by their luminance.  The overall effect is to shrink bright pixel regions around the border.\r\n    // Lone pixels are likely to dissolve completely.  This effect can be tuned by adjusting the shimmer\r\n    // filter inverse strength.  The bigger it is, the less a pixel's luminance will matter.\r\n    const float kShimmerFilterInverseStrength = 1.0f;\r\n    float weight1 = 1.0f / (luma1 + kShimmerFilterInverseStrength);\r\n    float weight2 = 1.0f / (luma2 + kShimmerFilterInverseStrength);\r\n    float weight3 = 1.0f / (luma3 + kShimmerFilterInverseStrength);\r\n    float weight4 = 1.0f / (luma4 + kShimmerFilterInverseStrength);\r\n    float weightSum = weight1 + weight2 + weight3 + weight4;\r\n\r\n    BloomResult[DTid.xy] = (color1 * weight1 + color2 * weight2 + color3 * weight3 + color4 * weight4) / weightSum;\r\n\r\n    float luma = (luma1 + luma2 + luma3 + luma4) * 0.25;\r\n\r\n    // Prevent log(0) and put only pure black pixels in Histogram[0]\r\n    if (luma == 0.0)\r\n    {\r\n        LumaResult[DTid.xy] = 0;\r\n    }\r\n    else\r\n    {\r\n        const float MinLog = Exposure[4];\r\n        const float RcpLogRange = Exposure[7];\r\n        float logLuma = saturate((log2(luma) - MinLog) * RcpLogRange);\t// Rescale to [0.0, 1.0]\r\n        LumaResult[DTid.xy] = logLuma * 254.0 + 1.0;\t\t\t\t\t// Rescale to [1, 255]\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BloomExtractAndDownsampleLdrCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for extracting bright pixels and downsampling them to an unblurred bloom buffer.\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nSamplerState BiLinearClamp : register( s0 );\r\nTexture2D<float3> SourceTex : register( t0 );\r\nRWTexture2D<float3> BloomResult : register( u0 );\r\n\r\ncbuffer cb0\r\n{\r\n    float2 g_inverseOutputSize;\r\n    float g_bloomThreshold;\r\n}\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    // We need the scale factor and the size of one pixel so that our four samples are right in the middle\r\n    // of the quadrant they are covering.\r\n    float2 uv = (DTid.xy + 0.5) * g_inverseOutputSize;\r\n    float2 offset = g_inverseOutputSize * 0.25;\r\n\r\n    // Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x\r\n    float3 color1 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x, -offset.y), 0 );\r\n    float3 color2 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x, -offset.y), 0 );\r\n    float3 color3 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x,  offset.y), 0 );\r\n    float3 color4 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x,  offset.y), 0 );\r\n\r\n    float luma1 = RGBToLuminance(color1);\r\n    float luma2 = RGBToLuminance(color2);\r\n    float luma3 = RGBToLuminance(color3);\r\n    float luma4 = RGBToLuminance(color4);\r\n\r\n    const float kSmallEpsilon = 0.0001;\r\n\r\n    float ScaledThreshold = g_bloomThreshold;\r\n\r\n    // We perform a brightness filter pass, where lone bright pixels will contribute less.\r\n    color1 *= max(kSmallEpsilon, luma1 - ScaledThreshold) / (luma1 + kSmallEpsilon);\r\n    color2 *= max(kSmallEpsilon, luma2 - ScaledThreshold) / (luma2 + kSmallEpsilon);\r\n    color3 *= max(kSmallEpsilon, luma3 - ScaledThreshold) / (luma3 + kSmallEpsilon);\r\n    color4 *= max(kSmallEpsilon, luma4 - ScaledThreshold) / (luma4 + kSmallEpsilon);\r\n\r\n    // The shimmer filter helps remove stray bright pixels from the bloom buffer by inversely weighting\r\n    // them by their luminance.  The overall effect is to shrink bright pixel regions around the border.\r\n    // Lone pixels are likely to dissolve completely.  This effect can be tuned by adjusting the shimmer\r\n    // filter inverse strength.  The bigger it is, the less a pixel's luminance will matter.\r\n    const float kShimmerFilterInverseStrength = 1.0f;\r\n    float weight1 = 1.0f / (luma1 + kShimmerFilterInverseStrength);\r\n    float weight2 = 1.0f / (luma2 + kShimmerFilterInverseStrength);\r\n    float weight3 = 1.0f / (luma3 + kShimmerFilterInverseStrength);\r\n    float weight4 = 1.0f / (luma4 + kShimmerFilterInverseStrength);\r\n    float weightSum = weight1 + weight2 + weight3 + weight4;\r\n\r\n    BloomResult[DTid.xy] = (color1 * weight1 + color2 * weight2 + color3 * weight3 + color4 * weight4) / weightSum;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BlurCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for guassian blurring a single RGB buffer.\r\n//\r\n// For the intended bloom blurring algorithm, this shader is expected to be used only on\r\n// the lowest resolution bloom buffer before starting the series of upsample-and-blur\r\n// passes.\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nTexture2D<float3> InputBuf : register( t0 );\r\nRWTexture2D<float3> Result : register( u0 );\r\n\r\ncbuffer cb0 : register(b0)\r\n{\r\n    float2 g_inverseDimensions;\r\n}\r\n\r\n// The guassian blur weights (derived from Pascal's triangle)\r\nstatic const float Weights[5] = { 70.0f / 256.0f, 56.0f / 256.0f, 28.0f / 256.0f, 8.0f / 256.0f, 1.0f / 256.0f };\r\n\r\nfloat3 BlurPixels( float3 a, float3 b, float3 c, float3 d, float3 e, float3 f, float3 g, float3 h, float3 i )\r\n{\r\n    return Weights[0]*e + Weights[1]*(d+f) + Weights[2]*(c+g) + Weights[3]*(b+h) + Weights[4]*(a+i);\r\n}\r\n\r\n// 16x16 pixels with an 8x8 center that we will be blurring writing out.  Each uint is two color channels packed together\r\ngroupshared uint CacheR[128];\r\ngroupshared uint CacheG[128];\r\ngroupshared uint CacheB[128];\r\n\r\nvoid Store2Pixels( uint index, float3 pixel1, float3 pixel2 )\r\n{\r\n    CacheR[index] = f32tof16(pixel1.r) | f32tof16(pixel2.r) << 16;\r\n    CacheG[index] = f32tof16(pixel1.g) | f32tof16(pixel2.g) << 16;\r\n    CacheB[index] = f32tof16(pixel1.b) | f32tof16(pixel2.b) << 16;\r\n}\r\n\r\nvoid Load2Pixels( uint index, out float3 pixel1, out float3 pixel2 )\r\n{\r\n    uint rr = CacheR[index];\r\n    uint gg = CacheG[index];\r\n    uint bb = CacheB[index];\r\n    pixel1 = float3( f16tof32(rr      ), f16tof32(gg      ), f16tof32(bb      ) );\r\n    pixel2 = float3( f16tof32(rr >> 16), f16tof32(gg >> 16), f16tof32(bb >> 16) );\r\n}\r\n\r\nvoid Store1Pixel( uint index, float3 pixel )\r\n{\r\n    CacheR[index] = asuint(pixel.r);\r\n    CacheG[index] = asuint(pixel.g);\r\n    CacheB[index] = asuint(pixel.b);\r\n}\r\n\r\nvoid Load1Pixel( uint index, out float3 pixel )\r\n{\r\n    pixel = asfloat( uint3(CacheR[index], CacheG[index], CacheB[index]) );\r\n}\r\n\r\n// Blur two pixels horizontally.  This reduces LDS reads and pixel unpacking.\r\nvoid BlurHorizontally( uint outIndex, uint leftMostIndex )\r\n{\r\n    float3 s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n    Load2Pixels( leftMostIndex + 0, s0, s1 );\r\n    Load2Pixels( leftMostIndex + 1, s2, s3 );\r\n    Load2Pixels( leftMostIndex + 2, s4, s5 );\r\n    Load2Pixels( leftMostIndex + 3, s6, s7 );\r\n    Load2Pixels( leftMostIndex + 4, s8, s9 );\r\n    \r\n    Store1Pixel(outIndex  , BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8));\r\n    Store1Pixel(outIndex+1, BlurPixels(s1, s2, s3, s4, s5, s6, s7, s8, s9));\r\n}\r\n\r\nvoid BlurVertically( uint2 pixelCoord, uint topMostIndex )\r\n{\r\n    float3 s0, s1, s2, s3, s4, s5, s6, s7, s8;\r\n    Load1Pixel( topMostIndex   , s0 );\r\n    Load1Pixel( topMostIndex+ 8, s1 );\r\n    Load1Pixel( topMostIndex+16, s2 );\r\n    Load1Pixel( topMostIndex+24, s3 );\r\n    Load1Pixel( topMostIndex+32, s4 );\r\n    Load1Pixel( topMostIndex+40, s5 );\r\n    Load1Pixel( topMostIndex+48, s6 );\r\n    Load1Pixel( topMostIndex+56, s7 );\r\n    Load1Pixel( topMostIndex+64, s8 );\r\n\r\n    Result[pixelCoord] = BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8);\r\n}\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    //\r\n    // Load 4 pixels per thread into LDS\r\n    //\r\n    int2 GroupUL = (Gid.xy << 3) - 4;\t\t\t\t// Upper-left pixel coordinate of group read location\r\n    int2 ThreadUL = (GTid.xy << 1) + GroupUL;\t\t// Upper-left pixel coordinate of quad that this thread will read\r\n\r\n    //\r\n    // Store 4 unblurred pixels in LDS\r\n    //\r\n    int destIdx = GTid.x + (GTid.y << 4);\r\n    Store2Pixels(destIdx+0, InputBuf[ThreadUL + uint2(0, 0)], InputBuf[ThreadUL + uint2(1, 0)]);\r\n    Store2Pixels(destIdx+8, InputBuf[ThreadUL + uint2(0, 1)], InputBuf[ThreadUL + uint2(1, 1)]);\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    //\r\n    // Horizontally blur the pixels in Cache\r\n    //\r\n    uint row = GTid.y << 4;\r\n    BlurHorizontally(row + (GTid.x << 1), row + GTid.x + (GTid.x & 4));\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    //\r\n    // Vertically blur the pixels and write the result to memory\r\n    //\r\n    BlurVertically(DTid.xy, (GTid.y << 3) + GTid.x);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BoundNeighborhoodCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"TemporalRS.hlsli\"\r\n\r\nTexture2D<float3> InputColor : register(t0);\r\nRWTexture2D<float3> OutMin : register(u0);\r\nRWTexture2D<float3> OutMax : register(u1);\r\n\r\n#define BORDER_SIZE 1\r\n#define GROUP_SIZE_X 8\r\n#define GROUP_SIZE_Y 8\r\n#define GROUP_SIZE (GROUP_SIZE_X * GROUP_SIZE_Y)\r\n#define TILE_SIZE_X (GROUP_SIZE_X + 2 * BORDER_SIZE)\r\n#define TILE_SIZE_Y (GROUP_SIZE_Y + 2 * BORDER_SIZE)\r\n#define TILE_PIXEL_COUNT (TILE_SIZE_X * TILE_SIZE_Y)\r\n\r\ngroupshared float gs_MinR[TILE_PIXEL_COUNT];\r\ngroupshared float gs_MinG[TILE_PIXEL_COUNT];\r\ngroupshared float gs_MinB[TILE_PIXEL_COUNT];\r\ngroupshared float gs_MaxR[TILE_PIXEL_COUNT];\r\ngroupshared float gs_MaxG[TILE_PIXEL_COUNT];\r\ngroupshared float gs_MaxB[TILE_PIXEL_COUNT];\r\n\r\nvoid ConvolveH( uint Idx )\r\n{\r\n    gs_MinR[Idx] = min(min(gs_MinR[Idx - 1], gs_MinR[Idx]), gs_MinR[Idx + 1]);\r\n    gs_MinG[Idx] = min(min(gs_MinG[Idx - 1], gs_MinG[Idx]), gs_MinG[Idx + 1]);\r\n    gs_MinB[Idx] = min(min(gs_MinB[Idx - 1], gs_MinB[Idx]), gs_MinB[Idx + 1]);\r\n    gs_MaxR[Idx] = max(max(gs_MaxR[Idx - 1], gs_MaxR[Idx]), gs_MaxR[Idx + 1]);\r\n    gs_MaxG[Idx] = max(max(gs_MaxG[Idx - 1], gs_MaxG[Idx]), gs_MaxG[Idx + 1]);\r\n    gs_MaxB[Idx] = max(max(gs_MaxB[Idx - 1], gs_MaxB[Idx]), gs_MaxB[Idx + 1]);\r\n}\r\n\r\nvoid ConvolveV( uint Idx, uint2 st )\r\n{\r\n    float minR = min(min(gs_MinR[Idx - TILE_SIZE_X], gs_MinR[Idx]), gs_MinR[Idx + TILE_SIZE_X]);\r\n    float minG = min(min(gs_MinG[Idx - TILE_SIZE_X], gs_MinG[Idx]), gs_MinG[Idx + TILE_SIZE_X]);\r\n    float minB = min(min(gs_MinB[Idx - TILE_SIZE_X], gs_MinB[Idx]), gs_MinB[Idx + TILE_SIZE_X]);\r\n    OutMin[st] = float3(minR, minG, minB);\r\n\r\n    float maxR = max(max(gs_MaxR[Idx - TILE_SIZE_X], gs_MaxR[Idx]), gs_MaxR[Idx + TILE_SIZE_X]);\r\n    float maxG = max(max(gs_MaxG[Idx - TILE_SIZE_X], gs_MaxG[Idx]), gs_MaxG[Idx + TILE_SIZE_X]);\r\n    float maxB = max(max(gs_MaxB[Idx - TILE_SIZE_X], gs_MaxB[Idx]), gs_MaxB[Idx + TILE_SIZE_X]);\r\n    OutMax[st] = float3(maxR, maxG, maxB);\r\n}\r\n\r\n[RootSignature(Temporal_RootSig)]\r\n[numthreads( GROUP_SIZE_X, GROUP_SIZE_Y, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex )\r\n{\r\n    // Load tile pixels\r\n\r\n    int2 GroupUL = Gid.xy * uint2(GROUP_SIZE_X, GROUP_SIZE_Y) - BORDER_SIZE;\r\n    for (uint i = GI; i < TILE_PIXEL_COUNT; i += GROUP_SIZE)\r\n    {\r\n        float3 Color = InputColor[GroupUL + uint2(i % TILE_SIZE_X, i / TILE_SIZE_X)];\r\n        gs_MinR[i] = gs_MaxR[i] = Color.r;\r\n        gs_MinG[i] = gs_MaxG[i] = Color.g;\r\n        gs_MinB[i] = gs_MaxB[i] = Color.b;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint Idx = (GTid.x + BORDER_SIZE) + (GTid.y + BORDER_SIZE) * TILE_SIZE_X;\r\n\r\n    float R0 = gs_MinR[Idx], R1 = gs_MinR[Idx - 1], R2 = gs_MinR[Idx + 1], R3 = gs_MinR[Idx - TILE_SIZE_X], R4 = gs_MinR[Idx + TILE_SIZE_X];\r\n    float minR = min(min(R0, R1), min(min(R2, R3), R4));\r\n    float maxR = max(max(R0, R1), max(max(R2, R3), R4));\r\n\r\n    float G0 = gs_MinG[Idx], G1 = gs_MinG[Idx - 1], G2 = gs_MinG[Idx + 1], G3 = gs_MinG[Idx - TILE_SIZE_X], G4 = gs_MinG[Idx + TILE_SIZE_X];\r\n    float minG = min(min(G0, G1), min(min(G2, G3), G4));\r\n    float maxG = max(max(G0, G1), max(max(G2, G3), G4));\r\n\r\n    float B0 = gs_MinB[Idx], B1 = gs_MinB[Idx - 1], B2 = gs_MinB[Idx + 1], B3 = gs_MinB[Idx - TILE_SIZE_X], B4 = gs_MinB[Idx + TILE_SIZE_X];\r\n    float minB = min(min(B0, B1), min(min(B2, B3), B4));\r\n    float maxB = max(max(B0, B1), max(max(B2, B3), B4));\r\n\r\n    OutMin[DTid.xy] = float3(minR, minG, minB);\r\n    OutMax[DTid.xy] = float3(maxR, maxG, maxB);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/BufferCopyPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D ColorTex : register(t0);\r\nSamplerState BilinearSampler : register(s0);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    float2 RcpDestDim;\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat4 main( float4 position : SV_Position ) : SV_Target0\r\n{\r\n    //float2 UV = saturate(RcpDestDim * position.xy);\r\n    //return ColorTex.SampleLevel(BilinearSampler, UV, 0);\r\n    return ColorTex[(int2)position.xy];\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/CameraMotionBlurPrePassCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"MotionBlurRS.hlsli\"\r\n#include \"PixelPacking_Velocity.hlsli\"\r\n\r\n// We can use the original depth buffer or a linearized one.  In this case, we use linear Z because\r\n// we have discarded the 32-bit depth buffer but still retain a 16-bit linear buffer (previously\r\n// used by SSAO.)  Note that hyperbolic Z is reversed by default (TBD) for increased precision, so\r\n// its Z=0 maps to the far plane.  With linear Z, Z=0 maps to the eye position.  Both extend to Z=1.\r\n\r\n//#define USE_LINEAR_Z\r\n\r\nTexture2D<float3> ColorBuffer : register(t0);\r\nTexture2D<float> DepthBuffer : register(t1);\r\nRWTexture2D<float4> PrepBuffer : register(u0);\r\nRWTexture2D<packed_velocity_t> VelocityBuffer : register(u1);\r\n\r\ncbuffer CB1 : register(b1)\r\n{\r\n    matrix CurToPrevXForm;\r\n}\r\n\r\nfloat4 GetSampleData( uint2 st )\r\n{\r\n    float2 CurPixel = st + 0.5;\r\n    float Depth = DepthBuffer[st];\r\n#ifdef USE_LINEAR_Z\r\n    float4 HPos = float4( CurPixel * Depth, 1.0, Depth );\r\n#else\r\n    float4 HPos = float4( CurPixel, Depth, 1.0 );\r\n#endif\r\n    float4 PrevHPos = mul( CurToPrevXForm, HPos );\r\n\r\n    PrevHPos.xyz /= PrevHPos.w;\r\n\r\n#ifdef USE_LINEAR_Z\r\n    PrevHPos.z = PrevHPos.w;\r\n#endif\r\n\r\n    float3 Velocity = PrevHPos.xyz - float3(CurPixel, Depth);\r\n\r\n    VelocityBuffer[st] = PackVelocity(Velocity);\r\n\r\n    // Clamp speed at 4 pixels and normalize it.\r\n    return float4(ColorBuffer[st], 1.0) * saturate(length(Velocity.xy) / 4);\r\n}\r\n\r\n[RootSignature(MotionBlur_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint2 corner = DTid.xy << 1;\r\n    float4 sample0 = GetSampleData( corner + uint2(0, 0) );\r\n    float4 sample1 = GetSampleData( corner + uint2(1, 0) );\r\n    float4 sample2 = GetSampleData( corner + uint2(0, 1) );\r\n    float4 sample3 = GetSampleData( corner + uint2(1, 1) );\r\n\r\n    float combinedMotionWeight = sample0.a + sample1.a + sample2.a + sample3.a;\r\n    PrepBuffer[DTid.xy] = floor(0.25 * combinedMotionWeight * 3.0) / 3.0 * float4(\r\n        (sample0.rgb + sample1.rgb + sample2.rgb + sample3.rgb) / combinedMotionWeight, 1.0 );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/CameraMotionBlurPrePassLinearZCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define USE_LINEAR_Z\r\n#include \"CameraMotionBlurPrePassCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/CameraVelocityCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"MotionBlurRS.hlsli\"\r\n#include \"PixelPacking_Velocity.hlsli\"\r\n\r\n// We can use the original depth buffer or a linearized one.  In this case, we use linear Z because\r\n// we have discarded the 32-bit depth buffer but still retain a 16-bit linear buffer (previously\r\n// used by SSAO.)  Note that hyperbolic Z is reversed by default (TBD) for increased precision, so\r\n// its Z=0 maps to the far plane.  With linear Z, Z=0 maps to the eye position.  Both extend to Z=1.\r\n#define USE_LINEAR_Z\r\n\r\nTexture2D<float> DepthBuffer : register(t0);\r\nRWTexture2D<packed_velocity_t> VelocityBuffer : register(u0);\r\n\r\ncbuffer CBuffer : register(b1)\r\n{\r\n    matrix CurToPrevXForm;\r\n}\r\n\r\n[RootSignature(MotionBlur_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint2 st = DTid.xy;\r\n    float2 CurPixel = st + 0.5;\r\n    float Depth = DepthBuffer[st];\r\n#ifdef USE_LINEAR_Z\r\n    float4 HPos = float4( CurPixel * Depth, 1.0, Depth );\r\n#else\r\n    float4 HPos = float4( CurPixel, Depth, 1.0 );\r\n#endif\r\n    float4 PrevHPos = mul( CurToPrevXForm, HPos );\r\n\r\n    PrevHPos.xyz /= PrevHPos.w;\r\n\r\n#ifdef USE_LINEAR_Z\r\n    PrevHPos.z = PrevHPos.w;\r\n#endif\r\n\r\n    VelocityBuffer[st] = PackVelocity(PrevHPos.xyz - float3(CurPixel, Depth));\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ColorSpaceUtility.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#pragma warning( disable : 3571 )\n\n#ifndef __COLOR_SPACE_UTILITY_HLSLI__\n#define __COLOR_SPACE_UTILITY_HLSLI__\n\n//\n// Gamma ramps and encoding transfer functions\n//\n// Orthogonal to color space though usually tightly coupled.  For instance, sRGB is both a\n// color space (defined by three basis vectors and a white point) and a gamma ramp.  Gamma\n// ramps are designed to reduce perceptual error when quantizing floats to integers with a\n// limited number of bits.  More variation is needed in darker colors because our eyes are\n// more sensitive in the dark.  The way the curve helps is that it spreads out dark values\n// across more code words allowing for more variation.  Likewise, bright values are merged\n// together into fewer code words allowing for less variation.\n//\n// The sRGB curve is not a true gamma ramp but rather a piecewise function comprising a linear\n// section and a power function.  When sRGB-encoded colors are passed to an LCD monitor, they\n// look correct on screen because the monitor expects the colors to be encoded with sRGB, and it\n// removes the sRGB curve to linearize the values.  When textures are encoded with sRGB--as many\n// are--the sRGB curve needs to be removed before involving the colors in linear mathematics such\n// as physically based lighting.\n\nfloat3 ApplySRGBCurve( float3 x )\n{\n    // Approximately pow(x, 1.0 / 2.2)\n    return x < 0.0031308 ? 12.92 * x : 1.055 * pow(x, 1.0 / 2.4) - 0.055;\n}\n\nfloat3 RemoveSRGBCurve( float3 x )\n{\n    // Approximately pow(x, 2.2)\n    return x < 0.04045 ? x / 12.92 : pow( (x + 0.055) / 1.055, 2.4 );\n}\n\n// These functions avoid pow() to efficiently approximate sRGB with an error < 0.4%.\nfloat3 ApplySRGBCurve_Fast( float3 x )\n{\n    return x < 0.0031308 ? 12.92 * x : 1.13005 * sqrt(x - 0.00228) - 0.13448 * x + 0.005719;\n}\n\nfloat3 RemoveSRGBCurve_Fast( float3 x )\n{\n    return x < 0.04045 ? x / 12.92 : -7.43605 * x - 31.24297 * sqrt(-0.53792 * x + 1.279924) + 35.34864;\n}\n\n// The OETF recommended for content shown on HDTVs.  This \"gamma ramp\" may increase contrast as\n// appropriate for viewing in a dark environment.  Always use this curve with Limited RGB as it is\n// used in conjunction with HDTVs.\nfloat3 ApplyREC709Curve( float3 x )\n{\n    return x < 0.0181 ? 4.5 * x : 1.0993 * pow(x, 0.45) - 0.0993;\n}\n\nfloat3 RemoveREC709Curve( float3 x )\n{\n    return x < 0.08145 ? x / 4.5 : pow((x + 0.0993) / 1.0993, 1.0 / 0.45);\n}\n\n// This is the new HDR transfer function, also called \"PQ\" for perceptual quantizer.  Note that REC2084\n// does not also refer to a color space.  REC2084 is typically used with the REC2020 color space.\nfloat3 ApplyREC2084Curve(float3 L)\n{\n    float m1 = 2610.0 / 4096.0 / 4;\n    float m2 = 2523.0 / 4096.0 * 128;\n    float c1 = 3424.0 / 4096.0;\n    float c2 = 2413.0 / 4096.0 * 32;\n    float c3 = 2392.0 / 4096.0 * 32;\n    float3 Lp = pow(L, m1);\n    return pow((c1 + c2 * Lp) / (1 + c3 * Lp), m2);\n}\n\nfloat3 RemoveREC2084Curve(float3 N)\n{\n    float m1 = 2610.0 / 4096.0 / 4;\n    float m2 = 2523.0 / 4096.0 * 128;\n    float c1 = 3424.0 / 4096.0;\n    float c2 = 2413.0 / 4096.0 * 32;\n    float c3 = 2392.0 / 4096.0 * 32;\n    float3 Np = pow(N, 1 / m2);\n    return pow(max(Np - c1, 0) / (c2 - c3 * Np), 1 / m1);\n}\n\n//\n// Color space conversions\n//\n// These assume linear (not gamma-encoded) values.  A color space conversion is a change\n// of basis (like in Linear Algebra).  Since a color space is defined by three vectors--\n// the basis vectors--changing space involves a matrix-vector multiplication.  Note that\n// changing the color space may result in colors that are \"out of bounds\" because some\n// color spaces have larger gamuts than others.  When converting some colors from a wide\n// gamut to small gamut, negative values may result, which are inexpressible in that new\n// color space.\n//\n// It would be ideal to build a color pipeline which never throws away inexpressible (but\n// perceivable) colors.  This means using a color space that is as wide as possible.  The\n// XYZ color space is the neutral, all-encompassing color space, but it has the unfortunate\n// property of having negative values (specifically in X and Z).  To correct this, a further\n// transformation can be made to X and Z to make them always positive.  They can have their\n// precision needs reduced by dividing by Y, allowing X and Z to be packed into two UNORM8s.\n// This color space is called YUV for lack of a better name.\n//\n\n// Note:  Rec.709 and sRGB share the same color primaries and white point.  Their only difference\n// is the transfer curve used.\n\nfloat3 REC709toREC2020( float3 RGB709 )\n{\n    static const float3x3 ConvMat =\n    {\n        0.627402, 0.329292, 0.043306,\n        0.069095, 0.919544, 0.011360,\n        0.016394, 0.088028, 0.895578\n    };\n    return mul(ConvMat, RGB709);\n}\n\nfloat3 REC2020toREC709(float3 RGB2020)\n{\n    static const float3x3 ConvMat =\n    {\n        1.660496, -0.587656, -0.072840,\n        -0.124547, 1.132895, -0.008348,\n        -0.018154, -0.100597, 1.118751\n    };\n    return mul(ConvMat, RGB2020);\n}\n\nfloat3 REC709toDCIP3( float3 RGB709 )\n{\n    static const float3x3 ConvMat =\n    {\n        0.822458, 0.177542, 0.000000,\n        0.033193, 0.966807, 0.000000,\n        0.017085, 0.072410, 0.910505\n    };\n    return mul(ConvMat, RGB709);\n}\n\nfloat3 DCIP3toREC709( float3 RGB709 )\n{\n    static const float3x3 ConvMat =\n    {\n        1.224947, -0.224947, 0.000000,\n        -0.042056, 1.042056, 0.000000,\n        -0.019641, -0.078651, 1.098291\n    };\n    return mul(ConvMat, RGB709);\n}\n\n#endif // __COLOR_SPACE_UTILITY_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/CopyBackPostBufferCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nRWTexture2D<float3> SceneColor : register( u0 );\r\nTexture2D<uint> PostBuffer : register( t0 );\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    SceneColor[DTid.xy] = Unpack_R11G11B10_FLOAT(PostBuffer[DTid.xy]);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DebugDrawHistogramCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nByteAddressBuffer Histogram : register( t0 );\r\nStructuredBuffer<float> Exposure : register( t1 );\r\nRWTexture2D<float3> ColorBuffer : register( u0 );\r\n\r\ngroupshared uint gs_hist[256];\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 256, 1, 1 )]\r\nvoid main( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint histValue = Histogram.Load(GI * 4);\r\n\r\n    // Compute the maximum histogram value, but don't include the black pixel\r\n    gs_hist[GI] = GI == 0 ? 0 : histValue;\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 128) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 64) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 32) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 16) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 8) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 4) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 2) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n    gs_hist[GI] = max(gs_hist[GI], gs_hist[(GI + 1) % 256]);\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint maxHistValue = gs_hist[GI];\r\n\r\n    uint2 BufferDim;\r\n    ColorBuffer.GetDimensions(BufferDim.x, BufferDim.y);\r\n\r\n    const uint2 RectCorner = uint2(BufferDim.x / 2 - 512, BufferDim.y - 256);\r\n    const uint2 GroupCorner = RectCorner + DTid.xy * 4;\r\n\r\n    uint height = 127 - DTid.y * 4;\r\n    uint threshold = histValue * 128 / max(1, maxHistValue);\r\n\r\n    float3 OutColor = (GI == (uint)Exposure[3]) ? float3(1.0, 1.0, 0.0) : float3(0.5, 0.5, 0.5);\r\n\r\n    for (uint i = 0; i < 4; ++i)\r\n    {\r\n        float3 MaskedColor = (height - i) < threshold ? OutColor : float3(0, 0, 0);\r\n\r\n        // 4-wide column with 2 pixels for the histogram bar and 2 for black spacing\r\n        ColorBuffer[GroupCorner + uint2(0, i)] = MaskedColor;\r\n        ColorBuffer[GroupCorner + uint2(1, i)] = MaskedColor;\r\n        ColorBuffer[GroupCorner + uint2(2, i)] = float3(0, 0, 0);\r\n        ColorBuffer[GroupCorner + uint2(3, i)] = float3(0, 0, 0);\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DebugLuminanceHdr2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"DebugLuminanceHdrCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DebugLuminanceHdrCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ToneMappingUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nStructuredBuffer<float> Exposure : register(t0);\r\nTexture2D<float3> Bloom : register(t1);\r\n#if SUPPORT_TYPED_UAV_LOADS\r\nRWTexture2D<float3> SrcColor : register(u0);\r\n#else\r\nRWTexture2D<uint> DstColor : register(u0);\r\nTexture2D<float3> SrcColor : register(t2);\r\n#endif\r\nRWTexture2D<float> OutLuma : register(u1);\r\nSamplerState LinearSampler : register( s0 );\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float2 g_RcpBufferDim;\r\n    float g_BloomStrength;\r\n};\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float2 TexCoord = (DTid.xy + 0.5) * g_RcpBufferDim;\r\n\r\n    // Load HDR and bloom\r\n    float3 hdrColor = SrcColor[DTid.xy] + g_BloomStrength * Bloom.SampleLevel(LinearSampler, TexCoord, 0);\r\n\r\n    // Tone map to LDR and convert to greyscale\r\n    float luma = ToneMapLuma(RGBToLuminance(hdrColor) * Exposure[0]);\r\n\r\n    float logLuma = LinearToLogLuminance(luma);\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    SrcColor[DTid.xy] = luma.xxx;\r\n#else\r\n    DstColor[DTid.xy] = Pack_R11G11B10_FLOAT(luma.xxx);\r\n#endif\r\n    OutLuma[DTid.xy] = logLuma;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DebugLuminanceLdr2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"DebugLuminanceLdrCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DebugLuminanceLdrCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nTexture2D<float3> Bloom : register( t0 );\r\n#if SUPPORT_TYPED_UAV_LOADS\r\nRWTexture2D<float3> SrcColor : register(u0);\r\n#else\r\nRWTexture2D<uint> DstColor : register(u0);\r\nTexture2D<float3> SrcColor : register(t2);\r\n#endif\r\nRWTexture2D<float> OutLuma : register(u1);\r\nSamplerState LinearSampler : register( s0 );\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float2 g_RcpBufferDim;\r\n    float g_BloomStrength;\r\n};\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float2 TexCoord = (DTid.xy + 0.5) * g_RcpBufferDim;\r\n\r\n    // Load LDR and bloom\r\n    float3 ldrColor = SrcColor[DTid.xy];\r\n\r\n    ldrColor += g_BloomStrength * Bloom.SampleLevel(LinearSampler, TexCoord, 0);\r\n\r\n    // Load LDR value from HDR buffer\r\n    float luma = RGBToLuminance( ldrColor );\r\n\r\n    float logLuma = LinearToLogLuminance(luma);\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    SrcColor[DTid.xy] = luma.xxx;\r\n#else\r\n    DstColor[DTid.xy] = Pack_R11G11B10_FLOAT(luma.xxx);\r\n#endif\r\n    OutLuma[DTid.xy] = logLuma;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DebugSSAOCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"SSAORS.hlsli\"\r\n\r\nTexture2D<float> SsaoBuffer : register( t0 );\r\nRWTexture2D<float3> OutColor : register( u0 );\r\n\r\n[RootSignature(SSAO_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    OutColor[DTid.xy] = SsaoBuffer[DTid.xy].xxx;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFCombine2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"DoFCombineCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFCombineCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nTexture2D<float3> DoFColorBuffer : register(t0);\r\nTexture2D<float> DoFAlphaBuffer : register(t1);\r\nTexture2D<float3> TileClass : register(t2);\r\nTexture2D<float> LNFullDepth : register(t3);\r\nStructuredBuffer<uint> WorkQueue : register(t4);\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    RWTexture2D<float3> DstColor : register(u0);\r\n#else\r\n    RWTexture2D<uint> DstColor : register(u0);\r\n#endif\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 16 + GTid.xy;\r\n\r\n    float2 UV = (st + 0.5) * RcpBufferDim;\r\n    float Depth = LNFullDepth[st];\r\n    float3 DoFColor = DoFColorBuffer.SampleLevel(BilinearSampler, UV, 0);\r\n    float FgAlpha = DoFAlphaBuffer.SampleLevel(BilinearSampler, UV, 0);\r\n\r\n    float TileMinDepth = TileClass[Tile].y;\r\n    float BgPercent = BackgroundPercent(Depth, TileMinDepth);\r\n    float PixelBlurriness = saturate((ComputeCoC(Depth) - 1.0) / 1.5);\r\n    float CombinedFactor = lerp(PixelBlurriness, lerp(FgAlpha, 1.0, PixelBlurriness), BgPercent);\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    DstColor[st] = lerp(DstColor[st], DoFColor, CombinedFactor);\r\n#else\r\n    DstColor[st] = Pack_R11G11B10_FLOAT(lerp(Unpack_R11G11B10_FLOAT(DstColor[st]), DoFColor, CombinedFactor));\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFCombineFast2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"DoFCombineFastCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFCombineFastCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nTexture2D<float3> DoFColorBuffer : register(t0);\r\nTexture2D<float> DoFAlphaBuffer : register(t1);\r\nTexture2D<float3> TileClass : register(t2);\r\nTexture2D<float> LNFullDepth : register(t3);\r\nStructuredBuffer<uint> WorkQueue : register(t4);\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    RWTexture2D<float3> DstColor : register(u0);\r\n#else\r\n    RWTexture2D<uint> DstColor : register(u0);\r\n#endif\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 16 + GTid.xy;\r\n\r\n    float2 UV = (st + 0.5) * RcpBufferDim;\r\n    float Depth = LNFullDepth[st];\r\n    float3 DoFColor = DoFColorBuffer.SampleLevel(BilinearSampler, UV, 0);\r\n    float FgAlpha = DoFAlphaBuffer.SampleLevel(BilinearSampler, UV, 0);\r\n\r\n    float TileMinDepth = TileClass[Tile].y;\r\n    float BgPercent = BackgroundPercent(Depth, TileMinDepth);\r\n    float PixelBlurriness = saturate((ComputeCoC(Depth) - 1.0) / 1.5);\r\n    float CombinedFactor = lerp(PixelBlurriness, lerp(FgAlpha, 1.0, PixelBlurriness), BgPercent);\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    DstColor[st] = lerp(DstColor[st], DoFColor, CombinedFactor);\r\n#else\r\n    DstColor[st] = Pack_R11G11B10_FLOAT(lerp(Unpack_R11G11B10_FLOAT(DstColor[st]), DoFColor, CombinedFactor));\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFCommon.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#include \"DoFRS.hlsli\"\n\n#define USE_LINEAR_Z 1\n\nSamplerState PointSampler : register(s0);\nSamplerState ClampSampler : register(s1);\nSamplerState BilinearSampler: register(s2);\n\ncbuffer CB0 : register(b0)\n{\n    float FocusCenter;\n    float FocalSpread;\n    float FocalMinDist;\t// Closer than this is max blurriness\n    float FocalMaxDist;\t// Farther than this is also max blurriness\n    float2 RcpBufferDim;\n    float2 RcpColorBufferDim; //color buffer might be different res (DRR)\n    uint2 FullDimension;\n    int2 HalfDimensionMinusOne;\n    uint2 TiledDimension;\n    float2 InvTiledDimension;\n    uint DebugMode;\n    uint DisablePreFilter;\n    float ForegroundRange;\n    float RcpForegroundRange;\n    float AntiSparkleFilterStrength;\n}\n\n#define DEPTH_FOREGROUND_RANGE 0.01\n#define MATH_CONST_PI 3.1415926535897\n#define MAX_COC_RADIUS 16.0\n#define RING1_THRESHOLD 1.0\n#define RING2_THRESHOLD 6.0\n#define RING3_THRESHOLD 11.0\n\nfloat Max3( float a, float b, float c) { return max(max(a, b), c); }\nfloat Min3( float a, float b, float c) { return min(min(a, b), c); }\nfloat Med3( float a, float b, float c) { return clamp(a, min(b, c), max(b, c)); }\nfloat Max4( float a, float b, float c, float d) { return Max3(a, b, max(c, d)); }\nfloat Min4( float a, float b, float c, float d) { return Min3(a, b, min(c, d)); }\nfloat Max4( float4 vec ) { return Max4( vec.x, vec.y, vec.z, vec.w ); }\nfloat Min4( float4 vec ) { return Min4( vec.x, vec.y, vec.z, vec.w ); }\n\nfloat ComputeCoC( float Depth )\n{\n    return max(1.0 / sqrt(MATH_CONST_PI), MAX_COC_RADIUS * saturate( abs(Depth - FocusCenter) * FocalSpread ));\n}\n\nfloat ComputeSignedCoC( float Depth )\n{\n    return ComputeCoC(Depth) * sign(Depth - FocusCenter);\n}\n\nfloat BackgroundPercent( float Depth, float TileMinDepth )\n{\n    return saturate((Depth - TileMinDepth) * RcpForegroundRange - 1.0);\n}\n\nfloat ForegroundPercent( float Depth, float TileMinDepth )\n{\n    return 1.0 - BackgroundPercent(Depth, TileMinDepth);\n}\n\nfloat2 DepthCmp2( float Depth, float TileMinDepth )\n{\n    float depthCmp = BackgroundPercent(Depth, TileMinDepth);\n    return float2(depthCmp, 1.0 - depthCmp);\n}\n\nfloat SampleAlpha( float CoC )\n{\n    return rcp(MATH_CONST_PI * CoC * CoC);\n}\n\nfloat ComputeRenormalizationFactor( float ForegroundDepth, float MaxCoC )\n{\n    float FgCoC = ComputeCoC(ForegroundDepth);\n    float Rings = (FgCoC - 1) / 5;\n    float NumSamples = 1 + saturate(Rings) * 8 + saturate(Rings - 1) * 16 + saturate(Rings - 2) * 24;\n    return 2.0 * MATH_CONST_PI * FgCoC * FgCoC / NumSamples;\n}\n\nstatic const float2 s_Ring1[8] =\n{\n    {  6.000000,  0.000000 }, { -6.000000, -0.000000 },\n    {  4.242641,  4.242641 }, { -4.242641, -4.242641 },\n    {  0.000000,  6.000000 }, { -0.000000, -6.000000 },\n    { -4.242641,  4.242641 }, {  4.242641, -4.242641 },\n}; //  s_Ring1\n\nstatic const float2 s_Ring2[16] =\n{\n    {  11.000000,  0.000000 }, { -11.000000, -0.000000 },\n    {  10.162675,  4.209518 }, { -10.162675, -4.209518 },\n    {  7.778175,   7.778175 }, { -7.778175, -7.778175 },\n    {  4.209518,  10.162675 }, { -4.209518, -10.162675 },\n    {  0.000000,  11.000000 }, { -0.000000, -11.000000 },\n    { -4.209518,  10.162675 }, {  4.209518, -10.162675 },\n    { -7.778175,   7.778175 }, {  7.778175, -7.778175 },\n    { -10.162675,  4.209518 }, {  10.162675, -4.209518 },\n}; //  s_Ring2\n\nstatic const float2 s_Ring3[24] =\n{\n    {  16.000000,  0.000000 }, { -16.000000, -0.000000 },\n    {  15.454813,  4.141105 }, { -15.454813, -4.141105 },\n    {  13.856406,  8.000000 }, { -13.856406, -8.000000 },\n    {  11.313708, 11.313708 }, { -11.313708, -11.313708 },\n    {  8.000000,  13.856406 }, { -8.000000, -13.856406 },\n    {  4.141105,  15.454813 }, { -4.141105, -15.454813 },\n    {  0.000000,  16.000000 }, { -0.000000, -16.000000 },\n    { -4.141105,  15.454813 }, {  4.141105, -15.454813 },\n    { -8.000000,  13.856406 }, {  8.000000, -13.856406 },\n    { -11.313708, 11.313708 }, {  11.313708, -11.313708 },\n    { -13.856406,  8.000000 }, {  13.856406, -8.000000 },\n    { -15.454813,  4.141105 }, {  15.454813, -4.141105 },\n}; //  s_Ring3\n\nstatic const int s_Ring1Q[8] =\n{\n    3, -3,\n    50, -50,\n    72, -72,\n    46, -46,\n}; //  s_Ring1Q\n\nstatic const int s_Ring2Q[16] =\n{\n    6, -6,\n    53, -53,\n    100, -100,\n    122, -122,\n    144, -144,\n    118, -118,\n    92, -92,\n    43, -43,\n}; //  s_Ring2Q\n\nstatic const int s_Ring3Q[24] =\n{\n    8, -8,\n    56, -56,\n    103, -103,\n    150, -150,\n    172, -172,\n    194, -194,\n    192, -192,\n    190, -190,\n    164, -164,\n    138, -138,\n    89, -89,\n    40, -40,\n}; //  s_Ring3Q\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFDebugBlueCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nStructuredBuffer<uint> WorkQueue : register(t5);\r\nRWTexture2D<float3> DstColor : register(u0);\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 16 + GTid.xy;\r\n\r\n    DstColor[st] = float3(0, 0, 1);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFDebugGreenCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nStructuredBuffer<uint> WorkQueue : register(t5);\r\nRWTexture2D<float3> DstColor : register(u0);\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 16 + GTid.xy;\r\n\r\n    DstColor[st] = float3(0, 1, 0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFDebugRedCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nStructuredBuffer<uint> WorkQueue : register(t5);\r\nRWTexture2D<float3> DstColor : register(u0);\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 16 + GTid.xy;\r\n\r\n    DstColor[st] = float3(1, 0, 0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFMedianFilterCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> InputColor : register(t0);\r\nTexture2D<float> InputAlpha : register(t1);\r\nStructuredBuffer<uint> WorkQueue : register(t2);\r\nRWTexture2D<float3> OutputColor : register(u0);\r\nRWTexture2D<float> OutputAlpha : register(u1);\r\n\r\n// This define will run a 3x3 median filter an all four channels separately.  This is\r\n// the slowest and probably not the most correct way to do things.\r\n//#define PER_CHANNEL_MEDIAN\r\n\r\n// This enables separate 3x3 median filters on the luminance of the color and the alpha\r\n// buffer.  The color brightness is rescaled to the median luminance.  This is faster\r\n// than doing a median four separate channels, and it's potentially more correct because\r\n// filtering R, G, and B separately will cause color shifts.\r\n//#define LUMA_ALPHA_MEDIAN\r\n\r\n// The fastest and default option is to filter only the luminance.  The four components\r\n// will be selected from the pixel that had the median luminance.  Luminance is not\r\n// rescaled.  The other code paths have been left in until it has been fully decided\r\n// that they are unnecessary or wrong.\r\n\r\ngroupshared uint gs_RG[100];\r\ngroupshared float gs_L[100];\r\n#ifdef SEPARATE_ALPHA_MEDIAN\r\ngroupshared float gs_B[100];\r\ngroupshared float gs_A[100];\r\n#else\r\ngroupshared uint gs_BA[100];\r\n#endif\r\n\r\nfloat Med9( float x0, float x1, float x2,\r\n            float x3, float x4, float x5,\r\n            float x6, float x7, float x8 )\r\n{\r\n    float A = Max3(Min3(x0, x1, x2), Min3(x3, x4, x5), Min3(x6, x7, x8));\r\n    float B = Min3(Max3(x0, x1, x2), Max3(x3, x4, x5), Max3(x6, x7, x8));\r\n    float C = Med3(Med3(x0, x1, x2), Med3(x3, x4, x5), Med3(x6, x7, x8));\r\n    return Med3(A, B, C);\r\n}\r\n\r\nvoid StoreColor( uint idx, float R, float G, float B, float A )\r\n{\r\n    gs_RG[idx] = f32tof16(R) << 16 | f32tof16(G);\r\n#ifdef SEPARATE_ALPHA_MEDIAN\r\n    gs_A[idx] = A;\r\n    gs_B[idx] = B;\r\n#else\r\n    gs_BA[idx] = f32tof16(B) << 16 | f32tof16(A);\r\n#endif\r\n\r\n    float Luma = dot(float3(R, G, B), float3(0.212671, 0.715160, 0.072169)) + 1.0;\r\n    gs_L[idx] = asfloat((asuint(Luma) & ~0xFF) | idx);\r\n}\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n\r\n\r\n    if (GTid.x < 5 && GTid.y < 5)\r\n    {\r\n        float2 PrefetchUV = 2 * (st + GTid.xy) * RcpBufferDim;\r\n        float4 R = InputColor.GatherRed(  ClampSampler, PrefetchUV);\r\n        float4 G = InputColor.GatherGreen(ClampSampler, PrefetchUV);\r\n        float4 B = InputColor.GatherBlue( ClampSampler, PrefetchUV);\r\n        float4 A = InputAlpha.GatherRed(  ClampSampler, PrefetchUV);\r\n        uint destIdx = GTid.x * 2 + GTid.y * 2 * 10;\r\n        StoreColor(destIdx   , R.w, G.w, B.w, A.w);\r\n        StoreColor(destIdx+ 1, R.z, G.z, B.z, A.z);\r\n        StoreColor(destIdx+10, R.x, G.x, B.x, A.x);\r\n        StoreColor(destIdx+11, R.y, G.y, B.y, A.y);\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint ulIdx = GTid.x + GTid.y * 10;\r\n\r\n    float MedL = Med9(\r\n        gs_L[ulIdx   ], gs_L[ulIdx+ 1], gs_L[ulIdx+ 2],\r\n        gs_L[ulIdx+10], gs_L[ulIdx+11], gs_L[ulIdx+12],\r\n        gs_L[ulIdx+20], gs_L[ulIdx+21], gs_L[ulIdx+22]);\r\n\r\n    uint cIdx = asuint(MedL) & 0xFF;\r\n    uint RG = gs_RG[cIdx];\r\n#ifdef SEPARATE_ALPHA_MEDIAN\r\n    float Blue = gs_B[cIdx];\r\n#else\r\n    uint BA = gs_BA[cIdx];\r\n    float Blue = f16tof32(BA >> 16);\r\n#endif\r\n    OutputColor[st] = float3( f16tof32(RG >> 16), f16tof32(RG), Blue );\r\n\r\n#ifdef SEPARATE_ALPHA_MEDIAN\r\n    OutputAlpha[st] = Med9(\r\n        gs_A[ulIdx   ], gs_A[ulIdx+ 1], gs_A[ulIdx+ 2],\r\n        gs_A[ulIdx+10], gs_A[ulIdx+11], gs_A[ulIdx+12],\r\n        gs_A[ulIdx+20], gs_A[ulIdx+21], gs_A[ulIdx+22]);\r\n#else\r\n    OutputAlpha[st] = f16tof32(BA);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFMedianFilterFixupCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> InputColor : register(t0);\r\nTexture2D<float> InputAlpha : register(t1);\r\nStructuredBuffer<uint> WorkQueue : register(t2);\r\nRWTexture2D<float3> OutputColor : register(u0);\r\nRWTexture2D<float> OutputAlpha : register(u1);\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n\r\n    OutputColor[st] = InputColor[st];\r\n    OutputAlpha[st] = InputAlpha[st];\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFMedianFilterSepAlphaCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SEPARATE_ALPHA_MEDIAN\r\n#include \"DoFMedianFilterCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPass1CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float> LNDepthBuffer : register(t0);\t\t// Linear/normalized depth buffer\r\nRWTexture2D<float3> TileClass : register(u0);\r\n\r\ngroupshared float gs_ClosestDepthSearch[64];\r\ngroupshared float gs_FarthestDepthSearch[64];\r\ngroupshared float gs_MaximumCoC[64];\r\n\r\nfloat MaxCoC( float4 Depths )\r\n{\r\n    float MaxDepthRelativeToFocus = Max4(abs(Depths - FocusCenter.xxxx));\r\n    return max(1.0 / sqrt(MATH_CONST_PI), MAX_COC_RADIUS * saturate( MaxDepthRelativeToFocus * FocalSpread ));\r\n}\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float2 uv = (DTid.xy * 2 + 1) * RcpBufferDim;\r\n    float4 Depths = LNDepthBuffer.Gather(ClampSampler, uv);\r\n\r\n    float TileMinDepth = Min4(Depths);\r\n    float TileMaxDepth = Max4(Depths);\r\n    float TileMaxCoC = MaxCoC(Depths);\r\n\r\n    for (uint i = 32; i > 0; i >>= 1)\r\n    {\r\n        // Write and sync\r\n        gs_ClosestDepthSearch[GI] = TileMinDepth;\r\n        gs_FarthestDepthSearch[GI] = TileMaxDepth;\r\n        gs_MaximumCoC[GI] = TileMaxCoC;\r\n        GroupMemoryBarrierWithGroupSync();\r\n\r\n        // Read and sync\r\n        TileMinDepth = min(TileMinDepth, gs_ClosestDepthSearch[(GI + i) % 64]);\r\n        TileMaxDepth = max(TileMaxDepth, gs_FarthestDepthSearch[(GI + i) % 64]);\r\n        TileMaxCoC = max(TileMaxCoC, gs_MaximumCoC[(GI + i) % 64]);\r\n        GroupMemoryBarrierWithGroupSync();\r\n    }\r\n\r\n    if (GI == 0)\r\n        TileClass[Gid.xy] = float3(TileMaxCoC, TileMinDepth, TileMaxDepth);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPass2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> ColorBuffer : register(t0);\r\nTexture2D<float3> PresortBuffer : register(t1);\r\nTexture2D<float3> TileClass : register(t2);\r\nStructuredBuffer<uint> WorkQueue : register(t3);\r\nRWTexture2D<float3> OutputColor : register(u0);\r\nRWTexture2D<float> OutputAlpha : register(u1);\r\n\r\ngroupshared uint gs_RG[24 * 24];\t// Red, Green\r\ngroupshared uint gs_BW[24 * 24];\t// Blue, Weight\r\ngroupshared uint gs_CF[24 * 24];\t// CoC, FG Weight\r\n\r\nvoid PrefetchPixel(int2 Corner, uint2 Offset, float FgRenormFactor, float TileMinDepth)\r\n{\r\n    uint ldsIdx = Offset.x + Offset.y * 24;\r\n    uint2 st = clamp(Corner + Offset, 0, HalfDimensionMinusOne);\r\n    float3 PreSortData = PresortBuffer[st];\r\n    float SampleAlpha = PreSortData.y;\r\n    float4 Color = float4(ColorBuffer[st], 1) * SampleAlpha * FgRenormFactor;\r\n    gs_RG[ldsIdx] = f32tof16(Color.r) | f32tof16(Color.g) << 16;\r\n    gs_BW[ldsIdx] = f32tof16(Color.b) | f32tof16(Color.w) << 16;\r\n    float NumRings = PreSortData.x;\r\n    float FgPercent = ForegroundPercent(PreSortData.z, TileMinDepth);\r\n    gs_CF[ldsIdx] = f32tof16(NumRings) | f32tof16(FgPercent) << 16;\r\n}\r\n\r\nvoid AccumulateSample( uint ldsIdx, float SampleRadius, inout float4 BackgroundAccum, inout float4 ForegroundAccum )\r\n{\r\n    uint RG = gs_RG[ldsIdx];\r\n    uint BW = gs_BW[ldsIdx];\r\n    float4 SampleColor = float4(f16tof32(RG), f16tof32(RG >> 16), f16tof32(BW), f16tof32(BW >> 16));\r\n    uint CF = gs_CF[ldsIdx];\r\n    float CoC = f16tof32(CF);\r\n    float Fg = f16tof32(CF >> 16);\r\n\r\n    float Weight = saturate(1.0 - (SampleRadius - CoC));\r\n    BackgroundAccum += SampleColor * (1 - Fg) * Weight;\r\n    ForegroundAccum += SampleColor * Fg * Weight;\r\n}\r\n\r\nvoid AccumulateOneRing( uint ldsIdx, inout float4 Background, inout float4 Foreground )\r\n{\r\n    [unroll]\r\n    for (uint i = 0; i < 8; ++i)\r\n        AccumulateSample(ldsIdx + s_Ring1Q[i], 1, Background, Foreground);\r\n}\r\n\r\nvoid AccumulateTwoRings( uint ldsIdx, inout float4 Background, inout float4 Foreground )\r\n{\r\n    [unroll]\r\n    for (uint i = 0; i < 16; ++i)\r\n        AccumulateSample(ldsIdx + s_Ring2Q[i], 2, Background, Foreground);\r\n}\r\n\r\nvoid AccumulateThreeRings( uint ldsIdx, inout float4 Background, inout float4 Foreground )\r\n{\r\n    [unroll]\r\n    for (uint i = 0; i < 24; ++i)\r\n        AccumulateSample(ldsIdx + s_Ring3Q[i], 3, Background, Foreground);\r\n}\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n\r\n    float TileMinDepth = TileClass[Tile].y;\r\n    float FgRenormFactor = TileClass[Tile].z;\r\n\r\n    int2 TileUL = Tile * 8 - 8;\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 0,  0), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 0,  8), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 0, 16), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 8,  0), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 8,  8), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 8, 16), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2(16,  0), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2(16,  8), FgRenormFactor, TileMinDepth);\r\n    PrefetchPixel(TileUL, GTid.xy + uint2(16, 16), FgRenormFactor, TileMinDepth);\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n    uint ldsIdx = GTid.x + GTid.y * 24 + 25 * 8;\r\n\r\n    float RingCount = (TileClass[Tile].x - 1.0) / 5.0;\r\n\r\n    uint RG = gs_RG[ldsIdx];\r\n    uint BW = gs_BW[ldsIdx];\r\n    float4 CenterColor = float4(f16tof32(RG), f16tof32(RG >> 16), f16tof32(BW), f16tof32(BW >> 16));\r\n    float Fg = f16tof32(gs_CF[ldsIdx] >> 16);\r\n\r\n    float4 Background = CenterColor * (1.01 - Fg);\r\n    float4 Foreground = CenterColor * Fg;\r\n\r\n#ifdef SUPPORT_DEBUGGING\r\n    if (DebugMode == 4)\r\n    {\r\n        float Rings = clamp(RingCount, 0.0, 2.99999);\r\n        OutputColor[st] = frac(float3(saturate(Rings), saturate(Rings - 1.0), saturate(Rings - 2.0)));\r\n        OutputAlpha[st] = 1.0;\r\n        return;\r\n    }\r\n#endif\r\n\r\n    AccumulateOneRing(ldsIdx, Background, Foreground);\r\n\r\n    if (RingCount > 1.0)\r\n        AccumulateTwoRings(ldsIdx, Background, Foreground);\r\n\r\n    if (RingCount > 2.0)\r\n        AccumulateThreeRings(ldsIdx, Background, Foreground);\r\n\r\n    Background.rgb /= (Background.a + 0.00001);\r\n    Foreground.rgb /= (Foreground.a + 0.00001);\r\n\r\n    float Alpha = saturate(Foreground.a);\r\n\r\n#ifdef SUPPORT_DEBUGGING\r\n    if (DebugMode == 1)\r\n    {\r\n        OutputColor[st] = Foreground.rgb;\r\n        OutputAlpha[st] = 1.0;\r\n    }\r\n    else if (DebugMode == 2)\r\n    {\r\n        OutputColor[st] = Background.rgb;\r\n        OutputAlpha[st] = 1.0;\r\n    }\r\n    else if (DebugMode == 3)\r\n    {\r\n        OutputColor[st] = Alpha.xxx;\r\n        OutputAlpha[st] = 1.0;\r\n    }\r\n    else\r\n#endif\r\n    {\r\n        OutputColor[st] = lerp(Background.rgb, Foreground.rgb, Alpha);\r\n        OutputAlpha[st] = lerp(Alpha, 1.0, 0.5);\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPass2DebugCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_DEBUGGING\r\n#include \"DoFPass2CS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPass2FastCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> ColorBuffer : register(t0);\r\nTexture2D<float3> TileClass : register(t2);\r\nStructuredBuffer<uint> WorkQueue : register(t3);\r\nRWTexture2D<float3> OutputColor : register(u0);\r\nRWTexture2D<float> OutputAlpha : register(u1);\r\n\r\ngroupshared uint gs_RB[24 * 24];\r\ngroupshared float gs_Gr[24 * 24];\r\n\r\nvoid PrefetchPixel(int2 Corner, uint2 Offset)\r\n{\r\n    uint ldsIdx = Offset.x + Offset.y * 24;\r\n    uint2 st = clamp(Corner + Offset, 0, HalfDimensionMinusOne);\r\n    float3 Color = ColorBuffer[st];\r\n    gs_RB[ldsIdx] = f32tof16(Color.r) | f32tof16(Color.b) << 16;\r\n    gs_Gr[ldsIdx] = Color.g;\r\n}\r\n\r\nfloat3 LoadColor( uint ldsIdx )\r\n{\r\n    uint RB = gs_RB[ldsIdx];\r\n    return float3( f16tof32(RB), gs_Gr[ldsIdx], f16tof32(RB >> 16) );\r\n}\r\n\r\nfloat4 AccumulateOneRing( uint ldsIdx )\r\n{\r\n    float3 RingSamples = 0;\r\n    [unroll]\r\n    for (uint i = 0; i < 8; i++)\r\n        RingSamples += LoadColor(ldsIdx + s_Ring1Q[i]);\r\n    return float4(RingSamples, 8);\r\n}\r\n\r\nfloat4 AccumulateTwoRings( uint ldsIdx )\r\n{\r\n    float3 RingSamples = 0;\r\n    [unroll]\r\n    for (uint i = 0; i < 16; i++)\r\n        RingSamples += LoadColor(ldsIdx + s_Ring2Q[i]);\r\n    return float4(RingSamples, 16);\r\n}\r\n\r\nfloat4 AccumulateThreeRings( uint ldsIdx )\r\n{\r\n    float3 RingSamples = 0;\r\n    [unroll]\r\n    for (uint i = 0; i < 24; i++)\r\n        RingSamples += LoadColor(ldsIdx + s_Ring3Q[i]);\r\n    return float4(RingSamples, 24);\r\n}\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n\r\n    int2 TileUL = Tile * 8 - 8;\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 0,  0));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 0,  8));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 0, 16));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 8,  0));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 8,  8));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2( 8, 16));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2(16,  0));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2(16,  8));\r\n    PrefetchPixel(TileUL, GTid.xy + uint2(16, 16));\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n    uint ldsIdx = GTid.x + GTid.y * 24 + 25 * 8;\r\n\r\n    float3 CenterColor = LoadColor(ldsIdx);\r\n    float TileCoC = TileClass[Tile].x;\r\n    float RingCount = (TileCoC - 1.0) / 5.0;\r\n\r\n    float4 Foreground = float4(CenterColor, 1);\r\n\r\n    Foreground += saturate(RingCount) * AccumulateOneRing(ldsIdx);\r\n\r\n    if (RingCount > 1.0)\r\n        Foreground += saturate(RingCount - 1.0) * AccumulateTwoRings(ldsIdx);\r\n\r\n    if (RingCount > 2.0)\r\n        Foreground += saturate(RingCount - 2.0) * AccumulateThreeRings(ldsIdx);\r\n\r\n    OutputColor[st] = Foreground.rgb / Foreground.w;\r\n    OutputAlpha[st] = 1.0;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPass2FixupCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> ColorBuffer : register(t0);\r\nTexture2D<float3> PresortBuffer : register(t1);\r\nStructuredBuffer<uint> WorkQueue : register(t3);\r\nRWTexture2D<float3> OutputColor : register(u0);\r\nRWTexture2D<float> OutputAlpha : register(u1);\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n\r\n    float Alpha = saturate(PresortBuffer[st].z);\r\n\r\n    OutputColor[st] = ColorBuffer[st];\r\n    OutputAlpha[st] = 1.0;//lerp(Alpha, 1.0, 0.75);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPreFilterCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float> LNDepthBuffer : register(t0);\r\nTexture2D<float3> TileClass : register(t1);\r\nTexture2D<float3> ColorBuffer : register(t2);\r\nStructuredBuffer<uint> WorkQueue : register(t3);\r\n\r\n// Half res\r\nRWTexture2D<float3> PresortBuffer : register(u0);\r\nRWTexture2D<float3> OutputBuffer : register(u1);\r\n\r\ngroupshared uint RGBuffer[100];\r\ngroupshared uint BWBuffer[100];\r\ngroupshared float DepthBuffer[100];\r\n\r\nvoid LoadSample( out float4 Color, out float Depth, uint LsIdx )\r\n{\r\n    uint RG = RGBuffer[LsIdx];\r\n    uint BW = BWBuffer[LsIdx];\r\n    Color.r = f16tof32(RG >> 16);\r\n    Color.g = f16tof32(RG);\r\n    Color.b = f16tof32(BW >> 16);\r\n    Color.w = f16tof32(BW);\r\n    Depth = DepthBuffer[LsIdx];\r\n}\r\n\r\nfloat4 WeightByInverseLuminance( float3 Color )\r\n{\r\n    float Luminance = dot(Color, float3(0.212671, 0.715160, 0.072169));\r\n    return float4(Color, 1) * rcp(Luminance * AntiSparkleFilterStrength + 1.0);\r\n}\r\n\r\nfloat ComputeSampleWeight( float SampleDepth, float CmpDepth )\r\n{\r\n    return 1.0 - saturate(abs(CmpDepth - SampleDepth) * RcpForegroundRange - 1.0);\r\n}\r\n\r\nfloat4 GetWeightedSample( uint LsIdx, float CenterDepth )\r\n{\r\n    float4 Color; float SampleDepth;\r\n    LoadSample(Color, SampleDepth, LsIdx);\r\n    return Color * ComputeSampleWeight(SampleDepth, CenterDepth);\r\n}\r\n\r\nfloat4 AccumulateOneRing( uint LsIdx, float CenterDepth )\r\n{\r\n    float4 AccumColor = \r\n        GetWeightedSample(LsIdx - 1,  CenterDepth) +\r\n        GetWeightedSample(LsIdx + 1,  CenterDepth) +\r\n        GetWeightedSample(LsIdx - 10, CenterDepth) +\r\n        GetWeightedSample(LsIdx + 10, CenterDepth);\r\n\r\n    AccumColor += 0.75 * (\r\n        GetWeightedSample(LsIdx - 9,  CenterDepth) +\r\n        GetWeightedSample(LsIdx - 11, CenterDepth) +\r\n        GetWeightedSample(LsIdx + 9,  CenterDepth) +\r\n        GetWeightedSample(LsIdx + 11, CenterDepth)\r\n        );\r\n\r\n    return AccumColor;\r\n}\r\n\r\nvoid LoadBlurriestSample( uint lsIdx, int2 st )\r\n{\r\n    float2 uv = st * RcpBufferDim;\r\n    float2 colorUV = st * RcpColorBufferDim;\r\n\r\n    float4 Depths = LNDepthBuffer.Gather(ClampSampler, uv);\r\n    float4 Reds = ColorBuffer.GatherRed(ClampSampler, colorUV);\r\n    float4 Greens = ColorBuffer.GatherGreen(ClampSampler, colorUV);\r\n    float4 Blues = ColorBuffer.GatherBlue(ClampSampler, colorUV);\r\n\r\n    Depths = clamp(Depths, FocalMinDist, FocalMaxDist);\r\n    float MaxDepth = Max4(Depths);\r\n    DepthBuffer[lsIdx] = MaxDepth;\r\n\r\n    float WeightX = ComputeSampleWeight(Depths.x, MaxDepth);\r\n    float WeightY = ComputeSampleWeight(Depths.y, MaxDepth);\r\n    float WeightZ = ComputeSampleWeight(Depths.z, MaxDepth);\r\n    float WeightW = ComputeSampleWeight(Depths.w, MaxDepth);\r\n\r\n    float3 Color = (\r\n        WeightX * float3(Reds.x, Greens.x, Blues.x) +\r\n        WeightY * float3(Reds.y, Greens.y, Blues.y) +\r\n        WeightZ * float3(Reds.z, Greens.z, Blues.z) +\r\n        WeightW * float3(Reds.w, Greens.w, Blues.w)\r\n        ) / (WeightX + WeightY + WeightZ + WeightW);\r\n\r\n    float4 WeightedColor = WeightByInverseLuminance(Color);\r\n    RGBuffer[lsIdx] = f32tof16(WeightedColor.r) << 16 | f32tof16(WeightedColor.g);\r\n    BWBuffer[lsIdx] = f32tof16(WeightedColor.b) << 16 | f32tof16(WeightedColor.w);\r\n}\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n\r\n    int2 TileCorner = Tile * 16 - 1;\r\n\r\n    LoadBlurriestSample(GI, TileCorner + uint2((GI % 10) * 2, (GI / 10) * 2));\r\n    if (GI < 36)\r\n    {\r\n        uint idx = GI + 64;\r\n        LoadBlurriestSample(idx, TileCorner + uint2((idx % 10) * 2, (idx / 10) * 2));\r\n    }\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint LsIdx = GTid.x + GTid.y * 10 + 11;\r\n    float4 Color; float Depth;\r\n    LoadSample(Color, Depth, LsIdx);\r\n\r\n    float CoC = ComputeCoC(Depth);\r\n\r\n    PresortBuffer[st] = float3(max(0, (CoC - 1.0) / 5.0), SampleAlpha(CoC), Depth);\r\n\r\n    if (CoC >= 1.0 && DisablePreFilter == 0)\r\n        Color += saturate(CoC - 1.0) * AccumulateOneRing(LsIdx, Depth);\r\n\r\n    OutputBuffer[st] = Color.rgb / Color.w;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPreFilterFastCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float> LNDepthBuffer : register(t0);\r\nTexture2D<float3> TileClass : register(t1);\r\nTexture2D<float3> ColorBuffer : register(t2);\r\nStructuredBuffer<uint> WorkQueue : register(t3);\r\n\r\n// Half res\r\nRWTexture2D<float3> PresortBuffer : register(u0);\r\nRWTexture2D<float3> OutputBuffer : register(u1);\r\n\r\ngroupshared uint RGBuffer[100];\r\ngroupshared uint BWBuffer[100];\r\ngroupshared float DepthBuffer[100];\r\n\r\nvoid LoadSample( out float4 Color, out float Depth, uint LsIdx )\r\n{\r\n    uint RG = RGBuffer[LsIdx];\r\n    uint BW = BWBuffer[LsIdx];\r\n    Color.r = f16tof32(RG >> 16);\r\n    Color.g = f16tof32(RG);\r\n    Color.b = f16tof32(BW >> 16);\r\n    Color.w = f16tof32(BW);\r\n    Depth = DepthBuffer[LsIdx];\r\n}\r\n\r\nfloat4 WeightByInverseLuminance( float3 Color )\r\n{\r\n    float Luminance = dot(Color, float3(0.212671, 0.715160, 0.072169));\r\n    return float4(Color, 1) * rcp(Luminance * AntiSparkleFilterStrength + 1.0);\r\n}\r\n\r\nfloat4 GetSample( uint LsIdx )\r\n{\r\n    uint RG = RGBuffer[LsIdx];\r\n    uint BW = BWBuffer[LsIdx];\r\n    return float4(f16tof32(RG >> 16), f16tof32(RG), f16tof32(BW >> 16), f16tof32(BW));\r\n}\r\n\r\nfloat4 AccumulateOneRing( uint LsIdx, float CenterDepth )\r\n{\r\n    float4 AccumColor = \r\n        GetSample(LsIdx -  1) +\r\n        GetSample(LsIdx +  1) +\r\n        GetSample(LsIdx - 10) +\r\n        GetSample(LsIdx + 10);\r\n\r\n    AccumColor += 0.75 * (\r\n        GetSample(LsIdx -  9) +\r\n        GetSample(LsIdx - 11) +\r\n        GetSample(LsIdx +  9) +\r\n        GetSample(LsIdx + 11)\r\n        );\r\n\r\n    return AccumColor;\r\n}\r\n\r\nvoid LoadBlurriestSample( uint lsIdx, int2 st )\r\n{\r\n    float2 uv = st * RcpBufferDim;\r\n    float2 colorUV = st * RcpColorBufferDim;\r\n\r\n    float4 Color = WeightByInverseLuminance(ColorBuffer.SampleLevel(BilinearSampler, colorUV, 0));\r\n    RGBuffer[lsIdx] = f32tof16(Color.r) << 16 | f32tof16(Color.g);\r\n    BWBuffer[lsIdx] = f32tof16(Color.b) << 16 | f32tof16(Color.a);\r\n\r\n    float4 Depths = LNDepthBuffer.Gather(ClampSampler, uv);\r\n    Depths = clamp(Depths, FocalMinDist, FocalMaxDist);\r\n    float MaxDepth = Max4(Depths);\r\n    DepthBuffer[lsIdx] = MaxDepth;\r\n}\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n\r\n    int2 TileCorner = Tile * 16 - 1;\r\n\r\n    LoadBlurriestSample(GI, TileCorner + uint2((GI % 10) * 2, (GI / 10) * 2));\r\n    if (GI < 36)\r\n    {\r\n        uint idx = GI + 64;\r\n        LoadBlurriestSample(idx, TileCorner + uint2((idx % 10) * 2, (idx / 10) * 2));\r\n    }\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint LsIdx = GTid.x + GTid.y * 10 + 11;\r\n    float4 Color; float Depth;\r\n    LoadSample(Color, Depth, LsIdx);\r\n\r\n    float CoC = ComputeCoC(Depth);\r\n\r\n    PresortBuffer[st] = float3((CoC - 1.0) / 5.0, SampleAlpha(CoC), Depth);\r\n\r\n    if (CoC >= 1.0 && DisablePreFilter == 0)\r\n        Color += saturate(CoC - 1.0) * AccumulateOneRing(LsIdx, Depth);\r\n\r\n    OutputBuffer[st] = Color.rgb / Color.w;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFPreFilterFixupCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float> LNDepthBuffer : register(t0);\r\nTexture2D<float3> TileClass : register(t1);\r\nTexture2D<float3> ColorBuffer : register(t2);\r\nStructuredBuffer<uint> WorkQueue : register(t3);\r\n\r\n// Half res\r\nRWTexture2D<float3> PresortBuffer : register(u0);\r\nRWTexture2D<float3> OutputBuffer : register(u1);\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint TileCoord = WorkQueue[Gid.x];\r\n    uint2 Tile = uint2(TileCoord & 0xFFFF, TileCoord >> 16);\r\n    uint2 st = Tile * 8 + GTid.xy;\r\n\r\n    float2 uv = (2 * st + 1) * RcpBufferDim;\r\n    float2 colorUV = (2 * st + 1) * RcpColorBufferDim;\r\n\r\n    OutputBuffer[st] = ColorBuffer.SampleLevel(BilinearSampler, colorUV, 0);\r\n    float Depth = LNDepthBuffer.SampleLevel(PointSampler, uv, 0);\r\n    PresortBuffer[st] = float3(0.0, 1.0, Depth);\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define DoF_RootSig \\\n    \"RootFlags(0), \" \\\n    \"CBV(b0), \" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 6)),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 3)),\" \\\n    \"RootConstants(b1, num32BitConstants = 1), \" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_POINT),\" \\\n    \"StaticSampler(s1,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_POINT),\" \\\n    \"StaticSampler(s2,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFTilePassCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> InputClass : register(t0);\r\nRWTexture2D<float3> TileClass : register(u0);\r\nRWStructuredBuffer<uint> WorkQueue : register(u1);\r\nRWStructuredBuffer<uint> FastQueue : register(u2);\r\n\r\ngroupshared float gs_MaxCoC[100];\r\ngroupshared float gs_MinDepth[100];\r\ngroupshared float gs_MaxDepth[100];\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    if (GTid.x < 5 && GTid.y < 5)\r\n    {\r\n        float2 PrefetchUV = (DTid.xy + GTid.xy) * InvTiledDimension;\r\n        float4 MaxCoCs = InputClass.GatherRed(ClampSampler, PrefetchUV);\r\n        float4 MinDepths = InputClass.GatherGreen(ClampSampler, PrefetchUV);\r\n        float4 MaxDepths = InputClass.GatherBlue(ClampSampler, PrefetchUV);\r\n        int destIdx = GTid.x * 2 + GTid.y * 2 * 10;\r\n        gs_MaxCoC[destIdx   ] = MaxCoCs.w;\r\n        gs_MaxCoC[destIdx+ 1] = MaxCoCs.z;\r\n        gs_MaxCoC[destIdx+10] = MaxCoCs.x;\r\n        gs_MaxCoC[destIdx+11] = MaxCoCs.y;\r\n        gs_MinDepth[destIdx   ] = MinDepths.w;\r\n        gs_MinDepth[destIdx+ 1] = MinDepths.z;\r\n        gs_MinDepth[destIdx+10] = MinDepths.x;\r\n        gs_MinDepth[destIdx+11] = MinDepths.y;\r\n        gs_MaxDepth[destIdx   ] = MaxDepths.w;\r\n        gs_MaxDepth[destIdx+ 1] = MaxDepths.z;\r\n        gs_MaxDepth[destIdx+10] = MaxDepths.x;\r\n        gs_MaxDepth[destIdx+11] = MaxDepths.y;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    if (any(DTid.xy >= TiledDimension))\r\n        return;\r\n\r\n    uint ulIdx = GTid.x + GTid.y * 10;\r\n\r\n    float MaxCoC0 = Max3(gs_MaxCoC[ulIdx   ], gs_MaxCoC[ulIdx+ 1], gs_MaxCoC[ulIdx+ 2]);\r\n    float MaxCoC1 = Max3(gs_MaxCoC[ulIdx+10], gs_MaxCoC[ulIdx+11], gs_MaxCoC[ulIdx+12]);\r\n    float MaxCoC2 = Max3(gs_MaxCoC[ulIdx+20], gs_MaxCoC[ulIdx+21], gs_MaxCoC[ulIdx+22]);\r\n    float FinalMaxCoC = Max3(MaxCoC0, MaxCoC1, MaxCoC2);\r\n\r\n    float MinDepth0 = Min3(gs_MinDepth[ulIdx   ], gs_MinDepth[ulIdx+ 1], gs_MinDepth[ulIdx+ 2]);\r\n    float MinDepth1 = Min3(gs_MinDepth[ulIdx+10], gs_MinDepth[ulIdx+11], gs_MinDepth[ulIdx+12]);\r\n    float MinDepth2 = Min3(gs_MinDepth[ulIdx+20], gs_MinDepth[ulIdx+21], gs_MinDepth[ulIdx+22]);\r\n    float FinalMinDepth = Min3(MinDepth0, MinDepth1, MinDepth2);\r\n    FinalMinDepth = clamp(FinalMinDepth, FocalMinDist, FocalMaxDist);\r\n\r\n    float MaxDepth0 = Max3(gs_MaxDepth[ulIdx   ], gs_MaxDepth[ulIdx+ 1], gs_MaxDepth[ulIdx+ 2]);\r\n    float MaxDepth1 = Max3(gs_MaxDepth[ulIdx+10], gs_MaxDepth[ulIdx+11], gs_MaxDepth[ulIdx+12]);\r\n    float MaxDepth2 = Max3(gs_MaxDepth[ulIdx+20], gs_MaxDepth[ulIdx+21], gs_MaxDepth[ulIdx+22]);\r\n    float FinalMaxDepth = Max3(MaxDepth0, MaxDepth1, MaxDepth2);\r\n    FinalMaxDepth = clamp(FinalMaxDepth, FocalMinDist, FocalMaxDist);\r\n\r\n    float FgAlphaNormalizationTerm = ComputeRenormalizationFactor( FinalMinDepth, FinalMaxCoC );\r\n\r\n    TileClass[DTid.xy] = float3(FinalMaxCoC, FinalMinDepth, FgAlphaNormalizationTerm);\r\n\r\n    if (FinalMaxCoC >= 1.0)\r\n    {\r\n        if (FinalMaxDepth - FinalMinDepth > ForegroundRange)\r\n            WorkQueue[WorkQueue.IncrementCounter()] = DTid.x | DTid.y << 16;\r\n        else\r\n            FastQueue[FastQueue.IncrementCounter()] = DTid.x | DTid.y << 16;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DoFTilePassFixupCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"DoFCommon.hlsli\"\r\n\r\nTexture2D<float3> InputClass : register(t0);\r\nRWStructuredBuffer<uint> FixupQueue : register(u0);\r\n\r\ngroupshared float gs_MaxCoC[100];\r\n\r\n[RootSignature(DoF_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    if (GTid.x < 5 && GTid.y < 5)\r\n    {\r\n        float2 PrefetchUV = (DTid.xy + GTid.xy) * InvTiledDimension;\r\n        float4 MaxCoCs = InputClass.GatherRed(ClampSampler, PrefetchUV);\r\n        int destIdx = GTid.x * 2 + GTid.y * 2 * 10;\r\n        gs_MaxCoC[destIdx   ] = MaxCoCs.w;\r\n        gs_MaxCoC[destIdx+ 1] = MaxCoCs.z;\r\n        gs_MaxCoC[destIdx+10] = MaxCoCs.x;\r\n        gs_MaxCoC[destIdx+11] = MaxCoCs.y;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    if (any(DTid.xy >= TiledDimension))\r\n        return;\r\n\r\n    uint ulIdx = GTid.x + GTid.y * 10;\r\n\r\n    float TileMaxCoC = gs_MaxCoC[ulIdx+11];\r\n\r\n    float MaxCoC0 = Max3(gs_MaxCoC[ulIdx   ], gs_MaxCoC[ulIdx+ 1], gs_MaxCoC[ulIdx+ 2]);\r\n    float MaxCoC1 = max(gs_MaxCoC[ulIdx+10], gs_MaxCoC[ulIdx+12]);\r\n    float MaxCoC2 = Max3(gs_MaxCoC[ulIdx+20], gs_MaxCoC[ulIdx+21], gs_MaxCoC[ulIdx+22]);\r\n    float MaxNeighborCoC = Max3(MaxCoC0, MaxCoC1, MaxCoC2);\r\n\r\n    if (TileMaxCoC < 1.0 && MaxNeighborCoC >= 1.0)\r\n        FixupQueue[FixupQueue.IncrementCounter()] = DTid.x | DTid.y << 16;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DownsampleBloomAllCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for downsampling 16x16 blocks of pixels down to 8x8, 4x4, 2x2, and 1x1 blocks.\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nTexture2D<float3> BloomBuf : register( t0 );\r\nRWTexture2D<float3> Result1 : register( u0 );\r\nRWTexture2D<float3> Result2 : register( u1 );\r\nRWTexture2D<float3> Result3 : register( u2 );\r\nRWTexture2D<float3> Result4 : register( u3 );\r\nSamplerState BiLinearClamp : register( s0 );\r\n\r\ncbuffer cb0 : register(b0)\r\n{\r\n    float2 g_inverseDimensions;\r\n}\r\n\r\ngroupshared float3 g_Tile[64];\t// 8x8 input pixels\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    // You can tell if both x and y are divisible by a power of two with this value\r\n    uint parity = DTid.x | DTid.y;\r\n\r\n    // Downsample and store the 8x8 block\r\n    float2 centerUV = (float2(DTid.xy) * 2.0f + 1.0f) * g_inverseDimensions;\r\n    float3 avgPixel = BloomBuf.SampleLevel(BiLinearClamp, centerUV, 0.0f);\r\n    g_Tile[GI] = avgPixel;\r\n    Result1[DTid.xy] = avgPixel;\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // Downsample and store the 4x4 block\r\n    if ((parity & 1) == 0)\r\n    {\r\n        avgPixel = 0.25f * (avgPixel + g_Tile[GI+1] + g_Tile[GI+8] + g_Tile[GI+9]);\r\n        g_Tile[GI] = avgPixel;\r\n        Result2[DTid.xy >> 1] = avgPixel;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // Downsample and store the 2x2 block\r\n    if ((parity & 3) == 0)\r\n    {\r\n        avgPixel = 0.25f * (avgPixel + g_Tile[GI+2] + g_Tile[GI+16] + g_Tile[GI+18]);\r\n        g_Tile[GI] = avgPixel;\r\n        Result3[DTid.xy >> 2] = avgPixel;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // Downsample and store the 1x1 block\r\n    if ((parity & 7) == 0)\r\n    {\r\n        avgPixel = 0.25f * (avgPixel + g_Tile[GI+4] + g_Tile[GI+32] + g_Tile[GI+36]);\r\n        Result4[DTid.xy >> 3] = avgPixel;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/DownsampleBloomCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for downsampling 16x16 blocks of pixels down to 4x4 and 1x1 blocks.\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nTexture2D<float3> BloomBuf : register( t0 );\r\nRWTexture2D<float3> Result1 : register( u0 );\r\nRWTexture2D<float3> Result2 : register( u1 );\r\nSamplerState BiLinearClamp : register( s0 );\r\n\r\ncbuffer cb0 : register(b0)\r\n{\r\n    float2 g_inverseDimensions;\r\n}\r\n\r\ngroupshared float3 g_Tile[64];\t// 8x8 input pixels\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint GI : SV_GroupIndex, uint3 Did : SV_DispatchThreadID )\r\n{\r\n    // You can tell if both x and y are divisible by a power of two with this value\r\n    uint parity = Did.x | Did.y;\r\n\r\n    // Store the first downsampled quad per thread\r\n    float2 centerUV = (float2(Did.xy) * 2.0f + 1.0f) * g_inverseDimensions;\r\n    float3 avgPixel = BloomBuf.SampleLevel(BiLinearClamp, centerUV, 0.0f);\r\n    g_Tile[GI] = avgPixel;\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    if ((parity & 1) == 0)\r\n    {\r\n        avgPixel = 0.25f * (avgPixel + g_Tile[GI+1] + g_Tile[GI+8] + g_Tile[GI+9]);\r\n        g_Tile[GI] = avgPixel;\r\n        Result1[Did.xy >> 1] = avgPixel;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    if ((parity & 3) == 0)\r\n    {\r\n        avgPixel = avgPixel + g_Tile[GI+2] + g_Tile[GI+16] + g_Tile[GI+18];\r\n        g_Tile[GI] = avgPixel;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    if ((parity & 7) == 0)\r\n    {\r\n        avgPixel = 0.0625f * (avgPixel + g_Tile[GI+4] + g_Tile[GI+32] + g_Tile[GI+36]);\r\n        Result2[Did.xy >> 3] = avgPixel;\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ExtractLumaCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for extracting bright pixels and saving a log-luminance map (quantized to 8 bits).  This\r\n// is then used to generate an 8-bit histogram.\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nSamplerState BiLinearClamp : register( s0 );\r\nTexture2D<float3> SourceTex : register( t0 );\r\nStructuredBuffer<float> Exposure : register( t1 );\r\nRWTexture2D<uint> LumaResult : register( u0 );\r\n\r\ncbuffer cb0\r\n{\r\n    float2 g_inverseOutputSize;\r\n}\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    // We need the scale factor and the size of one pixel so that our four samples are right in the middle\r\n    // of the quadrant they are covering.\r\n    float2 uv = DTid.xy * g_inverseOutputSize;\r\n    float2 offset = g_inverseOutputSize * 0.25f;\r\n\r\n    // Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x\r\n    float3 color1 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x, -offset.y), 0 );\r\n    float3 color2 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x, -offset.y), 0 );\r\n    float3 color3 = SourceTex.SampleLevel( BiLinearClamp, uv + float2(-offset.x,  offset.y), 0 );\r\n    float3 color4 = SourceTex.SampleLevel( BiLinearClamp, uv + float2( offset.x,  offset.y), 0 );\r\n\r\n    // Compute average luminance\r\n    float luma = RGBToLuminance(color1 + color2 + color3 + color4) * 0.25;\r\n\r\n    // Prevent log(0) and put only pure black pixels in Histogram[0]\r\n    if (luma == 0.0)\r\n    {\r\n        LumaResult[DTid.xy] = 0;\r\n    }\r\n    else\r\n    {\r\n        const float MinLog = Exposure[4];\r\n        const float RcpLogRange = Exposure[7];\r\n        float logLuma = saturate((log2(luma) - MinLog) * RcpLogRange);\t// Rescale to [0.0, 1.0]\r\n        LumaResult[DTid.xy] = logLuma * 254.0 + 1.0;\t\t\t\t\t// Rescale to [1, 255]\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass1CS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n// Description:  A Compute-optimized implementation of FXAA 3.11 (PC Quality).  The\n// improvements take advantage of work queues (RWStructuredBuffer with atomic counters)\n// for these benefits:\n// \n// 1) Split horizontal and vertical edge searches into separate dispatches to reduce\n// shader complexity and incoherent branching.\n// 2) Delay writing new pixel colors until after the source buffer has been fully\n// analyzed.  This avoids the write-after-scattered-read hazard.\n// 3) Modify source buffer in-place rather than ping-ponging buffers, which reduces\n// bandwidth and memory demands.\n//\n// In addition to the above-mentioned benefits of using UAVs, the first pass also\n// takes advantage of groupshared memory for storing luma values, further reducing\n// fetches and bandwidth.\n//\n// Another optimization is in the generation of perceived brightness (luma) of pixels.\n// The original implementation used sRGB as a good approximation of log-luminance.  A\n// more precise representation of log-luminance allows the algorithm to operate with a\n// higher threshold value while still finding perceivable edges across the full range\n// of brightness.  The approximation used here is (1 - 2^(-4L)) * 16/15, where L =\n// dot( LinearRGB, float3(0.212671, 0.715160, 0.072169) ).  A threshold of 0.2 is\n// recommended with log-luminance computed this way.\n//\n\n// Original Boilerplate:\n//\n/*============================================================================\n\n\n                    NVIDIA FXAA 3.11 by TIMOTHY LOTTES\n\n\n------------------------------------------------------------------------------\nCOPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED.\n------------------------------------------------------------------------------\nTO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED\n*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA\nOR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR\nCONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR\nLOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION,\nOR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE\nTHIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n*/\n\n#include \"FXAARootSignature.hlsli\"\n\nRWByteAddressBuffer WorkCount : register(u0);\nRWByteAddressBuffer WorkQueue : register(u1);\nRWBuffer<float3> ColorQueue : register(u2);\n#if SUPPORT_TYPED_UAV_LOADS\n  Texture2D<float3> Color : register(t0);\n  float3 FetchColor( int2 st ) { return Color[st]; }\n#else\n  #include \"PixelPacking.hlsli\"\n  Texture2D<uint> Color : register(t0);\n  float3 FetchColor( int2 st ) { return Unpack_R11G11B10_FLOAT(Color[st]); }\n#endif\nSamplerState LinearSampler : register(s0);\n\n#define BOUNDARY_SIZE 1\n#define ROW_WIDTH (8 + BOUNDARY_SIZE * 2)\ngroupshared float gs_LumaCache[ROW_WIDTH * ROW_WIDTH];\n\n// If pre-computed, source luminance as a texture, otherwise write it out for Pass2\n#ifdef USE_LUMA_INPUT_BUFFER\n    Texture2D<float> Luma : register(t1);\n#else\n    RWTexture2D<float> Luma : register(u3);\n#endif\n\n//\n// Helper functions\n//\nfloat RGBToLogLuminance( float3 LinearRGB )\n{\n    float Luma = dot( LinearRGB, float3(0.212671, 0.715160, 0.072169) );\n    return log2(1 + Luma * 15) / 4;\n}\n\n[RootSignature(FXAA_RootSig)]\n[numthreads( 8, 8, 1 )]\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\n{\n    uint2 PixelCoord = DTid.xy + StartPixel;\n\n#ifdef USE_LUMA_INPUT_BUFFER\n    // Load 4 lumas per thread into LDS (but only those needed to fill our pixel cache)\n    if (max(GTid.x, GTid.y) < ROW_WIDTH / 2)\n    {\n        int2 ThreadUL = PixelCoord + GTid.xy - (BOUNDARY_SIZE - 1);\n        float4 Luma4 = Luma.Gather(LinearSampler, ThreadUL * RcpTextureSize);\n        uint LoadIndex = (GTid.x + GTid.y * ROW_WIDTH) * 2;\n        gs_LumaCache[LoadIndex                ] = Luma4.w;\n        gs_LumaCache[LoadIndex + 1            ] = Luma4.z;\n        gs_LumaCache[LoadIndex + ROW_WIDTH    ] = Luma4.x;\n        gs_LumaCache[LoadIndex + ROW_WIDTH + 1] = Luma4.y;\n    }\n#else\n    // Because we can't use Gather() on RGB, we make each thread read two pixels (but only those needed).\n    if (GI < ROW_WIDTH * ROW_WIDTH / 2)\n    {\n        uint LdsCoord = GI;\n        int2 UavCoord = StartPixel + uint2(GI % ROW_WIDTH, GI / ROW_WIDTH) + Gid.xy * 8 - BOUNDARY_SIZE;\n        float Luma1 = RGBToLogLuminance(FetchColor(UavCoord));\n        Luma[UavCoord] = Luma1;\n        gs_LumaCache[LdsCoord] = Luma1;\n\n        LdsCoord += ROW_WIDTH * ROW_WIDTH / 2;\n        UavCoord += int2(0, ROW_WIDTH / 2);\n        float Luma2 = RGBToLogLuminance(FetchColor(UavCoord));\n        Luma[UavCoord] = Luma2;\n        gs_LumaCache[LdsCoord] = Luma2;\n    }\n#endif\n\n    GroupMemoryBarrierWithGroupSync();\n\n    uint CenterIdx = (GTid.x + BOUNDARY_SIZE) + (GTid.y + BOUNDARY_SIZE) * ROW_WIDTH;\n\n    // Load the ordinal and center luminances\n    float lumaN  = gs_LumaCache[CenterIdx - ROW_WIDTH];\n    float lumaW  = gs_LumaCache[CenterIdx - 1];\n    float lumaM  = gs_LumaCache[CenterIdx];\n    float lumaE  = gs_LumaCache[CenterIdx + 1];\n    float lumaS  = gs_LumaCache[CenterIdx + ROW_WIDTH];\n\n    // Contrast threshold test\n    float rangeMax = max(max(lumaN, lumaW), max(lumaE, max(lumaS, lumaM)));\n    float rangeMin = min(min(lumaN, lumaW), min(lumaE, min(lumaS, lumaM)));\n    float range = rangeMax - rangeMin;\n    if (range < ContrastThreshold)\n        return;\n\n    // Load the corner luminances\n    float lumaNW = gs_LumaCache[CenterIdx - ROW_WIDTH - 1];\n    float lumaNE = gs_LumaCache[CenterIdx - ROW_WIDTH + 1];\n    float lumaSW = gs_LumaCache[CenterIdx + ROW_WIDTH - 1];\n    float lumaSE = gs_LumaCache[CenterIdx + ROW_WIDTH + 1];\n\n    // Pre-sum a few terms so the results can be reused\n    float lumaNS = lumaN + lumaS;\n    float lumaWE = lumaW + lumaE;\n    float lumaNWSW = lumaNW + lumaSW;\n    float lumaNESE = lumaNE + lumaSE;\n    float lumaSWSE = lumaSW + lumaSE;\n    float lumaNWNE = lumaNW + lumaNE;\n\n    // Compute horizontal and vertical contrast; see which is bigger\n    float edgeHorz = abs(lumaNWSW - 2.0 * lumaW) + abs(lumaNS - 2.0 * lumaM) * 2.0 + abs(lumaNESE - 2.0 * lumaE);\n    float edgeVert = abs(lumaSWSE - 2.0 * lumaS) + abs(lumaWE - 2.0 * lumaM) * 2.0 + abs(lumaNWNE - 2.0 * lumaN);\n\n    // Also compute local contrast in the 3x3 region.  This can identify standalone pixels that alias.\n    float avgNeighborLuma = ((lumaNS + lumaWE) * 2.0 + lumaNWSW + lumaNESE) / 12.0;\n    float subpixelShift = saturate(pow(smoothstep(0, 1, abs(avgNeighborLuma - lumaM) / range), 2) * SubpixelRemoval * 2);\n\n    float NegGrad = (edgeHorz >= edgeVert ? lumaN : lumaW) - lumaM;\n    float PosGrad = (edgeHorz >= edgeVert ? lumaS : lumaE) - lumaM;\n    uint GradientDir = abs(PosGrad) >= abs(NegGrad) ? 1 : 0;\n    uint Subpix = uint(subpixelShift * 254.0) & 0xFE;\n\n    // Packet header: [ 12 bits Y | 12 bits X | 7 bit Subpix | 1 bit dir(Grad) ]\n    uint WorkHeader = PixelCoord.y << 20 | PixelCoord.x << 8 | Subpix | GradientDir;\n\n    if (edgeHorz >= edgeVert)\n    {\n        uint WorkIdx;\n        WorkCount.InterlockedAdd(0, 1, WorkIdx);\n        WorkQueue.Store(WorkIdx*4, WorkHeader);\n        ColorQueue[WorkIdx] = FetchColor(PixelCoord + uint2(0, 2 * GradientDir - 1));\n    }\n    else\n    {\n        uint WorkIdx;\n        WorkCount.InterlockedAdd(4, 1, WorkIdx);\n        WorkIdx = LastQueueIndex - WorkIdx;\n        WorkQueue.Store(WorkIdx*4, WorkHeader);\n        ColorQueue[WorkIdx] = FetchColor(PixelCoord + uint2(2 * GradientDir - 1, 0));\n    }\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass1_Luma2_CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define USE_LUMA_INPUT_BUFFER\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"FXAAPass1CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass1_Luma_CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define USE_LUMA_INPUT_BUFFER\r\n#include \"FXAAPass1CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass1_RGB2_CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"FXAAPass1CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass1_RGB_CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#include \"FXAAPass1CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2CS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#include \"FXAARootSignature.hlsli\"\n#include \"PixelPacking.hlsli\"\n\nTexture2D<float> Luma : register(t0);\nByteAddressBuffer WorkQueue : register(t1);\nBuffer<float3> ColorQueue : register(t2);\n#if SUPPORT_TYPED_UAV_LOADS\nRWTexture2D<float3> DstColor : register(u0);\n#else\nRWTexture2D<uint> DstColor : register(u0);\n#endif\nSamplerState LinearSampler : register(s0);\n\n\n// Note that the number of samples in each direction is one less than the number of sample distances.  The last\n// is the maximum distance that should be used, but whether that sample is \"good\" or \"bad\" doesn't affect the result,\n// so we don't need to load it.\n#ifdef FXAA_EXTREME_QUALITY\n    #define NUM_SAMPLES 11\n    static const float s_SampleDistances[12] =\t// FXAA_QUALITY__PRESET == 39\n    {\n        1.0, 2.0, 3.0, 4.0, 5.0, 6.5, 8.5, 10.5, 12.5, 14.5, 18.5, 36.5, \n    };\n#else\n    #define NUM_SAMPLES 7\n    static const float s_SampleDistances[8] =\t// FXAA_QUALITY__PRESET == 25\n    {\n        1.0, 2.5, 4.5, 6.5, 8.5, 10.5, 14.5, 22.5\n    };\n#endif\n\n[RootSignature(FXAA_RootSig)]\n[numthreads(64, 1, 1)]\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\n{\n#ifdef VERTICAL_ORIENTATION\n    uint ItemIdx = LastQueueIndex - DTid.x;\n#else\n    uint ItemIdx = DTid.x;\n#endif\n    uint WorkHeader = WorkQueue.Load(ItemIdx * 4);\n    uint2 ST = uint2(WorkHeader >> 8, WorkHeader >> 20) & 0xFFF;\n    uint GradientDir = WorkHeader & 1; // Determines which side of the pixel has the highest contrast\n    float Subpix = (WorkHeader & 0xFE) / 254.0 * 0.5;      // 7-bits to encode [0, 0.5]\n\n#ifdef VERTICAL_ORIENTATION\n    float NextLuma = Luma[ST + int2(GradientDir * 2 - 1, 0)];\n    float2 StartUV = (ST + float2(GradientDir, 0.5)) * RcpTextureSize;\n#else\n    float NextLuma = Luma[ST + int2(0, GradientDir * 2 - 1)];\n    float2 StartUV = (ST + float2(0.5, GradientDir)) * RcpTextureSize;\n#endif\n    float ThisLuma = Luma[ST];\n    float CenterLuma = (NextLuma + ThisLuma) * 0.5;         // Halfway between this and next; center of the contrasting edge\n    float GradientSgn = sign(NextLuma - ThisLuma);          // Going down in brightness or up?\n    float GradientMag = abs(NextLuma - ThisLuma) * 0.25;    // How much contrast?  When can we stop looking?\n\n    float NegDist = s_SampleDistances[NUM_SAMPLES];\n    float PosDist = s_SampleDistances[NUM_SAMPLES];\n    bool NegGood = false;\n    bool PosGood = false;\n\n    for (uint iter = 0; iter < NUM_SAMPLES; ++iter)\n    {\n        const float Distance = s_SampleDistances[iter];\n\n#ifdef VERTICAL_ORIENTATION\n        float2 NegUV = StartUV - float2(0, RcpTextureSize.y) * Distance;\n        float2 PosUV = StartUV + float2(0, RcpTextureSize.y) * Distance;\n#else\n        float2 NegUV = StartUV - float2(RcpTextureSize.x, 0) * Distance;\n        float2 PosUV = StartUV + float2(RcpTextureSize.x, 0) * Distance;\n#endif\n\n        // Check for a negative endpoint\n        float NegGrad = Luma.SampleLevel(LinearSampler, NegUV, 0) - CenterLuma;\n        if (abs(NegGrad) >= GradientMag && Distance < NegDist)\n        {\n            NegDist = Distance;\n            NegGood = sign(NegGrad) == GradientSgn;\n        }\n\n        // Check for a positive endpoint\n        float PosGrad = Luma.SampleLevel(LinearSampler, PosUV, 0) - CenterLuma;\n        if (abs(PosGrad) >= GradientMag && Distance < PosDist)\n        {\n            PosDist = Distance;\n            PosGood = sign(PosGrad) == GradientSgn;\n        }\n    }\n\n    // Ranges from 0.0 to 0.5\n    float PixelShift = 0.5 - min(NegDist, PosDist) / (PosDist + NegDist);\n    bool GoodSpan = NegDist < PosDist ? NegGood : PosGood;\n    PixelShift = max(Subpix, GoodSpan ? PixelShift : 0.0);\n\n    if (PixelShift > 0.01)\n    {\n#ifdef DEBUG_OUTPUT\n    #if SUPPORT_TYPED_UAV_LOADS\n        DstColor[ST] = float3(2.0 * PixelShift, 1.0 - 2.0 * PixelShift, 0);\n    #else\n        DstColor[ST] = Pack_R11G11B10_FLOAT(float3(2.0 * PixelShift, 1.0 - 2.0 * PixelShift, 0));\n    #endif\n#else\n    #if SUPPORT_TYPED_UAV_LOADS\n        DstColor[ST] = lerp(DstColor[ST], ColorQueue[ItemIdx], PixelShift);\n    #else\n        DstColor[ST] = Pack_R11G11B10_FLOAT(lerp(Unpack_R11G11B10_FLOAT(DstColor[ST]), ColorQueue[ItemIdx], PixelShift));\n    #endif\n#endif\n    }\n#ifdef DEBUG_OUTPUT\n    else\n    {\n    #if SUPPORT_TYPED_UAV_LOADS\n        DstColor[ST] = float3(0, 0, 0.25);\n    #else\n        DstColor[ST] = Pack_R11G11B10_FLOAT(float3(0, 0, 0.25));\n    #endif\n    }\n#endif\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2H2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n\r\n#include \"FXAAPass2CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2HCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"FXAAPass2CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2HDebug2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"FXAAPass2HDebugCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2HDebugCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define DEBUG_OUTPUT\r\n\r\n#include \"FXAAPass2CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2V2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define VERTICAL_ORIENTATION\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n\r\n#include \"FXAAPass2CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2VCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define VERTICAL_ORIENTATION\r\n\r\n#include \"FXAAPass2CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2VDebug2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"FXAAPass2VDebugCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAPass2VDebugCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define VERTICAL_ORIENTATION\r\n#define DEBUG_OUTPUT\r\n\r\n#include \"FXAAPass2CS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAAResolveWorkQueueCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// Used with FXAA to resolve the lengths of the two work queues and to generate DispatchIndirect parameters.\r\n// The work queues are also padded out to a multiple of 64 with dummy work items.\r\n//\r\n\r\n#include \"FXAARootSignature.hlsli\"\r\n\r\nRWByteAddressBuffer IndirectParams : register(u0);\r\nRWByteAddressBuffer WorkQueue : register(u1);\r\nRWByteAddressBuffer WorkCounts : register(u2);\r\n\r\n[RootSignature(FXAA_RootSig)]\r\n[numthreads( 64, 1, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint2 PixelCounts = WorkCounts.Load2(0);\r\n\r\n    // Write out padding to the buffer\r\n    uint PixelCountH = PixelCounts.x;\r\n    uint PaddedCountH = (PixelCountH + 63) & ~63;\r\n    if (GI + PixelCountH < PaddedCountH)\r\n        WorkQueue.Store(PixelCountH + GI, 0xffffffff);\r\n\r\n    // Write out padding to the buffer\r\n    uint PixelCountV = PixelCounts.y;\r\n    uint PaddedCountV = (PixelCountV + 63) & ~63;\r\n    if (GI + PixelCountV < PaddedCountV)\r\n        WorkQueue.Store(LastQueueIndex - PixelCountV - GI, 0xffffffff);\r\n\r\n    DeviceMemoryBarrierWithGroupSync();\r\n\r\n    if (GI == 0)\r\n    {\r\n        IndirectParams.Store(0 , PaddedCountH >> 6);\r\n        IndirectParams.Store(12, PaddedCountV >> 6);\r\n        WorkCounts.Store2(0, 0);\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/FXAARootSignature.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define FXAA_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants=7), \" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 5)),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 6)),\" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n\ncbuffer CB0 : register(b0)\n{\n    float2 RcpTextureSize;\n    float ContrastThreshold;\t// default = 0.2, lower is more expensive\n    float SubpixelRemoval;\t\t// default = 0.75, lower blurs less\n    uint LastQueueIndex;\n    uint2 StartPixel;\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateHistogramCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The group size is 16x16, but one group iterates over an entire 16-wide column of pixels (384 pixels tall)\r\n// Assuming the total workspace is 640x384, there will be 40 thread groups computing the histogram in parallel.\r\n// The histogram measures logarithmic luminance ranging from 2^-12 up to 2^4.  This should provide a nice window\r\n// where the exposure would range from 2^-4 up to 2^4.\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nTexture2D<uint> LumaBuf : register( t0 );\r\nRWByteAddressBuffer Histogram : register( u0 );\r\n\r\ngroupshared uint g_TileHistogram[256];\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    g_TileHistogram[GI] = 0;\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // Loop 24 times until the entire column has been processed\r\n    for (uint TopY = 0; TopY < 384; TopY += 16)\r\n    {\r\n        uint QuantizedLogLuma = LumaBuf[DTid.xy + uint2(0, TopY)];\r\n        InterlockedAdd( g_TileHistogram[QuantizedLogLuma], 1 );\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    Histogram.InterlockedAdd( GI * 4, g_TileHistogram[GI] );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsCS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 4), \" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 1)),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 4)),\" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n\n#ifndef NON_POWER_OF_TWO\n#define NON_POWER_OF_TWO 0\n#endif\n\nRWTexture2D<float4> OutMip1 : register(u0);\nRWTexture2D<float4> OutMip2 : register(u1);\nRWTexture2D<float4> OutMip3 : register(u2);\nRWTexture2D<float4> OutMip4 : register(u3);\nTexture2D<float4> SrcMip : register(t0);\nSamplerState BilinearClamp : register(s0);\n\ncbuffer CB0 : register(b0)\n{\n    uint SrcMipLevel;\t// Texture level of source mip\n    uint NumMipLevels;\t// Number of OutMips to write: [1, 4]\n    float2 TexelSize;\t// 1.0 / OutMip1.Dimensions\n}\n\n// The reason for separating channels is to reduce bank conflicts in the\n// local data memory controller.  A large stride will cause more threads\n// to collide on the same memory bank.\ngroupshared float gs_R[64];\ngroupshared float gs_G[64];\ngroupshared float gs_B[64];\ngroupshared float gs_A[64];\n\nvoid StoreColor( uint Index, float4 Color )\n{\n    gs_R[Index] = Color.r;\n    gs_G[Index] = Color.g;\n    gs_B[Index] = Color.b;\n    gs_A[Index] = Color.a;\n}\n\nfloat4 LoadColor( uint Index )\n{\n    return float4( gs_R[Index], gs_G[Index], gs_B[Index], gs_A[Index]);\n}\n\nfloat3 ApplySRGBCurve(float3 x)\n{\n    // This is exactly the sRGB curve\n    //return x < 0.0031308 ? 12.92 * x : 1.055 * pow(abs(x), 1.0 / 2.4) - 0.055;\n     \n    // This is cheaper but nearly equivalent\n    return x < 0.0031308 ? 12.92 * x : 1.13005 * sqrt(abs(x - 0.00228)) - 0.13448 * x + 0.005719;\n}\n\nfloat4 PackColor(float4 Linear)\n{\n#ifdef CONVERT_TO_SRGB\n    return float4(ApplySRGBCurve(Linear.rgb), Linear.a);\n#else\n    return Linear;\n#endif\n}\n\n[RootSignature(RootSig)]\n[numthreads( 8, 8, 1 )]\nvoid main( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )\n{\n    // One bilinear sample is insufficient when scaling down by more than 2x.\n    // You will slightly undersample in the case where the source dimension\n    // is odd.  This is why it's a really good idea to only generate mips on\n    // power-of-two sized textures.  Trying to handle the undersampling case\n    // will force this shader to be slower and more complicated as it will\n    // have to take more source texture samples.\n#if NON_POWER_OF_TWO == 0\n    float2 UV = TexelSize * (DTid.xy + 0.5);\n    float4 Src1 = SrcMip.SampleLevel(BilinearClamp, UV, SrcMipLevel);\n#elif NON_POWER_OF_TWO == 1\n    // > 2:1 in X dimension\n    // Use 2 bilinear samples to guarantee we don't undersample when downsizing by more than 2x\n    // horizontally.\n    float2 UV1 = TexelSize * (DTid.xy + float2(0.25, 0.5));\n    float2 Off = TexelSize * float2(0.5, 0.0);\n    float4 Src1 = 0.5 * (SrcMip.SampleLevel(BilinearClamp, UV1, SrcMipLevel) +\n        SrcMip.SampleLevel(BilinearClamp, UV1 + Off, SrcMipLevel));\n#elif NON_POWER_OF_TWO == 2\n    // > 2:1 in Y dimension\n    // Use 2 bilinear samples to guarantee we don't undersample when downsizing by more than 2x\n    // vertically.\n    float2 UV1 = TexelSize * (DTid.xy + float2(0.5, 0.25));\n    float2 Off = TexelSize * float2(0.0, 0.5);\n    float4 Src1 = 0.5 * (SrcMip.SampleLevel(BilinearClamp, UV1, SrcMipLevel) +\n        SrcMip.SampleLevel(BilinearClamp, UV1 + Off, SrcMipLevel));\n#elif NON_POWER_OF_TWO == 3\n    // > 2:1 in in both dimensions\n    // Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x\n    // in both directions.\n    float2 UV1 = TexelSize * (DTid.xy + float2(0.25, 0.25));\n    float2 O = TexelSize * 0.5;\n    float4 Src1 = SrcMip.SampleLevel(BilinearClamp, UV1, SrcMipLevel);\n    Src1 += SrcMip.SampleLevel(BilinearClamp, UV1 + float2(O.x, 0.0), SrcMipLevel);\n    Src1 += SrcMip.SampleLevel(BilinearClamp, UV1 + float2(0.0, O.y), SrcMipLevel);\n    Src1 += SrcMip.SampleLevel(BilinearClamp, UV1 + float2(O.x, O.y), SrcMipLevel);\n    Src1 *= 0.25;\n#endif\n\n    OutMip1[DTid.xy] = PackColor(Src1);\n\n    // A scalar (constant) branch can exit all threads coherently.\n    if (NumMipLevels == 1)\n        return;\n\n    // Without lane swizzle operations, the only way to share data with other\n    // threads is through LDS.\n    StoreColor(GI, Src1);\n\n    // This guarantees all LDS writes are complete and that all threads have\n    // executed all instructions so far (and therefore have issued their LDS\n    // write instructions.)\n    GroupMemoryBarrierWithGroupSync();\n\n    // With low three bits for X and high three bits for Y, this bit mask\n    // (binary: 001001) checks that X and Y are even.\n    if ((GI & 0x9) == 0)\n    {\n        float4 Src2 = LoadColor(GI + 0x01);\n        float4 Src3 = LoadColor(GI + 0x08);\n        float4 Src4 = LoadColor(GI + 0x09);\n        Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);\n\n        OutMip2[DTid.xy / 2] = PackColor(Src1);\n        StoreColor(GI, Src1);\n    }\n\n    if (NumMipLevels == 2)\n        return;\n\n    GroupMemoryBarrierWithGroupSync();\n\n    // This bit mask (binary: 011011) checks that X and Y are multiples of four.\n    if ((GI & 0x1B) == 0)\n    {\n        float4 Src2 = LoadColor(GI + 0x02);\n        float4 Src3 = LoadColor(GI + 0x10);\n        float4 Src4 = LoadColor(GI + 0x12);\n        Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);\n\n        OutMip3[DTid.xy / 4] = PackColor(Src1);\n        StoreColor(GI, Src1);\n    }\n\n    if (NumMipLevels == 3)\n        return;\n\n    GroupMemoryBarrierWithGroupSync();\n\n    // This bit mask would be 111111 (X & Y multiples of 8), but only one\n    // thread fits that criteria.\n    if (GI == 0)\n    {\n        float4 Src2 = LoadColor(GI + 0x04);\n        float4 Src3 = LoadColor(GI + 0x20);\n        float4 Src4 = LoadColor(GI + 0x24);\n        Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);\n\n        OutMip4[DTid.xy / 8] = PackColor(Src1);\n    }\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsGammaCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define CONVERT_TO_SRGB\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsGammaOddCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define CONVERT_TO_SRGB\r\n#define NON_POWER_OF_TWO 3\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsGammaOddXCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define CONVERT_TO_SRGB\r\n#define NON_POWER_OF_TWO 1\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsGammaOddYCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define CONVERT_TO_SRGB\r\n#define NON_POWER_OF_TWO 2\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsLinearCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsLinearOddCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define NON_POWER_OF_TWO 3\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsLinearOddXCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define NON_POWER_OF_TWO 1\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/GenerateMipsLinearOddYCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define NON_POWER_OF_TWO 2\r\n#include \"GenerateMipsCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/LinearizeDepthCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"SSAORS.hlsli\"\r\n\r\nRWTexture2D<float> LinearZ : register(u0);\r\nTexture2D<float> Depth : register(t0);\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float ZMagic;\t\t\t\t// (zFar - zNear) / zNear\r\n}\r\n\r\n[RootSignature(SSAO_RootSig)]\r\n[numthreads( 16, 16, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    LinearZ[DTid.xy] = 1.0 / (ZMagic * Depth[DTid.xy] + 1.0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/MagnifyPixelsPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\nSamplerState PointSampler : register(s1);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    float ScaleFactor;\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main( float4 position : SV_Position, float2 uv : TexCoord0 ) : SV_Target0\r\n{\r\n    float2 ScaledUV = ScaleFactor * (uv - 0.5) + 0.5;\r\n    return ColorTex.SampleLevel(PointSampler, ScaledUV, 0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/MotionBlurFinalPassCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"MotionBlurRS.hlsli\"\r\n#include \"PixelPacking_Velocity.hlsli\"\r\n\r\n#define MAX_SAMPLE_COUNT  10\r\n#define STEP_SIZE         3.0\r\n\r\nTexture2D<packed_velocity_t> VelocityBuffer : register(t0);\t\t// full resolution motion vectors\r\nTexture2D<float4> PrepBuffer : register(t1);\t\t// 1/4 resolution pre-weighted blurred color samples\r\nRWTexture2D<float3> DstColor : register(u0);\t\t// final output color (blurred and temporally blended)\r\nSamplerState LinearSampler : register(s0);\r\n\r\ncbuffer c0 : register(b0)\r\n{\r\n    float2 RcpBufferDim;\t// 1 / width, 1 / height\r\n}\r\n\r\n[RootSignature(MotionBlur_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint2 st = DTid.xy;\r\n    float2 position = st + 0.5;\r\n    float2 uv = position * RcpBufferDim;\r\n\r\n    float2 Velocity = UnpackVelocity(VelocityBuffer[st]).xy;\r\n    float3 thisColor = DstColor[st];\r\n\r\n    // Computing speed in this way will set the step size to two-pixel increments in the dominant\r\n    // direction.\r\n    float Speed = length(Velocity);\r\n\r\n    [branch]\r\n    if (Speed >= 4.0)\r\n    {\r\n        float4 accum = float4(thisColor, 1);\r\n\r\n        // Half of the speed goes in each direction\r\n        float halfSampleCount = min(MAX_SAMPLE_COUNT * 0.5, Speed * 0.5 / STEP_SIZE);\r\n\r\n        // Accumulate low-res, pre-weighted samples, summing their weights in alpha.\r\n        // The center sample is skipped because we are alpha blending onto it in the\r\n        // destination buffer.  Only its weight is considered.  Accumulating low-res\r\n        // samples is not so egregious because the center weight is still high res.\r\n        // Also, each of the low res samples is comprised of four pre-weighted high-\r\n        // res samples, so they are effectively masked at full resolution.\r\n        float2 deltaUV = Velocity / Speed * RcpBufferDim * STEP_SIZE;\r\n        float2 uv1 = uv;\r\n        float2 uv2 = uv;\r\n\r\n        // First accumulate the whole samples\r\n        for (float i = halfSampleCount - 1.0; i > 0.0; i -= 1.0)\r\n        {\r\n            accum += PrepBuffer.SampleLevel(LinearSampler, uv1 += deltaUV, 0);\r\n            accum += PrepBuffer.SampleLevel(LinearSampler, uv2 -= deltaUV, 0);\r\n        }\r\n\r\n        // This is almost the same as 'frac(halfSampleCount)' replaces 0 with 1.\r\n        float remainder = 1 + halfSampleCount - ceil(halfSampleCount);\r\n\r\n        // Then accumulate the fractional samples\r\n        deltaUV *= remainder;\r\n        accum += PrepBuffer.SampleLevel(LinearSampler, uv1 + deltaUV, 0) * remainder;\r\n        accum += PrepBuffer.SampleLevel(LinearSampler, uv2 - deltaUV, 0) * remainder;\r\n\r\n        thisColor = lerp(thisColor, accum.rgb / accum.a, saturate(Speed / 32.0));\r\n    }\r\n\r\n    DstColor[st] = thisColor;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/MotionBlurFinalPassPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"MotionBlurRS.hlsli\"\r\n#include \"PixelPacking_Velocity.hlsli\"\r\n\r\n#define MAX_SAMPLE_COUNT  10\r\n#define STEP_SIZE         3.0\r\n\r\nTexture2D<packed_velocity_t> VelocityBuffer : register(t0);\t// full resolution motion vectors\r\nTexture2D<float4> PrepBuffer : register(t1);\t\t// 1/4 resolution pre-weighted blurred color samples\r\nSamplerState LinearSampler : register(s0);\r\n\r\ncbuffer c0 : register(b0)\r\n{\r\n    float2 RcpBufferDim;\t// 1 / width, 1 / height\r\n}\r\n\r\n[RootSignature(MotionBlur_RootSig)]\r\nfloat4 main( float4 position : SV_Position ) : SV_Target0\r\n{\r\n    uint2 st = uint2(position.xy);\r\n    float2 uv = position.xy * RcpBufferDim;\r\n\r\n    float2 Velocity = UnpackVelocity(VelocityBuffer[st]).xy;\r\n\r\n    // Computing speed in this way will set the step size to two-pixel increments in the dominant\r\n    // direction.\r\n    float Speed = length(Velocity);\r\n\r\n    if (Speed < 4.0)\r\n        discard;\r\n\r\n    float4 accum = 0;\r\n\r\n    // Half of the speed goes in each direction\r\n    float halfSampleCount = min(MAX_SAMPLE_COUNT * 0.5, Speed * 0.5 / STEP_SIZE);\r\n\r\n    // Accumulate low-res, pre-weighted samples, summing their weights in alpha.\r\n    // The center sample is skipped because we are alpha blending onto it in the\r\n    // destination buffer.  Only its weight is considered.  Accumulating low-res\r\n    // samples is not so egregious because the center weight is still high res.\r\n    // Also, each of the low res samples is comprised of four pre-weighted high-\r\n    // res samples, so they are effectively masked at full resolution.\r\n    float2 deltaUV = Velocity / Speed * RcpBufferDim * STEP_SIZE;\r\n    float2 uv1 = uv;\r\n    float2 uv2 = uv;\r\n\r\n    // First accumulate the whole samples\r\n    for (float i = halfSampleCount - 1.0; i > 0.0; i -= 1.0)\r\n    {\r\n        accum += PrepBuffer.SampleLevel(LinearSampler, uv1 += deltaUV, 0);\r\n        accum += PrepBuffer.SampleLevel(LinearSampler, uv2 -= deltaUV, 0);\r\n    }\r\n\r\n    // This is almost the same as 'frac(halfSampleCount)' replaces 0 with 1.\r\n    float remainder = 1 + halfSampleCount - ceil(halfSampleCount);\r\n\r\n    // Then accumulate the fractional samples\r\n    deltaUV *= remainder;\r\n    accum += PrepBuffer.SampleLevel(LinearSampler, uv1 + deltaUV, 0) * remainder;\r\n    accum += PrepBuffer.SampleLevel(LinearSampler, uv2 - deltaUV, 0) * remainder;\r\n\r\n    return accum * (saturate(Speed / 32.0) / (accum.a + 1.0));\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/MotionBlurPrePassCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"MotionBlurRS.hlsli\"\r\n#include \"PixelPacking_Velocity.hlsli\"\r\n\r\nTexture2D<float3> ColorBuffer : register(t0);\r\nTexture2D<packed_velocity_t> VelocityBuffer : register(t1);\r\nRWTexture2D<float4> PrepBuffer : register(u0);\r\n\r\nfloat4 GetSampleData( uint2 st )\r\n{\r\n    float Speed = length(UnpackVelocity(VelocityBuffer[st]).xy);\r\n    return float4(ColorBuffer[st], 1.0) * saturate(Speed * 32.0 / 4.0);\r\n}\r\n\r\n[RootSignature(MotionBlur_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint2 corner = DTid.xy << 1;\r\n    float4 sample0 = GetSampleData( corner + uint2(0, 0) );\r\n    float4 sample1 = GetSampleData( corner + uint2(1, 0) );\r\n    float4 sample2 = GetSampleData( corner + uint2(0, 1) );\r\n    float4 sample3 = GetSampleData( corner + uint2(1, 1) );\r\n\r\n    float combinedMotionWeight = sample0.a + sample1.a + sample2.a + sample3.a + 0.0001;\r\n    PrepBuffer[DTid.xy] = floor(0.25 * combinedMotionWeight * 3.0) / 3.0 * float4(\r\n        (sample0.rgb + sample1.rgb + sample2.rgb + sample3.rgb) / combinedMotionWeight, 1.0 );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/MotionBlurRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define MotionBlur_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 4), \" \\\n    \"CBV(b1),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 8)),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 8)),\" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleBinCullingCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard \r\n//             Julia Careaga\r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\n#define THREAD_GROUP_SIZE 256\r\n\r\nStructuredBuffer<ParticleScreenData> g_VisibleParticles : register( t0 );\r\nStructuredBuffer<uint> g_LargeBinParticles : register( t1 );\r\nStructuredBuffer<uint> g_LargeBinCounters : register( t2 );\r\nRWStructuredBuffer<uint> g_BinParticles : register( u0 );\r\nRWStructuredBuffer<uint> g_BinCounters : register( u1 );\r\n\r\ngroupshared uint gs_BinCounters[16];\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    uint2 LogTilesPerBin;\r\n};\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(4, THREAD_GROUP_SIZE / 4, 1)]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    uint LargeBinsPerRow = (gBinsPerRow + 3) / 4;\r\n    uint ParticlesPerLargeBin = MAX_PARTICLES_PER_BIN * 16;\r\n\r\n    uint LargeBinIndex = Gid.y * LargeBinsPerRow + Gid.x;\r\n    uint ParticleCountInLargeBin = min(g_LargeBinCounters[LargeBinIndex], ParticlesPerLargeBin);\r\n\r\n    // Get the start location for particles in this bin\r\n    uint LargeBinStart = LargeBinIndex * ParticlesPerLargeBin;\r\n    uint2 FirstBin = Gid.xy * 4;\r\n\r\n    if (GI < 16)\r\n        gs_BinCounters[GI] = 0;\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    for (uint idx = GI; idx < ParticleCountInLargeBin; idx += THREAD_GROUP_SIZE)\r\n    {\r\n        uint SortKey = g_LargeBinParticles[LargeBinStart + idx]; \r\n        uint GlobalIdx = SortKey & 0x3FFFF;\r\n\r\n        uint Bounds = g_VisibleParticles[GlobalIdx].Bounds;\r\n        uint2 MinTile = uint2(Bounds >>  0, Bounds >>  8) & 0xFF;\r\n        uint2 MaxTile = uint2(Bounds >> 16, Bounds >> 24) & 0xFF;\r\n        uint2 MinBin = max(MinTile >> LogTilesPerBin, FirstBin);\r\n        uint2 MaxBin = min(MaxTile >> LogTilesPerBin, FirstBin + 3);\r\n\r\n        for (uint y = MinBin.y; y <= MaxBin.y; ++y)\r\n        {\r\n            for (uint x = MinBin.x; x <= MaxBin.x; ++x)\r\n            {\r\n                uint CounterIdx = (x & 3) | (y & 3) << 2;\r\n                uint BinOffset = (x + y * gBinsPerRow) * MAX_PARTICLES_PER_BIN;\r\n                uint AllocIdx;\r\n                InterlockedAdd(gs_BinCounters[CounterIdx], 1, AllocIdx);\r\n                AllocIdx = min(AllocIdx, MAX_PARTICLES_PER_BIN - 1);\r\n                g_BinParticles[BinOffset + AllocIdx] = SortKey;\r\n            }\r\n        }\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    if (GI < 16)\r\n    {\r\n        uint2 OutBin = FirstBin + GTid.xy;\r\n        g_BinCounters[OutBin.x + OutBin.y * gBinsPerRow] = gs_BinCounters[GI];\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleDepthBoundsCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard \r\n//             Alex Nankervis\r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nTexture2D<float> g_Input : register(t0);\r\nRWTexture2D<uint> g_Output8 : register(u0);\r\nRWTexture2D<uint> g_Output16 : register(u1);\r\nRWTexture2D<uint> g_Output32 : register(u2);\r\n\r\ngroupshared uint gs_Buffer[128];\r\n\r\nvoid Max4( uint This, uint Dx )\r\n{\r\n    uint MM1 = gs_Buffer[This + 1 * Dx];\r\n    uint MM2 = gs_Buffer[This + 8 * Dx];\r\n    uint MM3 = gs_Buffer[This + 9 * Dx];\r\n    GroupMemoryBarrierWithGroupSync();\r\n    InterlockedMax(gs_Buffer[This], max(MM1, max(MM2, MM3)));\r\n    GroupMemoryBarrierWithGroupSync();\r\n}\r\n\r\nuint PackMinMax( uint This )\r\n{\r\n    float Min = asfloat(~gs_Buffer[This + 64]);\r\n    float Max = asfloat(gs_Buffer[This]);\r\n    return f32tof16(Max) << 16 | f32tof16(saturate(Min - 0.001));\r\n}\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    // Load 4x4 depth values (per thread) and compute the min and max of each\r\n    float2 UV1 = (DTid.xy * 4 + 1) * gRcpBufferDim;\r\n    float2 UV2 = UV1 + float2(2, 0) * gRcpBufferDim;\r\n    float2 UV3 = UV1 + float2(0, 2) * gRcpBufferDim;\r\n    float2 UV4 = UV1 + float2(2, 2) * gRcpBufferDim;\r\n    \r\n    float4 ZQuad1 = g_Input.Gather(gSampPointClamp, UV1);\r\n    float4 ZQuad2 = g_Input.Gather(gSampPointClamp, UV2);\r\n    float4 ZQuad3 = g_Input.Gather(gSampPointClamp, UV3);\r\n    float4 ZQuad4 = g_Input.Gather(gSampPointClamp, UV4);\r\n\r\n    float4 MaxQuad = max(max(ZQuad1, ZQuad2), max(ZQuad3, ZQuad4));\r\n    float4 MinQuad = min(min(ZQuad1, ZQuad2), min(ZQuad3, ZQuad4));\r\n\r\n    float maxZ = max(max(MaxQuad.x, MaxQuad.y), max(MaxQuad.z, MaxQuad.w));\r\n    float minZ = min(min(MinQuad.x, MinQuad.y), min(MinQuad.z, MinQuad.w));\r\n\r\n    // Parallel reduction will reduce 4:1 per iteration.  This reduces LDS loads and stores\r\n    // and can take advantage of min3 and max3 instructions when available.\r\n\r\n    // Because each iteration puts 3/4 of active threads to sleep, threads are quickly wasted.\r\n    // Rather than have each active thread compute both a min and a max, it would be nice if\r\n    // we could wake up sleeping threads to share the burden.  It turns out this is possible!\r\n    // We can have all threads performing Max4() reductions, and by applying it to negative\r\n    // min values, we can find the min depth.  E.g. min(a, b) = -max(-a, -b)\r\n\r\n    // Max values to first 64, Min values to last 64\r\n    gs_Buffer[GI] = asuint(maxZ);\r\n    gs_Buffer[GI + 64] = ~asuint(minZ);\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // We don't need odd numbered threads, but we could utilize more threads\r\n    const uint This = GI * 2;\r\n\r\n    Max4(This, 1);\r\n\r\n    // if (X % 2 == 0 && Y % 2 == 0 && Y < 8)\r\n    if ((This & 0x49) == 0)\t\r\n    {\r\n        uint2 SubTile = uint2(This >> 1, This >> 4) & 3;\r\n        g_Output8[Gid.xy * 4 + SubTile] = PackMinMax(This);\r\n    }\r\n\r\n    Max4(This, 2);\r\n\r\n    // if (X % 4 == 0 && Y % 4 == 0 && Y < 8)\r\n    if ((This & 0x5B) == 0)\t\r\n    {\r\n        uint2 SubTile = uint2(This >> 2, This >> 5) & 1;\r\n        g_Output16[Gid.xy * 2 + SubTile] = PackMinMax(This);\r\n    }\r\n\r\n    Max4(This, 4);\r\n\r\n    if (This == 0)\r\n        g_Output32[Gid.xy] = PackMinMax(This);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleDispatchIndirectArgsCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga \r\n//\r\n\r\n#include \"ParticleRS.hlsli\"\r\n\r\nByteAddressBuffer g_ParticleInstance : register( t0 );\r\nRWByteAddressBuffer g_NumThreadGroups : register( u1 );\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(1, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    g_NumThreadGroups.Store(0, ( g_ParticleInstance.Load(0) + 63) / 64);\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleFinalDispatchIndirectArgsCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga \r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nByteAddressBuffer g_FinalInstanceCounter : register( t0 );\r\nRWByteAddressBuffer g_NumThreadGroups : register( u0 );\r\nRWByteAddressBuffer g_DrawIndirectArgs : register ( u1 );\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(1, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint particleCount = g_FinalInstanceCounter.Load(0);\r\n    g_NumThreadGroups.Store3(0, uint3((particleCount + 63) / 64, 1, 1));\r\n    g_DrawIndirectArgs.Store(4, particleCount);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleLargeBinCullingCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard \r\n//             Julia Careaga\r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\n#define MAX_PARTICLES_PER_LARGE_BIN (16 * MAX_PARTICLES_PER_BIN)\r\n\r\nStructuredBuffer<ParticleVertex> g_VertexBuffer : register(t0);\r\nByteAddressBuffer g_VertexCount : register(t1);\r\nRWStructuredBuffer<uint> g_LargeBinParticles : register(u0);\r\nRWStructuredBuffer<uint> g_LargeBinCounters : register(u1);\r\nRWStructuredBuffer<ParticleScreenData> g_VisibleParticles : register( u2 );\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    uint2 LogTilesPerLargeBin;\r\n};\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(64, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint VertexIdx = DTid.x;\r\n\r\n    if (VertexIdx >= g_VertexCount.Load(0))\r\n        return;\r\n\r\n    //\r\n    // Transform and cull the sprite\r\n    //\r\n    ParticleVertex Sprite = g_VertexBuffer[VertexIdx];\r\n\r\n    // Frustum cull before adding this particle to list of visible particles (for rendering)\r\n    float4 HPos = mul( gViewProj, float4(Sprite.Position, 1) );\r\n    float Height = Sprite.Size * gVertCotangent;\r\n    float Width = Height * gAspectRatio;\r\n    float3 Extent = abs(HPos.xyz) - float3(Width, Height, 0);\r\n\r\n    // Technically, we should check for HPos.z > 0 because this is D3D.  But there is only a tiny\r\n    // window of space between the eye and the near plane where this could be true.\r\n    if (max(max(0.0, Extent.x), max(Extent.y, Extent.z)) > HPos.w)\r\n        return;\r\n\r\n    //\r\n    // Generate tile-relevant draw data\r\n    //\r\n\r\n    ParticleScreenData Particle;\r\n\r\n    float RcpW = 1.0 / HPos.w;\r\n\r\n    // Compute texture LOD for this sprite\r\n    float ScreenSize = Height * RcpW * gBufferDim.y;\r\n    float TextureLevel = (float)firstbithigh(MaxTextureSize) - log2(ScreenSize);\r\n\r\n    Particle.Corner = float2(HPos.x - Width, -HPos.y - Height) * RcpW * 0.5 + 0.5;\r\n    Particle.RcpSize = HPos.w / float2(Width, Height);\r\n    Particle.Depth = saturate(HPos.w * gRcpFarZ);\r\n    Particle.Color = Sprite.Color;\r\n    Particle.TextureIndex = (float)Sprite.TextureID;\r\n    Particle.TextureLevel = TextureLevel;\r\n\r\n    float2 TopLeft = max(Particle.Corner * gBufferDim, 0.0);\r\n    float2 BottomRight = max(TopLeft + gBufferDim / Particle.RcpSize, 0.0);\r\n    uint2 EdgeTile = uint2(gTilesPerRow, gTilesPerCol) - 1;\r\n    uint2 MinTile = uint2(TopLeft) / TILE_SIZE;\r\n    uint2 MaxTile = min(EdgeTile, uint2(BottomRight) / TILE_SIZE);\r\n    Particle.Bounds = MinTile.x | MinTile.y << 8 | MaxTile.x << 16 | MaxTile.y << 24;\r\n\r\n    uint GlobalIdx = g_VisibleParticles.IncrementCounter();\r\n\r\n    g_VisibleParticles[GlobalIdx] = Particle;\r\n\r\n    //\r\n    // Insert the particle into all large bins it occupies\r\n    //\r\n\r\n    uint LargeBinsPerRow = (gBinsPerRow + 3) / 4;\r\n    uint2 MinLargeBin = MinTile >> LogTilesPerLargeBin;\r\n    uint2 MaxLargeBin = MaxTile >> LogTilesPerLargeBin;\r\n\r\n    uint SortKey = f32tof16(Particle.Depth) << 18 | GlobalIdx;\r\n\r\n    for (uint y = MinLargeBin.y; y <= MaxLargeBin.y; y++)\r\n    {\r\n        for (uint x = MinLargeBin.x; x <= MaxLargeBin.x; x++)\r\n        {\r\n            uint LargeBinIndex = y * LargeBinsPerRow + x;\r\n            uint AllocIdx;\r\n            InterlockedAdd(g_LargeBinCounters[LargeBinIndex], 1, AllocIdx);\r\n            AllocIdx = min(AllocIdx, MAX_PARTICLES_PER_LARGE_BIN - 1);\r\n            g_LargeBinParticles[LargeBinIndex * MAX_PARTICLES_PER_LARGE_BIN + AllocIdx] = SortKey;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleNoSortVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):   James Stanard\r\n\r\n#define DISABLE_PARTICLE_SORT 1\r\n#include \"ParticleVS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticlePS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//          Julia Careaga\r\n//\r\n\r\n#include \"ParticleUpdateCommon.hlsli\"\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nTexture2DArray<float4> ColorTex : register(t1);\r\nTexture2D<float> LinearDepthTex : register(t2);\r\n\r\n[RootSignature(Particle_RootSig)]\r\nfloat4 main(ParticleVertexOutput input ) : SV_Target0\r\n{\r\n    float3 uv = float3(input.TexCoord.xy, input.TexID);\r\n    float4 TextureColor = ColorTex.Sample( gSampLinearBorder, uv );\r\n    TextureColor.a *= saturate(1000.0 * (LinearDepthTex[(uint2)input.Pos.xy] - input.LinearZ));\r\n    TextureColor.rgb *= TextureColor.a;\r\n    return TextureColor * input.Color;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticlePreSortCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nStructuredBuffer<ParticleVertex> g_VertexBuffer : register( t0 );\r\nByteAddressBuffer g_VertexCount : register(t1);\r\nRWStructuredBuffer<uint> g_SortBuffer : register(u0);\r\nRWByteAddressBuffer g_DrawIndirectArgs : register(u1);\r\n\r\ngroupshared uint gs_SortKeys[2048];\r\n\r\nvoid FillSortKey( uint GroupStart, uint Offset, uint VertexCount )\r\n{\r\n    if (GroupStart + Offset >= VertexCount)\r\n    {\r\n        gs_SortKeys[Offset] = 0;\t\t// Z = 0 will sort to the end of the list (back to front)\r\n        return;\r\n    }\r\n\r\n    uint VertexIdx = GroupStart + Offset;\r\n    ParticleVertex Sprite = g_VertexBuffer[VertexIdx];\r\n\r\n    // Frustum cull before adding this particle to list of visible particles (for rendering)\r\n    float4 HPos = mul( gViewProj, float4(Sprite.Position, 1) );\r\n    float Height = Sprite.Size * gVertCotangent;\r\n    float Width = Height * gAspectRatio;\r\n    float3 Extent = abs(HPos.xyz) - float3(Width, Height, 0);\r\n\r\n    // Frustum cull rather than sorting and rendering every particle\r\n    if (max(max(0.0, Extent.x), max(Extent.y, Extent.z)) <= HPos.w)\r\n    {\r\n        // Encode depth as 14 bits because we only need [0, 1] at half precision.\r\n        // This gives us 18-bit indices--up to 256k particles.\r\n        float Depth = saturate(HPos.w * gRcpFarZ);\r\n        gs_SortKeys[Offset] = f32tof16(Depth) << 18 | VertexIdx;\r\n\r\n        // Increment the visible instance counter\r\n        g_DrawIndirectArgs.InterlockedAdd(4, 1);\r\n    }\r\n    else\r\n    {\r\n        // Cull particle index by sorting it to the end and not incrementing the visible instance counter\r\n        gs_SortKeys[Offset] = 0;\r\n    }\r\n}\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(1024, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex )\r\n{\r\n    uint VisibleParticles = g_VertexCount.Load(0);\r\n\r\n    uint GroupStart = Gid.x * 2048;\r\n\r\n    if (GroupStart > VisibleParticles)\r\n    {\r\n        g_SortBuffer[GroupStart + GI] = 0;\r\n        g_SortBuffer[GroupStart + GI + 1024] = 0;\r\n        return;\r\n    }\r\n\r\n    FillSortKey(GroupStart, GI, VisibleParticles);\r\n    FillSortKey(GroupStart, GI + 1024, VisibleParticles);\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint k;\r\n\r\n    [unroll]\r\n    for (k = 2; k <= 2048; k *= 2)\r\n    {\r\n        [unroll]\r\n        for (uint j = k / 2; j > 0; j /= 2)\r\n        {\r\n            uint Index1 = InsertZeroBit(GI, j);\r\n            uint Index2 = Index1 ^ (k == j * 2 ? k - 1 : j);\r\n\r\n            uint A = gs_SortKeys[Index1];\r\n            uint B = gs_SortKeys[Index2];\r\n\r\n            if (A < B)\r\n            {\r\n                gs_SortKeys[Index1] = B;\r\n                gs_SortKeys[Index2] = A;\r\n            }\r\n\r\n            GroupMemoryBarrierWithGroupSync();\r\n        }\r\n    }\r\n\r\n    g_SortBuffer[GroupStart + GI] = gs_SortKeys[GI];\r\n    g_SortBuffer[GroupStart + GI + 1024] = gs_SortKeys[GI + 1024];\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define Particle_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 3),\" \\\n    \"CBV(b1),\" \\\n    \"CBV(b2),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 8)),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 10)),\" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_LINEAR_MIP_POINT),\" \\\n    \"StaticSampler(s1,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_POINT), \" \\\n    \"StaticSampler(s2,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_POINT)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleSortIndirectArgsCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nRWByteAddressBuffer g_DispatchIndirectArgs : register(u0);\r\nRWByteAddressBuffer g_DrawIndirectArgs : register(u1);\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(1, 1, 1)]\r\nvoid main( uint GI : SV_GroupIndex )\r\n{\r\n    uint InstanceCount = g_DrawIndirectArgs.Load(4);\r\n    uint ThreadGroupCount = (InstanceCount + 2047) / 2048;\r\n\r\n    g_DispatchIndirectArgs.Store3(0, uint3(ThreadGroupCount, 1, 1));\r\n\r\n    // Reset instance count so we can cull and determine how many we need to actually draw\r\n    g_DrawIndirectArgs.Store(4, 0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleSpawnCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n//          James Stanard \r\n//\r\n\r\n#include \"ParticleUpdateCommon.hlsli\"\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nStructuredBuffer< ParticleSpawnData > g_ResetData : register( t0 );\r\nRWStructuredBuffer< ParticleMotion > g_OutputBuffer : register( u2 );\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(64, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    uint index = g_OutputBuffer.IncrementCounter();\r\n    if (index >= MaxParticles)\r\n        return;\r\n    \r\n    uint ResetDataIndex = RandIndex[DTid.x].x; \r\n    ParticleSpawnData rd  = g_ResetData[ResetDataIndex];\r\n        \r\n    float3 emitterVelocity = EmitPosW - LastEmitPosW; \r\n    float3 randDir = rd.Velocity.x * EmitRightW + rd.Velocity.y * EmitUpW + rd.Velocity.z * EmitDirW;\r\n    float3 newVelocity = emitterVelocity * EmitterVelocitySensitivity + randDir;\r\n    float3 adjustedPosition = EmitPosW - emitterVelocity * rd.Random + rd.SpreadOffset;\r\n\r\n    ParticleMotion newParticle;\r\n    newParticle.Position = adjustedPosition;\r\n    newParticle.Rotation = 0.0;\r\n    newParticle.Velocity = newVelocity + EmitDirW * EmitSpeed; \r\n    newParticle.Mass = rd.Mass; \r\n    newParticle.Age = 0.0;\r\n    newParticle.ResetDataIndex = ResetDataIndex; \r\n    g_OutputBuffer[index] = newParticle;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileCullingCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):   James Stanard \r\n//              Julia Careaga\r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nStructuredBuffer<uint> g_BinParticles : register(t0);\r\nStructuredBuffer<uint> g_BinCounters : register(t1);\r\nTexture2D<uint> g_DepthBounds : register(t2);\r\nStructuredBuffer<ParticleScreenData> g_VisibleParticles : register(t3);\r\n\r\nRWStructuredBuffer<uint> g_SortedParticles : register(u0);\r\nRWByteAddressBuffer g_TileHitMasks : register(u1);\r\nRWStructuredBuffer<uint> g_DrawPackets : register(u2);\r\nRWStructuredBuffer<uint> g_FastDrawPackets : register(u3);\r\nRWByteAddressBuffer g_DrawPacketCount : register(u4);\r\n\r\n#if TILES_PER_BIN < 64\r\n#define GROUP_THREAD_COUNT 64\r\n#else\r\n#define GROUP_THREAD_COUNT TILES_PER_BIN\r\n#endif\r\n#define GROUP_SIZE_X TILES_PER_BIN_X\r\n#define GROUP_SIZE_Y (GROUP_THREAD_COUNT / GROUP_SIZE_X)\r\n#define MASK_WORDS_PER_ITER (GROUP_THREAD_COUNT / 32)\r\n\r\ngroupshared uint gs_SortKeys[MAX_PARTICLES_PER_BIN];\r\ngroupshared uint gs_IntersectionMasks[TILES_PER_BIN * MASK_WORDS_PER_ITER];\r\ngroupshared uint gs_TileParticleCounts[TILES_PER_BIN];\r\ngroupshared uint gs_SlowTileParticleCounts[TILES_PER_BIN];\r\ngroupshared uint gs_MinMaxDepth[TILES_PER_BIN];\r\n\r\nvoid BitonicSort(uint GI, uint NumElements, uint NextPow2, uint NumThreads)\r\n{\r\n    for (uint k = 2; k <= NextPow2; k *= 2)\r\n    {\r\n        // Align NumElements to the next multiple of k\r\n        NumElements = (NumElements + k - 1) & ~(k - 1);\r\n\r\n        for (uint j = k / 2; j > 0; j /= 2)\r\n        {\r\n            // Loop over all N/2 unique element pairs\r\n            for (uint i = GI; i < NumElements / 2; i += NumThreads)\r\n            {\r\n                uint Index1 = InsertZeroBit(i, j);\r\n                uint Index2 = Index1 | j;\r\n\r\n                uint A = gs_SortKeys[Index1];\r\n                uint B = gs_SortKeys[Index2];\r\n\r\n                if ((A < B) != ((Index1 & k) == 0))\r\n                {\r\n                    gs_SortKeys[Index1] = B;\r\n                    gs_SortKeys[Index2] = A;\r\n                }\r\n            }\r\n\r\n            GroupMemoryBarrierWithGroupSync();\r\n        }\r\n    }\r\n}\r\n\r\nuint ComputeMaskOffset( uint2 Gid, uint2 GTid )\r\n{\r\n    // Sometimes we have more threads than tiles per bin.\r\n    uint2 OutTileCoord = Gid.xy * uint2(TILES_PER_BIN_X, TILES_PER_BIN_Y) + uint2(GTid.x, GTid.y % TILES_PER_BIN_Y);\r\n    uint OutTileIdx = OutTileCoord.x + OutTileCoord.y * gTileRowPitch;\r\n    return OutTileIdx * MAX_PARTICLES_PER_BIN / 8 + GTid.y / TILES_PER_BIN_Y * 4;\r\n}\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(GROUP_SIZE_X, GROUP_SIZE_Y, 1)]\r\nvoid main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    // Each group is assigned a bin\r\n    uint BinIndex = Gid.y * gBinsPerRow + Gid.x;\r\n\r\n    uint ParticleCountInBin = g_BinCounters[BinIndex];\r\n    if (ParticleCountInBin == 0)\t\r\n        return;\r\n\r\n    // Get the start location for particles in this bin\r\n    uint BinStart = BinIndex * MAX_PARTICLES_PER_BIN;\r\n\r\n    // Each thread is assigned a tile\r\n    uint2 TileCoord = Gid.xy * uint2(TILES_PER_BIN_X, TILES_PER_BIN_Y) + GTid.xy;\r\n\r\n    if (GI < TILES_PER_BIN)\r\n    {\r\n        gs_TileParticleCounts[GI] = 0;\r\n        gs_SlowTileParticleCounts[GI] = 0;\r\n        gs_MinMaxDepth[GI] = g_DepthBounds[TileCoord] << 2;\r\n    }\r\n\r\n    // Sometimes the counter value exceeds the actual storage size\r\n    ParticleCountInBin = min(MAX_PARTICLES_PER_BIN, ParticleCountInBin);\r\n\r\n    // Compute the next power of two for the bitonic sort\r\n    uint NextPow2 = countbits(ParticleCountInBin) <= 1 ? ParticleCountInBin : (2 << firstbithigh(ParticleCountInBin));\r\n\r\n    // Fill in the sort key array.  Each sort key has passenger data (in the least signficant\r\n    // bits, so that as the sort keys are moved around, they retain a pointer to the particle\r\n    // they refer to.\r\n    for (uint k = GI; k < NextPow2; k += GROUP_THREAD_COUNT)\r\n        gs_SortKeys[k] = k < ParticleCountInBin ? g_BinParticles[BinStart + k] : 0xffffffff;\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    // Sort the particles from front to back.\r\n    BitonicSort(GI, ParticleCountInBin, NextPow2, GROUP_THREAD_COUNT);\r\n\r\n    // Upper-left tile coord and lower-right coord, clamped to the screen\r\n    const int2 StartTile = Gid.xy * uint2(TILES_PER_BIN_X, TILES_PER_BIN_Y);\r\n\r\n    // Each thread writes the hit mask for one tile\r\n    uint OutOffsetInBytes = ComputeMaskOffset(Gid.xy, GTid.xy);\r\n\r\n    // Loop over all sorted particles, group-size count at a time\r\n    for (uint Iter = 0; Iter < ParticleCountInBin; Iter += GROUP_THREAD_COUNT)\r\n    {\r\n        // Reset temporary particle intersection masks.  There are two words (64-bits) per thread.\r\n        [unroll]\r\n        for (uint C = GI; C < TILES_PER_BIN * MASK_WORDS_PER_ITER; C += GROUP_THREAD_COUNT)\r\n            gs_IntersectionMasks[C] = 0;\r\n\r\n        GroupMemoryBarrierWithGroupSync();\r\n\r\n        // The array index of the particle this thread will test\r\n        uint SortIdx = Iter + GI;\r\n\r\n        // Compute word and bit to set (from thread index)\r\n        uint WordOffset = GI >> 5;\r\n        uint BitOffset = GI & 31;\r\n\r\n        // Only do the loads and stores if this is a valid index (see constant number of iterations comment above)\r\n        if (SortIdx < ParticleCountInBin)\r\n        {\r\n            uint SortKey = gs_SortKeys[SortIdx];\r\n            uint GlobalIdx = SortKey & 0x3FFFF;\r\n\r\n            // After this phase, all we care about is its global index\r\n            g_SortedParticles[BinStart + SortIdx] = SortKey;\r\n\r\n            uint Bounds = g_VisibleParticles[GlobalIdx].Bounds;\r\n            int2 MinTile = uint2(Bounds >>  0, Bounds >>  8) & 0xFF;\r\n            int2 MaxTile = uint2(Bounds >> 16, Bounds >> 24) & 0xFF;\r\n            MinTile = max(MinTile - StartTile, 0);\r\n            MaxTile = min(MaxTile - StartTile, int2(TILES_PER_BIN_X, TILES_PER_BIN_Y) - 1);\r\n\r\n            for (int y = MinTile.y; y <= MaxTile.y; y++)\r\n            {\r\n                for (int x = MinTile.x; x <= MaxTile.x; x++)\r\n                {\r\n                    uint TileIndex = y * TILES_PER_BIN_X + x;\r\n                    uint TileMaxZ = gs_MinMaxDepth[TileIndex];\r\n                    uint Inside = SortKey < TileMaxZ ? 1 : 0;\r\n                    uint SlowPath = SortKey > (TileMaxZ << 16) ? Inside : 0;\r\n                    InterlockedAdd(gs_SlowTileParticleCounts[TileIndex], SlowPath);\r\n                    InterlockedOr(gs_IntersectionMasks[TileIndex * MASK_WORDS_PER_ITER + WordOffset], Inside << BitOffset);\r\n                }\r\n            }\r\n        }\r\n\r\n        GroupMemoryBarrierWithGroupSync();\r\n\r\n#if TILES_PER_BIN < GROUP_THREAD_COUNT\r\n        // Copy the hit masks from LDS to the output buffer.  Here, each thread copies a single word\r\n        if (GI < TILES_PER_BIN * MASK_WORDS_PER_ITER)\r\n        {\r\n            uint TileIndex = GI % TILES_PER_BIN;\r\n            uint Offset = TileIndex * MASK_WORDS_PER_ITER + (GI / TILES_PER_BIN);\r\n            uint Mask = gs_IntersectionMasks[Offset];\r\n            InterlockedAdd(gs_TileParticleCounts[TileIndex], countbits(Mask));\r\n            g_TileHitMasks.Store(OutOffsetInBytes, Mask);\r\n            OutOffsetInBytes += 8;\r\n        }\r\n#else\r\n        // Copy the hit masks from LDS to the output buffer.  Here, each thread is assigned a tile.\r\n        uint Offset = GI * MASK_WORDS_PER_ITER;\r\n        [unroll]\r\n        for (uint O = 0; O < MASK_WORDS_PER_ITER; O += 2)\r\n        {\r\n            uint Mask0 = gs_IntersectionMasks[Offset+O];\r\n            uint Mask1 = gs_IntersectionMasks[Offset+O+1];\r\n            InterlockedAdd(gs_TileParticleCounts[GI], countbits(Mask0) + countbits(Mask1));\r\n            g_TileHitMasks.Store2( OutOffsetInBytes, uint2(Mask0, Mask1) );\r\n            OutOffsetInBytes += 8;\r\n        }\r\n#endif\r\n\r\n        GroupMemoryBarrierWithGroupSync();\r\n    }\r\n\r\n    if (GI >= TILES_PER_BIN)\r\n        return;\r\n\r\n    uint ParticleCountInThisThreadsTile = gs_TileParticleCounts[GI];\r\n    if (ParticleCountInThisThreadsTile > 0)\r\n    {\r\n        uint SlowParticlesInThisThreadsTile = gs_SlowTileParticleCounts[GI];\r\n        uint Packet = TileCoord.x << 16 | TileCoord.y << 24 | ParticleCountInThisThreadsTile;\r\n\r\n        uint NewPacketIndex;\r\n        if (SlowParticlesInThisThreadsTile > 0)\r\n        {\r\n            g_DrawPacketCount.InterlockedAdd(0, 1, NewPacketIndex);\r\n            g_DrawPackets[NewPacketIndex] = Packet;\r\n        }\r\n        else\r\n        {\r\n            g_DrawPacketCount.InterlockedAdd(12, 1, NewPacketIndex);\r\n            g_FastDrawPackets[NewPacketIndex] = Packet;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRender2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//          Alex Nankervis\r\n//          Julia Careaga\r\n//\r\n\r\n#include \"ParticleUtility.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\n//#define DEBUG_LOW_RES\r\n\r\n#define ALPHA_THRESHOLD (252.0 / 255.0)\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float gDynamicResLevel;\r\n    float gMipBias;\r\n};\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\nRWTexture2D<float3> g_OutputColorBuffer : register(u0);\r\n#else\r\nRWTexture2D<uint> g_OutputColorBuffer : register(u0);\r\n#endif\r\n\r\nStructuredBuffer<ParticleScreenData> g_VisibleParticles : register(t0);\r\nByteAddressBuffer g_HitMask : register(t1);\r\nTexture2DArray<float4> g_TexArray : register(t2);\r\nStructuredBuffer<uint> g_SortedParticles : register(t4);\r\n#ifndef DISABLE_DEPTH_TESTS\r\nTexture2D<float> g_InputDepthBuffer : register(t3);\r\nStructuredBuffer<uint> g_DrawPackets : register(t5);\r\nTexture2D<uint> g_TileDepthBounds : register(t7);\r\n#else\r\nStructuredBuffer<uint> g_DrawPackets : register(t6);\r\n#endif\r\n\r\nfloat4 SampleParticleColor( ParticleScreenData Particle, SamplerState Sampler, float2 UV, float LevelBias )\r\n{\r\n    float LOD = Particle.TextureLevel + LevelBias;\r\n\r\n    float4 Color = g_TexArray.SampleLevel( Sampler, float3(UV, Particle.TextureIndex), LOD);\r\n\r\n    // Multiply texture RGB with alpha.  Pre-multiplied alpha blending also permits additive blending.\r\n    Color.rgb *= Color.a;\r\n\r\n    return Color * Particle.Color;\r\n}\r\n\r\nvoid BlendPixel( inout float4 Dst, float4 Src, float Mask )\r\n{\r\n    Dst += Src * (1.0 - Dst.a) * Mask;\r\n}\r\n\r\nvoid BlendHighRes( inout float4x4 Quad, ParticleScreenData Particle, float2 PixelCoord, float4 Mask = 1 )\r\n{\r\n    float2 UV = (PixelCoord - Particle.Corner) * Particle.RcpSize;\r\n    float2 dUV = 0.5 * gRcpBufferDim * Particle.RcpSize;\r\n    float2 UV1 = UV - dUV;\r\n    float2 UV2 = UV + dUV;\r\n\r\n#if defined(DYNAMIC_RESOLUTION)\r\n    // Use point sampling for high-res rendering because this implies we're not rendering\r\n    // with the most detailed mip level anyway.\r\n    SamplerState Sampler = gSampPointBorder;\r\n    float LevelBias = gMipBias;\r\n#else\r\n    SamplerState Sampler = gSampLinearBorder;\r\n    float LevelBias = 0.0;\r\n#endif\r\n\r\n    BlendPixel(Quad[0], SampleParticleColor(Particle, Sampler, float2(UV1.x, UV2.y), LevelBias), Mask.x);\r\n    BlendPixel(Quad[1], SampleParticleColor(Particle, Sampler, float2(UV2.x, UV2.y), LevelBias), Mask.y);\r\n    BlendPixel(Quad[2], SampleParticleColor(Particle, Sampler, float2(UV2.x, UV1.y), LevelBias), Mask.z);\r\n    BlendPixel(Quad[3], SampleParticleColor(Particle, Sampler, float2(UV1.x, UV1.y), LevelBias), Mask.w);\r\n}\r\n\r\nvoid BlendLowRes( inout float4x4 Quad, ParticleScreenData Particle, float2 PixelCoord, float4 Mask = 1 )\r\n{\r\n    float2 UV = (PixelCoord - Particle.Corner) * Particle.RcpSize;\r\n    float4 Color = SampleParticleColor(Particle, gSampLinearBorder, UV, 1.0);\r\n#ifdef DEBUG_LOW_RES\r\n    Color.g *= 0.5;\r\n#endif\r\n    BlendPixel(Quad[0], Color, Mask.x);\r\n    BlendPixel(Quad[1], Color, Mask.y);\r\n    BlendPixel(Quad[2], Color, Mask.z);\r\n    BlendPixel(Quad[3], Color, Mask.w);\r\n}\r\n\r\nvoid WriteBlendedColor( uint2 ST, float4 Color )\r\n{\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    float3 DestColor = g_OutputColorBuffer[ST];\r\n    g_OutputColorBuffer[ST] = Color.rgb + DestColor * (1.0 - Color.a);\r\n#else\r\n    float3 DestColor = Unpack_R11G11B10_FLOAT(g_OutputColorBuffer[ST]);\r\n    g_OutputColorBuffer[ST] = Pack_R11G11B10_FLOAT(Color.rgb + DestColor * (1.0 - Color.a));\r\n#endif\r\n}\r\n\r\nvoid WriteBlendedQuad( uint2 ST, float4x4 Quad )\r\n{\r\n    WriteBlendedColor(ST + uint2(0, 0), Quad[3]);\r\n    WriteBlendedColor(ST + uint2(1, 0), Quad[2]);\r\n    WriteBlendedColor(ST + uint2(1, 1), Quad[1]);\r\n    WriteBlendedColor(ST + uint2(0, 1), Quad[0]);\r\n}\r\n\r\nfloat4x4 RenderParticles( uint2 TileCoord, uint2 ST, uint NumParticles, uint HitMaskStart, uint BinStart )\r\n{\r\n#ifndef DISABLE_DEPTH_TESTS\r\n    const uint TileNearZ = g_TileDepthBounds[TileCoord] << 18;\r\n    float4 Depths = g_InputDepthBuffer.Gather(gSampPointClamp, (ST + 1) * gRcpBufferDim);\r\n#endif\r\n\r\n    // VGPR\r\n    float4x4 Quad = 0.0;\r\n    const float2 PixelCoord = (ST + 1) * gRcpBufferDim;\r\n\r\n    uint BlendedParticles = 0;\r\n\r\n    while (BlendedParticles < NumParticles)\r\n    {\r\n        for (uint ParticleMask = g_HitMask.Load(HitMaskStart); ParticleMask != 0; ++BlendedParticles)\r\n        {\r\n            // Get the next bit and then clear it\r\n            uint SubIdx = firstbitlow(ParticleMask);\r\n            ParticleMask ^= 1 << SubIdx;\r\n\r\n            // Get global particle index from sorted buffer and then load the particle\r\n            uint SortKey = g_SortedParticles[BinStart + SubIdx];\r\n            uint ParticleIdx = SortKey & 0x3FFFF;\r\n            ParticleScreenData Particle = g_VisibleParticles[ParticleIdx];\r\n\r\n#if defined(DYNAMIC_RESOLUTION)\r\n            bool DoFullRes = (Particle.TextureLevel > gDynamicResLevel);\r\n#elif defined(LOW_RESOLUTION)\r\n            static const bool DoFullRes = false;\r\n#else\r\n            static const bool DoFullRes = true;\r\n#endif\r\n\r\n            if (DoFullRes)\r\n            {\r\n#ifndef DISABLE_DEPTH_TESTS\r\n                if (SortKey > TileNearZ)\r\n                {\r\n                    float4 DepthMask = saturate(1000.0 * (Depths - Particle.Depth));\r\n                    BlendHighRes(Quad, Particle, PixelCoord, DepthMask);\r\n                }\r\n                else\r\n#endif\r\n                {\r\n                    BlendHighRes(Quad, Particle, PixelCoord);\r\n                }\r\n            }\r\n            else\r\n            {\r\n#ifndef DISABLE_DEPTH_TESTS\r\n                if (SortKey > TileNearZ)\r\n                {\r\n                    float4 DepthMask = saturate(1000.0 * (Depths - Particle.Depth));\r\n                    BlendLowRes(Quad, Particle, PixelCoord, DepthMask);\r\n                }\r\n                else\r\n#endif\r\n                {\r\n                    BlendLowRes(Quad, Particle, PixelCoord);\r\n                }\r\n            }\r\n\r\n            //if (all(float4(Quad[0].a, Quad[1].a, Quad[2].a, Quad[3].a) > ALPHA_THRESHOLD))\r\n            //{\r\n            //\tQuad[0].a = Quad[1].a = Quad[2].a = Quad[3].a = 1.0;\r\n            //\treturn Quad;\r\n            //}\r\n\r\n        } // for\r\n\r\n        // Every outer loop iteration traverses 32 entries in the sorted particle list\r\n        HitMaskStart += 4;\r\n        BinStart += 32;\r\n\r\n    } // while\r\n\r\n    return Quad;\r\n}\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(TILE_SIZE / 2, TILE_SIZE / 2, 1)]\r\nvoid main( uint3 Gid : SV_GroupID, uint  GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID )\r\n{\r\n    const uint DrawPacket = g_DrawPackets[Gid.x];\r\n    uint2 TileCoord = uint2(DrawPacket >> 16, DrawPacket >> 24) & 0xFF;\r\n    const uint ParticleCount = DrawPacket & 0xFFFF;\r\n\r\n    const uint HitMaskSizeInBytes = MAX_PARTICLES_PER_BIN / 8;\r\n    const uint TileIndex = TileCoord.x + TileCoord.y * gTileRowPitch;\r\n    const uint HitMaskStart = TileIndex * HitMaskSizeInBytes;\r\n    const uint2 BinCoord = TileCoord / uint2(TILES_PER_BIN_X, TILES_PER_BIN_Y);\r\n    const uint BinIndex = BinCoord.x + BinCoord.y * gBinsPerRow;\r\n    const uint BinStart = BinIndex * MAX_PARTICLES_PER_BIN;\r\n\r\n    const uint2 ST = TileCoord * TILE_SIZE + 2 * GTid.xy;\r\n\r\n    float4x4 Quad = RenderParticles( TileCoord, ST, ParticleCount, HitMaskStart, BinStart );\r\n\r\n    WriteBlendedQuad(ST, Quad);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderFast2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define DISABLE_DEPTH_TESTS\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderFastCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define DISABLE_DEPTH_TESTS\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderFastDynamic2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define DYNAMIC_RESOLUTION\r\n#define DISABLE_DEPTH_TESTS\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderFastDynamicCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define DYNAMIC_RESOLUTION\r\n#define DISABLE_DEPTH_TESTS\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderFastLowRes2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define LOW_RESOLUTION\r\n#define DISABLE_DEPTH_TESTS\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderFastLowResCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define LOW_RESOLUTION\r\n#define DISABLE_DEPTH_TESTS\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderSlowDynamic2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define DYNAMIC_RESOLUTION\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderSlowDynamicCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define DYNAMIC_RESOLUTION\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderSlowLowRes2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define LOW_RESOLUTION\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleTileRenderSlowLowResCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#define LOW_RESOLUTION\r\n#include \"ParticleTileRenderCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleUpdateCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//          Julia Careaga\r\n//\r\n\r\n#include \"ParticleUpdateCommon.hlsli\"\r\n#include \"ParticleUtility.hlsli\"\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float gElapsedTime;\r\n};\r\n\r\nStructuredBuffer< ParticleSpawnData > g_ResetData : register( t0 );\r\nStructuredBuffer< ParticleMotion > g_InputBuffer : register( t1 );\r\nRWStructuredBuffer< ParticleVertex > g_VertexBuffer : register( u0 );\r\nRWStructuredBuffer< ParticleMotion > g_OutputBuffer : register( u2 );\r\n\r\n[RootSignature(Particle_RootSig)]\r\n[numthreads(64, 1, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    if (DTid.x >= MaxParticles)\r\n        return;\r\n\r\n    ParticleMotion ParticleState = g_InputBuffer[ DTid.x ];\r\n    ParticleSpawnData rd = g_ResetData[ ParticleState.ResetDataIndex ];\r\n\r\n    // Update age.  If normalized age exceeds 1, the particle does not renew its lease on life.\r\n    ParticleState.Age += gElapsedTime * rd.AgeRate;\r\n    if (ParticleState.Age >= 1.0)\r\n        return;\r\n\r\n    // Update position.  Compute two deltas to support rebounding off the ground plane.\r\n    float StepSize = (ParticleState.Position.y > 0.0 && ParticleState.Velocity.y < 0.0) ?\r\n        min(gElapsedTime, ParticleState.Position.y / -ParticleState.Velocity.y) : gElapsedTime;\r\n\r\n    ParticleState.Position += ParticleState.Velocity * StepSize;\r\n    ParticleState.Velocity += Gravity * ParticleState.Mass * StepSize;\r\n\r\n    // Rebound off the ground if we didn't consume all of the elapsed time\r\n    StepSize = gElapsedTime - StepSize;\r\n    if (StepSize > 0.0)\r\n    {\r\n        ParticleState.Velocity = reflect(ParticleState.Velocity, float3(0, 1, 0)) * Restitution;\r\n        ParticleState.Position += ParticleState.Velocity * StepSize;\r\n        ParticleState.Velocity += Gravity * ParticleState.Mass * StepSize;\r\n    }\r\n\r\n    // The spawn dispatch will be simultaneously adding particles as well.  It's possible to overflow.\r\n    uint index = g_OutputBuffer.IncrementCounter();\t\r\n    if (index >= MaxParticles)\r\n        return;\r\n\r\n    g_OutputBuffer[index] = ParticleState;\r\n\r\n    //\r\n    // Generate a sprite vertex\r\n    //\r\n\r\n    ParticleVertex Sprite;\r\n\r\n    Sprite.Position = ParticleState.Position;\r\n    Sprite.TextureID = TextureID;\r\n\r\n    // Update size and color\r\n    Sprite.Size = lerp(rd.StartSize, rd.EndSize, ParticleState.Age);\r\n    Sprite.Color = lerp(rd.StartColor, rd.EndColor, ParticleState.Age);\r\n\r\n    // ...Originally from Reflex...\r\n    // Use a trinomial to smoothly fade in a particle at birth and fade it out at death.\r\n    Sprite.Color *= ParticleState.Age * (1.0 - ParticleState.Age) * (1.0 - ParticleState.Age) * 6.7;\r\n\r\n    g_VertexBuffer[ g_VertexBuffer.IncrementCounter() ] = Sprite;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleUpdateCommon.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author(s):   Julia Careaga\n//              James Stanard\n//\n\ncbuffer EmissionProperties : register(b2)\n{\t\n    float3 LastEmitPosW;\n    float EmitSpeed;\n    float3 EmitPosW;\n    float FloorHeight;\n    float3 EmitDirW;\n    float Restitution;\n    float3 EmitRightW;\n    float EmitterVelocitySensitivity;\n    float3 EmitUpW;\n    uint MaxParticles;\n    float3 Gravity;\n    uint TextureID;\n    float3 EmissiveColor;\n    float pad;\n    uint4 RandIndex[64];\n};\n\nstruct ParticleSpawnData\n{\n    float AgeRate;\n    float RotationSpeed; \n    float StartSize;\n    float EndSize;\n    float3 Velocity;\n    float Mass;\n    float3 SpreadOffset;\n    float Random;\n    float4 StartColor;\n    float4 EndColor;\n};\n\nstruct ParticleMotion\n{\n    float3 Position;\n    float Mass; \n    float3 Velocity;\n    float Age;\n    float Rotation;\n    uint ResetDataIndex;\n};\n\nstruct ParticleVertexOutput\n{\n    float4 Pos : SV_POSITION;\n    float2 TexCoord : TEXCOORD0;\n    nointerpolation uint TexID : TEXCOORD1;\n    nointerpolation float4 Color : TEXCOORD2;\n    nointerpolation float LinearZ : TEXCOORD3;\n};\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleUtility.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author(s):  Julia Careaga\n//             James Stanard \n//\n\n#include \"ParticleRS.hlsli\"\n\n#define MAX_PARTICLES_PER_BIN 1024\n#define BIN_SIZE_X 128\n#define BIN_SIZE_Y 64\n#define TILE_SIZE 16\n\n#define TILES_PER_BIN_X (BIN_SIZE_X / TILE_SIZE)\n#define TILES_PER_BIN_Y (BIN_SIZE_Y / TILE_SIZE)\n#define TILES_PER_BIN (TILES_PER_BIN_X * TILES_PER_BIN_Y)\n\n#define MaxTextureSize 64\n\nSamplerState gSampLinearBorder : register(s0);\nSamplerState gSampPointBorder : register(s1);\nSamplerState gSampPointClamp : register(s2);\n\ncbuffer CBChangesPerView : register(b1)\n{\n    float4x4 gInvView;\n    float4x4 gViewProj;\n\n    float gVertCotangent;\n    float gAspectRatio;\n    float gRcpFarZ;\n    float gInvertZ;\n\n    float2 gBufferDim;\n    float2 gRcpBufferDim;\n\n    uint gBinsPerRow;\n    uint gTileRowPitch;\n    uint gTilesPerRow;\n    uint gTilesPerCol;\n};\n\nstruct ParticleVertex\n{\n    float3 Position;\n    float4 Color;\n    float Size;\n    uint TextureID;\n};\n\n// Intentionally left unpacked to allow scalar register loads and ops\nstruct ParticleScreenData\n{\n    float2 Corner;\t\t// Top-left location\n    float2 RcpSize;\t\t// 1/width, 1/height\n    float4 Color;\n    float Depth;\n    float TextureIndex;\n    float TextureLevel;\n    uint Bounds;\n};\n\nuint InsertZeroBit( uint Value, uint BitIdx )\n{\n    uint Mask = BitIdx - 1;\n    return (Value & ~Mask) << 1 | (Value & Mask);\n}\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ParticleVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):   James Stanard\r\n\r\n#include \"ParticleUpdateCommon.hlsli\"\r\n#include \"ParticleUtility.hlsli\"\r\n\r\nStructuredBuffer<ParticleVertex> g_VertexBuffer : register( t0 );\r\nStructuredBuffer<uint> g_IndexBuffer : register( t3 );\r\n\r\n[RootSignature(Particle_RootSig)]\r\nParticleVertexOutput main( uint BillboardVertex : SV_VertexID, uint InstanceId : SV_InstanceID )\r\n{\r\n#ifdef DISABLE_PARTICLE_SORT\r\n    ParticleVertex In = g_VertexBuffer[ InstanceId ];\r\n#else\r\n    ParticleVertex In = g_VertexBuffer[ g_IndexBuffer[InstanceId] & 0x3FFFF ];\r\n#endif\r\n    ParticleVertexOutput Out;\r\n\r\n    Out.TexCoord = float2((BillboardVertex >> 1) & 1, BillboardVertex & 1);\r\n    Out.Color = In.Color;\r\n    Out.TexID = In.TextureID;\r\n\r\n    float2 Corner = lerp( float2(-1, 1), float2(1, -1), Out.TexCoord );\r\n    float3 Position = mul( (float3x3)gInvView, float3(Corner * In.Size, 0) ) + In.Position;\r\n\r\n    Out.Pos = mul( gViewProj, float4(Position, 1) );\r\n    Out.LinearZ = Out.Pos.w * gRcpFarZ;\r\n\r\n    return Out;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PerfGraphBackgroundVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n//\r\n\r\n#include \"PerfGraphRS.hlsli\"\r\n\r\nstruct VSOutput\r\n{\r\n    float4 pos : SV_POSITION;\r\n    float3 col : COLOR;\r\n};\r\n\r\ncbuffer CB1 : register(b1)\r\n{\r\n    float RecSize;\r\n}\r\n\r\n[RootSignature(PerfGraph_RootSig)]\r\nVSOutput main( uint vertexID : SV_VertexID, uint instanceID : SV_InstanceID )\r\n{\r\n    //VSOutput Output;\r\n    //float2 uv = float2( (vertexID >> 1) & 1, vertexID & 1 );\r\n    //float2 Corner = lerp( float2(-1.0f, 1.0f), float2(1.0f, RecSize), uv );\r\n    //Corner.y -= 0.45f * instanceID;\r\n    //Output.pos = float4(Corner.xy, 1.0,1);\r\n    //Output.col = float3(0.0, 0.0, 0.0);\r\n    //return Output;\r\n\r\n    VSOutput Output;\r\n    float2 uv = float2( (vertexID >> 1) & 1, vertexID & 1 );\r\n    float2 Corner = lerp( float2(-1.0f, 1.0f), float2(1.0f, -1), uv );\r\n    Output.pos = float4(Corner.xy, 1.0,1);\r\n    Output.col = float3(0.0, 0.0, 0.0);\r\n    return Output;\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PerfGraphPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n//\r\n\r\n#include \"PerfGraphRS.hlsli\"\r\n\r\nstruct VSOutput\r\n{\r\n    float4 pos : SV_POSITION;\r\n    float3 col : COLOR;\r\n};\r\n\r\n[RootSignature(PerfGraph_RootSig)]\r\nfloat4 main( VSOutput input ) : SV_TARGET\r\n{\r\n    return float4(input.col, 0.75);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PerfGraphRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define PerfGraph_RootSig \\\n    \"RootFlags(0), \" \\\n    \"CBV(b0),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 2)),\" \\\n    \"SRV(t0, visibility = SHADER_VISIBILITY_VERTEX),\" \\\n    \"RootConstants(b1, num32BitConstants = 3)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PerfGraphVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Julia Careaga\r\n//\r\n\r\n#include \"PerfGraphRS.hlsli\"\r\n\r\ncbuffer CBGraphColor : register(b0)\r\n{\r\n    float3 Color;\r\n    float RcpXScale;\r\n    uint NodeCount;\r\n    uint FrameID;\r\n};\r\n\r\ncbuffer constants : register(b1)\r\n{\r\n    uint Instance;\r\n    float RcpYScale;\r\n}\r\n\r\nstruct VSOutput\r\n{\r\n    float4 pos : SV_POSITION;\r\n    float3 col : COLOR;\r\n};\r\n\r\nStructuredBuffer<float> PerfTimes : register(t0);\r\n\r\n[RootSignature(PerfGraph_RootSig)]\r\nVSOutput main( uint VertexID : SV_VertexID )\r\n{\r\n    // Assume NodeCount is a power of 2\r\n    uint offset = (FrameID + VertexID) & (NodeCount - 1);\r\n        \r\n    // TODO:  Stop interleaving data\r\n    float perfTime = saturate(PerfTimes[offset] * RcpYScale) * 2.0 - 1.0;\r\n    float frame = VertexID * RcpXScale - 1.0; \r\n\r\n    VSOutput output;\r\n    output.pos = float4(frame, perfTime, 1, 1);\r\n    output.col = Color;\r\n    return output;\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PixelPacking.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __PIXEL_PACKING_HLSLI__\n#define __PIXEL_PACKING_HLSLI__\n\n#include \"ColorSpaceUtility.hlsli\"\n#include \"PixelPacking_RGBE.hlsli\"\n#include \"PixelPacking_RGBM.hlsli\"\n#include \"PixelPacking_R11G11B10.hlsli\"\n\n#endif // __PIXEL_PACKING_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PixelPacking_LUV.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __PIXEL_PACKING_LUV_HLSLI__\n#define __PIXEL_PACKING_LUV_HLSLI__\n\n// This is the CIELUV color space which separates luminance from chrominance (like xyY) and rotates\n// chroma to be more perceptually uniform.  The intention is to be able to pack this triplet into a\n// custom 32-bit encoding that maximizes luminance precision (better than 12-bit PQ) while leaving\n// enough precision for chrominance to express all visible colors without (negligible) banding.\n\n/*\n// This describes the process of converting RGB to LUV.\n    \n// Start with the right RGBtoXYZ matrix for your color space (this one is sRGB D65)\n// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\nstatic const float3x3 RGBtoXYZ =\n{\n    0.412387, 0.357591, 0.180450,\n    0.212637, 0.715183, 0.072180,  <--The luminance dot product\n    0.019331, 0.119197, 0.950373\n};\n\n// Compute u' and v'.  UV is a two dimensional term describing the pixel's\n// chrominance (hue & saturation without brightness).  In this space (CIELUV),\n// chrominance is fairly perceptually uniform.\n// u' = 4X / (X + 15Y + 3Z)\n// v' = 9Y / (X + 15Y + 3Z)\n\n// Because all visible colors will be within the bounds of u':[0.00, 0.62], v':[0.01, 0.59],\n// we can normalize the values (for unorm representation).\n// U = u' / 0.62\n// V = v' / 0.59\n\n// If we compute these two values...\n// A = 4 / 9 * 0.59 / 0.62 * X\n// B = (X + 15 * Y + 3 * Z) * 0.59 / 9\n\n// ...we can derive our final LUV from A, Y, and B\n// L = Y\n// U = A / B\n// V = Y / B\n\n// We can compute (A, Y, B) by multiplying XYZ by this matrix\nstatic const float3x3 FixupMatrix =\n{\n    4.0 / 9.0 * 0.59 / 0.62, 0.0, 0.0,\n    0.0, 1.0, 0.0,\n    0.59 / 9.0, 15.0 * 0.59 / 9.0, 3.0 * 0.59 / 9.0\n};\n\n// But we should just concatenate the two matrices...\nstatic const float3x3 EncodeMatrix = mul(FixupMatrix, RGBtoXYZ);\n*/\n\nfloat3 Rec709toLUV(float3 RGB)\n{\n    static const float3x3 EncodeMatrix = \n    {\n        0.174414,  0.151239,  0.076320,\n        0.212637,  0.715183,  0.072180,\n        0.239929,  0.750147,  0.269713 \n    };\n\n    // Returns [A, Y, B], from which we can easily compress to LUV32\n    return mul(EncodeMatrix, RGB);\n}\n\nfloat3 LUVtoRec709(float3 AYB)\n{\n    static const float3x3 DecodeMatrix = \n    {\n         8.056027,  0.955680, -2.535335,\n        -2.324391,  1.668159,  0.211293,\n        -0.701623, -5.489756,  5.375334 \n    };\n\n    return mul(DecodeMatrix, AYB);\n}\n\nfloat3 Rec2020toLUV(float3 RGB)\n{\n    static const float3x3 EncodeMatrix = \n    {\n        0.269393,  0.061165,  0.071416,\n        0.262698,  0.678009,  0.059293,\n        0.300076,  0.681710,  0.278003 \n    };\n\n    // Returns [A, Y, B], from which we can easily compress to LUV32\n    return mul(EncodeMatrix, RGB);\n}\n\nfloat3 LUVtoRec2020(float3 AYB)\n{\n    static const float3x3 DecodeMatrix = \n    {\n         4.258579,  0.911167, -1.288312,\n        -1.588716,  1.537614,  0.080178,\n        -0.700901, -4.753993,  4.791068 \n    };\n\n    return mul(DecodeMatrix, AYB);\n}\n\nuint PackLUV(float3 AYB)\n{\n    if (AYB.y < 0.00005)\n        return 0;\n\n    uint L = (f32tof16(AYB.y) + 1) >> 1;\n    uint2 UV = saturate(AYB.xy / AYB.z) * 511.0 + 0.5;\n    return L | UV.x << 14 | UV.y << 23;\n}\n\nfloat3 UnpackLUV(uint LUV)\n{\n    float L = f16tof32((LUV << 1) & 0x7FFE);\n    float2 UV = (uint2(LUV >> 14, LUV >> 23) & 0x1FF) / 511.0;\n    float B = L / max(UV.y, 1e-6);\n    return float3(UV.x * B, L, B);\n}\n\n#endif // __PIXEL_PACKING_LUV_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PixelPacking_R11G11B10.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __PIXEL_PACKING_R11G11B10_HLSLI__\n#define __PIXEL_PACKING_R11G11B10_HLSLI__\n\n#include \"ColorSpaceUtility.hlsli\"\n\n// The standard 32-bit HDR color format.  Each float has a 5-bit exponent and no sign bit.\nuint Pack_R11G11B10_FLOAT( float3 rgb )\n{\n    // Clamp upper bound so that it doesn't accidentally round up to INF \n    // Exponent=15, Mantissa=1.11111\n    rgb = min(rgb, asfloat(0x477C0000));  \n    uint r = ((f32tof16(rgb.x) + 8) >> 4) & 0x000007FF;\n    uint g = ((f32tof16(rgb.y) + 8) << 7) & 0x003FF800;\n    uint b = ((f32tof16(rgb.z) + 16) << 17) & 0xFFC00000;\n    return r | g | b;\n}\n\nfloat3 Unpack_R11G11B10_FLOAT( uint rgb )\n{\n    float r = f16tof32((rgb << 4 ) & 0x7FF0);\n    float g = f16tof32((rgb >> 7 ) & 0x7FF0);\n    float b = f16tof32((rgb >> 17) & 0x7FE0);\n    return float3(r, g, b);\n}\n\n// An improvement to float is to store the mantissa in logarithmic form.  This causes a\n// smooth and continuous change in precision rather than having jumps in precision every\n// time the exponent increases by whole amounts.\nuint Pack_R11G11B10_FLOAT_LOG( float3 rgb )\n{\n    float3 flat_mantissa = asfloat(asuint(rgb) & 0x7FFFFF | 0x3F800000);\n    float3 curved_mantissa = min(log2(flat_mantissa) + 1.0, asfloat(0x3FFFFFFF));\n    rgb = asfloat(asuint(rgb) & 0xFF800000 | asuint(curved_mantissa) & 0x7FFFFF);\n\n    uint r = ((f32tof16(rgb.x) + 8) >>  4) & 0x000007FF;\n    uint g = ((f32tof16(rgb.y) + 8) <<  7) & 0x003FF800;\n    uint b = ((f32tof16(rgb.z) + 16) << 17) & 0xFFC00000;\n    return r | g | b;\n}\n\nfloat3 Unpack_R11G11B10_FLOAT_LOG( uint p )\n{\n    float3 rgb = f16tof32(uint3(p << 4, p >> 7, p >> 17) & uint3(0x7FF0, 0x7FF0, 0x7FE0));\n    float3 curved_mantissa = asfloat(asuint(rgb) & 0x7FFFFF | 0x3F800000);\n    float3 flat_mantissa = exp2(curved_mantissa - 1.0);\n    return asfloat(asuint(rgb) & 0xFF800000 | asuint(flat_mantissa) & 0x7FFFFF);\n}\n\n// As an alternative to floating point, we can store the log2 of a value in fixed point notation.\n// The 11-bit fields store 5.6 fixed point notation for log2(x) with an exponent bias of 15.  The\n// 10-bit field uses 5.5 fixed point.  The disadvantage here is we don't handle underflow.  Instead\n// we use the extra two exponent values to extend the range down through two more exponents.\n// Range = [2^-16, 2^16)\nuint Pack_R11G11B10_FIXED_LOG(float3 rgb)\n{\n    uint3 p = clamp((log2(rgb) + 16.0) * float3(64, 64, 32) + 0.5, 0.0, float3(2047, 2047, 1023));\n    return p.b << 22 | p.g << 11 | p.r;\n}\n\nfloat3 Unpack_R11G11B10_FIXED_LOG(uint p)\n{\n    return exp2((uint3(p, p >> 11, p >> 21) & uint3(2047, 2047, 2046)) / 64.0 - 16.0);\n}\n\n// These next two encodings are great for LDR data.  By knowing that our values are [0.0, 1.0]\n// (or [0.0, 2.0), incidentally), we can reduce how many bits we need in the exponent.  We can\n// immediately eliminate all postive exponents.  By giving more bits to the mantissa, we can\n// improve precision at the expense of range.  The 8E3 format goes one bit further, quadrupling\n// mantissa precision but increasing smallest exponent from -14 to -6.  The smallest value of 8E3\n// is 2^-14, while the smallest value of 7E4 is 2^-21.  Both are smaller than the smallest 8-bit\n// sRGB value, which is close to 2^-12.\n\n// This is like R11G11B10_FLOAT except that it moves one bit from each exponent to each mantissa.\nuint Pack_R11G11B10_E4_FLOAT( float3 rgb )\n{\n    // Clamp to [0.0, 2.0).  The magic number is 1.FFFFF x 2^0.  (We can't represent hex floats in HLSL.)\n    // This trick works because clamping your exponent to 0 reduces the number of bits needed by 1.\n    rgb = clamp( rgb, 0.0, asfloat(0x3FFFFFFF) );\n    uint r = ((f32tof16(rgb.r) + 4) >> 3 ) & 0x000007FF;\n    uint g = ((f32tof16(rgb.g) + 4) << 8 ) & 0x003FF800;\n    uint b = ((f32tof16(rgb.b) + 8) << 18) & 0xFFC00000;\n    return r | g | b;\n}\n\nfloat3 Unpack_R11G11B10_E4_FLOAT( uint rgb )\n{\n    float r = f16tof32((rgb << 3 ) & 0x3FF8);\n    float g = f16tof32((rgb >> 8 ) & 0x3FF8);\n    float b = f16tof32((rgb >> 18) & 0x3FF0);\n    return float3(r, g, b);\n}\n\n// This is like R11G11B10_FLOAT except that it moves two bits from each exponent to each mantissa.\nuint Pack_R11G11B10_E3_FLOAT( float3 rgb )\n{\n    // Clamp to [0.0, 2.0).  Divide by 256 to bias the exponent by -8.  This shifts it down to use one\n    // fewer bit while still taking advantage of the denormalization hardware.  In half precision,\n    // the exponent of 0 is 0xF.  Dividing by 256 makes the max exponent 0x7--one fewer bit.\n    rgb = clamp( rgb, 0.0, asfloat(0x3FFFFFFF) ) / 256.0;\n    uint r = ((f32tof16(rgb.r) + 2) >> 2 ) & 0x000007FF;\n    uint g = ((f32tof16(rgb.g) + 2) << 9 ) & 0x003FF800;\n    uint b = ((f32tof16(rgb.b) + 4) << 19) & 0xFFC00000;\n    return r | g | b;\n}\n\nfloat3 Unpack_R11G11B10_E3_FLOAT( uint rgb )\n{\n    float r = f16tof32((rgb << 2 ) & 0x1FFC);\n    float g = f16tof32((rgb >> 9 ) & 0x1FFC);\n    float b = f16tof32((rgb >> 19) & 0x1FF8);\n    return float3(r, g, b) * 256.0;\n}\n\n#endif // __PIXEL_PACKING_R11G11B10_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PixelPacking_RGBE.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __PIXEL_PACKING_RGBE_HLSLI__\n#define __PIXEL_PACKING_RGBE_HLSLI__\n\n#include \"ColorSpaceUtility.hlsli\"\n\n// RGBE, aka R9G9B9E5_SHAREDEXP, is an unsigned float HDR pixel format where red, green,\n// and blue all share the same exponent.  The color channels store a 9-bit value ranging\n// from [0/512, 511/512] which multiplies by 2^Exp and Exp ranges from [-16, 15].\n// Floating point specials are not encoded.\nuint PackRGBE(float3 rgb)\n{\n    // To determine the shared exponent, we must clamp the channels to an expressible range\n    const float kMaxVal = asfloat(0x477F8000); // 1.FF x 2^+15\n    const float kMinVal = asfloat(0x37800000); // 1.00 x 2^-16\n\n    // Non-negative and <= kMaxVal\n    rgb = clamp(rgb, 0, kMaxVal);\n\n    // From the maximum channel we will determine the exponent.  We clamp to a min value\n    // so that the exponent is within the valid 5-bit range.\n    float MaxChannel = max(max(kMinVal, rgb.r), max(rgb.g, rgb.b));\n\n    // 'Bias' has to have the biggest exponent plus 15 (and nothing in the mantissa).  When\n    // added to the three channels, it shifts the explicit '1' and the 8 most significant\n    // mantissa bits into the low 9 bits.  IEEE rules of float addition will round rather\n    // than truncate the discarded bits.  Channels with smaller natural exponents will be\n    // shifted further to the right (discarding more bits).\n    float Bias = asfloat((asuint(MaxChannel) + 0x07804000) & 0x7F800000);\n\n    // Shift bits into the right places\n    uint3 RGB = asuint(rgb + Bias);\n    uint E = (asuint(Bias) << 4) + 0x10000000;\n    return E | RGB.b << 18 | RGB.g << 9 | RGB.r & 0x1FF;\n}\n\nfloat3 UnpackRGBE(uint p)\n{\n    float3 rgb = uint3(p, p >> 9, p >> 18) & 0x1FF;\n    return ldexp(rgb, (int)(p >> 27) - 24);\n}\n\n// This non-standard variant applies a non-linear ramp to the mantissa to get better precision\n// with bright and saturated colors.  These colors tend to have one or two channels that prop\n// up the shared exponent, leaving little to no information in the dark channels.\nuint PackRGBE_sqrt(float3 rgb)\n{\n    // To determine the shared exponent, we must clamp the channels to an expressible range\n    const float kMaxVal = asfloat(0x477FFFFF); // 1.FFFFFF x 2^+15\n    const float kMinVal = asfloat(0x37800000); // 1.000000 x 2^-16\n\n    rgb = clamp(rgb, 0, kMaxVal);\n\n    float MaxChannel = max(max(kMinVal, rgb.r), max(rgb.g, rgb.b));\n\n    // Scaling the maximum channel puts it into the range [0, 1).  It does this by negating\n    // and subtracting one from the max exponent.\n    float Scale = asfloat((0x7EFFFFFF - asuint(MaxChannel)) & 0x7F800000);\n\n    // Shift bits into the right places\n    uint3 RGB = sqrt(rgb * Scale) * 511.0 + 0.5;\n    uint E = (0x47000000 - asuint(Scale)) << 4;\n    return E | RGB.b << 18 | RGB.g << 9 | RGB.r;\n}\n\nfloat3 UnpackRGBE_sqrt(uint p)\n{\n    float3 rgb = (uint3(p, p >> 9, p >> 18) & 0x1FF) / 511.0;\n    return ldexp(rgb * rgb, (int)(p >> 27) - 15);\n}\n\n#endif // __PIXEL_PACKING_RGBE_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PixelPacking_RGBM.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __PIXEL_PACKING_RGBM_HLSLI__\n#define __PIXEL_PACKING_RGBM_HLSLI__\n\n#include \"ColorSpaceUtility.hlsli\"\n\nfloat4 ToRGBM( float3 rgb, float PeakValue = 255.0 / 16.0 )\n{\n    rgb = saturate(rgb / PeakValue);\n    float maxVal = max(max(1e-6, rgb.x), max(rgb.y, rgb.z));\n    maxVal = ceil(maxVal * 255.0) / 255.0;\n    return float4(rgb / maxVal, maxVal);\n}\n\nfloat3 FromRGBM(float4 rgbm, float PeakValue = 255.0 / 16.0 )\n{\n    return rgbm.rgb * rgbm.a * PeakValue;\n}\n\n// RGBM is a good way to pack HDR values into R8G8B8A8_UNORM\nuint PackRGBM( float4 rgbm, bool sRGB = true )\n{\n    if (sRGB)\n        rgbm.rgb = ApplySRGBCurve(rgbm.rgb);\n    rgbm = rgbm * 255.0 + 0.5;\n    return (uint)rgbm.a << 24 | (uint)rgbm.b << 16 | (uint)rgbm.g << 8 | (uint)rgbm.r;\n}\n\nfloat4 UnpackRGBM( uint p, bool sRGB = true )\n{\n    float4 rgbm = float4(uint4(p, p >> 8, p >> 16, p >> 24) & 0xFF);\n    rgbm /= 255.0;\n    if (sRGB)\n        rgbm.rgb = RemoveSRGBCurve(rgbm.rgb);\n    return rgbm;\n}\n\n#endif // __PIXEL_PACKING_RGBM_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PixelPacking_Velocity.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __PIXEL_PACKING_VELOCITY_HLSLI__\n#define __PIXEL_PACKING_VELOCITY_HLSLI__\n\n#if 0\n// This is a custom packing that devotes 10 bits each to X and Y velocity but 12 bits to Z velocity.  Floats\n// are used instead of SNORM to increase precision around small deltas, which are the majority of deltas.\n// With TAA and Motion Blur, velocities are clamped, giving little reason to express them precisely in terms\n// of the size of the screen.\n#define packed_velocity_t uint\n\n// Designed to compress (-256.0, +256.0) with a signed 6e3 float\nuint PackXY( float x )\n{\n    uint signbit = asuint(x) >> 31;\n    x = clamp(abs(x / 32768.0), 0, asfloat(0x3BFFE000));\n    return (f32tof16(x) + 8) >> 4 | signbit << 9;\n}\n\nfloat UnpackXY( uint x )\n{\n    return f16tof32((x & 0x1FF) << 4 | (x >> 9) << 15) * 32768.0;\n}\n\n// Designed to compress (-1.0, 1.0) with a signed 8e3 float\nuint PackZ( float x )\n{\n    uint signbit = asuint(x) >> 31;\n    x = clamp(abs(x / 128.0), 0, asfloat(0x3BFFE000));\n    return (f32tof16(x) + 2) >> 2 | signbit << 11;\n}\n\nfloat UnpackZ( uint x )\n{\n    return f16tof32((x & 0x7FF) << 2 | (x >> 11) << 15) * 128.0;\n}\n\n// Pack the velocity to write to R10G10B10A2_UNORM\npacked_velocity_t PackVelocity( float3 Velocity )\n{\n    return PackXY(Velocity.x) | PackXY(Velocity.y) << 10 | PackZ(Velocity.z) << 20;\n}\n\n// Unpack the velocity from R10G10B10A2_UNORM\nfloat3 UnpackVelocity( packed_velocity_t Velocity )\n{\n    return float3(UnpackXY(Velocity & 0x3FF), UnpackXY((Velocity >> 10) & 0x3FF), UnpackZ(Velocity >> 20));\n}\n\n#elif 0\n#define packed_velocity_t float4\n\n// Pack the velocity to write to R10G10B10A2_UNORM\npacked_velocity_t PackVelocity( float3 Velocity )\n{\n    // Stretch dx,dy from [-64, 63.875] to [-512, 511] to [-0.5, 0.5) to [0, 1)\n    // Velocity.xy = (0,0) must be representable.\n    return float4(Velocity * float3(8, 8, 4096) / 1024.0 + 512 / 1023.0, 0);\n}\n\n// Unpack the velocity from R10G10B10A2_UNORM\nfloat3 UnpackVelocity( packed_velocity_t Velocity )\n{\n    return (Velocity.xyz - 512.0 / 1023.0) * float3(1024, 1024, 2) / 8.0;\n}\n#else\n#define packed_velocity_t float4\n\n// Pack the velocity to write to R16G16B16A16_FLOAT\npacked_velocity_t PackVelocity( float3 Velocity )\n{\n    return float4(Velocity * float3(16, 16, 32*1024), 0);\n}\n\n// Unpack the velocity from R10G10B10A2_UNORM\nfloat3 UnpackVelocity( packed_velocity_t Velocity )\n{\n    return Velocity.xyz / float3(16, 16, 32*1024);\n}\n\n#endif\n\n#endif // __PIXEL_PACKING_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PostEffectsRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define PostEffects_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 4), \" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 4)),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 4)),\" \\\n    \"CBV(b1),\" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR),\" \\\n    \"StaticSampler(s1,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PresentHDRPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ToneMappingUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\nTexture2D<float4> Overlay : register(t1);\r\n\r\nSamplerState BilinearClamp : register(s0);\r\n\r\nstruct PS_OUT\r\n{\r\n    float3 HdrOutput : SV_Target0;\r\n};\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float2 RcpDstSize;\r\n    float PaperWhite;\r\n    float MaxBrightness;\r\n    uint DebugMode;\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nPS_OUT main( float4 position : SV_Position )\r\n{\r\n    PS_OUT Out;\r\n\r\n    float4 UI = Overlay.SampleLevel(BilinearClamp, position.xy * RcpDstSize, 0);\r\n    float3 HDR = ColorTex[(int2)position.xy];\r\n    float3 SDR = TM_Stanard(HDR);\r\n\r\n    // Better to blend in linear space (unlike the hardware compositor)\r\n    UI.rgb = RemoveSRGBCurve(UI.rgb);\r\n\r\n    // SDR was not explicitly clamped to [0, 1] on input, but it will be on output\r\n    SDR = saturate(SDR) * (1 - UI.a) + UI.rgb;\r\n\r\n    HDR = REC709toREC2020(HDR);\r\n    UI.rgb = REC709toREC2020(UI.rgb) * PaperWhite;\r\n    SDR = REC709toREC2020(SDR) * PaperWhite;\r\n\r\n    // Tone map while in Rec.2020.  This allows values to taper to the maximum of the display.\r\n    HDR = TM_Stanard(HDR * PaperWhite / MaxBrightness) * MaxBrightness;\r\n\r\n    // Composite HDR buffer with UI\r\n    HDR = HDR * (1 - UI.a) + UI.rgb;\r\n\r\n    float3 FinalOutput;\r\n    switch (DebugMode)\r\n    {\r\n    case 0: FinalOutput = HDR; break;\r\n    case 1: FinalOutput = SDR; break;\r\n    default: FinalOutput = (position.x * RcpDstSize.x < 0.5 ? HDR : SDR); break;\r\n    }\r\n\r\n    // Current values are specified in nits.  Normalize to max specified brightness.\r\n    Out.HdrOutput = ApplyREC2084Curve(FinalOutput / 10000.0);\r\n    \r\n    return Out;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PresentRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define Present_RootSig \\\n    \"RootFlags(0), \" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 2)),\" \\\n    \"RootConstants(b0, num32BitConstants = 6), \" \\\n    \"SRV(t2, visibility = SHADER_VISIBILITY_PIXEL),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 1)), \" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR),\" \\\n    \"StaticSampler(s1,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_POINT)\"\n\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/PresentSDRPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main( float4 position : SV_Position ) : SV_Target0\r\n{\r\n    float3 LinearRGB = RemoveDisplayProfile(ColorTex[(int2)position.xy], LDR_COLOR_FORMAT);\r\n    return ApplyDisplayProfile(LinearRGB, DISPLAY_PLANE_FORMAT);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ResolveTAACS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"TemporalRS.hlsli\"\r\n\r\nTexture2D<float4> TemporalColor : register(t0);\r\nRWTexture2D<float3> OutColor : register(u0);\r\n\r\n[RootSignature(Temporal_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float4 Color = TemporalColor[DTid.xy];\r\n    OutColor[DTid.xy] = Color.rgb / max(Color.w, 1e-6);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/SSAORS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define SSAO_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 4), \" \\\n    \"CBV(b1), \" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 5)),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 5)),\" \\\n    \"SRV(t5), \" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR),\" \\\n    \"StaticSampler(s1,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ScreenQuadVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard\r\n//\r\n// A vertex shader for full-screen effects without a vertex buffer.  The\r\n// intent is to output an over-sized triangle that encompasses the entire\r\n// screen.  By doing so, we avoid rasterization inefficiency that could\r\n// result from drawing two triangles with a shared edge.\r\n//\r\n// Use null input layout\r\n// Draw(3)\r\n\r\n#include \"PresentRS.hlsli\"\r\n\r\n[RootSignature(Present_RootSig)]\r\nvoid main(\r\n    in uint VertID : SV_VertexID,\r\n    out float4 Pos : SV_Position,\r\n    out float2 Tex : TexCoord0\r\n)\r\n{\r\n    // Texture coordinates range [0, 2], but only [0, 1] appears on screen.\r\n    Tex = float2(uint2(VertID, VertID << 1) & 2);\r\n    Pos = float4(lerp(float2(-1, 1), float2(1, -1), Tex), 0, 1);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ShaderUtility.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __SHADER_UTILITY_HLSLI__\n#define __SHADER_UTILITY_HLSLI__\n\n#pragma warning( disable : 3571 )\n\n#include \"ColorSpaceUtility.hlsli\"\n#include \"PixelPacking.hlsli\"\n\n//#define RGBONLY\n#define YCOCG\n//#define YCBCR\n\n#ifdef RGBONLY\n#define ColorToLum \n#define LumToColor \n#endif\n#ifdef YCOCG\n#define ColorToLum RGB2YCoCg\n#define LumToColor YCoCg2RGB\n#endif\n#ifdef YCBCR\n#define ColorToLum RGB2YCbCr\n#define LumToColor YCbCr2RGB\n#endif\n\nfloat3 RGB2YCoCg(float3 RGB)\n{\n\tfloat3 o;\n\to.x = 0.25*RGB.r + 0.5*RGB.g + 0.25*RGB.b;\n\to.y = 0.5*RGB.r - 0.5*RGB.b;\n\to.z = -0.25*RGB.r + 0.5*RGB.g - 0.25*RGB.b;\n\treturn o;\n}\n\nfloat3 YCoCg2RGB(float3 YCoCg)\n{\n\tfloat3 o;\n\to.r = YCoCg.x + YCoCg.y - YCoCg.z;\n\to.g = YCoCg.x + YCoCg.z;\n\to.b = YCoCg.x - YCoCg.y - YCoCg.z;\n\treturn o;\n}\n\nfloat3 RGB2YCbCr(float3 rgb)\n{\n\tfloat3 RGB2Y = { 0.299, 0.587, 0.114 };\n\tfloat3 RGB2Cb = { -0.169, -0.331, 0.500 };\n\tfloat3 RGB2Cr = { 0.50000, -0.419, -0.081 };\n\n\treturn float3(dot(rgb, RGB2Y), dot(rgb, RGB2Cb) + 0.5, dot(rgb, RGB2Cr) + 0.5);\n}\n\nfloat3 YCbCr2RGB(float3 ycc_in)\n{\n\tfloat3 ycc = float3(ycc_in.x, ycc_in.y - 0.5, ycc_in.z - 0.5);\n\n\tfloat3 YCbCr2R = { 1.000, 0.000, 1.400 };\n\tfloat3 YCbCr2G = { 1.000,-0.343,-0.711 };\n\tfloat3 YCbCr2B = { 1.000, 1.765, 0.000 };\n\n\treturn float3(dot(ycc, YCbCr2R), dot(ycc, YCbCr2G), dot(ycc, YCbCr2B));\n}\n\n// Encodes a smooth logarithmic gradient for even distribution of precision natural to vision\nfloat LinearToLogLuminance( float x, float gamma = 4.0 )\n{\n    return log2(lerp(1, exp2(gamma), x)) / gamma;\n}\n\n// This assumes the default color gamut found in sRGB and REC709.  The color primaries determine these\n// coefficients.  Note that this operates on linear values, not gamma space.\nfloat RGBToLuminance( float3 x )\n{\n    return dot( x, float3(0.212671, 0.715160, 0.072169) );\t\t// Defined by sRGB/Rec.709 gamut\n}\n\nfloat MaxChannel(float3 x)\n{\n    return max(x.x, max(x.y, x.z));\n}\n\n// This is the same as above, but converts the linear luminance value to a more subjective \"perceived luminance\",\n// which could be called the Log-Luminance.\nfloat RGBToLogLuminance( float3 x, float gamma = 4.0 )\n{\n    return LinearToLogLuminance( RGBToLuminance(x), gamma );\n}\n\n// A fast invertible tone map that preserves color (Reinhard)\nfloat3 TM( float3 rgb )\n{\n    return rgb / (1 + RGBToLuminance(rgb));\n}\n\n// Inverse of preceding function\nfloat3 ITM( float3 rgb )\n{\n    return rgb / (1 - RGBToLuminance(rgb));\n}\n\n// 8-bit should range from 16 to 235\nfloat3 RGBFullToLimited8bit( float3 x )\n{\n    return saturate(x) * 219.0 / 255.0 + 16.0 / 255.0;\n}\n\nfloat3 RGBLimitedToFull8bit( float3 x )\n{\n    return saturate((x - 16.0 / 255.0) * 255.0 / 219.0);\n}\n\n// 10-bit should range from 64 to 940\nfloat3 RGBFullToLimited10bit( float3 x )\n{\n    return saturate(x) * 876.0 / 1023.0 + 64.0 / 1023.0;\n}\n\nfloat3 RGBLimitedToFull10bit( float3 x )\n{\n    return saturate((x - 64.0 / 1023.0) * 1023.0 / 876.0);\n}\n\n#define COLOR_FORMAT_LINEAR\t\t\t0\n#define COLOR_FORMAT_sRGB_FULL\t\t1\n#define COLOR_FORMAT_sRGB_LIMITED\t2\n#define COLOR_FORMAT_Rec709_FULL\t3\n#define COLOR_FORMAT_Rec709_LIMITED\t4\n#define COLOR_FORMAT_HDR10\t\t\t5\n#define COLOR_FORMAT_TV_DEFAULT\t\tCOLOR_FORMAT_Rec709_LIMITED\n#define COLOR_FORMAT_PC_DEFAULT\t\tCOLOR_FORMAT_sRGB_FULL\n\n#define HDR_COLOR_FORMAT\t\t\tCOLOR_FORMAT_LINEAR\n#define LDR_COLOR_FORMAT\t\t\tCOLOR_FORMAT_LINEAR\n#define DISPLAY_PLANE_FORMAT\t\tCOLOR_FORMAT_PC_DEFAULT\n\nfloat3 ApplyDisplayProfile( float3 x, int DisplayFormat )\n{\n    switch (DisplayFormat)\n    {\n    default:\n    case COLOR_FORMAT_LINEAR:\n        return x;\n    case COLOR_FORMAT_sRGB_FULL:\n        return ApplySRGBCurve(x);\n    case COLOR_FORMAT_sRGB_LIMITED:\n        return RGBFullToLimited10bit(ApplySRGBCurve(x));\n    case COLOR_FORMAT_Rec709_FULL:\n        return ApplyREC709Curve(x);\n    case COLOR_FORMAT_Rec709_LIMITED:\n        return RGBFullToLimited10bit(ApplyREC709Curve(x));\n    case COLOR_FORMAT_HDR10:\n        return ApplyREC2084Curve(REC709toREC2020(x));\n    };\n}\n\nfloat3 RemoveDisplayProfile( float3 x, int DisplayFormat )\n{\n    switch (DisplayFormat)\n    {\n    default:\n    case COLOR_FORMAT_LINEAR:\n        return x;\n    case COLOR_FORMAT_sRGB_FULL:\n        return RemoveSRGBCurve(x);\n    case COLOR_FORMAT_sRGB_LIMITED:\n        return RemoveSRGBCurve(RGBLimitedToFull10bit(x));\n    case COLOR_FORMAT_Rec709_FULL:\n        return RemoveREC709Curve(x);\n    case COLOR_FORMAT_Rec709_LIMITED:\n        return RemoveREC709Curve(RGBLimitedToFull10bit(x));\n    case COLOR_FORMAT_HDR10:\n        return REC2020toREC709(RemoveREC2084Curve(x));\n    };\n}\n\nfloat3 ConvertColor( float3 x, int FromFormat, int ToFormat )\n{\n    if (FromFormat == ToFormat)\n        return x;\n\n    return ApplyDisplayProfile(RemoveDisplayProfile(x, FromFormat), ToFormat);\n}\n\n#endif // __SHADER_UTILITY_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/SharpenTAACS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"TemporalRS.hlsli\"\r\n\r\nTexture2D<float4> TemporalColor : register(t0);\r\nRWTexture2D<float3> OutColor : register(u0);\r\n\r\nSamplerState LinearSampler : register(s0);\r\nSamplerState PointSampler : register(s1);\r\n\r\ncbuffer InlineConstants : register(b0)\r\n{\r\n    float WA, WB;\r\n}\r\n\r\n#define BORDER_SIZE 1\r\n#define GROUP_SIZE_X 8\r\n#define GROUP_SIZE_Y 8\r\n#define GROUP_SIZE (GROUP_SIZE_X * GROUP_SIZE_Y)\r\n#define TILE_SIZE_X (GROUP_SIZE_X + 2 * BORDER_SIZE)\r\n#define TILE_SIZE_Y (GROUP_SIZE_Y + 2 * BORDER_SIZE)\r\n#define TILE_PIXEL_COUNT (TILE_SIZE_X * TILE_SIZE_Y)\r\n\r\ngroupshared float gs_R[TILE_PIXEL_COUNT];\r\ngroupshared float gs_G[TILE_PIXEL_COUNT];\r\ngroupshared float gs_B[TILE_PIXEL_COUNT];\r\ngroupshared float gs_W[TILE_PIXEL_COUNT];\r\n\r\nfloat3 LoadSample(uint ldsIndex)\r\n{\r\n    return float3(gs_R[ldsIndex], gs_G[ldsIndex], gs_B[ldsIndex]);\r\n}\r\n\r\n[RootSignature(Temporal_RootSig)]\r\n[numthreads( GROUP_SIZE_X, GROUP_SIZE_Y, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex )\r\n{\r\n    int2 GroupUL = Gid.xy * uint2(GROUP_SIZE_X, GROUP_SIZE_Y) - BORDER_SIZE;\r\n    for (uint i = GI; i < TILE_PIXEL_COUNT; i += GROUP_SIZE)\r\n    {\r\n        int2 ST = GroupUL + int2(i % TILE_SIZE_X, i / TILE_SIZE_X);\r\n        float4 Color = TemporalColor[ST];\r\n        Color.rgb = log2(1.0 + Color.rgb / max(Color.w, 1e-6));\r\n        gs_R[i] = Color.r;\r\n        gs_G[i] = Color.g;\r\n        gs_B[i] = Color.b;\r\n        gs_W[i] = Color.w;\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint ldsIndex = (GTid.x + BORDER_SIZE) + (GTid.y + BORDER_SIZE) * TILE_SIZE_X;\r\n\r\n    float3 Center = LoadSample(ldsIndex);\r\n    float3 Neighbors = LoadSample(ldsIndex - 1) + LoadSample(ldsIndex + 1) +\r\n        LoadSample(ldsIndex - TILE_SIZE_X) + LoadSample(ldsIndex + TILE_SIZE_X);\r\n\r\n    // If the temporal weight is less than 0.5, it might be a brand new pixel.  Brand new pixels\r\n    // have not been antialiased at all and can be jarring.  Here we change the weights to actually\r\n    // blur rather than sharpen those pixels.\r\n    float TemporalWeight = gs_W[ldsIndex];\r\n    float CenterWeight = TemporalWeight <= 0.7 ? 0.4 : WA;\r\n    float LateralWeight = TemporalWeight <= 0.7 ? -0.15 : WB;\r\n\r\n\tOutColor[DTid.xy] = (exp2(max(0, CenterWeight * Center - LateralWeight * Neighbors)) - 1.0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/SharpeningUpsampleGammaPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define GAMMA_SPACE\r\n#include \"SharpeningUpsamplePS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/SharpeningUpsamplePS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n//--------------------------------------------------------------------------------------\r\n// Simple bicubic filter\r\n//\r\n// http://en.wikipedia.org/wiki/Bicubic_interpolation\r\n// http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html\r\n//\r\n//--------------------------------------------------------------------------------------\r\n\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PresentRS.hlsli\"\r\n\r\nTexture2D<float3> ColorTex : register(t0);\r\nSamplerState BilinearClamp : register(s0);\r\n\r\ncbuffer Constants : register(b0)\r\n{\r\n    float2 UVOffset0;\r\n    float2 UVOffset1;\r\n    float WA, WB;\r\n}\r\n\r\nfloat3 GetColor(float2 UV)\r\n{\r\n    float3 Color = ColorTex.SampleLevel(BilinearClamp, UV, 0);\r\n#ifdef GAMMA_SPACE\r\n    return ApplyDisplayProfile(Color, DISPLAY_PLANE_FORMAT);\r\n#else\r\n    return Color;\r\n#endif\r\n}\r\n\r\n[RootSignature(Present_RootSig)]\r\nfloat3 main(float4 position : SV_Position, float2 uv : TexCoord0) : SV_Target0\r\n{\r\n    float3 Color = WB * GetColor(uv) - WA * (\r\n        GetColor(uv + UVOffset0) + GetColor(uv - UVOffset0) +\r\n        GetColor(uv + UVOffset1) + GetColor(uv - UVOffset1));\r\n\r\n#ifdef GAMMA_SPACE\r\n    return Color;\r\n#else\r\n    return ApplyDisplayProfile(Color, DISPLAY_PLANE_FORMAT);\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/TemporalBlendCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"TemporalRS.hlsli\"\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"PixelPacking_Velocity.hlsli\"\r\n\r\nstatic const uint kLdsPitch = 16;\r\nstatic const uint kLdsRows = 16;\r\n\r\nRWTexture2D<float4> OutTemporal : register(u0);\r\n\r\nTexture2D<packed_velocity_t> VelocityBuffer : register(t0);\r\nTexture2D<float3> InColor : register(t1);\r\nTexture2D<float4> InTemporal : register(t2);\r\nTexture2D<float> CurDepth : register(t3);\r\nTexture2D<float> PreDepth : register(t4);\r\nTexture2D<float4> VarianceMap0 : register(t5);\r\nTexture2D<float2> VarianceMap1 : register(t6);\r\n\r\nSamplerState LinearSampler : register(s0);\r\nSamplerState PointSampler : register(s1);\r\n\r\ngroupshared float ldsDepth[kLdsPitch * kLdsRows];\r\ngroupshared float ldsR[kLdsPitch * kLdsRows];\r\ngroupshared float ldsG[kLdsPitch * kLdsRows];\r\ngroupshared float ldsB[kLdsPitch * kLdsRows];\r\n\r\nstatic const float PI = 3.1416;\r\n\r\n\r\ncbuffer CB1 : register(b1)\r\n{\r\n    float2 RcpBufferDim;    // 1 / width, 1 / height\r\n    float2 RcpColorBufferDim; // DRR - incolor might have different dimensions\r\n    float2 _Pad;\r\n    float TemporalBlendControl;\r\n    float RcpSpeedLimiter;\r\n    float2 JitterDelta;\r\n\tfloat2 JitterVector;\r\n\tuint  BicubicFiltering;\r\n\tuint  VisualSilhouette;\r\n\tuint  FrameOffset;\r\n\tuint  VisualDisocclusion;\r\n\tfloat VarianceExtension;\r\n\tfloat AccModifier;\r\n}\r\n\r\nvoid StoreRGB(uint ldsIdx, float3 RGB)\r\n{\r\n\tldsR[ldsIdx] = RGB.r;\r\n\tldsG[ldsIdx] = RGB.g;\r\n\tldsB[ldsIdx] = RGB.b;\r\n}\r\n\r\nfloat3 LoadRGB(uint ldsIdx)\r\n{\r\n\treturn float3(ldsR[ldsIdx], ldsG[ldsIdx], ldsB[ldsIdx]);\r\n}\r\n\r\nfloat2 STtoUV(float2 ST)\r\n{\r\n\treturn (ST + 0.5) * RcpBufferDim;\r\n}\r\n\r\nfloat3 ClipColor(float3 Color, float3 BoxMin, float3 BoxMax, float Dilation = 1.0)\r\n{\r\n    float3 BoxCenter = (BoxMax + BoxMin) * 0.5;\r\n    float3 HalfDim = (BoxMax - BoxMin) * 0.5 * Dilation + 0.001;\r\n    float3 Displacement = Color - BoxCenter;\r\n    float3 Units = abs(Displacement / HalfDim);\r\n    float MaxUnit = max(max(Units.x, Units.y), max(Units.z, 1.0));\r\n    return BoxCenter + Displacement / MaxUnit;\r\n}\r\n\r\nbool ColorBoxTest(float3 Color, float3 BoxMin, float3 BoxMax) {\r\n\treturn (\r\n\t\t(Color.x >= BoxMin.x)\r\n\t\t&& (Color.y >= BoxMin.y)\r\n\t\t&& (Color.z >= BoxMin.z)\r\n\t\t&& (Color.x <= BoxMax.x)\r\n\t\t&& (Color.y <= BoxMax.y)\r\n\t\t&& (Color.z <= BoxMax.z)\r\n\t\t);\r\n}\r\n\r\nfloat MaxOf(float4 Depths) { return max(max(Depths.x, Depths.y), max(Depths.z, Depths.w)); }\r\nfloat MinOf(float4 Depths) { return min(min(Depths.x, Depths.y), min(Depths.z, Depths.w)); }\r\n\r\n// Find closest pixel in 3x3 window with plus pattern\r\nint2 GetClosestPixel(uint Idx, out float ClosestDepth)\r\n{\r\n    float DepthO = ldsDepth[Idx];\r\n    float DepthW = ldsDepth[Idx - 1];\r\n    float DepthE = ldsDepth[Idx + 1];\r\n    float DepthN = ldsDepth[Idx - kLdsPitch];\r\n    float DepthS = ldsDepth[Idx + kLdsPitch];\r\n\r\n    ClosestDepth = min(DepthO, min(min(DepthW, DepthE), min(DepthN, DepthS)));\r\n\r\n    if (DepthN == ClosestDepth)\r\n        return int2(0, -1);\r\n    else if (DepthS == ClosestDepth)\r\n        return int2(0, +1);\r\n    else if (DepthW == ClosestDepth)\r\n        return int2(-1, 0);\r\n    else if (DepthE == ClosestDepth)\r\n        return int2(+1, 0);\r\n\r\n    return int2(0, 0);\r\n}\r\n\r\n// Find closest pixel in 3x3 window with cross pattern\r\nint2 GetClosestPixelX(uint Idx, out float ClosestDepth)\r\n{\r\n\tfloat DepthO = ldsDepth[Idx];\r\n\tfloat DepthNW = ldsDepth[Idx - 1 - kLdsPitch];\r\n\tfloat DepthNE = ldsDepth[Idx + 1 - kLdsPitch];\r\n\tfloat DepthSW = ldsDepth[Idx - 1 + kLdsPitch];\r\n\tfloat DepthSE = ldsDepth[Idx + 1 + kLdsPitch];\r\n\r\n\tClosestDepth = min(DepthO, min(min(DepthNW, DepthNE), min(DepthSW, DepthSE)));\r\n\r\n\tif (DepthNW == ClosestDepth)\r\n\t\treturn int2(-1, -1);\r\n\telse if (DepthNE == ClosestDepth)\r\n\t\treturn int2(+1, -1);\r\n\telse if (DepthSW == ClosestDepth)\r\n\t\treturn int2(-1, +1);\r\n\telse if (DepthSE == ClosestDepth)\r\n\t\treturn int2(+1, +1);\r\n\r\n\treturn int2(0, 0);\r\n}\r\n\r\n\r\n// Find closest pixel in 3x3 window with both plus and cross pattern\r\nint2 GetClosestPixel3x3(uint Idx, out float ClosestDepth)\r\n{\r\n\tint2 closestPixX, closestPixP, closestPix;\r\n\tfloat closestDepthX, closestDepthP;\r\n\r\n\tclosestPixP = GetClosestPixel(Idx, closestDepthP);\r\n\tclosestPixX = GetClosestPixelX(Idx, closestDepthX);\r\n\r\n\tClosestDepth = closestDepthP;\r\n\tclosestPix = closestPixP;\r\n\r\n\tif (closestDepthX < closestDepthP) {\r\n\t\tclosestPix = closestPixX;\r\n\t\tClosestDepth = closestDepthX;\r\n\t}\r\n\treturn closestPix;\r\n}\r\n\r\n\r\n// Find closest pixel in 7x7 window but only sample at the end of corner and plus\r\nint2 GetClosestPixelExtend(uint Idx, out float ClosestDepth, float VarExtensionRequest)\r\n{\r\n\tint offset = 1 + floor(VarExtensionRequest);\r\n\tfloat DepthO = ldsDepth[Idx];\r\n\tfloat DepthW = ldsDepth[Idx - offset];\r\n\tfloat DepthE = ldsDepth[Idx + offset];\r\n\tfloat DepthN = ldsDepth[Idx - offset *kLdsPitch];\r\n\tfloat DepthS = ldsDepth[Idx + offset *kLdsPitch];\r\n\tfloat DepthNW = ldsDepth[Idx - offset * kLdsPitch - offset];\r\n\tfloat DepthNE = ldsDepth[Idx - offset * kLdsPitch + offset];\r\n\tfloat DepthSW = ldsDepth[Idx + offset * kLdsPitch - offset];\r\n\tfloat DepthSE = ldsDepth[Idx + offset * kLdsPitch + offset];\r\n\r\n\tfloat ClosestPlus = min(min(DepthW, DepthE), min(DepthN, DepthS));\r\n\tfloat ClosestCross =min(min(DepthSE, DepthSW), min(DepthNE, DepthNW));\r\n\tClosestDepth = min(DepthO, min(ClosestPlus, ClosestCross));\r\n\tif (DepthN == ClosestDepth)\r\n\t\treturn int2(0, -offset);\r\n\telse if (DepthS == ClosestDepth)\r\n\t\treturn int2(0, +offset);\r\n\telse if (DepthW == ClosestDepth)\r\n\t\treturn int2(-offset, 0);\r\n\telse if (DepthE == ClosestDepth)\r\n\t\treturn int2(+offset, 0);\r\n\telse if (DepthSE == ClosestDepth)\r\n\t\treturn int2(+offset, +offset);\r\n\telse if (DepthSW == ClosestDepth)\r\n\t\treturn int2(-offset, +offset);\r\n\telse if (DepthNE == ClosestDepth)\r\n\t\treturn int2(+offset, -offset);\r\n\telse if (DepthNW == ClosestDepth)\r\n\t\treturn int2(-offset, -offset);\r\n\treturn int2(0, 0);\r\n}\r\n\r\n// Find closest pixel in 7x7 window but only sample at the end of corner and plus, with offset\r\nint2 GetClosestPixelExtendAdditional(uint Idx, out float ClosestDepth)\r\n{\r\n\tint offset = 3;\r\n\tint offset1 = 1;\r\n\tfloat DepthW = ldsDepth[Idx - offset + offset1 * kLdsPitch];\r\n\tfloat DepthE = ldsDepth[Idx + offset - offset1 * kLdsPitch];\r\n\tfloat DepthN = ldsDepth[Idx - offset * kLdsPitch - offset1];\r\n\tfloat DepthS = ldsDepth[Idx + offset * kLdsPitch + offset1];\r\n\tfloat DepthNW = ldsDepth[Idx - offset * kLdsPitch - offset + offset1 * kLdsPitch];\r\n\tfloat DepthNE = ldsDepth[Idx - offset * kLdsPitch + offset - offset1];\r\n\tfloat DepthSW = ldsDepth[Idx + offset * kLdsPitch - offset + offset1];\r\n\tfloat DepthSE = ldsDepth[Idx + offset * kLdsPitch + offset - offset1 * kLdsPitch];\r\n\r\n\tfloat ClosestPlus = min(min(DepthW, DepthE), min(DepthN, DepthS));\r\n\tfloat ClosestCross = min(min(DepthSE, DepthSW), min(DepthNE, DepthNW));\r\n\tClosestDepth = min(ClosestPlus, ClosestCross);\r\n\tif (DepthN == ClosestDepth)\r\n\t\treturn int2(-offset1, -offset);\r\n\telse if (DepthS == ClosestDepth)\r\n\t\treturn int2(+offset1, +offset);\r\n\telse if (DepthW == ClosestDepth)\r\n\t\treturn int2(-offset, +offset1);\r\n\telse if (DepthE == ClosestDepth)\r\n\t\treturn int2(+offset, -offset1);\r\n\telse if (DepthSE == ClosestDepth)\r\n\t\treturn int2(+offset, +offset - offset1);\r\n\telse if (DepthSW == ClosestDepth)\r\n\t\treturn int2(-offset + offset1, +offset);\r\n\telse if (DepthNE == ClosestDepth)\r\n\t\treturn int2(+offset - offset1, -offset);\r\n\telse if (DepthNW == ClosestDepth)\r\n\t\treturn int2(-offset, -offset + offset1);\r\n\treturn int2(0, 0);\r\n}\r\n\r\n//=======================================================================================\r\nfloat4 CubicHermite(float4 A, float4 B, float4 C, float4 D, float t)\r\n{\r\n\tfloat t2 = t*t;\r\n\tfloat t3 = t*t*t;\r\n\tfloat4 a = -A / 2.0 + (3.0*B) / 2.0 - (3.0*C) / 2.0 + D / 2.0;\r\n\tfloat4 b = A - (5.0*B) / 2.0 + 2.0*C - D / 2.0;\r\n\tfloat4 c = -A / 2.0 + C / 2.0;\r\n\tfloat4 d = B;\r\n\r\n\treturn a*t3 + b*t2 + c*t + d;\r\n}\r\n//=======================================================================================\r\nfloat4 CubicLagrange(float4 A, float4 B, float4 C, float4 D, float t)\r\n{\r\n\r\n\tfloat c_x0 = -1.0f;\r\n\tfloat c_x1 = 0.0f;\r\n\tfloat c_x2 = 1.0f;\r\n\tfloat c_x3 = 2.0f;\r\n\r\n\treturn\r\n\t\tA *\r\n\t\t(\r\n\t\t(t - c_x1) / (c_x0 - c_x1) *\r\n\t\t\t(t - c_x2) / (c_x0 - c_x2) *\r\n\t\t\t(t - c_x3) / (c_x0 - c_x3)\r\n\t\t\t) +\r\n\t\tB *\r\n\t\t(\r\n\t\t(t - c_x0) / (c_x1 - c_x0) *\r\n\t\t\t(t - c_x2) / (c_x1 - c_x2) *\r\n\t\t\t(t - c_x3) / (c_x1 - c_x3)\r\n\t\t\t) +\r\n\t\tC *\r\n\t\t(\r\n\t\t(t - c_x0) / (c_x2 - c_x0) *\r\n\t\t\t(t - c_x1) / (c_x2 - c_x1) *\r\n\t\t\t(t - c_x3) / (c_x2 - c_x3)\r\n\t\t\t) +\r\n\t\tD *\r\n\t\t(\r\n\t\t(t - c_x0) / (c_x3 - c_x0) *\r\n\t\t\t(t - c_x1) / (c_x3 - c_x1) *\r\n\t\t\t(t - c_x2) / (c_x3 - c_x2)\r\n\t\t\t);\r\n}\r\n// 16-tap bicubic sampling\r\nfloat4 BicubicSampling16(Texture2D<float4> Texture, float2 STV) {\r\n\tfloat2 pixel = float2(STV.x / RcpBufferDim.x, STV.y / RcpBufferDim.y) + float2(0.5f, 0.5f);\r\n\tfloat2 c_onePixel = 1.f *RcpBufferDim;\r\n\tfloat2 c_twoPixels = 2.f *RcpBufferDim;\r\n\tfloat2 Frac;\r\n\tFrac.x = frac(pixel.x);\r\n\tFrac.y = frac(pixel.y);\r\n\r\n\tfloat2 P = floor(pixel) -float2(0.5f, 0.5f);\r\n\tP = P*RcpBufferDim;\r\n\t//\r\n\tfloat4 C00 = InTemporal.SampleLevel(PointSampler, P + float2(-c_onePixel.x, -c_onePixel.y), 0);\r\n\tfloat4 C10 = InTemporal.SampleLevel(PointSampler, P + float2(0.f, -c_onePixel.y), 0);\r\n\tfloat4 C20 = InTemporal.SampleLevel(PointSampler, P + float2(c_onePixel.x, -c_onePixel.y), 0);\r\n\tfloat4 C30 = InTemporal.SampleLevel(PointSampler, P + float2(c_twoPixels.x, -c_onePixel.y), 0);\r\n\t//\r\n\tfloat4 C01 = InTemporal.SampleLevel(PointSampler, P + float2(-c_onePixel.x, 0.f), 0);\r\n\tfloat4 C11 = InTemporal.SampleLevel(PointSampler, P + float2(0.f, 0.f), 0);\r\n\tfloat4 C21 = InTemporal.SampleLevel(PointSampler, P + float2(c_onePixel.x, 0.f), 0);\r\n\tfloat4 C31 = InTemporal.SampleLevel(PointSampler, P + float2(c_twoPixels.x, 0.f), 0);\r\n\t//\r\n\tfloat4 C02 = InTemporal.SampleLevel(PointSampler, P + float2(-c_onePixel.x, c_onePixel.y), 0);\r\n\tfloat4 C12 = InTemporal.SampleLevel(PointSampler, P + float2(0.f, c_onePixel.y), 0);\r\n\tfloat4 C22 = InTemporal.SampleLevel(PointSampler, P + float2(c_onePixel.x, c_onePixel.y), 0);\r\n\tfloat4 C32 = InTemporal.SampleLevel(PointSampler, P + float2(c_twoPixels.x, c_onePixel.y), 0);\r\n\t//\r\n\tfloat4 C03 = InTemporal.SampleLevel(PointSampler, P + float2(-c_onePixel.x, c_twoPixels.y), 0);\r\n\tfloat4 C13 = InTemporal.SampleLevel(PointSampler, P + float2(0.f, c_twoPixels.y), 0);\r\n\tfloat4 C23 = InTemporal.SampleLevel(PointSampler, P + float2(c_onePixel.x, c_twoPixels.y), 0);\r\n\tfloat4 C33 = InTemporal.SampleLevel(PointSampler, P + float2(c_twoPixels.x, c_twoPixels.y), 0);\r\n\r\n\tfloat4 color;\r\n\r\n\tfloat4 CP0X = CubicHermite(C00, C10, C20, C30, Frac.x);\r\n\tfloat4 CP1X = CubicHermite(C01, C11, C21, C31, Frac.x);\r\n\tfloat4 CP2X = CubicHermite(C02, C12, C22, C32, Frac.x);\r\n\tfloat4 CP3X = CubicHermite(C03, C13, C23, C33, Frac.x);\r\n\r\n\tcolor = CubicHermite(CP0X, CP1X, CP2X, CP3X, Frac.y);\r\n\treturn color;\r\n}\r\n// optimized 5-tap bicubic sampling\r\nfloat4 BicubicSampling5(Texture2D<float4> Texture, float2 STV) {\r\n\tfloat2 pixel = float2(STV.x / RcpBufferDim.x, STV.y / RcpBufferDim.y) + float2(0.5f, 0.5f);\r\n\tfloat2 c_onePixel = 1.f *RcpBufferDim;\r\n\tfloat2 c_twoPixels = 2.f *RcpBufferDim;\r\n\tfloat2 Frac;\r\n\tFrac.x = frac(pixel.x);\r\n\tFrac.y = frac(pixel.y);\r\n\r\n\tfloat2 P = floor(pixel) - float2(0.5f, 0.5f);\r\n\tP = P*RcpBufferDim;\r\n\t// 5-tap bicubic sampling (for Hermite/Carmull-Rom filter) -- (approximate from original 16->9-tap bilinear fetching) \r\n\tfloat2 t = Frac;\r\n\tfloat2 t2 = t*t;\r\n\tfloat2 t3 = t2*t;\r\n\tfloat s = 0.5;\t// s is potentially adjustable\r\n\tfloat2 w0 = -s*t3 + 2 * s*t2 - s*t;\r\n\tfloat2 w1 = (2 - s) * t3 + (s - 3)*t2 + 1;\r\n\tfloat2 w2 = (s - 2)*t3 + (3 - 2 * s)*t2 + s*t;\r\n\tfloat2 w3 = s*t3 - s*t2;\r\n\tfloat2 s0 = w1 + w2;\r\n\tfloat2 f0 = w2 / (w1 + w2);\r\n\tfloat2 m0 = P + f0 * RcpBufferDim;\r\n\tfloat2 tc0 = P - c_onePixel;\r\n\tfloat2 tc3 = P + c_twoPixels;\r\n\t\r\n\tfloat4 A = Texture.SampleLevel(LinearSampler, float2(m0.x, tc0.y), 0);\r\n\tfloat4 B = Texture.SampleLevel(LinearSampler, float2(tc0.x, m0.y), 0);\r\n\tfloat4 C = Texture.SampleLevel(LinearSampler, float2(m0.x, m0.y), 0);\r\n\tfloat4 D = Texture.SampleLevel(LinearSampler, float2(tc3.x, m0.y), 0);\r\n\tfloat4 E = Texture.SampleLevel(LinearSampler, float2(m0.x, tc3.y), 0);\r\n\tfloat4 color =\t(0.5 * (A + B) * w0.x + A * s0.x + 0.5 * (A + B) * w3.x) * w0.y +\r\n\t\t\t\t\t(B * w0.x + C * s0.x + D * w3.x) * s0.y +\r\n\t\t\t\t\t(0.5 * (B + E) * w0.x + E * s0.x + 0.5 * (D + E) * w3.x) * w3.y;\r\n\treturn color;\r\n}\r\n\r\n\r\nbool CheckSilhouette(uint LdsIdx, int2 ST, float3 Velocity, float CompareDepth, float VarExtensionRequest) {\r\n\tbool NoSilhouetteDetected = false;\r\n\tfloat CompareDepthExt;\r\n\tint2 DepthOffset = GetClosestPixelExtend(LdsIdx, CompareDepthExt, VarExtensionRequest);\r\n\tfloat3 VelocityExt = UnpackVelocity(VelocityBuffer[ST + DepthOffset]);\r\n\tfloat Threshold = 0.5*TemporalBlendControl;\r\n\tNoSilhouetteDetected = abs(length(Velocity.xy) - length(VelocityExt.xy)) < Threshold;\r\n\t// always treat boundary between geometry and empty space as silhouette\r\n\tNoSilhouetteDetected = NoSilhouetteDetected && (CompareDepth < 1.f);\r\n\treturn NoSilhouetteDetected;\r\n}\r\n\r\nvoid GetVarianceBox(uint2 ST, out float3 BoxMin, out float3 BoxMax, float VarExtensionFactor) {\r\n\t//float LOD = (VarianceExtension - 1)*VarExtensionFactor;\r\n\tfloat LOD = VarExtensionFactor;\r\n\tfloat4 TempVariance0 = VarianceMap0.SampleLevel(LinearSampler, STtoUV(ST), LOD);\r\n\tfloat2 TempVariance1 = VarianceMap1.SampleLevel(LinearSampler, STtoUV(ST), LOD);\r\n\tfloat3 mu = TempVariance0.xyz;\r\n\tfloat3 m2 = float3(TempVariance0.w, TempVariance1.xy);\r\n\tfloat3 var = max(0.f, m2 - mu * mu);\r\n\tfloat3 sigma = sqrt(var) * 1.2f;\r\n\tBoxMin = (mu - sigma);\r\n\tBoxMax = (mu + sigma);\r\n}\r\n\r\nfloat GetShadingWeight1Tap(uint2 ST, int2 pixelJitter) {\r\n\tfloat2 fractJitter = JitterVector - float2(pixelJitter);\r\n\tint2 pixOffset = ST % 2;\r\n\tfloat2 delta = pixOffset + fractJitter - float2(1, 1);\r\n\tfloat dist = delta.x*delta.x + delta.y*delta.y;\r\n\tfloat sigma2 = 2.f*0.7f*0.7f;\r\n\tfloat w = exp(-dist / sigma2);\r\n\treturn w;\r\n}\r\n\r\n\r\nfloat GetShadingWeightLanczos(uint2 ST, int2 pixelJitter) {\r\n\tfloat2 fractJitter = JitterVector - float2(pixelJitter);\r\n\tint2 pixOffset = ST % 2;\r\n\tfloat2 delta = pixOffset + fractJitter - float2(1, 1);\r\n\tfloat x = min(1.f, length(delta));\r\n\tfloat w = (x == 0) ? 1 : 2 * sin(PI * x)*sin(PI * x / 2) / (PI * PI * x * x);\r\n\treturn w;\r\n}\r\n\r\nvoid ApplyTemporalBlend(uint2 ST, uint LdsIdx)\r\n{\r\n\t// If jitter exceeds a pixel cancel pixel offset\r\n\tint2 pixelJitter = floor(JitterVector);\r\n\tint2 STP = max(0, ST - pixelJitter);\r\n\tfloat3 CurrentColor = LoadRGB(LdsIdx);\r\n\tfloat3 Velocity;\r\n\tfloat CompareDepth;\r\n\tfloat3 BoxMin, BoxMax;\r\n\r\n    Velocity = UnpackVelocity(VelocityBuffer[ST + GetClosestPixel3x3(LdsIdx, CompareDepth)]);\r\n\r\n    CompareDepth += Velocity.z;\r\n\r\n    // The temporal depth is the actual depth of the pixel found at the same reprojected location.\r\n\tfloat TemporalDepthMax = MaxOf(PreDepth.Gather(LinearSampler, STtoUV(STP + Velocity.xy))) + 1e-3;\r\n\r\n\t// Fast-moving pixels cause motion blur and probably don't need TAA\r\n\tfloat SpeedFactor = saturate(1.0 - length(Velocity.xy) * RcpSpeedLimiter);\r\n\r\n    // Fetch temporal color.  Its \"confidence\" weight is stored in alpha.\r\n\tfloat4 Temp;\r\n\tif (BicubicFiltering == 1) {\r\n\t\tTemp = BicubicSampling5(InTemporal, STtoUV(STP + Velocity.xy));\r\n\t}\r\n\telse {\r\n\t\tTemp = InTemporal.SampleLevel(LinearSampler, STtoUV(STP + Velocity.xy), 0);\r\n\t}\r\n\r\n    float3 TemporalColor = Temp.rgb;\r\n\tfloat TemporalWeight = Temp.w;\r\n\r\n\t// Pixel colors are pre-multiplied by their weight to enable bilinear filtering.  Divide by weight to recover color.\r\n\tTemporalColor /= max(TemporalWeight, 1e-6);\r\n\r\n\t// Update the confidence term based on speed and disocclusion\r\n\tuint NoDisocclusion = step(CompareDepth, TemporalDepthMax);\r\n\tTemporalWeight *= SpeedFactor * NoDisocclusion;\r\n\r\n\t// No Variance Extension needed off from a fresh disocclusion\r\n\t// Slowly increase the variance extension (between 0 to VarianceExtension-1)\r\n\tfloat VarExtensionFactorRequest = TemporalWeight * TemporalWeight * (VarianceExtension - 1);\r\n\r\n\t// Check velocity difference in box covered the requested Variance Extension window\r\n\tbool NoSilhouetteInBox = CheckSilhouette(LdsIdx, ST, Velocity, CompareDepth, VarExtensionFactorRequest);\r\n\r\n\t// Nullify the requested variance extension if there is silhouette in the requested window\r\n\tfloat VarExtension = VarExtensionFactorRequest *NoSilhouetteInBox;\r\n\tGetVarianceBox(ST, BoxMin, BoxMax, VarExtension);\r\n\t\r\n\tTemporalColor = ClipColor(ColorToLum(TemporalColor), BoxMin, BoxMax, 1.f);\r\n\tTemporalColor = LumToColor(TemporalColor);\r\n\r\n\t// Blend previous color with new color based on confidence.  Confidence steadily grows with each iteration\r\n    // until it is broken by movement such as through disocclusion, color changes, or moving beyond the resolution\r\n    // of the velocity buffer.\r\n\tTemporalColor = ITM(lerp(TM(CurrentColor), TM(TemporalColor), (TemporalWeight)));\r\n\r\n\t// Update weight\r\n\tTemporalWeight = saturate(rcp(2.0 - TemporalWeight + AccModifier*0.1f));\r\n\r\n    // Quantize weight to what is representable\r\n    TemporalWeight = f16tof32(f32tof16(TemporalWeight));\r\n\r\n    // Breaking this up into two buffers means it can be 40 bits instead of 64.\r\n\tOutTemporal[STP] = float4(TemporalColor, 1) * TemporalWeight;\r\n\tif (VisualSilhouette) {\r\n\t\t// visualize silhouette detection\r\n\t\tOutTemporal[STP] = float4((1-NoSilhouetteInBox) || (1 - NoDisocclusion), 10*(CompareDepth - Velocity.z), 100*(CompareDepth - Velocity.z), 1) * TemporalWeight;\r\n\t}\r\n\tif (VisualDisocclusion) {\r\n\t\t// visualize disocclusoin detection\r\n\t\tOutTemporal[STP] = float4(1 - NoDisocclusion, 10 * (CompareDepth - Velocity.z), 100 * (CompareDepth - Velocity.z), 1) * TemporalWeight;\r\n\t}\r\n}\r\n\r\n[RootSignature(Temporal_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main(uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID)\r\n{\r\n    const uint ldsHalfPitch = kLdsPitch/2;\r\n\r\n    // Prefetch an 16x16 tile of pixels (8x8 colors) including a 4 pixel border\r\n\t// 16x16 IDs with 4 IDs per thread = 64 threads\r\n\r\n\tfor (uint i = GI; i < (kLdsPitch * kLdsRows / 4); i += 64)\r\n    {\r\n        uint X = (i % ldsHalfPitch)*2;\r\n        uint Y = (i / ldsHalfPitch)*2;\r\n        uint TopLeftIdx = X + Y * kLdsPitch;\r\n        int2 TopLeftST = Gid.xy * uint2(8, 8) - 4 + uint2(X, Y);\r\n        float2 ColorUV = RcpColorBufferDim * (TopLeftST + float2(1, 1));\r\n        float2 UV = RcpBufferDim * (TopLeftST + float2(1, 1));\r\n\r\n        float4 Depths = CurDepth.Gather(LinearSampler, UV);\r\n        ldsDepth[TopLeftIdx + 0] = Depths.w;\r\n        ldsDepth[TopLeftIdx + 1] = Depths.z;\r\n        ldsDepth[TopLeftIdx + kLdsPitch] = Depths.x;\r\n        ldsDepth[TopLeftIdx + 1 + kLdsPitch] = Depths.y;\r\n\r\n        float4 R4 = InColor.GatherRed(LinearSampler, ColorUV);\r\n        float4 G4 = InColor.GatherGreen(LinearSampler, ColorUV);\r\n        float4 B4 = InColor.GatherBlue(LinearSampler, ColorUV);\r\n        StoreRGB(TopLeftIdx, float3(R4.w, G4.w, B4.w));\r\n        StoreRGB(TopLeftIdx + 1, float3(R4.z, G4.z, B4.z));\r\n        StoreRGB(TopLeftIdx + kLdsPitch, float3(R4.x, G4.x, B4.x));\r\n        StoreRGB(TopLeftIdx + 1 + kLdsPitch, float3(R4.y, G4.y, B4.y));\r\n    }\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    uint Idx = GTid.x + GTid.y * kLdsPitch + (kLdsPitch + 1)*4;\r\n\r\n    uint2 ST = DTid.xy;\r\n\tApplyTemporalBlend(ST, Idx);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/TemporalRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define Temporal_RootSig \\\n    \"RootFlags(0), \" \\\n    \"RootConstants(b0, num32BitConstants = 4),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 10)),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 10)),\" \\\n    \"CBV(b1), \" \\\n    \"StaticSampler(s0,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR),\" \\\n    \"StaticSampler(s1,\" \\\n        \"addressU = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressV = TEXTURE_ADDRESS_BORDER,\" \\\n        \"addressW = TEXTURE_ADDRESS_BORDER,\" \\\n        \"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_POINT)\"\n\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/TextAntialiasPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"TextRS.hlsli\"\r\n\r\ncbuffer cbFontParams : register(b0)\r\n{\r\n    float4 Color;\r\n    float2 ShadowOffset;\r\n    float ShadowHardness;\r\n    float ShadowOpacity;\r\n    float HeightRange;\t// The range of the signed distance field.\r\n}\r\n\r\nTexture2D<float> SignedDistanceFieldTex : register( t0 );\r\nSamplerState LinearSampler : register( s0 );\r\n\r\nstruct PS_INPUT\r\n{\r\n    float4 pos : SV_POSITION;\r\n    float2 uv : TEXCOORD0;\r\n};\r\n\r\nfloat GetAlpha( float2 uv )\r\n{\r\n    return saturate(SignedDistanceFieldTex.Sample(LinearSampler, uv) * HeightRange + 0.5);\r\n}\r\n\r\n[RootSignature(Text_RootSig)]\r\nfloat4 main( PS_INPUT Input ) : SV_Target\r\n{\r\n    return float4(Color.rgb, 1) * GetAlpha(Input.uv) * Color.a;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/TextRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define Text_RootSig \\\n    \"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), \" \\\n    \"CBV(b0, visibility = SHADER_VISIBILITY_VERTEX),\" \\\n    \"CBV(b0, visibility = SHADER_VISIBILITY_PIXEL),\" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 1), visibility = SHADER_VISIBILITY_PIXEL),\" \\\n    \"StaticSampler(s0, visibility = SHADER_VISIBILITY_PIXEL,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"filter = FILTER_MIN_MAG_MIP_LINEAR)\"\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/TextShadowPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"TextRS.hlsli\"\r\n\r\ncbuffer cbFontParams : register(b0)\r\n{\r\n    float4 Color;\r\n    float2 ShadowOffset;\r\n    float ShadowHardness;\r\n    float ShadowOpacity;\r\n    float HeightRange;\t// The range of the signed distance field.\r\n}\r\n\r\nTexture2D<float> SignedDistanceFieldTex : register( t0 );\r\nSamplerState LinearSampler : register( s0 );\r\n\r\nstruct PS_INPUT\r\n{\r\n    float4 pos : SV_POSITION;\r\n    float2 uv : TEXCOORD0;\r\n};\r\n\r\nfloat GetAlpha( float2 uv, float range )\r\n{\r\n    return saturate(SignedDistanceFieldTex.Sample(LinearSampler, uv) * range + 0.5);\r\n}\r\n\r\n[RootSignature(Text_RootSig)]\r\nfloat4 main( PS_INPUT Input ) : SV_Target\r\n{\r\n    float alpha1 = GetAlpha(Input.uv, HeightRange) * Color.a;\r\n    float alpha2 = GetAlpha(Input.uv - ShadowOffset, HeightRange * ShadowHardness) * ShadowOpacity * Color.a;\r\n    return float4( Color.rgb * alpha1, lerp(alpha2, 1, alpha1) );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/TextVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"TextRS.hlsli\"\r\n\r\ncbuffer cbFontParams : register(b0)\r\n{\r\n    float2 Scale;\t\t\t// Scale and offset for transforming coordinates\r\n    float2 Offset;\r\n    float2 InvTexDim;\t\t// Normalizes texture coordinates\r\n    float TextSize;\t\t\t// Height of text in destination pixels\r\n    float TextScale;\t\t// TextSize / FontHeight\r\n    float DstBorder;\t\t// Extra space around a glyph measured in screen space coordinates\r\n    uint SrcBorder;\t\t\t// Extra spacing around glyphs to avoid sampling neighboring glyphs\r\n}\r\n\r\nstruct VS_INPUT\r\n{\r\n    float2 ScreenPos : POSITION;\t// Upper-left position in screen pixel coordinates\r\n    uint4  Glyph : TEXCOORD;\t\t// X, Y, Width, Height in texel space\r\n};\r\n\r\nstruct VS_OUTPUT\r\n{\r\n    float4 Pos : SV_POSITION;\t// Upper-left and lower-right coordinates in clip space\r\n    float2 Tex : TEXCOORD0;\t\t// Upper-left and lower-right normalized UVs\r\n};\r\n\r\n[RootSignature(Text_RootSig)]\r\nVS_OUTPUT main( VS_INPUT input, uint VertID : SV_VertexID )\r\n{\r\n    const float2 xy0 = input.ScreenPos - DstBorder;\r\n    const float2 xy1 = input.ScreenPos + DstBorder + float2(TextScale * input.Glyph.z, TextSize);\r\n    const uint2 uv0 = input.Glyph.xy - SrcBorder;\r\n    const uint2 uv1 = input.Glyph.xy + SrcBorder + input.Glyph.zw;\r\n\r\n    float2 uv = float2( VertID & 1, (VertID >> 1) & 1 );\r\n\r\n    VS_OUTPUT output;\r\n    output.Pos = float4( lerp(xy0, xy1, uv) * Scale + Offset, 0, 1 );\r\n    output.Tex = lerp(uv0, uv1, uv) * InvTexDim;\r\n    return output;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ToneMap2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ToneMapCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ToneMapCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"ToneMappingUtility.hlsli\"\r\n#include \"PostEffectsRS.hlsli\"\r\n#include \"PixelPacking.hlsli\"\r\n\r\nStructuredBuffer<float> Exposure : register( t0 );\r\nTexture2D<float3> Bloom : register( t1 );\r\n#if SUPPORT_TYPED_UAV_LOADS\r\nRWTexture2D<float3> ColorRW : register( u0 );\r\n#else\r\nRWTexture2D<uint> DstColor : register( u0 );\r\nTexture2D<float3> SrcColor : register( t2 );\r\n#endif\r\nRWTexture2D<float> OutLuma : register( u1 );\r\nSamplerState LinearSampler : register( s0 );\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float2 g_RcpBufferDim;\r\n    float g_BloomStrength;\r\n};\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    float2 TexCoord = (DTid.xy + 0.5) * g_RcpBufferDim;\r\n\r\n    // Load HDR and bloom\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    float3 hdrColor = ColorRW[DTid.xy];\r\n#else\r\n    float3 hdrColor = SrcColor[DTid.xy];\r\n#endif\r\n\r\n    hdrColor += g_BloomStrength * Bloom.SampleLevel(LinearSampler, TexCoord, 0);\r\n    hdrColor *= Exposure[0];\r\n\r\n#if ENABLE_HDR_DISPLAY_MAPPING\r\n\r\n    // Write the HDR color as-is and defer display mapping until we composite with UI\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    ColorRW[DTid.xy] = hdrColor;\r\n#else\r\n    DstColor[DTid.xy] = Pack_R11G11B10_FLOAT(hdrColor);\r\n#endif\r\n    OutLuma[DTid.xy] = LinearToLogLuminance(ToneMapLuma(RGBToLuminance(hdrColor)));\r\n\r\n#else\r\n\r\n    // Tone map to SDR\r\n    float3 sdrColor = TM_Stanard(hdrColor);\r\n\r\n#if SUPPORT_TYPED_UAV_LOADS\r\n    ColorRW[DTid.xy] = sdrColor;\r\n#else\r\n    DstColor[DTid.xy] = Pack_R11G11B10_FLOAT(sdrColor);\r\n#endif\r\n    OutLuma[DTid.xy] = RGBToLogLuminance(sdrColor);\r\n\r\n#endif\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ToneMapHDR2CS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define ENABLE_HDR_DISPLAY_MAPPING 1\r\n#define SUPPORT_TYPED_UAV_LOADS 1\r\n#include \"ToneMapCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ToneMapHDRCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#define ENABLE_HDR_DISPLAY_MAPPING 1\r\n#include \"ToneMapCS.hlsl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/ToneMappingUtility.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#ifndef __TONE_MAPPING_UTILITY_HLSLI__\n#define __TONE_MAPPING_UTILITY_HLSLI__\n\n#include \"ShaderUtility.hlsli\"\n\n//\n// Reinhard\n// \n\n// The Reinhard tone operator.  Typically, the value of k is 1.0, but you can adjust exposure by 1/k.\n// I.e. TM_Reinhard(x, 0.5) == TM_Reinhard(x * 2.0, 1.0)\nfloat3 TM_Reinhard(float3 hdr, float k = 1.0)\n{\n    return hdr / (hdr + k);\n}\n\n// The inverse of Reinhard\nfloat3 ITM_Reinhard(float3 sdr, float k = 1.0)\n{\n    return k * sdr / (k - sdr);\n}\n\n//\n// Reinhard-Squared\n//\n\n// This has some nice properties that improve on basic Reinhard.  Firstly, it has a \"toe\"--that nice,\n// parabolic upswing that enhances contrast and color saturation in darks.  Secondly, it has a long\n// shoulder giving greater detail in highlights and taking longer to desaturate.  It's invertible, scales\n// to HDR displays, and is easy to control.\n//\n// The default constant of 0.25 was chosen for two reasons.  It maps closely to the effect of Reinhard\n// with a constant of 1.0.  And with a constant of 0.25, there is an inflection point at 0.25 where the\n// curve touches the line y=x and then begins the shoulder.\n//\n// Note:  If you are currently using ACES and you pre-scale by 0.6, then k=0.30 looks nice as an alternative\n// without any other adjustments.\n\nfloat3 TM_ReinhardSq(float3 hdr, float k = 0.25)\n{\n    float3 reinhard = hdr / (hdr + k);\n    return reinhard * reinhard;\n}\n\nfloat3 ITM_ReinhardSq(float3 sdr, float k = 0.25)\n{\n    return k * (sdr + sqrt(sdr)) / (1.0 - sdr);\n}\n\n//\n// Stanard (New)\n//\n\n// This is the new tone operator.  It resembles ACES in many ways, but it is simpler to evaluate with ALU.  One\n// advantage it has over Reinhard-Squared is that the shoulder goes to white more quickly and gives more overall\n// brightness and contrast to the image.\n\nfloat3 TM_Stanard(float3 hdr)\n{\n    return TM_Reinhard(hdr * sqrt(hdr), sqrt(4.0 / 27.0));\n}\n\nfloat3 ITM_Stanard(float3 sdr)\n{\n    return pow(ITM_Reinhard(sdr, sqrt(4.0 / 27.0)), 2.0 / 3.0);\n}\n\n//\n// Stanard (Old)\n//\n\n// This is the old tone operator first used in HemiEngine and then MiniEngine.  It's simplistic, efficient,\n// invertible, and gives nice results, but it has no toe, and the shoulder goes to white fairly quickly.\n//\n// Note that I removed the distinction between tone mapping RGB and tone mapping Luma.  Philosophically, I\n// agree with the idea of trying to remap brightness to displayable values while preserving hue.  But you\n// run into problems where one or more color channels end up brighter than 1.0 and get clipped.\n\nfloat3 ToneMap( float3 hdr )\n{\n    return 1 - exp2(-hdr);\n}\n\nfloat3 InverseToneMap(float3 sdr)\n{\n    return -log2(max(1e-6, 1 - sdr));\n}\n\nfloat ToneMapLuma( float luma )\n{\n    return 1 - exp2(-luma);\n}\n\nfloat InverseToneMapLuma(float luma)\n{\n    return -log2(max(1e-6, 1 - luma));\n}\n\n//\n// ACES\n//\n\n// The next generation of filmic tone operators.\n\nfloat3 ToneMapACES( float3 hdr )\n{\n    const float A = 2.51, B = 0.03, C = 2.43, D = 0.59, E = 0.14;\n    return saturate((hdr * (A * hdr + B)) / (hdr * (C * hdr + D) + E));\n}\n\nfloat3 InverseToneMapACES( float3 sdr )\n{\n    const float A = 2.51, B = 0.03, C = 2.43, D = 0.59, E = 0.14;\n    return 0.5 * (D * sdr - sqrt(((D*D - 4*C*E) * sdr + 4*A*E-2*B*D) * sdr + B*B) - B) / (A - C * sdr);\n}\n\n#endif // __TONE_MAPPING_UTILITY_HLSLI__\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/UpsampleAndBlurCS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// The CS for combining a lower resolution bloom buffer with a higher resolution buffer\r\n// (via bilinear upsampling) and then guassian blurring the resultant buffer.\r\n//\r\n// For the intended bloom blurring algorithm, it is expected that this shader will be\r\n// used repeatedly to upsample and blur successively higher resolutions until the final\r\n// bloom buffer is the destination.\r\n//\r\n\r\n#include \"PostEffectsRS.hlsli\"\r\n\r\nTexture2D<float3> HigherResBuf : register( t0 );\r\nTexture2D<float3> LowerResBuf : register( t1 );\r\nSamplerState LinearBorder : register( s1 );\r\nRWTexture2D<float3> Result : register( u0 );\r\n\r\ncbuffer cb0 : register(b0)\r\n{\r\n    float2 g_inverseDimensions;\r\n    float g_upsampleBlendFactor;\r\n}\r\n\r\n// The guassian blur weights (derived from Pascal's triangle)\r\nstatic const float Weights5[3] = { 6.0f / 16.0f, 4.0f / 16.0f, 1.0f / 16.0f };\r\nstatic const float Weights7[4] = { 20.0f / 64.0f, 15.0f / 64.0f, 6.0f / 64.0f, 1.0f / 64.0f };\r\nstatic const float Weights9[5] = { 70.0f / 256.0f, 56.0f / 256.0f, 28.0f / 256.0f, 8.0f / 256.0f, 1.0f / 256.0f };\r\n\r\nfloat3 Blur5( float3 a, float3 b, float3 c, float3 d, float3 e, float3 f, float3 g, float3 h, float3 i )\r\n{\r\n    return Weights5[0]*e + Weights5[1]*(d+f) + Weights5[2]*(c+g);\r\n}\r\n\r\nfloat3 Blur7( float3 a, float3 b, float3 c, float3 d, float3 e, float3 f, float3 g, float3 h, float3 i )\r\n{\r\n    return Weights7[0]*e + Weights7[1]*(d+f) + Weights7[2]*(c+g) + Weights7[3]*(b+h);\r\n}\r\n\r\nfloat3 Blur9( float3 a, float3 b, float3 c, float3 d, float3 e, float3 f, float3 g, float3 h, float3 i )\r\n{\r\n    return Weights9[0]*e + Weights9[1]*(d+f) + Weights9[2]*(c+g) + Weights9[3]*(b+h) + Weights9[4]*(a+i);\r\n}\r\n\r\n#define BlurPixels Blur9\r\n\r\n// 16x16 pixels with an 8x8 center that we will be blurring writing out.  Each uint is two color channels packed together\r\ngroupshared uint CacheR[128];\r\ngroupshared uint CacheG[128];\r\ngroupshared uint CacheB[128];\r\n\r\nvoid Store2Pixels( uint index, float3 pixel1, float3 pixel2 )\r\n{\r\n    CacheR[index] = f32tof16(pixel1.r) | f32tof16(pixel2.r) << 16;\r\n    CacheG[index] = f32tof16(pixel1.g) | f32tof16(pixel2.g) << 16;\r\n    CacheB[index] = f32tof16(pixel1.b) | f32tof16(pixel2.b) << 16;\r\n}\r\n\r\nvoid Load2Pixels( uint index, out float3 pixel1, out float3 pixel2 )\r\n{\r\n    uint3 RGB = uint3(CacheR[index], CacheG[index], CacheB[index]);\r\n    pixel1 = f16tof32(RGB);\r\n    pixel2 = f16tof32(RGB >> 16);\r\n}\r\n\r\nvoid Store1Pixel( uint index, float3 pixel )\r\n{\r\n    CacheR[index] = asuint(pixel.r);\r\n    CacheG[index] = asuint(pixel.g);\r\n    CacheB[index] = asuint(pixel.b);\r\n}\r\n\r\nvoid Load1Pixel( uint index, out float3 pixel )\r\n{\r\n    pixel = asfloat( uint3(CacheR[index], CacheG[index], CacheB[index]) );\r\n}\r\n\r\n// Blur two pixels horizontally.  This reduces LDS reads and pixel unpacking.\r\nvoid BlurHorizontally( uint outIndex, uint leftMostIndex )\r\n{\r\n    float3 s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n    Load2Pixels( leftMostIndex + 0, s0, s1 );\r\n    Load2Pixels( leftMostIndex + 1, s2, s3 );\r\n    Load2Pixels( leftMostIndex + 2, s4, s5 );\r\n    Load2Pixels( leftMostIndex + 3, s6, s7 );\r\n    Load2Pixels( leftMostIndex + 4, s8, s9 );\r\n    \r\n    Store1Pixel(outIndex  , BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8));\r\n    Store1Pixel(outIndex+1, BlurPixels(s1, s2, s3, s4, s5, s6, s7, s8, s9));\r\n}\r\n\r\nvoid BlurVertically( uint2 pixelCoord, uint topMostIndex )\r\n{\r\n    float3 s0, s1, s2, s3, s4, s5, s6, s7, s8;\r\n    Load1Pixel( topMostIndex   , s0 );\r\n    Load1Pixel( topMostIndex+ 8, s1 );\r\n    Load1Pixel( topMostIndex+16, s2 );\r\n    Load1Pixel( topMostIndex+24, s3 );\r\n    Load1Pixel( topMostIndex+32, s4 );\r\n    Load1Pixel( topMostIndex+40, s5 );\r\n    Load1Pixel( topMostIndex+48, s6 );\r\n    Load1Pixel( topMostIndex+56, s7 );\r\n    Load1Pixel( topMostIndex+64, s8 );\r\n\r\n    Result[pixelCoord] = BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8);\r\n}\r\n\r\n[RootSignature(PostEffects_RootSig)]\r\n[numthreads( 8, 8, 1 )]\r\nvoid main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID )\r\n{\r\n    //\r\n    // Load 4 pixels per thread into LDS\r\n    //\r\n    int2 GroupUL = (Gid.xy << 3) - 4;\t\t\t\t// Upper-left pixel coordinate of group read location\r\n    int2 ThreadUL = (GTid.xy << 1) + GroupUL;\t\t// Upper-left pixel coordinate of quad that this thread will read\r\n\r\n    //\r\n    // Store 4 blended-but-unblurred pixels in LDS\r\n    //\r\n    float2 uvUL = (float2(ThreadUL) + 0.5) * g_inverseDimensions;\r\n    float2 uvLR = uvUL + g_inverseDimensions;\r\n    float2 uvUR = float2(uvLR.x, uvUL.y);\r\n    float2 uvLL = float2(uvUL.x, uvLR.y);\r\n    int destIdx = GTid.x + (GTid.y << 4);\r\n\r\n    float3 pixel1a = lerp(HigherResBuf[ThreadUL + uint2(0, 0)], LowerResBuf.SampleLevel(LinearBorder, uvUL, 0.0f), g_upsampleBlendFactor);\r\n    float3 pixel1b = lerp(HigherResBuf[ThreadUL + uint2(1, 0)], LowerResBuf.SampleLevel(LinearBorder, uvUR, 0.0f), g_upsampleBlendFactor);\r\n    Store2Pixels(destIdx+0, pixel1a, pixel1b);\r\n\r\n    float3 pixel2a = lerp(HigherResBuf[ThreadUL + uint2(0, 1)], LowerResBuf.SampleLevel(LinearBorder, uvLL, 0.0f), g_upsampleBlendFactor);\r\n    float3 pixel2b = lerp(HigherResBuf[ThreadUL + uint2(1, 1)], LowerResBuf.SampleLevel(LinearBorder, uvLR, 0.0f), g_upsampleBlendFactor);\r\n    Store2Pixels(destIdx+8, pixel2a, pixel2b);\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    //\r\n    // Horizontally blur the pixels in Cache\r\n    //\r\n    uint row = GTid.y << 4;\r\n    BlurHorizontally(row + (GTid.x << 1), row + GTid.x + (GTid.x & 4));\r\n\r\n    GroupMemoryBarrierWithGroupSync();\r\n\r\n    //\r\n    // Vertically blur the pixels and write the result to memory\r\n    //\r\n    BlurVertically(DTid.xy, (GTid.y << 3) + GTid.x);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Shaders/VarianceMapCS.hlsl",
    "content": "\r\n#include \"ShaderUtility.hlsli\"\r\n#include \"TemporalRS.hlsli\"\r\n\r\nRWTexture2D<float4> OutVariance0 : register(u0);\r\nRWTexture2D<float2> OutVariance1 : register(u1);\r\nTexture2D<float3> InColor : register(t0);\r\n\r\nSamplerState LinearSampler : register(s0);\r\nSamplerState PointSampler : register(s1);\r\n\r\ncbuffer InlineConstants : register(b0)\r\n{\r\n\tfloat2 RcpBufferDim;\t// 1 / width, 1 / height\r\n}\r\n\r\n// For each 8x8 tile being processed, we need to fetch 10x10 window with 1 pixel border on each side\r\n// in order to compute 3x3 moments of variance per pixel\r\n#define BORDER_SIZE 1\r\n#define GROUP_SIZE_X 8\r\n#define GROUP_SIZE_Y 8\r\n#define GROUP_SIZE (GROUP_SIZE_X * GROUP_SIZE_Y)\r\n#define TILE_SIZE_X (GROUP_SIZE_X + 2 * BORDER_SIZE)\r\n#define TILE_SIZE_Y (GROUP_SIZE_Y + 2 * BORDER_SIZE)\r\n#define TILE_PIXEL_COUNT (TILE_SIZE_X * TILE_SIZE_Y)\r\n\r\ngroupshared float ldsR[TILE_PIXEL_COUNT];\r\ngroupshared float ldsG[TILE_PIXEL_COUNT];\r\ngroupshared float ldsB[TILE_PIXEL_COUNT];\r\n\r\nvoid StoreRGB(uint ldsIdx, float3 RGB)\r\n{\r\n\tldsR[ldsIdx] = RGB.r;\r\n\tldsG[ldsIdx] = RGB.g;\r\n\tldsB[ldsIdx] = RGB.b;\r\n}\r\n\r\nfloat3 LoadRGB(uint ldsIdx)\r\n{\r\n\treturn float3(ldsR[ldsIdx], ldsG[ldsIdx], ldsB[ldsIdx]);\r\n}\r\n\r\n[RootSignature(Temporal_RootSig)]\r\n[numthreads(GROUP_SIZE_X, GROUP_SIZE_Y, 1)]\r\nvoid main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV_DispatchThreadID, uint GI : SV_GroupIndex)\r\n{\r\n\tconst uint ldsHalfPitch = TILE_SIZE_X / 2;\r\n\r\n\tfor (uint i = GI; i < (TILE_PIXEL_COUNT/4); i += GROUP_SIZE)\r\n\t{\r\n\t\tuint X = (i % ldsHalfPitch) * 2;\r\n\t\tuint Y = (i / ldsHalfPitch) * 2;\r\n\t\tuint TopLeftIdx = X + Y * TILE_SIZE_X;\r\n\t\tint2 TopLeftST = Gid.xy * uint2(GROUP_SIZE_X, GROUP_SIZE_Y) - 1 + uint2(X, Y);\r\n\t\tfloat2 UV = RcpBufferDim * (TopLeftST + float2(1, 1));\r\n\r\n\t\tfloat4 R4 = InColor.GatherRed(LinearSampler, UV);\r\n\t\tfloat4 G4 = InColor.GatherGreen(LinearSampler, UV);\r\n\t\tfloat4 B4 = InColor.GatherBlue(LinearSampler, UV);\r\n\t\tStoreRGB(TopLeftIdx, float3(R4.w, G4.w, B4.w));\r\n\t\tStoreRGB(TopLeftIdx + 1, float3(R4.z, G4.z, B4.z));\r\n\t\tStoreRGB(TopLeftIdx + TILE_SIZE_X, float3(R4.x, G4.x, B4.x));\r\n\t\tStoreRGB(TopLeftIdx + 1 + TILE_SIZE_X, float3(R4.y, G4.y, B4.y));\r\n\t}\r\n\r\n\tGroupMemoryBarrierWithGroupSync();\r\n\tuint Idx = GTid.x + GTid.y * TILE_SIZE_X + (TILE_SIZE_X + 1);\r\n\tuint2 ST = DTid.xy;\r\n\r\n\tfloat3 m1, m2, temp;\r\n\tfloat n = 9.f;\r\n\tm1 = m2 = temp = float3(0, 0, 0);\r\n\r\n\tfor (int k = -1; k <= 1; k++) {\r\n\t\tfor (int j = -1; j <= 1; j++) {\r\n\t\t\ttemp = LoadRGB(Idx + k + j*TILE_SIZE_X);\r\n\t\t\ttemp = ColorToLum(temp);\r\n\t\t\tm1 += temp;\r\n\t\t\tm2 += temp*temp;\r\n\t\t}\r\n\t}\r\n\tm1 /= n;\r\n\tm2 /= n;\r\n\r\n\tOutVariance0[ST] = float4(m1, m2.x);\r\n\tOutVariance1[ST] = m2.yz;\r\n\r\n}"
  },
  {
    "path": "MiniEngine/Core/ShadowBuffer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"ShadowBuffer.h\"\r\n#include \"EsramAllocator.h\"\r\n#include \"CommandContext.h\"\r\n\r\nvoid ShadowBuffer::Create( const std::wstring& Name, uint32_t Width, uint32_t Height, D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr )\r\n{\r\n    DepthBuffer::Create( Name, Width, Height, DXGI_FORMAT_D16_UNORM, VidMemPtr );\r\n\r\n    m_Viewport.TopLeftX = 0.0f;\r\n    m_Viewport.TopLeftY = 0.0f;\r\n    m_Viewport.Width = (float)Width;\r\n    m_Viewport.Height = (float)Height;\r\n    m_Viewport.MinDepth = 0.0f;\r\n    m_Viewport.MaxDepth = 1.0f;\r\n\r\n    // Prevent drawing to the boundary pixels so that we don't have to worry about shadows stretching\r\n    m_Scissor.left = 1;\r\n    m_Scissor.top = 1;\r\n    m_Scissor.right = (LONG)Width - 2;\r\n    m_Scissor.bottom = (LONG)Height - 2;\r\n}\r\n\r\nvoid ShadowBuffer::Create( const std::wstring& Name, uint32_t Width, uint32_t Height, EsramAllocator& Allocator )\r\n{\r\n    DepthBuffer::Create( Name, Width, Height, DXGI_FORMAT_D16_UNORM, Allocator );\r\n\r\n    m_Viewport.TopLeftX = 0.0f;\r\n    m_Viewport.TopLeftY = 0.0f;\r\n    m_Viewport.Width = (float)Width;\r\n    m_Viewport.Height = (float)Height;\r\n    m_Viewport.MinDepth = 0.0f;\r\n    m_Viewport.MaxDepth = 1.0f;\r\n\r\n    // Prevent drawing to the boundary pixels so that we don't have to worry about shadows stretching\r\n    m_Scissor.left = 1;\r\n    m_Scissor.top = 1;\r\n    m_Scissor.right = (LONG)Width - 2;\r\n    m_Scissor.bottom = (LONG)Height - 2;\r\n}\r\n\r\nvoid ShadowBuffer::BeginRendering( GraphicsContext& Context )\r\n{\r\n    Context.TransitionResource(*this, D3D12_RESOURCE_STATE_DEPTH_WRITE, true);\r\n    Context.ClearDepth(*this);\r\n    Context.SetDepthStencilTarget(GetDSV());\r\n    Context.SetViewportAndScissor(m_Viewport, m_Scissor);\r\n}\r\n\r\nvoid ShadowBuffer::EndRendering( GraphicsContext& Context )\r\n{\r\n    Context.TransitionResource(*this, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ShadowBuffer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"DepthBuffer.h\"\r\n\r\nclass EsramAllocator;\r\n\r\nclass GraphicsContext;\r\n\r\nclass ShadowBuffer : public DepthBuffer\r\n{\r\npublic:\r\n    ShadowBuffer() {}\r\n        \r\n    void Create( const std::wstring& Name, uint32_t Width, uint32_t Height,\r\n        D3D12_GPU_VIRTUAL_ADDRESS VidMemPtr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN );\r\n    void Create( const std::wstring& Name, uint32_t Width, uint32_t Height, EsramAllocator& Allocator );\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE GetSRV() const { return GetDepthSRV(); }\r\n\r\n    void BeginRendering( GraphicsContext& context );\r\n    void EndRendering( GraphicsContext& context );\r\n\r\nprivate:\r\n    D3D12_VIEWPORT m_Viewport;\r\n    D3D12_RECT m_Scissor;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/ShadowCamera.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"ShadowCamera.h\"\r\n\r\nusing namespace Math;\r\n\r\nvoid GameCore::ShadowCamera::UpdateMatrix(\r\n    Vector3 LightDirection, Vector3 ShadowCenter, Vector3 ShadowBounds,\r\n    uint32_t BufferWidth, uint32_t BufferHeight, uint32_t BufferPrecision )\r\n{\r\n    SetLookDirection( LightDirection, Vector3(kZUnitVector) );\r\n\r\n    // Converts world units to texel units so we can quantize the camera position to whole texel units\r\n    Vector3 RcpDimensions = Recip(ShadowBounds);\r\n    Vector3 QuantizeScale = Vector3((float)BufferWidth, (float)BufferHeight, (float)((1 << BufferPrecision) - 1)) * RcpDimensions;\r\n\r\n    //\r\n    // Recenter the camera at the quantized position\r\n    //\r\n\r\n    // Transform to view space\r\n    ShadowCenter = ~GetRotation() * ShadowCenter;\r\n    // Scale to texel units, truncate fractional part, and scale back to world units\r\n    ShadowCenter = Floor( ShadowCenter * QuantizeScale ) / QuantizeScale;\r\n    // Transform back into world space\r\n    ShadowCenter = GetRotation() * ShadowCenter;\r\n\r\n    SetPosition( ShadowCenter );\r\n\r\n    SetProjMatrix( Matrix4::MakeScale(Vector3(2.0f, 2.0f, 1.0f) * RcpDimensions) );\r\n\r\n    Update();\r\n\r\n    // Transform from clip space to texture space\r\n    m_ShadowMatrix =  Matrix4( AffineTransform( Matrix3::MakeScale( 0.5f, -0.5f, 1.0f ), Vector3(0.5f, 0.5f, 0.0f) ) ) * m_ViewProjMatrix;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/ShadowCamera.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Camera.h\"\r\n\r\nnamespace GameCore\r\n{\r\n    using namespace Math;\r\n\r\n    class ShadowCamera : public BaseCamera\r\n    {\r\n    public:\r\n\r\n        ShadowCamera() {}\r\n\r\n        void UpdateMatrix( \r\n            Vector3 LightDirection,\t\t// Direction parallel to light, in direction of travel\r\n            Vector3 ShadowCenter,\t\t// Center location on far bounding plane of shadowed region\r\n            Vector3 ShadowBounds,\t\t// Width, height, and depth in world space represented by the shadow buffer\r\n            uint32_t BufferWidth,\t\t// Shadow buffer width\r\n            uint32_t BufferHeight,\t\t// Shadow buffer height--usually same as width\r\n            uint32_t BufferPrecision\t// Bit depth of shadow buffer--usually 16 or 24\r\n            );\r\n\r\n        // Used to transform world space to texture space for shadow sampling\r\n        const Matrix4& GetShadowMatrix() const { return m_ShadowMatrix; }\r\n\r\n    private:\r\n\r\n        Matrix4 m_ShadowMatrix;\r\n    };\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/SystemTime.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"SystemTime.h\"\r\n\r\ndouble SystemTime::sm_CpuTickDelta = 0.0;\r\n\r\n// Query the performance counter frequency\r\nvoid SystemTime::Initialize( void )\r\n{\r\n    LARGE_INTEGER frequency;\r\n    ASSERT(TRUE == QueryPerformanceFrequency(&frequency), \"Unable to query performance counter frequency\");\r\n    sm_CpuTickDelta = 1.0 / static_cast<double>(frequency.QuadPart);\r\n}\r\n\r\n// Query the current value of the performance counter\r\nint64_t SystemTime::GetCurrentTick( void )\r\n{\r\n    LARGE_INTEGER currentTick;\r\n    ASSERT(TRUE == QueryPerformanceCounter(&currentTick), \"Unable to query performance counter value\");\r\n    return static_cast<int64_t>(currentTick.QuadPart);\r\n}\r\n\r\nvoid SystemTime::BusyLoopSleep( float SleepTime )\r\n{\r\n    int64_t finalTick = (int64_t)((double)SleepTime / sm_CpuTickDelta) + GetCurrentTick();\r\n    while (GetCurrentTick() < finalTick);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/SystemTime.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// Contains classes needed to time executing code.\r\n//\r\n\r\n#pragma once\r\n\r\nclass SystemTime\r\n{\r\npublic:\r\n\r\n    // Query the performance counter frequency\r\n    static void Initialize( void );\r\n\r\n    // Query the current value of the performance counter\r\n    static int64_t GetCurrentTick( void );\r\n\r\n    static void BusyLoopSleep( float SleepTime );\r\n\r\n    static inline double TicksToSeconds( int64_t TickCount )\r\n    {\r\n        return TickCount * sm_CpuTickDelta;\r\n    }\r\n\r\n    static inline double TicksToMillisecs( int64_t TickCount )\r\n    {\r\n        return TickCount * sm_CpuTickDelta * 1000.0;\r\n    }\r\n\r\n    static inline double TimeBetweenTicks( int64_t tick1, int64_t tick2 )\r\n    {\r\n        return TicksToSeconds(tick2 - tick1);\r\n    }\r\n\r\nprivate:\r\n\r\n    // The amount of time that elapses between ticks of the performance counter\r\n    static double sm_CpuTickDelta;\r\n};\r\n\r\n\r\nclass CpuTimer\r\n{\r\npublic:\r\n\r\n    CpuTimer()\r\n    {\r\n        m_StartTick = 0ll;\r\n        m_ElapsedTicks = 0ll;\r\n    }\r\n\r\n    void Start()\r\n    {\r\n        if (m_StartTick == 0ll)\r\n            m_StartTick = SystemTime::GetCurrentTick();\r\n    }\r\n\r\n    void Stop()\r\n    {\r\n        if (m_StartTick != 0ll)\r\n        {\r\n            m_ElapsedTicks += SystemTime::GetCurrentTick() - m_StartTick;\r\n            m_StartTick = 0ll;\r\n        }\r\n    }\r\n\r\n    void Reset()\r\n    {\r\n        m_ElapsedTicks = 0ll;\r\n        m_StartTick = 0ll;\r\n    }\r\n\r\n    double GetTime() const\r\n    {\r\n        return SystemTime::TicksToSeconds(m_ElapsedTicks);\r\n    }\r\n\r\nprivate:\r\n\r\n    int64_t m_StartTick;\r\n    int64_t m_ElapsedTicks;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/TemporalEffects.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"TemporalEffects.h\"\r\n#include \"BufferManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"SystemTime.h\"\r\n#include \"PostEffects.h\"\r\n\r\n#include \"CompiledShaders/TemporalBlendCS.h\"\r\n#include \"CompiledShaders/BoundNeighborhoodCS.h\"\r\n#include \"CompiledShaders/ResolveTAACS.h\"\r\n#include \"CompiledShaders/SharpenTAACS.h\"\r\n#include \"CompiledShaders/VarianceMapCS.h\"\r\n\r\nusing namespace Graphics;\r\nusing namespace Math;\r\nusing namespace TemporalEffects;\r\n\r\nnamespace TemporalEffects\r\n{\r\n    BoolVar SilhouetteVis(\"Graphics/AA/TAA/Silhouette Visual in Motion\", false);\r\n    BoolVar VelocityVis(\"Graphics/AA/TAA/Disocclusion Visual\", false);\r\n    BoolVar EnableTAA(\"Graphics/AA/TAA/Enable\", false);\r\n    ExpVar NumSamples(\"Graphics/AA/TAA/NumSamples\", 3.f, 3.f, 4.f, 1.f);\r\n    NumVar Sharpness(\"Graphics/AA/TAA/Sharpness\", 0.0f, 0.0f, 1.0f, 0.25f);\r\n    NumVar SilhouetteThreshold(\"Graphics/AA/TAA/Silhouette Threshold Factor\", 1.0f, 0.0f, 3.0f, 0.1f);\r\n    NumVar VarianceExtension(\"Graphics/AA/TAA/Variance Extension\", 3.0f, 1.0f, 40.0f, 0.5f);\r\n    ExpVar TemporalSpeedLimit(\"Graphics/AA/TAA/Speed Limit\", 32.0f, 1.0f, 1024.0f, 1.0f);\r\n    BoolVar TriggerReset(\"Graphics/AA/TAA/Reset\", false);\r\n    BoolVar TriggerBicubicFiltering(\"Graphics/AA/TAA/Bicubic Filtering\", true);\r\n    BoolVar TriggerBlurNoise(\"Graphics/AA/TAA/Blue Noise\", false);\r\n    NumVar TemporalAccModifier(\"Graphics/AA/TAA/Temporal Acc Modifier\", 0.0f, 0.0f, 1.0f, 0.05f);\r\n\r\n    RootSignature s_RootSignature;\r\n\r\n    ComputePSO s_TemporalBlendCS;\r\n    ComputePSO s_BoundNeighborhoodCS;\r\n    ComputePSO s_SharpenTAACS;\r\n    ComputePSO s_ResolveTAACS;\r\n    ComputePSO s_VarianceMapCS;\r\n\r\n    uint32_t s_FrameIndex = 0;\r\n    uint32_t s_FrameIndexMod2 = 0;\r\n    float s_JitterX = 0.5f;\r\n    float s_JitterY = 0.5f;\r\n    float s_JitterDeltaX = 0.0f;\r\n    float s_JitterDeltaY = 0.0f;\r\n\r\n    void ComputeVarianceMap(CommandContext& BaseContext);\r\n    void ApplyTemporalAA(ComputeContext& Context);\r\n    void SharpenImage(ComputeContext& Context, ColorBuffer& TemporalColor);\r\n}\r\n\r\nvoid TemporalEffects::Initialize(void)\r\n{\r\n    s_RootSignature.Reset(4, 2);\r\n    s_RootSignature[0].InitAsConstants(0, 4);\r\n    s_RootSignature[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 10);\r\n    s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 10);\r\n    s_RootSignature[3].InitAsConstantBuffer(1);\r\n    s_RootSignature.InitStaticSampler(0, SamplerLinearBorderDesc);\r\n    s_RootSignature.InitStaticSampler(1, SamplerPointBorderDesc);\r\n    s_RootSignature.Finalize(L\"Temporal RS\");\r\n\r\n#define CreatePSO( ObjName, ShaderByteCode ) \\\r\n    ObjName.SetRootSignature(s_RootSignature); \\\r\n    ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \\\r\n    ObjName.Finalize();\r\n\r\n    CreatePSO(s_TemporalBlendCS, g_pTemporalBlendCS);\r\n    CreatePSO(s_BoundNeighborhoodCS, g_pBoundNeighborhoodCS);\r\n    CreatePSO(s_SharpenTAACS, g_pSharpenTAACS);\r\n    CreatePSO(s_ResolveTAACS, g_pResolveTAACS);\r\n    CreatePSO(s_VarianceMapCS, g_pVarianceMapCS);\r\n\r\n#undef CreatePSO\r\n}\r\n\r\nvoid TemporalEffects::Shutdown(void)\r\n{\r\n}\r\n\r\nvoid TemporalEffects::Update(uint64_t FrameIndex)\r\n{\r\n    s_FrameIndex = (uint32_t) FrameIndex;\r\n    s_FrameIndexMod2 = s_FrameIndex % 2;\r\n\r\n    if (EnableTAA)\r\n    {\r\n        const float* OffsetHalton;\r\n        const float* OffsetBlueNoise;\r\n\r\n        //const float* OffsetHalton = Halton23_64[s_FrameIndex % 64];\r\n        //const float* OffsetBlueNoise = BlueNoise_64[s_FrameIndex % 64];\r\n\r\n\r\n        if (NumSamples == 64) {\r\n            static const float BlueNoise_64[64][2] = {\r\n                { 0.593750, 0.718750 },\r\n            { 0.000000,1.343750 },\r\n            { 1.281250,0.968750 },\r\n            { 1.281250,1.500000 },\r\n            { 0.531250,1.968750 },\r\n            { 0.812500,1.468750 },\r\n            { 1.062500,0.562500 },\r\n            { 0.937500,1.875000 },\r\n            { 1.593750,1.281250 },\r\n            { 0.906250,1.093750 },\r\n            { 1.781250,1.656250 },\r\n            { 0.218750,1.812500 },\r\n            { 1.093750,0.156250 },\r\n            { 1.406250,0.406250 },\r\n            { 1.562500,0.125000 },\r\n            { 0.312500,0.656250 },\r\n            { 1.750000,1.062500 },\r\n            { 1.656250,0.593750 },\r\n            { 0.250000,0.093750 },\r\n            { 1.812500,0.343750 },\r\n            { 1.843750,1.968750 },\r\n            { 0.406250,1.000000 },\r\n            { 0.843750,0.781250 },\r\n            { 1.343750,1.250000 },\r\n            { 1.531250,1.593750 },\r\n            { 0.218750,1.218750 },\r\n            { 0.656250,0.968750 },\r\n            { 0.718750,1.250000 },\r\n            { 0.500000,0.468750 },\r\n            { 0.187500,1.562500 },\r\n            { 0.718750,1.750000 },\r\n            { 1.968750,1.000000 },\r\n            { 1.593750,1.875000 },\r\n            { 1.125000,1.281250 },\r\n            { 1.875000,0.593750 },\r\n            { 1.468750,0.875000 },\r\n            { 0.906250,0.406250 },\r\n            { 0.000000,1.656250 },\r\n            { 1.156250,1.968750 },\r\n            { 0.593750,1.406250 },\r\n            { 0.125000,0.843750 },\r\n            { 0.656250,0.156250 },\r\n            { 1.343750,0.125000 },\r\n            { 0.250000,0.312500 },\r\n            { 1.437500,0.625000 },\r\n            { 0.500000,1.750000 },\r\n            { 0.875000,0.187500 },\r\n            { 1.156250,1.656250 },\r\n            { 0.031250,0.468750 },\r\n            { 1.718750,1.437500 },\r\n            { 0.468750,0.281250 },\r\n            { 1.781250,0.875000 },\r\n            { 1.468750,1.093750 },\r\n            { 0.031250,0.250000 },\r\n            { 0.750000,0.562500 },\r\n            { 1.375000,1.906250 },\r\n            { 1.031250,0.781250 },\r\n            { 0.031250,1.906250 },\r\n            { 1.125000,0.375000 },\r\n            { 0.437500,1.187500 },\r\n            { 0.687500,0.343750 },\r\n            { 0.312500,1.406250 },\r\n            { 1.093750,1.062500 },\r\n            { 1.781250,0.156250 }\r\n            };\r\n\r\n            OffsetHalton = BlueNoise_64[s_FrameIndex % 64];\r\n            OffsetBlueNoise = BlueNoise_64[s_FrameIndex % 64];\r\n        }\r\n        else if (NumSamples == 16) {\r\n            static const float Halton23_16[16][2] = {\r\n                { 0.000000, 0.000000 },\r\n            { 0.500000,0.333333 },\r\n            { 0.250000,0.666667 },\r\n            { 0.750000,0.111111 },\r\n            { 0.125000,0.444444 },\r\n            { 0.625000,0.777778 },\r\n            { 0.375000,0.222222 },\r\n            { 0.875000,0.555556 },\r\n            { 0.062500,0.888889 },\r\n            { 0.562500,0.037037 },\r\n            { 0.312500,0.370370 },\r\n            { 0.812500,0.703704 },\r\n            { 0.187500,0.148148 },\r\n            { 0.687500,0.481481 },\r\n            { 0.437500,0.814815 },\r\n            { 0.937500,0.259259 },\r\n            };\r\n\r\n            static const float BlueNoise_16[16][2] = {\r\n            { 1.500000,0.593750 },\r\n            { 1.218750,1.375000 },\r\n            { 1.687500,1.906250 },\r\n            { 0.375000,0.843750 },\r\n            { 1.125000,1.875000 },\r\n            { 0.718750,1.656250 },\r\n            { 1.937500,0.718750 },\r\n            { 0.656250,0.125000 },\r\n            { 0.906250,0.937500 },\r\n            { 1.656250,1.437500 },\r\n            { 0.500000,1.281250 },\r\n            { 0.218750,0.062500 },\r\n            { 1.843750,0.312500 },\r\n            { 1.093750,0.562500 },\r\n            { 0.062500,1.218750 },\r\n            { 0.281250,1.656250 },\r\n            };\r\n\r\n            //static const float BlueNoise_16[16][2] = {\r\n            //{ 1.718750,1.031250 },\r\n            //{ 0.531250,0.187500 },\r\n            //{ 0.750000,1.281250 },\r\n            //{ 1.468750,1.968750 },\r\n            //{ 1.593750,0.406250 },\r\n            //{ 0.625000,0.718750 },\r\n            //{ 1.812500,1.531250 },\r\n            //{ 0.437500,1.531250 },\r\n            //{ 1.375000,0.750000 },\r\n            //{ 0.937500,1.687500 },\r\n            //{ 0.218750,0.500000 },\r\n            //{ 1.312500,1.281250 },\r\n            //{ 0.156250,1.843750 },\r\n            //{ 0.968750,0.406250 },\r\n            //{ 0.187500,1.062500 },\r\n            //{ 0.968750,0.968750 }\r\n            //};\r\n\r\n\r\n            OffsetHalton = Halton23_16[s_FrameIndex % 16];\r\n            OffsetBlueNoise = BlueNoise_16[s_FrameIndex % 16];\r\n        }\r\n        else {\r\n            static const float Halton23_8[8][2] = {\r\n            { 0.0f / 8.0f, 0.0f / 9.0f },{ 4.0f / 8.0f, 3.0f / 9.0f },\r\n            { 2.0f / 8.0f, 6.0f / 9.0f },{ 6.0f / 8.0f, 1.0f / 9.0f },\r\n            { 1.0f / 8.0f, 4.0f / 9.0f },{ 5.0f / 8.0f, 7.0f / 9.0f },\r\n            { 3.0f / 8.0f, 2.0f / 9.0f },{ 7.0f / 8.0f, 5.0f / 9.0f }\r\n            };\r\n\r\n            static const float BlueNoise_8[8][2] = {\r\n            { 1.906250,1.062500 },\r\n            { 0.968750,1.656250 },\r\n            { 1.218750,0.906250 },\r\n            { 1.437500,0.281250 },\r\n            { 0.562500,0.968750 },\r\n            { 0.343750,1.593750 },\r\n            { 0.093750,0.343750 },\r\n            { 1.656250,1.656250 }\r\n            };\r\n\r\n            //static const float BlueNoise_8[8][2] = {\r\n            //{ 1.031250,1.625000 },\r\n            //{ 1.687500,0.625000 },\r\n            //{ 0.375000,0.500000 },\r\n            //{ 0.281250,1.843750 },\r\n            //{ 1.656250,1.281250 },\r\n            //{ 1.031250,0.281250 },\r\n            //{ 0.343750,1.156250 },\r\n            //{ 0.968750,0.968750 }\r\n            //};\r\n\r\n            OffsetHalton = Halton23_8[s_FrameIndex % 8];\r\n            OffsetBlueNoise = BlueNoise_8[s_FrameIndex % 8];\r\n        }\r\n\r\n\r\n        if (TriggerBlurNoise) {\r\n            s_JitterDeltaX = s_JitterX - OffsetBlueNoise[0] * 0.5f;\r\n            s_JitterDeltaY = s_JitterY - OffsetBlueNoise[1] * 0.5f;\r\n            s_JitterX = OffsetBlueNoise[0] * 0.5f;\r\n            s_JitterY = OffsetBlueNoise[1] * 0.5f;\r\n        }\r\n        else {\r\n            s_JitterDeltaX = s_JitterX - OffsetHalton[0];\r\n            s_JitterDeltaY = s_JitterY - OffsetHalton[1];\r\n            s_JitterX = OffsetHalton[0];\r\n            s_JitterY = OffsetHalton[1];\r\n        }\r\n    }\r\n    else\r\n    {\r\n        s_JitterDeltaX = s_JitterX - 0.5f;\r\n        s_JitterDeltaY = s_JitterY - 0.5f;\r\n        s_JitterX = 0.5f;\r\n        s_JitterY = 0.5f;\r\n    }\r\n}\r\n\r\nuint32_t TemporalEffects::GetFrameIndexMod2(void)\r\n{\r\n    return s_FrameIndexMod2;\r\n}\r\n\r\nvoid TemporalEffects::GetJitterOffset(float& JitterX, float& JitterY)\r\n{\r\n    JitterX = s_JitterX;\r\n    JitterY = s_JitterY;\r\n}\r\n\r\nvoid TemporalEffects::ClearHistory(CommandContext& Context)\r\n{\r\n    GraphicsContext& gfxContext = Context.GetGraphicsContext();\r\n\r\n    if (EnableTAA)\r\n    {\r\n        gfxContext.TransitionResource(g_TemporalColor[0], D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n        gfxContext.TransitionResource(g_TemporalColor[1], D3D12_RESOURCE_STATE_RENDER_TARGET, true);\r\n        gfxContext.ClearColor(g_TemporalColor[0]);\r\n        gfxContext.ClearColor(g_TemporalColor[1]);\r\n    }\r\n}\r\n\r\nvoid TemporalEffects::ResolveImage(CommandContext& BaseContext)\r\n{\r\n    ScopedTimer _prof(L\"Temporal Resolve\", BaseContext);\r\n\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n\r\n    static bool s_EnableTAA = false;\r\n\r\n    if (EnableTAA != s_EnableTAA || TriggerReset)\r\n    {\r\n        ClearHistory(Context);\r\n        s_EnableTAA = EnableTAA;\r\n        TriggerReset = false;\r\n    }\r\n\r\n    uint32_t Src = s_FrameIndexMod2;\r\n    uint32_t Dst = Src ^ 1;\r\n\r\n    if (EnableTAA)\r\n    {\r\n        ComputeVarianceMap(BaseContext);\r\n        ApplyTemporalAA(Context);\r\n        SharpenImage(Context, g_TemporalColor[Dst]);\r\n    }\r\n}\r\n\r\nvoid TemporalEffects::ComputeVarianceMap(CommandContext& BaseContext)\r\n{\r\n    ComputeContext& Context = BaseContext.GetComputeContext();\r\n    Context.SetRootSignature(s_RootSignature);\r\n    Context.SetPipelineState(s_VarianceMapCS);\r\n\r\n    Context.SetConstants(0, 1.0f / g_pSceneColorBuffer->GetWidth(), 1.0f / g_pSceneColorBuffer->GetHeight());\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_VarianceMap[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_VarianceMap[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.SetDynamicDescriptor(1, 0, g_pSceneColorBuffer->GetSRV());\r\n    Context.SetDynamicDescriptor(2, 0, g_VarianceMap[0].GetUAV());\r\n    Context.SetDynamicDescriptor(2, 1, g_VarianceMap[1].GetUAV());\r\n\r\n    // generate variance map of 3x3 window\r\n    Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n\r\n    // generate mipmap for the variance maps\r\n    g_VarianceMap[0].GenerateMipMaps(BaseContext);\r\n    g_VarianceMap[1].GenerateMipMaps(BaseContext);\r\n\r\n}\r\n\r\nvoid TemporalEffects::ApplyTemporalAA(ComputeContext& Context)\r\n{\r\n    ScopedTimer _prof(L\"Resolve Image\", Context);\r\n\r\n    uint32_t Src = s_FrameIndexMod2;\r\n    uint32_t Dst = Src ^ 1;\r\n\r\n    Context.SetRootSignature(s_RootSignature);\r\n    Context.SetPipelineState(s_TemporalBlendCS);\r\n\r\n    __declspec(align(16)) struct ConstantBuffer\r\n    {\r\n        float RcpBufferDim[2];\r\n        float RcpInColorBufferDim[2];\r\n        float _Pad[2];\r\n        float SilhouetteThresholdFactor;\r\n        float RcpSeedLimiter;\r\n        float CombinedJitterDelta[2];\r\n        float CombinedJitterVector[2];\r\n        uint32_t  BicubicFiltering;\r\n        uint32_t  VisualSilhouette;\r\n        uint32_t  FrameOffset;\r\n        uint32_t  VisualDisocclusion;\r\n        float VarianceExtensionFactor;\r\n        float AccModifierFactor;\r\n    };\r\n\r\n    ConstantBuffer cbv = {\r\n       1.0f / g_VelocityBuffer.GetWidth(), 1.0f / g_VelocityBuffer.GetHeight(),\r\n       1.0f / g_pSceneColorBuffer->GetWidth(), 1.0f / g_pSceneColorBuffer->GetHeight(),\r\n       0.0f, 0.0f, //pad\r\n       (float) SilhouetteThreshold, 1.0f / TemporalSpeedLimit,\r\n       s_JitterDeltaX, s_JitterDeltaY,\r\n       s_JitterX, s_JitterY,\r\n       (uint32_t) (TriggerBicubicFiltering ? 1 : 0),\r\n       (uint32_t) (SilhouetteVis ? 1 : 0),\r\n       (uint32_t) s_FrameIndexMod2,\r\n       (uint32_t) (VelocityVis ? 1 : 0),\r\n       (float) VarianceExtension,\r\n       (float) TemporalAccModifier,\r\n    };\r\n\r\n    Context.SetDynamicConstantBufferView(3, sizeof(cbv), &cbv);\r\n\r\n    Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_TemporalColor[Src], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_TemporalColor[Dst], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(g_LinearDepth[Src], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_LinearDepth[Dst], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_VarianceMap[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(g_VarianceMap[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.SetDynamicDescriptor(1, 0, g_VelocityBuffer.GetSRV());\r\n    Context.SetDynamicDescriptor(1, 1, g_pSceneColorBuffer->GetSRV());\r\n    Context.SetDynamicDescriptor(1, 2, g_TemporalColor[Src].GetSRV());\r\n    Context.SetDynamicDescriptor(1, 3, g_LinearDepth[Src].GetSRV());\r\n    Context.SetDynamicDescriptor(1, 4, g_LinearDepth[Dst].GetSRV());\r\n    Context.SetDynamicDescriptor(1, 5, g_VarianceMap[0].GetSRV());\r\n    Context.SetDynamicDescriptor(1, 6, g_VarianceMap[1].GetSRV());\r\n    Context.SetDynamicDescriptor(2, 0, g_TemporalColor[Dst].GetUAV());\r\n\r\n    Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight(), 8, 8);\r\n}\r\n\r\nvoid TemporalEffects::SharpenImage(ComputeContext& Context, ColorBuffer& TemporalColor)\r\n{\r\n    ScopedTimer _prof(L\"Sharpen or Copy Image\", Context);\r\n\r\n    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(TemporalColor, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n    Context.SetPipelineState(Sharpness >= 0.001f ? s_SharpenTAACS : s_ResolveTAACS);\r\n    Context.SetConstants(0, 1.0f + Sharpness, 0.25f * Sharpness);\r\n    Context.SetDynamicDescriptor(1, 0, TemporalColor.GetSRV());\r\n    Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n    Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/TemporalEffects.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"EngineTuning.h\"\r\n\r\nclass CommandContext;\r\nclass DepthBuffer;\r\n\r\nnamespace TemporalEffects\r\n{\r\n    // Temporal antialiasing involves jittering sample positions and accumulating color over time to \r\n    // effectively supersample the image.\r\n    extern BoolVar EnableTAA;\r\n    extern BoolVar TriggerReset;\r\n\r\n    void Initialize( void );\r\n\r\n    void Shutdown( void );\r\n\r\n    // Call once per frame to increment the internal frame counter and, in the case of TAA, choosing the next\r\n    // jittered sample position.\r\n    void Update( uint64_t FrameIndex );\r\n\r\n    // Returns whether the frame is odd or even\r\n    uint32_t GetFrameIndexMod2( void );\r\n\r\n    // Jitter values are neutral at 0.5 and vary from [0, 1).  Jittering only occurs when temporal antialiasing\r\n    // is enabled.  You can use these values to jitter your viewport or projection matrix.\r\n    void GetJitterOffset( float& JitterX, float& JitterY );\r\n\r\n\t// Compute 1st and 2nd moments of variance with 3x3 window per pixel\r\n\tvoid ComputeVarianceMap(CommandContext& BaseContext);\r\n\r\n    void ClearHistory(CommandContext& Context);\r\n\r\n    void ResolveImage(CommandContext& Context);\r\n\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/TextRenderer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"TextRenderer.h\"\r\n#include \"FileUtility.h\"\r\n#include \"TextureManager.h\"\r\n#include \"SystemTime.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include \"PipelineState.h\"\r\n#include \"RootSignature.h\"\r\n#include \"BufferManager.h\"\r\n#include \"CompiledShaders/TextVS.h\"\r\n#include \"CompiledShaders/TextAntialiasPS.h\"\r\n#include \"CompiledShaders/TextShadowPS.h\"\r\n#include \"Fonts/consola24.h\"\r\n#include <map>\r\n#include <string>\r\n#include <cstdio>\r\n#include <memory>\r\n#include <malloc.h>\r\n\r\nusing namespace Graphics;\r\nusing namespace Math;\r\nusing namespace std;\r\n\r\nnamespace TextRenderer\r\n{\r\n    class Font\r\n    {\r\n    public:\r\n        Font()\r\n        {\r\n            m_NormalizeXCoord = 0.0f;\r\n            m_NormalizeYCoord = 0.0f;\r\n            m_FontLineSpacing = 0.0f;\r\n            m_AntialiasRange = 0.0f;\r\n            m_FontHeight = 0;\r\n            m_BorderSize = 0;\r\n            m_TextureWidth = 0;\r\n            m_TextureHeight = 0;\r\n        }\r\n\r\n        ~Font()\r\n        {\r\n            m_Dictionary.clear();\r\n        }\r\n\r\n        void LoadFromBinary( const wchar_t* fontName, const uint8_t* pBinary, const size_t binarySize )\r\n        {\r\n            (fontName);\r\n\r\n            // We should at least use this to assert that we have a complete file\r\n            (binarySize);\r\n\r\n            struct FontHeader\r\n            {\r\n                char FileDescriptor[8];\t\t// \"SDFFONT\\0\"\r\n                uint8_t  majorVersion;\t\t// '1'\r\n                uint8_t  minorVersion;\t\t// '0'\r\n                uint16_t borderSize;\t\t// Pixel empty space border width\r\n                uint16_t textureWidth;\t\t// Width of texture buffer\r\n                uint16_t textureHeight;\t\t// Height of texture buffer\r\n                uint16_t fontHeight;\t\t// Font height in 12.4\r\n                uint16_t advanceY;\t\t\t// Line height in 12.4\r\n                uint16_t numGlyphs;\t\t\t// Glyph count in texture\r\n                uint16_t searchDist;\t\t// Range of search space 12.4\r\n            };\r\n\r\n            FontHeader* header = (FontHeader*)pBinary;\r\n            m_NormalizeXCoord = 1.0f / (header->textureWidth * 16);\r\n            m_NormalizeYCoord = 1.0f / (header->textureHeight * 16);\r\n            m_FontHeight = header->fontHeight;\r\n            m_FontLineSpacing = (float)header->advanceY / (float)header->fontHeight;\r\n            m_BorderSize = header->borderSize * 16;\r\n            m_AntialiasRange = (float)header->searchDist / header->fontHeight;\r\n            uint16_t textureWidth = header->textureWidth;\r\n            uint16_t textureHeight = header->textureHeight;\r\n            uint16_t NumGlyphs = header->numGlyphs;\r\n\r\n            const wchar_t* wcharList = (wchar_t*)(pBinary + sizeof(FontHeader));\r\n            const Glyph* glyphData = (Glyph*)(wcharList + NumGlyphs);\r\n            const void* texelData = glyphData + NumGlyphs;\r\n\r\n            for (uint16_t i = 0; i < NumGlyphs; ++i)\r\n                m_Dictionary[wcharList[i]] = glyphData[i];\r\n\r\n            m_Texture.Create( textureWidth, textureHeight, DXGI_FORMAT_R8_SNORM, texelData );\r\n\r\n            DEBUGPRINT( \"Loaded SDF font:  %ls (ver. %d.%d)\", fontName, header->majorVersion, header->minorVersion);\r\n        }\r\n\r\n        bool Load( const wstring& fileName )\r\n        {\r\n            Utility::ByteArray ba = Utility::ReadFileSync( fileName );\r\n\r\n            if (ba->size() == 0)\r\n            {\r\n                ERROR( \"Cannot open file %ls\", fileName.c_str() );\r\n                return false;\r\n            }\r\n\r\n            LoadFromBinary( fileName.c_str(), ba->data(), ba->size() );\r\n\r\n            return true;\r\n        }\r\n\r\n        // Each character has an XY start offset, a width, and they all share the same height\r\n        struct Glyph\r\n        {\r\n            uint16_t x, y, w;\r\n            int16_t bearing;\r\n            uint16_t advance;\r\n        };\r\n\r\n        const Glyph* GetGlyph( wchar_t ch ) const\r\n        {\r\n            auto it = m_Dictionary.find( ch );\r\n            return it == m_Dictionary.end() ? nullptr : &it->second;\r\n        }\r\n\r\n        // Get the texel height of the font in 12.4 fixed point\r\n        uint16_t GetHeight( void ) const { return m_FontHeight; }\r\n\r\n        // Get the size of the border in 12.4 fixed point\r\n        uint16_t GetBorderSize( void ) const { return m_BorderSize; }\r\n\r\n        // Get the line advance height given a certain font size\r\n        float GetVerticalSpacing( float size ) const { return size * m_FontLineSpacing; }\r\n\r\n        // Get the texture object\r\n        const Texture& GetTexture( void ) const { return m_Texture; }\r\n\r\n        float GetXNormalizationFactor() const { return m_NormalizeXCoord; }\r\n        float GetYNormalizationFactor() const { return m_NormalizeYCoord; }\r\n\r\n        // Get the range in terms of height values centered on the midline that represents a pixel\r\n        // in screen space (according to the specified font size.)\r\n        // The pixel alpha should range from 0 to 1 over the height range 0.5 +/- 0.5 * aaRange.\r\n        float GetAntialiasRange( float size ) const { return Max( 1.0f, size * m_AntialiasRange ); }\r\n\r\n    private:\r\n        float m_NormalizeXCoord;\r\n        float m_NormalizeYCoord;\r\n        float m_FontLineSpacing;\r\n        float m_AntialiasRange;\r\n        uint16_t m_FontHeight;\r\n        uint16_t m_BorderSize;\r\n        uint16_t m_TextureWidth;\r\n        uint16_t m_TextureHeight;\r\n        Texture m_Texture;\r\n        map<wchar_t, Glyph> m_Dictionary;\r\n    };\r\n\r\n    map< wstring, unique_ptr<Font> > LoadedFonts;\r\n\r\n    const Font* GetOrLoadFont(const wstring& filename)\r\n    {\r\n        auto fontIter = LoadedFonts.find( filename );\r\n        if (fontIter != LoadedFonts.end())\r\n            return fontIter->second.get();\r\n\r\n        Font* newFont = new Font();\r\n        if (filename == L\"default\")\r\n            newFont->LoadFromBinary(L\"default\", g_pconsola24, sizeof(g_pconsola24));\r\n        else\r\n            newFont->Load(L\"Fonts/\" + filename + L\".fnt\");\r\n        LoadedFonts[filename].reset(newFont);\r\n        return newFont;\r\n    }\r\n\r\n    RootSignature s_RootSignature;\r\n    GraphicsPSO s_TextPSO[2];\t// 0: R8G8B8A8_UNORM   1: R11G11B10_FLOAT\r\n    GraphicsPSO s_ShadowPSO[2];\t// 0: R8G8B8A8_UNORM   1: R11G11B10_FLOAT\r\n\r\n\r\n} // namespace TextRenderer\r\n\r\nvoid TextRenderer::Initialize( void )\r\n{\r\n    s_RootSignature.Reset(3, 1);\r\n    s_RootSignature.InitStaticSampler(0, SamplerLinearClampDesc, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    s_RootSignature[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_VERTEX);\r\n    s_RootSignature[1].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    s_RootSignature.Finalize(L\"TextRenderer\", D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);\r\n\r\n    // The glyph vertex description.  One vertex will correspond to a single character.\r\n    D3D12_INPUT_ELEMENT_DESC vertElem[] =\r\n    {\r\n        { \"POSITION\", 0, DXGI_FORMAT_R32G32_FLOAT     , 0, 0, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 },\r\n        { \"TEXCOORD\", 0, DXGI_FORMAT_R16G16B16A16_UINT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }\r\n    };\r\n\r\n    s_TextPSO[0].SetRootSignature(s_RootSignature);\r\n    s_TextPSO[0].SetRasterizerState( Graphics::RasterizerTwoSided );\r\n    s_TextPSO[0].SetBlendState( Graphics::BlendPreMultiplied );\r\n    s_TextPSO[0].SetDepthStencilState( Graphics::DepthStateDisabled );\r\n    s_TextPSO[0].SetInputLayout(_countof(vertElem), vertElem);\r\n    s_TextPSO[0].SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);\r\n    s_TextPSO[0].SetVertexShader( g_pTextVS, sizeof(g_pTextVS) );\r\n    s_TextPSO[0].SetPixelShader( g_pTextAntialiasPS, sizeof(g_pTextAntialiasPS) );\r\n    s_TextPSO[0].SetRenderTargetFormats(1, &g_OverlayBuffer.GetFormat(), DXGI_FORMAT_UNKNOWN);\r\n    s_TextPSO[0].Finalize();\r\n\r\n    s_TextPSO[1] = s_TextPSO[0];\r\n    s_TextPSO[1].SetRenderTargetFormats(1, &g_pSceneColorBuffer->GetFormat(), DXGI_FORMAT_UNKNOWN);\r\n    s_TextPSO[1].Finalize();\r\n\r\n    s_ShadowPSO[0] = s_TextPSO[0];\r\n    s_ShadowPSO[0].SetPixelShader(g_pTextShadowPS, sizeof(g_pTextShadowPS) );\r\n    s_ShadowPSO[0].Finalize();\r\n\r\n    s_ShadowPSO[1] = s_ShadowPSO[0];\r\n    s_ShadowPSO[1].SetRenderTargetFormats(1, &g_pSceneColorBuffer->GetFormat(), DXGI_FORMAT_UNKNOWN);\r\n    s_ShadowPSO[1].Finalize();\r\n}\r\n\r\nvoid TextRenderer::Shutdown( void )\r\n{\r\n    LoadedFonts.clear();\r\n}\r\n\r\nTextContext::TextContext( GraphicsContext& CmdContext, float ViewWidth, float ViewHeight )\r\n    : m_Context(CmdContext)\r\n{\r\n    m_HDR = FALSE;\r\n    m_CurrentFont = nullptr;\r\n    m_ViewWidth = ViewWidth;\r\n    m_ViewHeight = ViewHeight;\r\n\r\n    // Transform from text view space to clip space.\r\n    const float vpX = 0.0f;\r\n    const float vpY = 0.0f;\r\n    const float twoDivW = 2.0f / ViewWidth;\r\n    const float twoDivH = 2.0f / ViewHeight;\r\n    m_VSParams.ViewportTransform = Vector4(twoDivW, -twoDivH, -vpX * twoDivW - 1.0f, vpY * twoDivH + 1.0f);\r\n\r\n    // The font texture dimensions are still unknown\r\n    m_VSParams.NormalizeX = 1.0f;\r\n    m_VSParams.NormalizeY = 1.0f;\r\n\r\n    ResetSettings();\r\n}\r\n\r\nvoid TextContext::ResetSettings( void )\r\n{\r\n    m_EnableShadow = true;\r\n    ResetCursor(0.0f, 0.0f);\r\n    m_ShadowOffsetX = 0.05f;\r\n    m_ShadowOffsetY = 0.05f;\r\n    m_PSParams.ShadowHardness = 0.5f;\r\n    m_PSParams.ShadowOpacity = 1.0f;\r\n    m_PSParams.TextColor = Color(1.0f, 1.0f, 1.0f, 1.0f);\r\n\r\n    m_VSConstantBufferIsStale = true;\r\n    m_PSConstantBufferIsStale = true;\r\n    m_TextureIsStale = true;\r\n\r\n    SetFont( L\"default\", 24.0f );\r\n}\r\n\r\nvoid  TextContext::SetLeftMargin( float x ) { m_LeftMargin = x; }\r\nvoid  TextContext::SetCursorX( float x ) { m_TextPosX = x; }\r\nvoid  TextContext::SetCursorY( float y ) { m_TextPosY = y; }\r\nvoid  TextContext::NewLine( void ) { m_TextPosX = m_LeftMargin; m_TextPosY += m_LineHeight; }\r\nfloat TextContext::GetLeftMargin( void ) { return m_LeftMargin; }\r\nfloat TextContext::GetCursorX( void ) { return m_TextPosX; }\r\nfloat TextContext::GetCursorY( void ) { return m_TextPosY; }\r\n\r\n\r\nvoid TextContext::ResetCursor(float x, float y)\r\n{\r\n    m_LeftMargin = x;\r\n    m_TextPosX = x;\r\n    m_TextPosY = y;\r\n}\r\n\r\nvoid TextContext::EnableDropShadow(bool enable)\r\n{\r\n    if (m_EnableShadow == enable)\r\n        return;\r\n\r\n    m_EnableShadow = enable;\r\n\r\n    m_Context.SetPipelineState( m_EnableShadow ? TextRenderer::s_ShadowPSO[m_HDR] : TextRenderer::s_TextPSO[m_HDR] );\r\n}\r\n\r\nvoid TextContext::SetShadowOffset(float xPercent, float yPercent)\r\n{\r\n    m_ShadowOffsetX = xPercent;\r\n    m_ShadowOffsetY = yPercent;\r\n    m_PSParams.ShadowOffsetX = m_CurrentFont->GetHeight() * m_ShadowOffsetX * m_VSParams.NormalizeX;\r\n    m_PSParams.ShadowOffsetY = m_CurrentFont->GetHeight() * m_ShadowOffsetY * m_VSParams.NormalizeY;\r\n    m_PSConstantBufferIsStale = true;\r\n}\r\n\r\nvoid TextContext::SetShadowParams(float opacity, float width)\r\n{\r\n    m_PSParams.ShadowHardness = 1.0f / width;\r\n    m_PSParams.ShadowOpacity = opacity;\r\n    m_PSConstantBufferIsStale = true;\r\n}\r\n\r\nvoid TextContext::SetColor( Color c )\r\n{\r\n    m_PSParams.TextColor = c;\r\n    m_PSConstantBufferIsStale = true;\r\n}\r\n\r\nfloat TextContext::GetVerticalSpacing( void )\r\n{\r\n    return m_LineHeight;\r\n}\r\n\r\nvoid TextContext::Begin( bool EnableHDR )\r\n{\r\n    ResetSettings();\r\n\r\n    m_HDR = (BOOL)EnableHDR;\r\n\r\n    m_Context.SetRootSignature(TextRenderer::s_RootSignature);\r\n    m_Context.SetPipelineState(TextRenderer::s_ShadowPSO[m_HDR]);\r\n    m_Context.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);\r\n}\r\n\r\nvoid TextContext::SetFont( const wstring& fontName, float size )\r\n{\r\n    // If that font is already set or doesn't exist, return.\r\n    const TextRenderer::Font* NextFont = TextRenderer::GetOrLoadFont( fontName );\r\n    if (NextFont == m_CurrentFont || NextFont == nullptr)\r\n    {\r\n        if (size > 0.0f)\r\n            SetTextSize(size);\r\n\r\n        return;\r\n    }\r\n\r\n    m_CurrentFont = NextFont;\r\n\r\n    // Check to see if a new size was specified\r\n    if (size > 0.0f)\r\n        m_VSParams.TextSize = size;\r\n\r\n    // Update constants directly tied to the font or the font size\r\n    m_LineHeight = NextFont->GetVerticalSpacing( m_VSParams.TextSize );\r\n    m_VSParams.NormalizeX = m_CurrentFont->GetXNormalizationFactor();\r\n    m_VSParams.NormalizeY = m_CurrentFont->GetYNormalizationFactor();\r\n    m_VSParams.Scale = m_VSParams.TextSize / m_CurrentFont->GetHeight();\r\n    m_VSParams.DstBorder = m_CurrentFont->GetBorderSize() * m_VSParams.Scale;\r\n    m_VSParams.SrcBorder = m_CurrentFont->GetBorderSize();\r\n    m_PSParams.ShadowOffsetX = m_CurrentFont->GetHeight() * m_ShadowOffsetX * m_VSParams.NormalizeX;\r\n    m_PSParams.ShadowOffsetY = m_CurrentFont->GetHeight() * m_ShadowOffsetY * m_VSParams.NormalizeY;\r\n    m_PSParams.HeightRange = m_CurrentFont->GetAntialiasRange( m_VSParams.TextSize );\r\n    m_VSConstantBufferIsStale = true;\r\n    m_PSConstantBufferIsStale = true;\r\n    m_TextureIsStale = true;\r\n}\r\n\r\nvoid TextContext::SetTextSize( float size )\r\n{\r\n    if (m_VSParams.TextSize == size)\r\n        return;\r\n\r\n    m_VSParams.TextSize = size;\r\n    m_VSConstantBufferIsStale = true;\r\n\r\n    if (m_CurrentFont != nullptr)\r\n    {\r\n        m_PSParams.HeightRange = m_CurrentFont->GetAntialiasRange( m_VSParams.TextSize );\r\n        m_VSParams.Scale = m_VSParams.TextSize / m_CurrentFont->GetHeight();\r\n        m_VSParams.DstBorder = m_CurrentFont->GetBorderSize() * m_VSParams.Scale;\r\n        m_PSConstantBufferIsStale = true;\r\n        m_LineHeight = m_CurrentFont->GetVerticalSpacing( size );\r\n    }\r\n    else\r\n        m_LineHeight = 0.0f;\r\n}\r\n\r\nvoid TextContext::SetViewSize( float ViewWidth, float ViewHeight )\r\n{\r\n    m_ViewWidth = ViewWidth;\r\n    m_ViewHeight = ViewHeight;\r\n\r\n    const float vpX = 0.0f;\r\n    const float vpY = 0.0f;\r\n    const float twoDivW = 2.0f / ViewWidth;\r\n    const float twoDivH = 2.0f / ViewHeight;\r\n\r\n    // Essentially transform from screen coordinates to to clip space with W = 1.\r\n    m_VSParams.ViewportTransform = Vector4(twoDivW, -twoDivH, -vpX * twoDivW - 1.0f, vpY * twoDivH + 1.0f);\r\n    m_VSConstantBufferIsStale = true;\r\n}\r\n\r\nvoid TextContext::End( void )\r\n{\r\n    m_VSConstantBufferIsStale = true;\r\n    m_PSConstantBufferIsStale = true;\r\n    m_TextureIsStale = true;\r\n}\r\n\r\nvoid TextContext::SetRenderState( void )\r\n{\r\n    WARN_ONCE_IF(nullptr == m_CurrentFont, \"Attempted to draw text without a font\");\r\n\r\n    if (m_VSConstantBufferIsStale)\r\n    {\r\n        m_Context.SetDynamicConstantBufferView(0, sizeof(m_VSParams), &m_VSParams);\r\n        m_VSConstantBufferIsStale = false;\r\n    }\r\n\r\n    if (m_PSConstantBufferIsStale)\r\n    {\r\n        m_Context.SetDynamicConstantBufferView(1, sizeof(m_PSParams), &m_PSParams);\r\n        m_PSConstantBufferIsStale = false;\r\n    }\r\n\r\n    if (m_TextureIsStale)\r\n    {\r\n        m_Context.SetDynamicDescriptors(2, 0, 1, &m_CurrentFont->GetTexture().GetSRV());\r\n        m_TextureIsStale = false;\r\n    }\r\n}\r\n\r\n// These are made with templates to handle char and wchar_t simultaneously.\r\nUINT TextContext::FillVertexBuffer( TextVert volatile* verts, const char* str, size_t stride, size_t slen )\r\n{\r\n    UINT charsDrawn = 0;\r\n\r\n    const float UVtoPixel = m_VSParams.Scale;\r\n\r\n    float curX = m_TextPosX;\r\n    float curY = m_TextPosY;\r\n\r\n    const uint16_t texelHeight = m_CurrentFont->GetHeight();\r\n\r\n    const char* iter = str;\r\n    for (size_t i = 0; i < slen; ++i)\r\n    {\r\n        wchar_t wc = (stride == 2 ? *(wchar_t*)iter : *iter);\r\n        iter += stride;\r\n\r\n        // Terminate on null character (this really shouldn't happen with string or wstring)\r\n        if (wc == L'\\0')\r\n            break;\r\n\r\n        // Handle newlines by inserting a carriage return and line feed\r\n        if (wc == L'\\n')\r\n        {\r\n            curX = m_LeftMargin;\r\n            curY += m_LineHeight;\r\n            continue;\r\n        }\r\n\r\n        const TextRenderer::Font::Glyph* gi = m_CurrentFont->GetGlyph(wc);\r\n\r\n        // Ignore missing characters\r\n        if (nullptr == gi)\r\n            continue;\r\n\r\n        verts->X = curX + (float)gi->bearing * UVtoPixel;\r\n        verts->Y = curY;\r\n        verts->U = gi->x;\r\n        verts->V = gi->y;\r\n        verts->W = gi->w;\r\n        verts->H = texelHeight;\r\n        ++verts;\r\n\r\n        // Advance the cursor position\r\n        curX += (float)gi->advance * UVtoPixel;\r\n        ++charsDrawn;\r\n    }\r\n\r\n    m_TextPosX = curX;\r\n    m_TextPosY = curY;\r\n\r\n    return charsDrawn;\r\n}\r\n\r\nvoid TextContext::DrawString( const std::wstring& str )\r\n{\r\n    SetRenderState();\r\n\r\n    void* stackMem = _malloca((str.size() + 1) * 16);\r\n    TextVert* vbPtr = Math::AlignUp((TextVert*)stackMem, 16);\r\n    UINT primCount = FillVertexBuffer(vbPtr, (char*)str.c_str(), 2, str.size());\r\n\r\n    if (primCount > 0)\r\n    {\r\n        m_Context.SetDynamicVB(0, primCount, sizeof(TextVert), vbPtr);\r\n        m_Context.DrawInstanced( 4, primCount );\r\n    }\r\n\r\n    _freea(stackMem);\r\n}\r\n\r\nvoid TextContext::DrawString( const std::string& str )\r\n{\r\n    SetRenderState();\r\n\r\n    void* stackMem = _malloca((str.size() + 1) * 16);\r\n    TextVert* vbPtr = Math::AlignUp((TextVert*)stackMem, 16);\r\n    UINT primCount = FillVertexBuffer(vbPtr, (char*)str.c_str(), 1, str.size());\r\n\r\n    if (primCount > 0)\r\n    {\r\n        m_Context.SetDynamicVB(0, primCount, sizeof(TextVert), vbPtr);\r\n        m_Context.DrawInstanced( 4, primCount );\r\n    }\r\n\r\n    _freea(stackMem);\r\n}\r\n\r\nvoid TextContext::DrawFormattedString( const wchar_t* format, ... )\r\n{\r\n    wchar_t buffer[256];\r\n    va_list ap;\r\n    va_start(ap, format);\r\n    vswprintf( buffer, 256, format, ap );\r\n    DrawString( wstring(buffer) );\r\n}\r\n\r\nvoid TextContext::DrawFormattedString( const char* format, ... )\r\n{\r\n    char buffer[256];\r\n    va_list ap;\r\n    va_start(ap, format);\r\n    vsprintf_s( buffer, 256, format, ap );\r\n    DrawString( string(buffer) );\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/TextRenderer.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"Color.h\"\r\n#include \"Math/Vector.h\"\r\n#include <string>\r\n\r\nclass Color;\r\nclass GraphicsContext;\r\n\r\nnamespace TextRenderer\r\n{\r\n    // Initialize the text renderer's resources and designate the dimensions of the drawable\r\n    // view space.  These dimensions do not have to match the actual pixel width and height of\r\n    // the viewport.  Instead they create a coordinate space for placing text within the\r\n    // viewport.  For instance, if you specify a ViewWidth of 2.0f, then CursorX = 1.0f marks\r\n    // the middle of the viewport.\r\n    void Initialize( void );\r\n    void Shutdown( void );\r\n\r\n    class Font;\r\n}\r\n\r\nclass TextContext\r\n{\r\npublic:\r\n    TextContext( GraphicsContext& CmdContext, float CanvasWidth = 1920.0f, float CanvasHeight = 1080.0f );\r\n\r\n    GraphicsContext& GetCommandContext() const { return m_Context; }\r\n\r\n    // Put settings back to the defaults.\r\n    void ResetSettings( void );\r\n\r\n    //\r\n    // Control various text properties\r\n    //\r\n\r\n    // Choose a font from the Fonts folder.  Previously loaded fonts are cached in memory.\r\n    void SetFont( const std::wstring& fontName, float TextSize = 0.0f );\r\n\r\n    // Resize the view space.  This determines the coordinate space of the cursor position and font size.  You can always\r\n    // set the view size to the same dimensions regardless of actual display resolution.  It is assumed, however, that the\r\n    // aspect ratio of this virtual coordinate system matches the actual display aspect ratio.\r\n    void SetViewSize( float ViewWidth, float ViewHeight );\r\n\r\n    // Set the size of the text relative to the ViewHeight.  The aspect of the text is preserved from\r\n    // the TTF as long as the aspect ratio of the view space is the same as the actual viewport.\r\n    void SetTextSize( float PixelHeight );\r\n\r\n    // Move the cursor position--the upper-left anchor for the text.\r\n    void ResetCursor( float x, float y );\r\n    void SetLeftMargin( float x );\r\n    void SetCursorX( float x );\r\n    void SetCursorY( float y );\r\n    void NewLine( void );\r\n    float GetLeftMargin( void );\r\n    float GetCursorX( void );\r\n    float GetCursorY( void );\r\n\r\n    // Turn on or off drop shadow.\r\n    void EnableDropShadow( bool enable );\r\n\r\n    // Adjust shadow parameters.\r\n    void SetShadowOffset( float xPercent, float yPercent );\r\n    void SetShadowParams( float opacity, float width );\r\n\r\n    // Set the color and transparency of text.\r\n    void SetColor( Color color );\r\n\r\n    // Get the amount to advance the Y position to begin a new line\r\n    float GetVerticalSpacing( void );\r\n\r\n    //\r\n    // Rendering commands\r\n    //\r\n\r\n    // Begin and end drawing commands\r\n    void Begin( bool EnableHDR = false );\r\n    void End( void );\r\n\r\n    // Draw a string\r\n    void DrawString( const std::wstring& str );\r\n    void DrawString( const std::string& str );\r\n\r\n    // A more powerful function which formats text like printf().  Very slow by comparison, so use it\r\n    // only if you're going to format text anyway.\r\n    void DrawFormattedString( const wchar_t* format, ... );\r\n    void DrawFormattedString( const char* format, ... );\r\n\r\nprivate:\r\n\r\n    __declspec(align(16)) struct VertexShaderParams\r\n    {\r\n        Math::Vector4 ViewportTransform;\r\n        float NormalizeX, NormalizeY, TextSize;\r\n        float Scale, DstBorder;\r\n        uint32_t SrcBorder;\r\n    };\r\n\r\n    __declspec(align(16)) struct PixelShaderParams\r\n    {\r\n        Color TextColor;\r\n        float ShadowOffsetX, ShadowOffsetY;\r\n        float ShadowHardness;\t\t// More than 1 will cause aliasing\r\n        float ShadowOpacity;\t\t// Should make less opaque when making softer\r\n        float HeightRange;\r\n    };\r\n\r\n    void SetRenderState(void);\r\n\r\n    // 16 Byte structure to represent an entire glyph in the text vertex buffer\r\n    __declspec(align(16)) struct TextVert\r\n    {\r\n        float X, Y;\t\t\t\t// Upper-left glyph position in screen space\r\n        uint16_t U, V, W, H;\t// Upper-left glyph UV and the width in texture space\r\n    };\r\n\r\n    UINT FillVertexBuffer( TextVert volatile* verts, const char* str, size_t stride, size_t slen );\r\n    void DrawStringInternal( const std::string& str );\r\n    void DrawStringInternal( const std::wstring& str );\r\n\r\n    GraphicsContext& m_Context;\r\n    const TextRenderer::Font* m_CurrentFont;\r\n    VertexShaderParams m_VSParams;\r\n    PixelShaderParams m_PSParams;\r\n    bool m_VSConstantBufferIsStale;\t// Tracks when the CB needs updating\r\n    bool m_PSConstantBufferIsStale;\t// Tracks when the CB needs updating\r\n    bool m_TextureIsStale;\r\n    bool m_EnableShadow;\r\n    float m_LeftMargin;\r\n    float m_TextPosX;\r\n    float m_TextPosY;\r\n    float m_LineHeight;\r\n    float m_ViewWidth;\t\t\t\t// Width of the drawable area\r\n    float m_ViewHeight;\t\t\t\t// Height of the drawable area\r\n    float m_ShadowOffsetX;\t\t\t// Percentage of the font's TextSize should the shadow be offset\r\n    float m_ShadowOffsetY;\t\t\t// Percentage of the font's TextSize should the shadow be offset\r\n    BOOL m_HDR;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Core/TextureManager.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard \r\n//             Alex Nankervis\r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"TextureManager.h\"\r\n#include \"FileUtility.h\"\r\n#include \"DDSTextureLoader.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CommandContext.h\"\r\n#include <map>\r\n#include <thread>\r\n\r\n#include <iostream>\r\n\r\nusing namespace std;\r\nusing namespace Graphics;\r\n\r\nstatic UINT BytesPerPixel( DXGI_FORMAT Format )\r\n{\r\n    return (UINT)BitsPerPixel(Format) / 8;\r\n};\r\n\r\nvoid Texture::Create( size_t Pitch, size_t Width, size_t Height, DXGI_FORMAT Format, const void* InitialData )\r\n{\r\n    m_UsageState = D3D12_RESOURCE_STATE_COPY_DEST;\r\n\r\n    D3D12_RESOURCE_DESC texDesc = {};\r\n    texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\r\n    texDesc.Width = Width;\r\n    texDesc.Height = (UINT)Height;\r\n    texDesc.DepthOrArraySize = 1;\r\n    texDesc.MipLevels = 1;\r\n    texDesc.Format = Format;\r\n    texDesc.SampleDesc.Count = 1;\r\n    texDesc.SampleDesc.Quality = 0;\r\n    texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;\r\n    texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;\r\n\r\n    D3D12_HEAP_PROPERTIES HeapProps;\r\n    HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;\r\n    HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n    HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n    HeapProps.CreationNodeMask = 1;\r\n    HeapProps.VisibleNodeMask = 1;\r\n\r\n    ASSERT_SUCCEEDED(g_Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &texDesc,\r\n        m_UsageState, nullptr, MY_IID_PPV_ARGS(m_pResource.ReleaseAndGetAddressOf())));\r\n\r\n    m_pResource->SetName(L\"Texture\");\r\n\r\n    D3D12_SUBRESOURCE_DATA texResource;\r\n    texResource.pData = InitialData;\r\n    texResource.RowPitch = Pitch * BytesPerPixel(Format);\r\n    texResource.SlicePitch = texResource.RowPitch * Height;\r\n\r\n    CommandContext::InitializeTexture(*this, 1, &texResource);\r\n\r\n    if (m_hCpuDescriptorHandle.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_hCpuDescriptorHandle = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n    g_Device->CreateShaderResourceView(m_pResource.Get(), nullptr, m_hCpuDescriptorHandle);\r\n}\r\n\r\nvoid Texture::CreateTGAFromMemory( const void* _filePtr, size_t, bool sRGB )\r\n{\r\n    const uint8_t* filePtr = (const uint8_t*)_filePtr;\r\n\r\n    // Skip first two bytes\r\n    filePtr += 2;\r\n\r\n    /*uint8_t imageTypeCode =*/ *filePtr++;\r\n\r\n    // Ignore another 9 bytes\r\n    filePtr += 9;\r\n\r\n    uint16_t imageWidth = *(uint16_t*)filePtr;\r\n    filePtr += sizeof(uint16_t);\r\n    uint16_t imageHeight = *(uint16_t*)filePtr;\r\n    filePtr += sizeof(uint16_t);\r\n    uint8_t bitCount = *filePtr++;\r\n\r\n    // Ignore another byte\r\n    filePtr++;\r\n\r\n    uint32_t* formattedData = new uint32_t[imageWidth * imageHeight];\r\n    uint32_t* iter = formattedData;\r\n\r\n    uint8_t numChannels = bitCount / 8;\r\n    uint32_t numBytes = imageWidth * imageHeight * numChannels;\r\n\r\n    switch (numChannels)\r\n    {\r\n    default:\r\n        break;\r\n    case 3:\r\n        for (uint32_t byteIdx = 0; byteIdx < numBytes; byteIdx += 3)\r\n        {\r\n            *iter++ = 0xff000000 | filePtr[0] << 16 | filePtr[1] << 8 | filePtr[2];\r\n            filePtr += 3;\r\n        }\r\n        break;\r\n    case 4:\r\n        for (uint32_t byteIdx = 0; byteIdx < numBytes; byteIdx += 4)\r\n        {\r\n            *iter++ = filePtr[3] << 24 | filePtr[0] << 16 | filePtr[1] << 8 | filePtr[2];\r\n            filePtr += 4;\r\n        }\r\n        break;\r\n    }\r\n\r\n    Create( imageWidth, imageHeight, sRGB ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM, formattedData );\r\n\r\n    delete [] formattedData;\r\n}\r\n\r\nbool Texture::CreateDDSFromMemory( const void* filePtr, size_t fileSize, bool sRGB )\r\n{\r\n    if (m_hCpuDescriptorHandle.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN)\r\n        m_hCpuDescriptorHandle = AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n\r\n    HRESULT hr = CreateDDSTextureFromMemory( Graphics::g_Device,\r\n        (const uint8_t*)filePtr, fileSize, 0, sRGB, &m_pResource, m_hCpuDescriptorHandle );\r\n\r\n    return SUCCEEDED(hr);\r\n}\r\n\r\nvoid Texture::CreatePIXImageFromMemory( const void* memBuffer, size_t fileSize )\r\n{\r\n    struct Header\r\n    {\r\n        DXGI_FORMAT Format;\r\n        uint32_t Pitch;\r\n        uint32_t Width;\r\n        uint32_t Height;\r\n    };\r\n    const Header& header = *(Header*)memBuffer;\r\n\r\n    ASSERT(fileSize >= header.Pitch * BytesPerPixel(header.Format) * header.Height + sizeof(Header),\r\n        \"Raw PIX image dump has an invalid file size\");\r\n\r\n    Create(header.Pitch, header.Width, header.Height, header.Format, (uint8_t*)memBuffer + sizeof(Header));\r\n}\r\n\r\nnamespace TextureManager\r\n{\r\n    wstring s_RootPath = L\"\";\r\n    map< wstring, unique_ptr<ManagedTexture> > s_TextureCache;\r\n\tbool s_reportError = false;\r\n\r\n    void Initialize( const std::wstring& TextureLibRoot )\r\n    {\r\n        s_RootPath = TextureLibRoot;\r\n    }\r\n\r\n    void Shutdown( void )\r\n    {\r\n        s_TextureCache.clear();\r\n    }\r\n\r\n\tvoid ReportLoadErrors(bool enable) {\r\n\t\ts_reportError = enable;\r\n\t}\r\n\r\n    pair<ManagedTexture*, bool> FindOrLoadTexture( const wstring& fileName )\r\n    {\r\n        static mutex s_Mutex;\r\n        lock_guard<mutex> Guard(s_Mutex);\r\n\r\n        auto iter = s_TextureCache.find(fileName);\r\n\r\n        // If it's found, it has already been loaded or the load process has begun\r\n        if (iter != s_TextureCache.end())\r\n            return make_pair(iter->second.get(), false);\r\n\r\n        ManagedTexture* NewTexture = new ManagedTexture(fileName);\r\n        s_TextureCache[fileName].reset( NewTexture );\r\n\r\n        // This was the first time it was requested, so indicate that the caller must read the file\r\n        return make_pair(NewTexture, true);\r\n    }\r\n\r\n    const Texture& GetBlackTex2D(void)\r\n    {\r\n        auto ManagedTex = FindOrLoadTexture(L\"DefaultBlackTexture\");\r\n\r\n        ManagedTexture* ManTex = ManagedTex.first;\r\n        const bool RequestsLoad = ManagedTex.second;\r\n\r\n        if (!RequestsLoad)\r\n        {\r\n            ManTex->WaitForLoad();\r\n            return *ManTex;\r\n        }\r\n\r\n        uint32_t BlackPixel = 0;\r\n        ManTex->Create(1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, &BlackPixel);\r\n        return *ManTex;\r\n    }\r\n\r\n    const Texture& GetWhiteTex2D(void)\r\n    {\r\n        auto ManagedTex = FindOrLoadTexture(L\"DefaultWhiteTexture\");\r\n\r\n        ManagedTexture* ManTex = ManagedTex.first;\r\n        const bool RequestsLoad = ManagedTex.second;\r\n\r\n        if (!RequestsLoad)\r\n        {\r\n            ManTex->WaitForLoad();\r\n            return *ManTex;\r\n        }\r\n\r\n        uint32_t WhitePixel = 0xFFFFFFFFul;\r\n        ManTex->Create(1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, &WhitePixel);\r\n        return *ManTex;\r\n    }\r\n\r\n    const Texture& GetMagentaTex2D(void)\r\n    {\r\n        auto ManagedTex = FindOrLoadTexture(L\"DefaultMagentaTexture\");\r\n\r\n        ManagedTexture* ManTex = ManagedTex.first;\r\n        const bool RequestsLoad = ManagedTex.second;\r\n\r\n        if (!RequestsLoad)\r\n        {\r\n            ManTex->WaitForLoad();\r\n            return *ManTex;\r\n        }\r\n\r\n        uint32_t MagentaPixel = 0x00FF00FF;\r\n        ManTex->Create(1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, &MagentaPixel);\r\n        return *ManTex;\r\n    }\r\n\r\n} // namespace TextureManager\r\n\r\nvoid ManagedTexture::WaitForLoad( void ) const\r\n{\r\n    volatile D3D12_CPU_DESCRIPTOR_HANDLE& VolHandle = (volatile D3D12_CPU_DESCRIPTOR_HANDLE&)m_hCpuDescriptorHandle;\r\n    volatile bool& VolValid = (volatile bool&)m_IsValid;\r\n    while (VolHandle.ptr == D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN && VolValid)\r\n        this_thread::yield();\r\n}\r\n\r\nvoid ManagedTexture::SetToInvalidTexture( void )\r\n{\r\n    m_hCpuDescriptorHandle = TextureManager::GetMagentaTex2D().GetSRV();\r\n    m_IsValid = false;\r\n}\r\n\r\nconst ManagedTexture* TextureManager::LoadFromFile( const std::wstring& fileName, bool sRGB )\r\n{\r\n    std::wstring CatPath = fileName;\r\n\r\n\t// debugging\r\n\t//std::wcout << L\"LoadFromFile(\" << fileName << L\")\" << std::endl;\r\n\r\n    const ManagedTexture* Tex = LoadDDSFromFile( CatPath + L\".dds\", sRGB );\r\n    if (!Tex->IsValid())\r\n        Tex = LoadTGAFromFile( CatPath + L\".tga\", sRGB );\r\n\r\n    return Tex;\r\n}\r\n\r\nconst ManagedTexture* TextureManager::LoadDDSFromFile( const std::wstring& fileName, bool sRGB )\r\n{\r\n    auto ManagedTex = FindOrLoadTexture(fileName);\r\n\r\n    ManagedTexture* ManTex = ManagedTex.first;\r\n    const bool RequestsLoad = ManagedTex.second;\r\n\r\n    if (!RequestsLoad)\r\n    {\r\n        ManTex->WaitForLoad();\r\n        return ManTex;\r\n    }\r\n\r\n    Utility::ByteArray ba = Utility::ReadFileSync( s_RootPath + fileName );\r\n    if (ba->size() == 0 || !ManTex->CreateDDSFromMemory( ba->data(), ba->size(), sRGB ))\r\n        ManTex->SetToInvalidTexture();\r\n    else\r\n        ManTex->GetResource()->SetName(fileName.c_str());\r\n\r\n    return ManTex;\r\n}\r\n\r\nconst ManagedTexture* TextureManager::LoadTGAFromFile( const std::wstring& fileName, bool sRGB )\r\n{\r\n    auto ManagedTex = FindOrLoadTexture(fileName);\r\n\r\n    ManagedTexture* ManTex = ManagedTex.first;\r\n    const bool RequestsLoad = ManagedTex.second;\r\n\r\n    if (!RequestsLoad)\r\n    {\r\n        ManTex->WaitForLoad();\r\n        return ManTex;\r\n    }\r\n\t\r\n\tUtility::ByteArray ba = Utility::ReadFileSync(s_RootPath + fileName);\r\n    if (ba->size() > 0)\r\n    {\r\n        ManTex->CreateTGAFromMemory( ba->data(), ba->size(), sRGB );\r\n        ManTex->GetResource()->SetName(fileName.c_str());\r\n    }\r\n\telse {\r\n\t\tif(s_reportError)\r\n\t\t\tstd::wcout << L\"Failed to load asset: \" << s_RootPath << fileName << std::endl;\r\n\t\tManTex->SetToInvalidTexture();\r\n\t}\r\n\r\n    return ManTex;\r\n}\r\n\r\n\r\nconst ManagedTexture* TextureManager::LoadPIXImageFromFile( const std::wstring& fileName )\r\n{\r\n    auto ManagedTex = FindOrLoadTexture(fileName);\r\n\r\n    ManagedTexture* ManTex = ManagedTex.first;\r\n    const bool RequestsLoad = ManagedTex.second;\r\n\r\n    if (!RequestsLoad)\r\n    {\r\n        ManTex->WaitForLoad();\r\n        return ManTex;\r\n    }\r\n\r\n    Utility::ByteArray ba = Utility::ReadFileSync( s_RootPath + fileName );\r\n    if (ba->size() > 0)\r\n    {\r\n        ManTex->CreatePIXImageFromMemory(ba->data(), ba->size());\r\n        ManTex->GetResource()->SetName(fileName.c_str());\r\n    }\r\n    else\r\n        ManTex->SetToInvalidTexture();\r\n\r\n    return ManTex;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/TextureManager.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//             Alex Nankervis\r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n#include \"GpuResource.h\"\r\n#include \"Utility.h\"\r\n\r\nclass Texture : public GpuResource\r\n{\r\n    friend class CommandContext;\r\n\r\npublic:\r\n\r\n    Texture() { m_hCpuDescriptorHandle.ptr = D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN; }\r\n    Texture(D3D12_CPU_DESCRIPTOR_HANDLE Handle) : m_hCpuDescriptorHandle(Handle) {}\r\n\r\n    // Create a 1-level 2D texture\r\n    void Create(size_t Pitch, size_t Width, size_t Height, DXGI_FORMAT Format, const void* InitData );\r\n    void Create(size_t Width, size_t Height, DXGI_FORMAT Format, const void* InitData )\r\n    {\r\n        Create(Width, Width, Height, Format, InitData);\r\n    }\r\n\r\n    void CreateTGAFromMemory( const void* memBuffer, size_t fileSize, bool sRGB );\r\n    bool CreateDDSFromMemory( const void* memBuffer, size_t fileSize, bool sRGB );\r\n    void CreatePIXImageFromMemory( const void* memBuffer, size_t fileSize );\r\n\r\n    virtual void Destroy() override\r\n    {\r\n        GpuResource::Destroy();\r\n        m_hCpuDescriptorHandle.ptr = 0;\r\n    }\r\n\r\n    const D3D12_CPU_DESCRIPTOR_HANDLE& GetSRV() const { return m_hCpuDescriptorHandle; }\r\n\r\n    bool operator!() { return m_hCpuDescriptorHandle.ptr == 0; }\r\n\r\nprotected:\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_hCpuDescriptorHandle;\r\n};\r\n\r\nclass ManagedTexture : public Texture\r\n{\r\npublic:\r\n    ManagedTexture( const std::wstring& FileName ) : m_MapKey(FileName), m_IsValid(true) {}\r\n\r\n    void operator= ( const Texture& Texture );\r\n\r\n    void WaitForLoad(void) const;\r\n    void Unload(void);\r\n\r\n    void SetToInvalidTexture(void);\r\n    bool IsValid(void) const { return m_IsValid; }\r\n\r\nprivate:\r\n    std::wstring m_MapKey;\t\t// For deleting from the map later\r\n    bool m_IsValid;\r\n};\r\n\r\nnamespace TextureManager\r\n{\r\n    void Initialize( const std::wstring& TextureLibRoot );\r\n    void Shutdown(void);\r\n\tvoid ReportLoadErrors(bool enable);\r\n\r\n    const ManagedTexture* LoadFromFile( const std::wstring& fileName, bool sRGB = false );\r\n    const ManagedTexture* LoadDDSFromFile( const std::wstring& fileName, bool sRGB = false );\r\n    const ManagedTexture* LoadTGAFromFile( const std::wstring& fileName, bool sRGB = false );\r\n    const ManagedTexture* LoadPIXImageFromFile( const std::wstring& fileName );\r\n\r\n    inline const ManagedTexture* LoadFromFile( const std::string& fileName, bool sRGB = false )\r\n    {\r\n        return LoadFromFile(MakeWStr(fileName), sRGB);\r\n    }\r\n\r\n    inline const ManagedTexture* LoadDDSFromFile( const std::string& fileName, bool sRGB = false )\r\n    {\r\n        return LoadDDSFromFile(MakeWStr(fileName), sRGB);\r\n    }\r\n\r\n    inline const ManagedTexture* LoadTGAFromFile( const std::string& fileName, bool sRGB = false )\r\n    {\r\n        return LoadTGAFromFile(MakeWStr(fileName), sRGB);\r\n    }\r\n\r\n    inline const ManagedTexture* LoadPIXImageFromFile( const std::string& fileName )\r\n    {\r\n        return LoadPIXImageFromFile(MakeWStr(fileName));\r\n    }\r\n\r\n    const Texture& GetBlackTex2D(void);\r\n    const Texture& GetWhiteTex2D(void);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Utility.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#include \"pch.h\"\r\n#include \"Utility.h\"\r\n#include <string>\r\n\r\n// A faster version of memcopy that uses SSE instructions.  TODO:  Write an ARM variant if necessary.\r\nvoid SIMDMemCopy( void* __restrict _Dest, const void* __restrict _Source, size_t NumQuadwords )\r\n{\r\n    ASSERT(Math::IsAligned(_Dest, 16));\r\n    ASSERT(Math::IsAligned(_Source, 16));\r\n\r\n    __m128i* __restrict Dest = (__m128i* __restrict)_Dest;\r\n    const __m128i* __restrict Source = (const __m128i* __restrict)_Source;\r\n\r\n    // Discover how many quadwords precede a cache line boundary.  Copy them separately.\r\n    size_t InitialQuadwordCount = (4 - ((size_t)Source >> 4) & 3) & 3;\r\n    if (InitialQuadwordCount > NumQuadwords)\r\n        InitialQuadwordCount = NumQuadwords;\r\n\r\n    switch (InitialQuadwordCount)\r\n    {\r\n    case 3: _mm_stream_si128(Dest + 2, _mm_load_si128(Source + 2));\t // Fall through\r\n    case 2: _mm_stream_si128(Dest + 1, _mm_load_si128(Source + 1));\t // Fall through\r\n    case 1: _mm_stream_si128(Dest + 0, _mm_load_si128(Source + 0));\t // Fall through\r\n    default:\r\n        break;\r\n    }\r\n\r\n    if (NumQuadwords == InitialQuadwordCount)\r\n        return;\r\n\r\n    Dest += InitialQuadwordCount;\r\n    Source += InitialQuadwordCount;\r\n    NumQuadwords -= InitialQuadwordCount;\r\n\r\n    size_t CacheLines = NumQuadwords >> 2;\r\n\r\n    switch (CacheLines)\r\n    {\r\n    default:\r\n    case 10: _mm_prefetch((char*)(Source + 36), _MM_HINT_NTA);\t// Fall through\r\n    case 9:  _mm_prefetch((char*)(Source + 32), _MM_HINT_NTA);\t// Fall through\r\n    case 8:  _mm_prefetch((char*)(Source + 28), _MM_HINT_NTA);\t// Fall through\r\n    case 7:  _mm_prefetch((char*)(Source + 24), _MM_HINT_NTA);\t// Fall through\r\n    case 6:  _mm_prefetch((char*)(Source + 20), _MM_HINT_NTA);\t// Fall through\r\n    case 5:  _mm_prefetch((char*)(Source + 16), _MM_HINT_NTA);\t// Fall through\r\n    case 4:  _mm_prefetch((char*)(Source + 12), _MM_HINT_NTA);\t// Fall through\r\n    case 3:  _mm_prefetch((char*)(Source + 8 ), _MM_HINT_NTA);\t// Fall through\r\n    case 2:  _mm_prefetch((char*)(Source + 4 ), _MM_HINT_NTA);\t// Fall through\r\n    case 1:  _mm_prefetch((char*)(Source + 0 ), _MM_HINT_NTA);\t// Fall through\r\n\r\n        // Do four quadwords per loop to minimize stalls.\r\n        for (size_t i = CacheLines; i > 0; --i)\r\n        {\r\n            // If this is a large copy, start prefetching future cache lines.  This also prefetches the\r\n            // trailing quadwords that are not part of a whole cache line.\r\n            if (i >= 10)\r\n                _mm_prefetch((char*)(Source + 40), _MM_HINT_NTA);\r\n\r\n            _mm_stream_si128(Dest + 0, _mm_load_si128(Source + 0));\r\n            _mm_stream_si128(Dest + 1, _mm_load_si128(Source + 1));\r\n            _mm_stream_si128(Dest + 2, _mm_load_si128(Source + 2));\r\n            _mm_stream_si128(Dest + 3, _mm_load_si128(Source + 3));\r\n\r\n            Dest += 4;\r\n            Source += 4;\r\n        }\r\n\r\n    case 0:\t// No whole cache lines to read\r\n        break;\r\n    }\r\n\r\n    // Copy the remaining quadwords\r\n    switch (NumQuadwords & 3)\r\n    {\r\n    case 3: _mm_stream_si128(Dest + 2, _mm_load_si128(Source + 2));\t // Fall through\r\n    case 2: _mm_stream_si128(Dest + 1, _mm_load_si128(Source + 1));\t // Fall through\r\n    case 1: _mm_stream_si128(Dest + 0, _mm_load_si128(Source + 0));\t // Fall through\r\n    default:\r\n        break;\r\n    }\r\n\r\n    _mm_sfence();\r\n}\r\n\r\nvoid SIMDMemFill( void* __restrict _Dest, __m128 FillVector, size_t NumQuadwords )\r\n{\r\n    ASSERT(Math::IsAligned(_Dest, 16));\r\n\r\n    register const __m128i Source = _mm_castps_si128(FillVector);\r\n    __m128i* __restrict Dest = (__m128i* __restrict)_Dest;\r\n\r\n    switch (((size_t)Dest >> 4) & 3)\r\n    {\r\n    case 1: _mm_stream_si128(Dest++, Source); --NumQuadwords;\t // Fall through\r\n    case 2: _mm_stream_si128(Dest++, Source); --NumQuadwords;\t // Fall through\r\n    case 3: _mm_stream_si128(Dest++, Source); --NumQuadwords;\t // Fall through\r\n    default:\r\n        break;\r\n    }\r\n\r\n    size_t WholeCacheLines = NumQuadwords >> 2;\r\n\r\n    // Do four quadwords per loop to minimize stalls.\r\n    while (WholeCacheLines--)\r\n    {\r\n        _mm_stream_si128(Dest++, Source);\r\n        _mm_stream_si128(Dest++, Source);\r\n        _mm_stream_si128(Dest++, Source);\r\n        _mm_stream_si128(Dest++, Source);\r\n    }\r\n\r\n    // Copy the remaining quadwords\r\n    switch (NumQuadwords & 3)\r\n    {\r\n    case 3: _mm_stream_si128(Dest++, Source);\t // Fall through\r\n    case 2: _mm_stream_si128(Dest++, Source);\t // Fall through\r\n    case 1: _mm_stream_si128(Dest++, Source);\t // Fall through\r\n    default:\r\n        break;\r\n    }\r\n\r\n    _mm_sfence();\r\n}\r\n\r\nstd::wstring MakeWStr( const std::string& str )\r\n{\r\n    return std::wstring(str.begin(), str.end());\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Core/Utility.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#include \"pch.h\"\r\n\r\nnamespace Utility\r\n{\r\n    inline void Print( const char* msg ) { printf(\"%s\", msg); }\r\n    inline void Print( const wchar_t* msg ) { wprintf(L\"%ws\", msg); }\r\n\r\n    inline void Printf( const char* format, ... )\r\n    {\r\n        char buffer[256];\r\n        va_list ap;\r\n        va_start(ap, format);\r\n        vsprintf_s(buffer, 256, format, ap);\r\n        Print(buffer);\r\n    }\r\n\r\n    inline void Printf( const wchar_t* format, ... )\r\n    {\r\n        wchar_t buffer[256];\r\n        va_list ap;\r\n        va_start(ap, format);\r\n        vswprintf(buffer, 256, format, ap);\r\n        Print(buffer);\r\n    }\r\n\r\n#ifndef RELEASE\r\n    inline void PrintSubMessage( const char* format, ... )\r\n    {\r\n        Print(\"--> \");\r\n        char buffer[256];\r\n        va_list ap;\r\n        va_start(ap, format);\r\n        vsprintf_s(buffer, 256, format, ap);\r\n        Print(buffer);\r\n        Print(\"\\n\");\r\n    }\r\n    inline void PrintSubMessage( const wchar_t* format, ... )\r\n    {\r\n        Print(\"--> \");\r\n        wchar_t buffer[256];\r\n        va_list ap;\r\n        va_start(ap, format);\r\n        vswprintf(buffer, 256, format, ap);\r\n        Print(buffer);\r\n        Print(\"\\n\");\r\n    }\r\n    inline void PrintSubMessage( void )\r\n    {\r\n    }\r\n#endif\r\n\r\n} // namespace Utility\r\n\r\n#ifdef ERROR\r\n#undef ERROR\r\n#endif\r\n#ifdef ASSERT\r\n#undef ASSERT\r\n#endif\r\n#ifdef HALT\r\n#undef HALT\r\n#endif\r\n\r\n#define HALT( ... ) ERROR( __VA_ARGS__ ) __debugbreak();\r\n\r\n#ifdef RELEASE\r\n\r\n    #define ASSERT( isTrue, ... ) (void)(isTrue)\r\n    #define WARN_ONCE_IF( isTrue, ... ) (void)(isTrue)\r\n    #define WARN_ONCE_IF_NOT( isTrue, ... ) (void)(isTrue)\r\n    #define ERROR( msg, ... )\r\n    #define DEBUGPRINT( msg, ... ) do {} while(0)\r\n    #define ASSERT_SUCCEEDED( hr, ... ) (void)(hr)\r\n\r\n#else\t// !RELEASE\r\n\r\n    #define STRINGIFY(x) #x\r\n    #define STRINGIFY_BUILTIN(x) STRINGIFY(x)\r\n    #define ASSERT( isFalse, ... ) \\\r\n        if (!(bool)(isFalse)) { \\\r\n            Utility::Print(\"\\nAssertion failed in \" STRINGIFY_BUILTIN(__FILE__) \" @ \" STRINGIFY_BUILTIN(__LINE__) \"\\n\"); \\\r\n            Utility::PrintSubMessage(\"\\'\" #isFalse \"\\' is false\"); \\\r\n            Utility::PrintSubMessage(__VA_ARGS__); \\\r\n            Utility::Print(\"\\n\"); \\\r\n            __debugbreak(); \\\r\n        }\r\n\r\n    #define ASSERT_SUCCEEDED( hr, ... ) \\\r\n        if (FAILED(hr)) { \\\r\n            Utility::Print(\"\\nHRESULT failed in \" STRINGIFY_BUILTIN(__FILE__) \" @ \" STRINGIFY_BUILTIN(__LINE__) \"\\n\"); \\\r\n            Utility::PrintSubMessage(\"hr = 0x%08X\", hr); \\\r\n            Utility::PrintSubMessage(__VA_ARGS__); \\\r\n            Utility::Print(\"\\n\"); \\\r\n            __debugbreak(); \\\r\n        }\r\n\r\n\r\n    #define WARN_ONCE_IF( isTrue, ... ) \\\r\n    { \\\r\n        static bool s_TriggeredWarning = false; \\\r\n        if ((bool)(isTrue) && !s_TriggeredWarning) { \\\r\n            s_TriggeredWarning = true; \\\r\n            Utility::Print(\"\\nWarning issued in \" STRINGIFY_BUILTIN(__FILE__) \" @ \" STRINGIFY_BUILTIN(__LINE__) \"\\n\"); \\\r\n            Utility::PrintSubMessage(\"\\'\" #isTrue \"\\' is true\"); \\\r\n            Utility::PrintSubMessage(__VA_ARGS__); \\\r\n            Utility::Print(\"\\n\"); \\\r\n        } \\\r\n    }\r\n\r\n    #define WARN_ONCE_IF_NOT( isTrue, ... ) WARN_ONCE_IF(!(isTrue), __VA_ARGS__)\r\n\r\n    #define ERROR( ... ) \\\r\n        Utility::Print(\"\\nError reported in \" STRINGIFY_BUILTIN(__FILE__) \" @ \" STRINGIFY_BUILTIN(__LINE__) \"\\n\"); \\\r\n        Utility::PrintSubMessage(__VA_ARGS__); \\\r\n        Utility::Print(\"\\n\");\r\n\r\n    #define DEBUGPRINT( msg, ... ) \\\r\n    Utility::Printf( msg \"\\n\", ##__VA_ARGS__ );\r\n\r\n#endif\r\n\r\n#define BreakIfFailed( hr ) if (FAILED(hr)) __debugbreak()\r\n\r\nvoid SIMDMemCopy( void* __restrict Dest, const void* __restrict Source, size_t NumQuadwords );\r\nvoid SIMDMemFill( void* __restrict Dest, __m128 FillVector, size_t NumQuadwords );\r\n\r\nstd::wstring MakeWStr( const std::string& str );\r\n"
  },
  {
    "path": "MiniEngine/Core/VectorMath.h",
    "content": "﻿//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n// This is a system of classes that wrap DirectXMath in a more object-oriented and concise (readable) way.  While these\r\n// classes are not designed to maximize throughput on the instruction level, they are designed to be easily understood.\r\n// I believe that the source of most math library inefficiency is in their being too confusing and not making the preferred\r\n// way of doing things obvious.  This leaves programmers constantly finding usage patterns that \"work for them\" but are\r\n// ultimately inefficient and don't use the API the \"way it was intended\".  The goal of this wrapper is to be cogent and\r\n// familiar.\r\n// \r\n// Note that DirectXMath treats vectors like [1x4] matrices (rows) rather than [4x1] matrices (columns).  Likewise, it\r\n// treats matrices like they are transposed, so that you would multiply a vector and a matrix like so:\r\n//\r\n//    Vector [1x4] = Vector [1x4] * Matrix [4x4]\r\n//\r\n// Applying multiple transforms to a vector involves concatenating on the outside, or right of the previous transform:\r\n//\r\n//    ProjectedPosition = ModelPosition * ModelToWorld * WorldToView * ViewToProj\r\n//\r\n// This is *not* how this API works because it is needlessly contrary to Math textbooks.  It's not \"wrong\", per se,\r\n// but it's a paradigm I'd like to see changed.  A vector is four floats.  A matrix is four consecutive vectors.  Whether\r\n// you think of them as row or column vectors of a matrix is just a matter of perspective.  In this library, you will see:\r\n//\r\n//    Vector [4x1] = Matrix4 [4x4] * Vector [4x1]\r\n//\r\n// and\r\n//\r\n//    ProjectedPosition = ViewToProj * WorldToView * ModelToWorld * ModelPosition\r\n//\r\n// One very happy result of this is that you can stop transposing every matrix you set in a shader constant buffer.  They\r\n// were always in the right format, you were just multiplying them backwards.  In the shader you should have been calling\r\n// mul( matrix, vector ) rather than mul( vector, matrix ).  Then you wouldn't have needed to transpose the matrix.\r\n//\r\n// It's possible to work in a transposed space:  (B*A*x)ᵀ = xᵀ*Aᵀ*Bᵀ   but why would you want to?\r\n//\r\n// Oh, and we use right-handed coordinate systems because that's what you learned in your Linear Algebra, Calculus, and\r\n// Physics classes.\r\n//\r\n// Peace,\r\n//   James\r\n\r\n\r\n#pragma once\r\n\r\n#include \"Math/Scalar.h\"\r\n#include \"Math/Vector.h\"\r\n#include \"Math/Quaternion.h\"\r\n#include \"Math/Matrix3.h\"\r\n#include \"Math/Transform.h\"\r\n#include \"Math/Matrix4.h\"\r\n#include \"Math/Functions.inl\"\r\n"
  },
  {
    "path": "MiniEngine/Core/d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#ifndef __D3DX12_H__\r\n#define __D3DX12_H__\r\n\r\n#include \"d3d12.h\"\r\n#include \"ART\\Wddm22Defs.h\"\r\n\r\n#if defined( __cplusplus )\r\n\r\nstruct CD3DX12_DEFAULT {};\r\nextern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT;\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{\r\n    return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width &&\r\n        l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RECT : public D3D12_RECT\r\n{\r\n    CD3DX12_RECT()\r\n    {}\r\n    explicit CD3DX12_RECT( const D3D12_RECT& o ) :\r\n        D3D12_RECT( o )\r\n    {}\r\n    explicit CD3DX12_RECT(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        right = Right;\r\n        bottom = Bottom;\r\n    }\r\n    ~CD3DX12_RECT() {}\r\n    operator const D3D12_RECT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BOX : public D3D12_BOX\r\n{\r\n    CD3DX12_BOX()\r\n    {}\r\n    explicit CD3DX12_BOX( const D3D12_BOX& o ) :\r\n        D3D12_BOX( o )\r\n    {}\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Right )\r\n    {\r\n        left = Left;\r\n        top = 0;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = 1;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Front,\r\n        LONG Right,\r\n        LONG Bottom,\r\n        LONG Back )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = Front;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = Back;\r\n    }\r\n    ~CD3DX12_BOX() {}\r\n    operator const D3D12_BOX&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{\r\n    return l.left == r.left && l.top == r.top && l.front == r.front &&\r\n        l.right == r.right && l.bottom == r.bottom && l.back == r.back;\r\n}\r\ninline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC\r\n{\r\n    CD3DX12_BLEND_DESC()\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) :\r\n        D3D12_BLEND_DESC( o )\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        AlphaToCoverageEnable = FALSE;\r\n        IndependentBlendEnable = FALSE;\r\n        const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =\r\n        {\r\n            FALSE,FALSE,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_LOGIC_OP_NOOP,\r\n            D3D12_COLOR_WRITE_ENABLE_ALL,\r\n        };\r\n        for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)\r\n            RenderTarget[ i ] = defaultRenderTargetBlendDesc;\r\n    }\r\n    ~CD3DX12_BLEND_DESC() {}\r\n    operator const D3D12_BLEND_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC\r\n{\r\n    CD3DX12_RASTERIZER_DESC()\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) :\r\n        D3D12_RASTERIZER_DESC( o )\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        FillMode = D3D12_FILL_MODE_SOLID;\r\n        CullMode = D3D12_CULL_MODE_BACK;\r\n        FrontCounterClockwise = FALSE;\r\n        DepthBias = D3D12_DEFAULT_DEPTH_BIAS;\r\n        DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;\r\n        SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;\r\n        DepthClipEnable = TRUE;\r\n        MultisampleEnable = FALSE;\r\n        AntialiasedLineEnable = FALSE;\r\n        ForcedSampleCount = 0;\r\n        ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;\r\n    }\r\n    explicit CD3DX12_RASTERIZER_DESC(\r\n        D3D12_FILL_MODE fillMode,\r\n        D3D12_CULL_MODE cullMode,\r\n        BOOL frontCounterClockwise,\r\n        INT depthBias,\r\n        FLOAT depthBiasClamp,\r\n        FLOAT slopeScaledDepthBias,\r\n        BOOL depthClipEnable,\r\n        BOOL multisampleEnable,\r\n        BOOL antialiasedLineEnable, \r\n        UINT forcedSampleCount, \r\n        D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster)\r\n    {\r\n        FillMode = fillMode;\r\n        CullMode = cullMode;\r\n        FrontCounterClockwise = frontCounterClockwise;\r\n        DepthBias = depthBias;\r\n        DepthBiasClamp = depthBiasClamp;\r\n        SlopeScaledDepthBias = slopeScaledDepthBias;\r\n        DepthClipEnable = depthClipEnable;\r\n        MultisampleEnable = multisampleEnable;\r\n        AntialiasedLineEnable = antialiasedLineEnable;\r\n        ForcedSampleCount = forcedSampleCount;\r\n        ConservativeRaster = conservativeRaster;\r\n    }\r\n    ~CD3DX12_RASTERIZER_DESC() {}\r\n    operator const D3D12_RASTERIZER_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO\r\n{\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) :\r\n        D3D12_RESOURCE_ALLOCATION_INFO( o )\r\n    {}\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO(\r\n        UINT64 size,\r\n        UINT64 alignment )\r\n    {\r\n        SizeInBytes = size;\r\n        Alignment = alignment;\r\n    }\r\n    operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES\r\n{\r\n    CD3DX12_HEAP_PROPERTIES()\r\n    {}\r\n    explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) :\r\n        D3D12_HEAP_PROPERTIES(o)\r\n    {}\r\n    CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference,\r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = D3D12_HEAP_TYPE_CUSTOM;\r\n        CPUPageProperty = cpuPageProperty;\r\n        MemoryPoolPreference = memoryPoolPreference;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    explicit CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_HEAP_TYPE type, \r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = type;\r\n        CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n        MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    operator const D3D12_HEAP_PROPERTIES&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    {\r\n        return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&\r\n            (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));\r\n    }\r\n};\r\ninline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{\r\n    return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && \r\n        l.MemoryPoolPreference == r.MemoryPoolPreference &&\r\n        l.CreationNodeMask == r.CreationNodeMask &&\r\n        l.VisibleNodeMask == r.VisibleNodeMask;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC\r\n{\r\n    CD3DX12_HEAP_DESC()\r\n    {}\r\n    explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) :\r\n        D3D12_HEAP_DESC(o)\r\n    {}\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_PROPERTIES properties, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = properties;\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_TYPE type, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_PROPERTIES properties, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = properties;\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_TYPE type, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    operator const D3D12_HEAP_DESC&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }\r\n};\r\ninline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{\r\n    return l.SizeInBytes == r.SizeInBytes &&\r\n        l.Properties == r.Properties && \r\n        l.Alignment == r.Alignment &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE\r\n{\r\n    CD3DX12_CLEAR_VALUE()\r\n    {}\r\n    explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) :\r\n        D3D12_CLEAR_VALUE(o)\r\n    {}\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        const FLOAT color[4] )\r\n    {\r\n        Format = format;\r\n        memcpy( Color, color, sizeof( Color ) );\r\n    }\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        FLOAT depth,\r\n        UINT8 stencil )\r\n    {\r\n        Format = format;\r\n        /* Use memcpy to preserve NAN values */\r\n        memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );\r\n        DepthStencil.Stencil = stencil;\r\n    }\r\n    operator const D3D12_CLEAR_VALUE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE : public D3D12_RANGE\r\n{\r\n    CD3DX12_RANGE()\r\n    {}\r\n    explicit CD3DX12_RANGE(const D3D12_RANGE &o) :\r\n        D3D12_RANGE(o)\r\n    {}\r\n    CD3DX12_RANGE( \r\n        SIZE_T begin, \r\n        SIZE_T end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE\r\n{\r\n    CD3DX12_SHADER_BYTECODE()\r\n    {}\r\n    explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) :\r\n        D3D12_SHADER_BYTECODE(o)\r\n    {}\r\n    CD3DX12_SHADER_BYTECODE(\r\n        ID3DBlob* pShaderBlob )\r\n    {\r\n        pShaderBytecode = pShaderBlob->GetBufferPointer();\r\n        BytecodeLength = pShaderBlob->GetBufferSize();\r\n    }\r\n    CD3DX12_SHADER_BYTECODE(\r\n        void* _pShaderBytecode,\r\n        SIZE_T bytecodeLength )\r\n    {\r\n        pShaderBytecode = _pShaderBytecode;\r\n        BytecodeLength = bytecodeLength;\r\n    }\r\n    operator const D3D12_SHADER_BYTECODE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE\r\n{\r\n    CD3DX12_TILED_RESOURCE_COORDINATE()\r\n    {}\r\n    explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) :\r\n        D3D12_TILED_RESOURCE_COORDINATE(o)\r\n    {}\r\n    CD3DX12_TILED_RESOURCE_COORDINATE( \r\n        UINT x, \r\n        UINT y, \r\n        UINT z, \r\n        UINT subresource ) \r\n    {\r\n        X = x;\r\n        Y = y;\r\n        Z = z;\r\n        Subresource = subresource;\r\n    }\r\n    operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE\r\n{\r\n    CD3DX12_TILE_REGION_SIZE()\r\n    {}\r\n    explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) :\r\n        D3D12_TILE_REGION_SIZE(o)\r\n    {}\r\n    CD3DX12_TILE_REGION_SIZE( \r\n        UINT numTiles, \r\n        BOOL useBox, \r\n        UINT width, \r\n        UINT16 height, \r\n        UINT16 depth ) \r\n    {\r\n        NumTiles = numTiles;\r\n        UseBox = useBox;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n    }\r\n    operator const D3D12_TILE_REGION_SIZE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING\r\n{\r\n    CD3DX12_SUBRESOURCE_TILING()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) :\r\n        D3D12_SUBRESOURCE_TILING(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_TILING( \r\n        UINT widthInTiles, \r\n        UINT16 heightInTiles, \r\n        UINT16 depthInTiles, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        WidthInTiles = widthInTiles;\r\n        HeightInTiles = heightInTiles;\r\n        DepthInTiles = depthInTiles;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE\r\n{\r\n    CD3DX12_TILE_SHAPE()\r\n    {}\r\n    explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) :\r\n        D3D12_TILE_SHAPE(o)\r\n    {}\r\n    CD3DX12_TILE_SHAPE( \r\n        UINT widthInTexels, \r\n        UINT heightInTexels, \r\n        UINT depthInTexels ) \r\n    {\r\n        WidthInTexels = widthInTexels;\r\n        HeightInTexels = heightInTexels;\r\n        DepthInTexels = depthInTexels;\r\n    }\r\n    operator const D3D12_TILE_SHAPE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) :\r\n        D3D12_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_RESOURCE_BARRIER Transition(\r\n        _In_ ID3D12Resource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER Aliasing(\r\n        _In_ ID3D12Resource* pResourceBefore,\r\n        _In_ ID3D12Resource* pResourceAfter)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER UAV(\r\n        _In_ ID3D12Resource* pResource)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3D12_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO\r\n{\r\n    CD3DX12_PACKED_MIP_INFO()\r\n    {}\r\n    explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) :\r\n        D3D12_PACKED_MIP_INFO(o)\r\n    {}\r\n    CD3DX12_PACKED_MIP_INFO( \r\n        UINT8 numStandardMips, \r\n        UINT8 numPackedMips, \r\n        UINT numTilesForPackedMips, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        NumStandardMips = numStandardMips;\r\n        NumPackedMips = numPackedMips;\r\n        NumTilesForPackedMips = numTilesForPackedMips;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_PACKED_MIP_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT\r\n{\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) :\r\n        D3D12_SUBRESOURCE_FOOTPRINT(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        DXGI_FORMAT format, \r\n        UINT width, \r\n        UINT height, \r\n        UINT depth, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = format;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n        RowPitch = rowPitch;\r\n    }\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        const D3D12_RESOURCE_DESC& resDesc, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = resDesc.Format;\r\n        Width = UINT( resDesc.Width );\r\n        Height = resDesc.Height;\r\n        Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);\r\n        RowPitch = rowPitch;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION\r\n{ \r\n    CD3DX12_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) :\r\n        D3D12_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n}; \r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) :\r\n        D3D12_DESCRIPTOR_RANGE(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS\r\n{\r\n    CD3DX12_ROOT_CONSTANTS() {}\r\n    explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) :\r\n        D3D12_ROOT_CONSTANTS(o)\r\n    {}\r\n    CD3DX12_ROOT_CONSTANTS(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_CONSTANTS &rootConstants,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        rootConstants.Num32BitValues = num32BitValues;\r\n        rootConstants.ShaderRegister = shaderRegister;\r\n        rootConstants.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) :\r\n        D3D12_ROOT_DESCRIPTOR(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER\r\n{\r\n    CD3DX12_ROOT_PARAMETER() {}\r\n    explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) :\r\n        D3D12_ROOT_PARAMETER(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC\r\n{\r\n    CD3DX12_STATIC_SAMPLER_DESC() {}\r\n    explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) :\r\n        D3D12_STATIC_SAMPLER_DESC(o)\r\n    {}\r\n    CD3DX12_STATIC_SAMPLER_DESC(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc,\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        samplerDesc.ShaderRegister = shaderRegister;\r\n        samplerDesc.Filter = filter;\r\n        samplerDesc.AddressU = addressU;\r\n        samplerDesc.AddressV = addressV;\r\n        samplerDesc.AddressW = addressW;\r\n        samplerDesc.MipLODBias = mipLODBias;\r\n        samplerDesc.MaxAnisotropy = maxAnisotropy;\r\n        samplerDesc.ComparisonFunc = comparisonFunc;\r\n        samplerDesc.BorderColor = borderColor;\r\n        samplerDesc.MinLOD = minLOD;\r\n        samplerDesc.MaxLOD = maxLOD;\r\n        samplerDesc.ShaderVisibility = shaderVisibility;\r\n        samplerDesc.RegisterSpace = registerSpace;\r\n    }\r\n    inline void Init(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            *this,\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    CD3DX12_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.NumParameters = numParameters;\r\n        desc.pParameters = _pParameters;\r\n        desc.NumStaticSamplers = numStaticSamplers;\r\n        desc.pStaticSamplers = _pStaticSamplers;\r\n        desc.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE1 : public D3D12_DESCRIPTOR_RANGE1\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE1() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE1(const D3D12_DESCRIPTOR_RANGE1 &o) :\r\n        D3D12_DESCRIPTOR_RANGE1(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE1(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE1 &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.Flags = flags;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE1 : public D3D12_ROOT_DESCRIPTOR_TABLE1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE1(const D3D12_ROOT_DESCRIPTOR_TABLE1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE1 &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR1 : public D3D12_ROOT_DESCRIPTOR1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR1(const D3D12_ROOT_DESCRIPTOR1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR1(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR1 &table, \r\n        UINT shaderRegister, \r\n        UINT registerSpace = 0, \r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n        table.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER1 : public D3D12_ROOT_PARAMETER1\r\n{\r\n    CD3DX12_ROOT_PARAMETER1() {}\r\n    explicit CD3DX12_ROOT_PARAMETER1(const D3D12_ROOT_PARAMETER1 &o) :\r\n        D3D12_ROOT_PARAMETER1(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE1::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_VERSIONED_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        Desc_1_0 = o;\r\n    }\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC1 &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        Desc_1_1 = o;\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init_1_1(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init_1_0(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_0(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        desc.Desc_1_0.NumParameters = numParameters;\r\n        desc.Desc_1_0.pParameters = _pParameters;\r\n        desc.Desc_1_0.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_0.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_0.Flags = flags;\r\n    }\r\n\r\n    inline void Init_1_1(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_1(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        desc.Desc_1_1.NumParameters = numParameters;\r\n        desc.Desc_1_1.pParameters = _pParameters;\r\n        desc.Desc_1_1.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_1.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_1.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_CPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_GPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )\r\n{ \r\n    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; \r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename T, typename U, typename V>\r\ninline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )\r\n{\r\n    MipSlice = static_cast<T>(Subresource % MipLevels);\r\n    ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);\r\n    PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ DX12_DEVICE* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format};\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo))))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) :\r\n        D3D12_RESOURCE_DESC( o )\r\n    {}\r\n    CD3DX12_RESOURCE_DESC( \r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags )\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, \r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, \r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex1D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex2D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, \r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex3D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    inline UINT16 Depth() const\r\n    { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT16 ArraySize() const\r\n    { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT8 PlaneCount(_In_ DX12_DEVICE* pDevice) const\r\n    { return D3D12GetFormatPlaneCount(pDevice, Format); }\r\n    inline UINT Subresources(_In_ DX12_DEVICE* pDevice) const\r\n    { return MipLevels * ArraySize() * PlaneCount(pDevice); }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Row-by-row memcpy\r\ninline void MemcpySubresource(\r\n    _In_ const D3D12_MEMCPY_DEST* pDest,\r\n    _In_ const D3D12_SUBRESOURCE_DATA* pSrc,\r\n    SIZE_T RowSizeInBytes,\r\n    UINT NumRows,\r\n    UINT NumSlices)\r\n{\r\n    for (UINT z = 0; z < NumSlices; ++z)\r\n    {\r\n        BYTE* pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;\r\n        const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * z;\r\n        for (UINT y = 0; y < NumRows; ++y)\r\n        {\r\n            memcpy(pDestSlice + pDest->RowPitch * y,\r\n                   pSrcSlice + pSrc->RowPitch * y,\r\n                   RowSizeInBytes);\r\n        }\r\n    }\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    UINT64 RequiredSize = 0;\r\n    \r\n    DX12_DEVICE* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ DX12_GRAPHICSCOMMANDLIST* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || \r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || \r\n        RequiredSize > (SIZE_T)-1 || \r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && \r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n    \r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources( \r\n    _In_ DX12_GRAPHICSCOMMANDLIST* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n       return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n       return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    DX12_DEVICE* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources( \r\n    _In_ DX12_GRAPHICSCOMMANDLIST* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    DX12_DEVICE* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout )\r\n{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline ID3D12CommandList * const * CommandListCast(DX12_GRAPHICSCOMMANDLIST * const * pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<ID3D12CommandList * const *>(pp);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// D3D12 exports a new method for serializing root signatures in the Windows 10 Anniversary Update.\r\n// To help enable root signature 1.1 features when they are available and not require maintaining\r\n// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when\r\n// 1.1 is not supported.\r\ninline HRESULT D3DX12SerializeVersionedRootSignature(\r\n    _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n    D3D_ROOT_SIGNATURE_VERSION MaxVersion,\r\n    _Outptr_ ID3DBlob** ppBlob,\r\n    _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob)\r\n{\r\n    switch (MaxVersion)\r\n    {\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n            switch (pRootSignatureDesc->Version)\r\n            {\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n                    return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n                {\r\n                    const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1;\r\n\r\n                    SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters;\r\n                    void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL;\r\n                    D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast<D3D12_ROOT_PARAMETER*>(pParameters);\r\n\r\n                    for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                    {\r\n                        pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType;\r\n                        pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility;\r\n\r\n                        switch (desc_1_1.pParameters[n].ParameterType)\r\n                        {\r\n                        case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:\r\n                            pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues;\r\n                            pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace;\r\n                            pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister;\r\n                            break;\r\n\r\n                        case D3D12_ROOT_PARAMETER_TYPE_CBV:\r\n                        case D3D12_ROOT_PARAMETER_TYPE_SRV:\r\n                        case D3D12_ROOT_PARAMETER_TYPE_UAV:\r\n                            pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace;\r\n                            pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister;\r\n                            break;\r\n\r\n                        case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:\r\n                            const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable;\r\n\r\n                            SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges;\r\n                            void* pDescriptorRanges = (DescriptorRangesSize > 0) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL;\r\n                            D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pDescriptorRanges);\r\n\r\n                            for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++)\r\n                            {\r\n                                pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister;\r\n                                pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors;\r\n                                pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart;\r\n                                pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType;\r\n                                pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace;\r\n                            }\r\n\r\n                            D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable;\r\n                            table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges;\r\n                            table_1_0.pDescriptorRanges = pDescriptorRanges_1_0;\r\n                        }\r\n                    }\r\n\r\n                    CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags);\r\n                    HRESULT hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n\r\n                    for (UINT n = 0; n < desc_1_0.NumParameters; n++)\r\n                    {\r\n                        if (desc_1_0.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n                        {\r\n                            HeapFree(GetProcessHeap(), 0, reinterpret_cast<void*>(const_cast<D3D12_DESCRIPTOR_RANGE*>(pParameters_1_0[n].DescriptorTable.pDescriptorRanges)));\r\n                        }\r\n                    }\r\n                    HeapFree(GetProcessHeap(), 0, pParameters);\r\n                    return hr;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n            return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);\r\n    }\r\n\r\n    return E_INVALIDARG;\r\n}\r\n\r\n#endif // defined( __cplusplus )\r\n\r\n#endif //__D3DX12_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "MiniEngine/Core/dds.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// This header defines constants and structures that are useful when parsing \r\n// DDS files.  DDS files were originally designed to use several structures\r\n// and constants that are native to DirectDraw and are defined in ddraw.h,\r\n// such as DDSURFACEDESC2 and DDSCAPS2.  This file defines similar \r\n// (compatible) constants and structures so that one can use DDS files \r\n// without needing to include ddraw.h.\r\n//\r\n// http://go.microsoft.com/fwlink/?LinkId=248926\r\n// http://go.microsoft.com/fwlink/?LinkId=248929\r\n//--------------------------------------------------------------------------------------\r\n\r\n#if defined(_MSC_VER)\r\n#pragma once\r\n#endif\r\n\r\n#include <dxgiformat.h>\r\n\r\n// VS 2010's stdint.h conflicts with intsafe.h\r\n#pragma warning(push)\r\n#pragma warning(disable : 4005)\r\n#include <stdint.h>\r\n#pragma warning(pop)\r\n\r\nnamespace DirectX\r\n{\r\n\r\n#pragma pack(push,1)\r\n\r\nconst uint32_t DDS_MAGIC = 0x20534444; // \"DDS \"\r\n\r\nstruct DDS_PIXELFORMAT\r\n{\r\n    uint32_t    size;\r\n    uint32_t    flags;\r\n    uint32_t    fourCC;\r\n    uint32_t    RGBBitCount;\r\n    uint32_t    RBitMask;\r\n    uint32_t    GBitMask;\r\n    uint32_t    BBitMask;\r\n    uint32_t    ABitMask;\r\n};\r\n\r\n#define DDS_FOURCC      0x00000004  // DDPF_FOURCC\r\n#define DDS_RGB         0x00000040  // DDPF_RGB\r\n#define DDS_RGBA        0x00000041  // DDPF_RGB | DDPF_ALPHAPIXELS\r\n#define DDS_LUMINANCE   0x00020000  // DDPF_LUMINANCE\r\n#define DDS_LUMINANCEA  0x00020001  // DDPF_LUMINANCE | DDPF_ALPHAPIXELS\r\n#define DDS_ALPHA       0x00000002  // DDPF_ALPHA\r\n#define DDS_PAL8        0x00000020  // DDPF_PALETTEINDEXED8\r\n\r\n#ifndef MAKEFOURCC\r\n    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \\\r\n                ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) |       \\\r\n                ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))\r\n#endif /* defined(MAKEFOURCC) */\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGB,  0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGB,  0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGB,  0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0,  8, 0xff, 0x00, 0x00, 0x00 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 };\r\n\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff };\r\n\r\n// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue\r\n\r\n// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)\r\nextern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 =\r\n    { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };\r\n\r\n#define DDS_HEADER_FLAGS_TEXTURE        0x00001007  // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT \r\n#define DDS_HEADER_FLAGS_MIPMAP         0x00020000  // DDSD_MIPMAPCOUNT\r\n#define DDS_HEADER_FLAGS_VOLUME         0x00800000  // DDSD_DEPTH\r\n#define DDS_HEADER_FLAGS_PITCH          0x00000008  // DDSD_PITCH\r\n#define DDS_HEADER_FLAGS_LINEARSIZE     0x00080000  // DDSD_LINEARSIZE\r\n\r\n#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT\r\n#define DDS_WIDTH  0x00000004 // DDSD_WIDTH\r\n\r\n#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE\r\n#define DDS_SURFACE_FLAGS_MIPMAP  0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP\r\n#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX\r\n\r\n#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX\r\n#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX\r\n#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY\r\n#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY\r\n#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ\r\n#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ\r\n\r\n#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\\\r\n                               DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\\\r\n                               DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )\r\n\r\n#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP\r\n\r\n#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME\r\n\r\n// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION\r\nenum DDS_RESOURCE_DIMENSION\r\n{\r\n    DDS_DIMENSION_TEXTURE1D = 2,\r\n    DDS_DIMENSION_TEXTURE2D = 3,\r\n    DDS_DIMENSION_TEXTURE3D = 4,\r\n};\r\n\r\n// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG\r\nenum DDS_RESOURCE_MISC_FLAG\r\n{\r\n   DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,\r\n};\r\n\r\nenum DDS_MISC_FLAGS2\r\n{\r\n    DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,\r\n};\r\n\r\nstruct DDS_HEADER\r\n{\r\n    uint32_t        size;\r\n    uint32_t        flags;\r\n    uint32_t        height;\r\n    uint32_t        width;\r\n    uint32_t        pitchOrLinearSize;\r\n    uint32_t        depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags\r\n    uint32_t        mipMapCount;\r\n    uint32_t        reserved1[11];\r\n    DDS_PIXELFORMAT ddspf;\r\n    uint32_t        caps;\r\n    uint32_t        caps2;\r\n    uint32_t        caps3;\r\n    uint32_t        caps4;\r\n    uint32_t        reserved2;\r\n};\r\n\r\nstruct DDS_HEADER_DXT10\r\n{\r\n    DXGI_FORMAT     dxgiFormat;\r\n    uint32_t        resourceDimension;\r\n    uint32_t        miscFlag; // see D3D11_RESOURCE_MISC_FLAG\r\n    uint32_t        arraySize;\r\n    uint32_t        miscFlags2; // see DDS_MISC_FLAGS2\r\n} ;\r\n\r\n#pragma pack(pop)\r\n\r\nstatic_assert( sizeof(DDS_HEADER) == 124, \"DDS Header size mismatch\" );\r\nstatic_assert( sizeof(DDS_HEADER_DXT10) == 20, \"DDS DX10 Extended Header size mismatch\");\r\n\r\n}; // namespace\r\n"
  },
  {
    "path": "MiniEngine/Core/pch.cpp",
    "content": "//\r\n// pch.cpp\r\n// Include the standard header and generate the precompiled header.\r\n//\r\n\r\n#include \"pch.h\"\r\n"
  },
  {
    "path": "MiniEngine/Core/pch.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  James Stanard \r\n//\r\n\r\n#pragma once\r\n\r\n#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union\r\n#pragma warning(disable:4328) // nonstandard extension used : class rvalue used as lvalue\r\n#pragma warning(disable:4324) // structure was padded due to __declspec(align())\r\n\r\n#ifndef WIN32_LEAN_AND_MEAN\r\n    #define WIN32_LEAN_AND_MEAN\r\n#endif\r\n#ifndef NOMINMAX\r\n    #define NOMINMAX\r\n#endif\r\n#include <windows.h>\r\n\r\n#include <d3d12.h>\r\n\r\n#pragma comment(lib, \"d3d12.lib\")\r\n#pragma comment(lib, \"dxgi.lib\")\r\n\r\n#define MY_IID_PPV_ARGS IID_PPV_ARGS\r\n#define D3D12_GPU_VIRTUAL_ADDRESS_NULL      ((D3D12_GPU_VIRTUAL_ADDRESS)0)\r\n#define D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN   ((D3D12_GPU_VIRTUAL_ADDRESS)-1)\r\n\r\n#include \"d3dx12.h\"\r\n\r\n#include <cstdint>\r\n#include <cstdio>\r\n#include <cstdarg>\r\n#include <vector>\r\n#include <memory>\r\n#include <string>\r\n#include <exception>\r\n\r\n#include <wrl.h>\r\n#include <ppltasks.h>\r\n\r\n#include \"Utility.h\"\r\n#include \"VectorMath.h\"\r\n#include \"EngineTuning.h\"\r\n#include \"EngineProfiling.h\"\r\n"
  },
  {
    "path": "MiniEngine/CreateNewLibrary.bat",
    "content": "@ECHO OFF\nREM This batch file generates a new MiniEngine library project for Visual Studio\nREM 2015 and 2017.  It is expected that python.exe is on your path and is version\nREM 3.0 or above.  If not, we recommend installing the latest version of Anaconda.\npython.exe Tools\\Scripts\\CreateNewProject.py LIB %1"
  },
  {
    "path": "MiniEngine/CreateNewSolution.bat",
    "content": "@ECHO OFF\nREM This batch file generates a new MiniEngine solution project for Visual Studio\nREM 2015 and 2017.  It is expected that python.exe is on your path and is version\nREM 3.0 or above.  If not, we recommend installing the latest version of Anaconda.\npython.exe Tools\\Scripts\\CreateNewProject.py APP %1"
  },
  {
    "path": "MiniEngine/License.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013-2015 Microsoft\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "MiniEngine/Model/Model.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Alex Nankervis\r\n//\r\n\r\n#include \"Model.h\"\r\n#include <string.h>\r\n#include <float.h>\r\n\r\nModel::Model()\r\n    : m_pMesh(nullptr)\r\n    , m_pMaterial(nullptr)\r\n    , m_pVertexData(nullptr)\r\n    , m_pIndexData(nullptr)\r\n    , m_pVertexDataDepth(nullptr)\r\n    , m_pIndexDataDepth(nullptr)\r\n    , m_SRVs(nullptr)\r\n{\r\n    Clear();\r\n}\r\n\r\nModel::~Model()\r\n{\r\n    Clear();\r\n}\r\n\r\nvoid Model::Clear()\r\n{\r\n    m_VertexBuffer.Destroy();\r\n    m_IndexBuffer.Destroy();\r\n    m_VertexBufferDepth.Destroy();\r\n    m_IndexBufferDepth.Destroy();\r\n\r\n    delete [] m_pMesh;\r\n    m_pMesh = nullptr;\r\n    m_Header.meshCount = 0;\r\n\r\n    delete [] m_pMaterial;\r\n    m_pMaterial = nullptr;\r\n    m_Header.materialCount = 0;\r\n\r\n    delete [] m_pVertexData;\r\n    delete [] m_pIndexData;\r\n    delete [] m_pVertexDataDepth;\r\n    delete [] m_pIndexDataDepth;\r\n\r\n    m_pVertexData = nullptr;\r\n    m_Header.vertexDataByteSize = 0;\r\n    m_pIndexData = nullptr;\r\n    m_Header.indexDataByteSize = 0;\r\n    m_pVertexDataDepth = nullptr;\r\n    m_Header.vertexDataByteSizeDepth = 0;\r\n    m_pIndexDataDepth = nullptr;\r\n\r\n    ReleaseTextures();\r\n\r\n    m_Header.boundingBox.min = Vector3(0.0f);\r\n    m_Header.boundingBox.max = Vector3(0.0f);\r\n}\r\n\r\n// assuming at least 3 floats for position\r\nvoid Model::ComputeMeshBoundingBox(unsigned int meshIndex, BoundingBox &bbox) const\r\n{\r\n    const Mesh *mesh = m_pMesh + meshIndex;\r\n\r\n    if (mesh->vertexCount > 0)\r\n    {\r\n        unsigned int vertexStride = mesh->vertexStride;\r\n\r\n        const float *p = (float*)(m_pVertexData + mesh->vertexDataByteOffset + mesh->attrib[attrib_position].offset);\r\n        const float *pEnd = (float*)(m_pVertexData + mesh->vertexDataByteOffset + mesh->vertexCount * mesh->vertexStride + mesh->attrib[attrib_position].offset);\r\n        bbox.min = Scalar(FLT_MAX);\r\n        bbox.max = Scalar(-FLT_MAX);\r\n\r\n        while (p < pEnd)\r\n        {\r\n            Vector3 pos(*(p + 0), *(p + 1), *(p + 2));\r\n\r\n            bbox.min = Min(bbox.min, pos);\r\n            bbox.max = Max(bbox.max, pos);\r\n\r\n            (*(uint8_t**)&p) += vertexStride;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        bbox.min = Scalar(0.0f);\r\n        bbox.max = Scalar(0.0f);\r\n    }\r\n}\r\n\r\nvoid Model::ComputeGlobalBoundingBox(BoundingBox &bbox) const\r\n{\r\n    if (m_Header.meshCount > 0)\r\n    {\r\n        bbox.min = Scalar(FLT_MAX);\r\n        bbox.max = Scalar(-FLT_MAX);\r\n        for (unsigned int meshIndex = 0; meshIndex < m_Header.meshCount; meshIndex++)\r\n        {\r\n            const Mesh *mesh = m_pMesh + meshIndex;\r\n\r\n            bbox.min = Min(bbox.min, mesh->boundingBox.min);\r\n            bbox.max = Max(bbox.max, mesh->boundingBox.max);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        bbox.min = Scalar(0.0f);\r\n        bbox.max = Scalar(0.0f);\r\n    }\r\n}\r\n\r\nvoid Model::ComputeAllBoundingBoxes()\r\n{\r\n    for (unsigned int meshIndex = 0; meshIndex < m_Header.meshCount; meshIndex++)\r\n    {\r\n        Mesh *mesh = m_pMesh + meshIndex;\r\n        ComputeMeshBoundingBox(meshIndex, mesh->boundingBox);\r\n    }\r\n    ComputeGlobalBoundingBox(m_Header.boundingBox);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Model/Model.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):   Alex Nankervis\r\n//              James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\n#include \"VectorMath.h\"\r\n#include \"TextureManager.h\"\r\n#include \"GpuBuffer.h\"\r\n\r\nusing namespace Math;\r\n\r\nclass Model\r\n{\r\npublic:\r\n\r\n    Model();\r\n    ~Model();\r\n\r\n    void Clear();\r\n\r\n    enum\r\n    {\r\n        attrib_mask_0 = (1 << 0),\r\n        attrib_mask_1 = (1 << 1),\r\n        attrib_mask_2 = (1 << 2),\r\n        attrib_mask_3 = (1 << 3),\r\n        attrib_mask_4 = (1 << 4),\r\n        attrib_mask_5 = (1 << 5),\r\n        attrib_mask_6 = (1 << 6),\r\n        attrib_mask_7 = (1 << 7),\r\n        attrib_mask_8 = (1 << 8),\r\n        attrib_mask_9 = (1 << 9),\r\n        attrib_mask_10 = (1 << 10),\r\n        attrib_mask_11 = (1 << 11),\r\n        attrib_mask_12 = (1 << 12),\r\n        attrib_mask_13 = (1 << 13),\r\n        attrib_mask_14 = (1 << 14),\r\n        attrib_mask_15 = (1 << 15),\r\n\r\n        // friendly name aliases\r\n        attrib_mask_position = attrib_mask_0,\r\n        attrib_mask_texcoord0 = attrib_mask_1,\r\n        attrib_mask_normal = attrib_mask_2,\r\n        attrib_mask_tangent = attrib_mask_3,\r\n        attrib_mask_bitangent = attrib_mask_4,\r\n    };\r\n\r\n    enum\r\n    {\r\n        attrib_0 = 0,\r\n        attrib_1 = 1,\r\n        attrib_2 = 2,\r\n        attrib_3 = 3,\r\n        attrib_4 = 4,\r\n        attrib_5 = 5,\r\n        attrib_6 = 6,\r\n        attrib_7 = 7,\r\n        attrib_8 = 8,\r\n        attrib_9 = 9,\r\n        attrib_10 = 10,\r\n        attrib_11 = 11,\r\n        attrib_12 = 12,\r\n        attrib_13 = 13,\r\n        attrib_14 = 14,\r\n        attrib_15 = 15,\r\n\r\n        // friendly name aliases\r\n        attrib_position = attrib_0,\r\n        attrib_texcoord0 = attrib_1,\r\n        attrib_normal = attrib_2,\r\n        attrib_tangent = attrib_3,\r\n        attrib_bitangent = attrib_4,\r\n\r\n        maxAttribs = 16\r\n    };\r\n\r\n    enum\r\n    {\r\n        attrib_format_none = 0,\r\n        attrib_format_ubyte,\r\n        attrib_format_byte,\r\n        attrib_format_ushort,\r\n        attrib_format_short,\r\n        attrib_format_float,\r\n\r\n        attrib_formats\r\n    };\r\n\r\n    struct BoundingBox\r\n    {\r\n        Vector3 min;\r\n        Vector3 max;\r\n    };\r\n\r\n    struct Header\r\n    {\r\n        uint32_t meshCount;\r\n        uint32_t materialCount;\r\n        uint32_t vertexDataByteSize;\r\n        uint32_t indexDataByteSize;\r\n        uint32_t vertexDataByteSizeDepth;\r\n        BoundingBox boundingBox;\r\n    };\r\n    Header m_Header;\r\n\r\n\tstruct Attrib\r\n\t{\r\n\t\tuint16_t offset; // byte offset from the start of the vertex\r\n\t\tuint16_t normalized; // if true, integer formats are interpreted as [-1, 1] or [0, 1]\r\n\t\tuint16_t components; // 1-4\r\n\t\tuint16_t format;\r\n\t};\r\n\tstruct Mesh\r\n    {\r\n        BoundingBox boundingBox;\r\n\r\n        unsigned int materialIndex;\r\n\r\n        unsigned int attribsEnabled;\r\n        unsigned int attribsEnabledDepth;\r\n        unsigned int vertexStride;\r\n        unsigned int vertexStrideDepth;\r\n        Attrib attrib[maxAttribs];\r\n        Attrib attribDepth[maxAttribs];\r\n\r\n        unsigned int vertexDataByteOffset;\r\n        unsigned int vertexCount;\r\n        unsigned int indexDataByteOffset;\r\n        unsigned int indexCount;\r\n\r\n        unsigned int vertexDataByteOffsetDepth;\r\n        unsigned int vertexCountDepth;\r\n    };\r\n    Mesh *m_pMesh;\r\n\r\n\tenum EMaterialTexChannels {\r\n\t\tMaterialTexChannel_Diffuse = 0,\r\n\t\tMaterialTexChannel_Specular,\r\n\t\tMaterialTexChannel_Emissive,\r\n\t\tMaterialTexChannel_Normal,\r\n\t\tMaterialTexChannel_Lightmap,\r\n\t\tMaterialTexChannel_Reflection,\r\n\t\tMaterialTexChannel_Opacity,\r\n\t\tMaterialTexChannel_Constants, // Not a real texture, but rather a structured buffer of material constants\r\n\t\tMaterialTexChannel_Count\r\n\t};\r\n\r\n    struct Material\r\n    {\r\n        Vector3 diffuse;\r\n        Vector3 specular;\r\n        Vector3 ambient;\r\n        Vector3 emissive;\r\n        Vector3 transparent; // light passing through a transparent surface is multiplied by this filter color\r\n        float opacity;\r\n        float shininess; // specular exponent\r\n        float specularStrength; // multiplier on top of specular color\r\n\t\tbool hasMask;\r\n\r\n        enum {maxTexPath = 128};\r\n        enum {texCount = 7};\r\n        char texDiffusePath[maxTexPath];\r\n        char texSpecularPath[maxTexPath];\r\n        char texEmissivePath[maxTexPath];\r\n        char texNormalPath[maxTexPath];\r\n        char texLightmapPath[maxTexPath];\r\n        char texReflectionPath[maxTexPath];\r\n\t\tchar texOpacityPath[maxTexPath];\r\n\r\n\t\tenum { maxMaterialName = 128 };\r\n        char name[maxMaterialName];\r\n    };\r\n    Material *m_pMaterial;\r\n\r\n\t//__declspec(align(16))\r\n\tstruct RenderMaterial {\r\n\t\tXMFLOAT3 diffuse;\r\n\t\tXMFLOAT3 specular;\r\n\t\tXMFLOAT3 emissive;\r\n\t\tfloat shininess;\r\n\t\tUINT32 textureMask; // indicates if the texture is defined for diffuse, specular, normal maps\r\n\t};\r\n\r\n    unsigned char *m_pVertexData;\r\n    unsigned char *m_pIndexData;\r\n    StructuredBuffer m_VertexBuffer;\r\n    ByteAddressBuffer m_IndexBuffer;\r\n    uint32_t m_VertexStride;\r\n\r\n    // optimized for depth-only rendering\r\n    unsigned char *m_pVertexDataDepth;\r\n    unsigned char *m_pIndexDataDepth;\r\n    StructuredBuffer m_VertexBufferDepth;\r\n    ByteAddressBuffer m_IndexBufferDepth;\r\n    uint32_t m_VertexStrideDepth;\r\n\r\n\tRenderMaterial* m_pMaterialConstants;\r\n\tStructuredBuffer m_MaterialConstants;\r\n\r\n\tvirtual bool Load(const char* filename)\r\n\t{\r\n\t\treturn LoadH3D(filename);\r\n\t}\r\n\r\n\tconst BoundingBox& GetBoundingBox() const\r\n\t{\r\n\t\treturn m_Header.boundingBox;\r\n\t}\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* GetSRVs( uint32_t materialIdx ) const\r\n    {\r\n        return m_SRVs + materialIdx * MaterialTexChannel_Count;\r\n    }\r\n\r\n\tstatic constexpr uint32_t kMaterialTexChannelCount() {\r\n\t\treturn MaterialTexChannel_Count;\r\n\t}\r\n\r\nprotected:\r\n\r\n\tbool LoadH3D(const char *filename);\r\n\tbool SaveH3D(const char *filename) const;\r\n\r\n\tvoid ComputeMeshBoundingBox(unsigned int meshIndex, BoundingBox &bbox) const;\r\n\tvoid ComputeGlobalBoundingBox(BoundingBox &bbox) const;\r\n\tvoid ComputeAllBoundingBoxes();\r\n\r\n    void ReleaseTextures();\r\n    void LoadTextures();\r\n    D3D12_CPU_DESCRIPTOR_HANDLE* m_SRVs;\r\n};\r\n"
  },
  {
    "path": "MiniEngine/Model/ModelH3D.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author:  Alex Nankervis\r\n//\r\n\r\n#include \"Model.h\"\r\n#include \"Utility.h\"\r\n#include \"TextureManager.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"DescriptorHeap.h\"\r\n#include \"CommandContext.h\"\r\n#include <stdio.h>\r\n\r\nbool Model::LoadH3D(const char *filename)\r\n{\r\n    FILE *file = nullptr;\r\n    if (0 != fopen_s(&file, filename, \"rb\"))\r\n        return false;\r\n\r\n    bool ok = false;\r\n\r\n    if (1 != fread(&m_Header, sizeof(Header), 1, file)) goto h3d_load_fail;\r\n\r\n    m_pMesh = new Mesh [m_Header.meshCount];\r\n    m_pMaterial = new Material [m_Header.materialCount];\r\n\r\n\tm_pMaterialConstants = new RenderMaterial[m_Header.materialCount];\r\n\r\n    if (m_Header.meshCount > 0)\r\n        if (1 != fread(m_pMesh, sizeof(Mesh) * m_Header.meshCount, 1, file)) goto h3d_load_fail;\r\n    if (m_Header.materialCount > 0)\r\n        if (1 != fread(m_pMaterial, sizeof(Material) * m_Header.materialCount, 1, file)) goto h3d_load_fail;\r\n\r\n    m_VertexStride = m_pMesh[0].vertexStride;\r\n    m_VertexStrideDepth = m_pMesh[0].vertexStrideDepth;\r\n#if _DEBUG\r\n    for (uint32_t meshIndex = 1; meshIndex < m_Header.meshCount; ++meshIndex)\r\n    {\r\n        const Mesh& mesh = m_pMesh[meshIndex];\r\n        ASSERT(mesh.vertexStride == m_VertexStride);\r\n        ASSERT(mesh.vertexStrideDepth == m_VertexStrideDepth);\r\n    }\r\n    for (uint32_t meshIndex = 0; meshIndex < m_Header.meshCount; ++meshIndex)\r\n    {\r\n        const Mesh& mesh = m_pMesh[meshIndex];\r\n\r\n        ASSERT( mesh.attribsEnabled ==\r\n            (attrib_mask_position | attrib_mask_texcoord0 | attrib_mask_normal | attrib_mask_tangent | attrib_mask_bitangent) );\r\n        ASSERT(mesh.attrib[0].components == 3 && mesh.attrib[0].format == Model::attrib_format_float); // position\r\n        ASSERT(mesh.attrib[1].components == 2 && mesh.attrib[1].format == Model::attrib_format_float); // texcoord0\r\n        ASSERT(mesh.attrib[2].components == 3 && mesh.attrib[2].format == Model::attrib_format_float); // normal\r\n        ASSERT(mesh.attrib[3].components == 3 && mesh.attrib[3].format == Model::attrib_format_float); // tangent\r\n        ASSERT(mesh.attrib[4].components == 3 && mesh.attrib[4].format == Model::attrib_format_float); // bitangent\r\n\r\n        ASSERT( mesh.attribsEnabledDepth ==\r\n            (attrib_mask_position) );\r\n        ASSERT(mesh.attrib[0].components == 3 && mesh.attrib[0].format == Model::attrib_format_float); // position\r\n    }\r\n#endif\r\n\r\n    m_pVertexData = new unsigned char[ m_Header.vertexDataByteSize ];\r\n    m_pIndexData = new unsigned char[ m_Header.indexDataByteSize ];\r\n    m_pVertexDataDepth = new unsigned char[ m_Header.vertexDataByteSizeDepth ];\r\n    m_pIndexDataDepth = new unsigned char[ m_Header.indexDataByteSize ];\r\n\r\n    if (m_Header.vertexDataByteSize > 0)\r\n        if (1 != fread(m_pVertexData, m_Header.vertexDataByteSize, 1, file)) goto h3d_load_fail;\r\n    if (m_Header.indexDataByteSize > 0)\r\n        if (1 != fread(m_pIndexData, m_Header.indexDataByteSize, 1, file)) goto h3d_load_fail;\r\n\r\n    if (m_Header.vertexDataByteSizeDepth > 0)\r\n        if (1 != fread(m_pVertexDataDepth, m_Header.vertexDataByteSizeDepth, 1, file)) goto h3d_load_fail;\r\n    if (m_Header.indexDataByteSize > 0)\r\n        if (1 != fread(m_pIndexDataDepth, m_Header.indexDataByteSize, 1, file)) goto h3d_load_fail;\r\n\r\n    m_VertexBuffer.Create(L\"VertexBuffer\", m_Header.vertexDataByteSize / m_VertexStride, m_VertexStride, m_pVertexData);\r\n    m_IndexBuffer.Create(L\"IndexBuffer\", m_Header.indexDataByteSize / sizeof(uint16_t), sizeof(uint16_t), m_pIndexData);\r\n    delete [] m_pVertexData;\r\n    m_pVertexData = nullptr;\r\n    delete [] m_pIndexData;\r\n    m_pIndexData = nullptr;\r\n\r\n    m_VertexBufferDepth.Create(L\"VertexBufferDepth\", m_Header.vertexDataByteSizeDepth / m_VertexStrideDepth, m_VertexStrideDepth, m_pVertexDataDepth);\r\n    m_IndexBufferDepth.Create(L\"IndexBufferDepth\", m_Header.indexDataByteSize / sizeof(uint16_t), sizeof(uint16_t), m_pIndexDataDepth);\r\n    delete [] m_pVertexDataDepth;\r\n    m_pVertexDataDepth = nullptr;\r\n    delete [] m_pIndexDataDepth;\r\n    m_pIndexDataDepth = nullptr;\r\n\r\n    LoadTextures();\r\n\r\n\tm_MaterialConstants.Create(L\"MaterialConstantsBuffer\", m_Header.materialCount, sizeof(RenderMaterial), (unsigned char*) m_pMaterialConstants);\r\n\tdelete[] m_pMaterialConstants;\r\n\r\n    ok = true;\r\n\r\nh3d_load_fail:\r\n\r\n    if (EOF == fclose(file))\r\n        ok = false;\r\n\r\n    return ok;\r\n}\r\n\r\nbool Model::SaveH3D(const char *filename) const\r\n{\r\n    FILE *file = nullptr;\r\n    if (0 != fopen_s(&file, filename, \"wb\"))\r\n        return false;\r\n\r\n    bool ok = false;\r\n\r\n    if (1 != fwrite(&m_Header, sizeof(Header), 1, file)) goto h3d_save_fail;\r\n\r\n    if (m_Header.meshCount > 0)\r\n        if (1 != fwrite(m_pMesh, sizeof(Mesh) * m_Header.meshCount, 1, file)) goto h3d_save_fail;\r\n    if (m_Header.materialCount > 0)\r\n        if (1 != fwrite(m_pMaterial, sizeof(Material) * m_Header.materialCount, 1, file)) goto h3d_save_fail;\r\n\r\n    if (m_Header.vertexDataByteSize > 0)\r\n        if (1 != fwrite(m_pVertexData, m_Header.vertexDataByteSize, 1, file)) goto h3d_save_fail;\r\n    if (m_Header.indexDataByteSize > 0)\r\n        if (1 != fwrite(m_pIndexData, m_Header.indexDataByteSize, 1, file)) goto h3d_save_fail;\r\n\r\n    if (m_Header.vertexDataByteSizeDepth > 0)\r\n        if (1 != fwrite(m_pVertexDataDepth, m_Header.vertexDataByteSizeDepth, 1, file)) goto h3d_save_fail;\r\n    if (m_Header.indexDataByteSize > 0)\r\n        if (1 != fwrite(m_pIndexDataDepth, m_Header.indexDataByteSize, 1, file)) goto h3d_save_fail;\r\n\r\n    ok = true;\r\n\r\nh3d_save_fail:\r\n\r\n    if (EOF == fclose(file))\r\n        ok = false;\r\n\r\n    return ok;\r\n}\r\n\r\nvoid Model::ReleaseTextures()\r\n{\r\n    /*\r\n    if (m_Textures != nullptr)\r\n    {\r\n        for (uint32_t materialIdx = 0; materialIdx < m_Header.materialCount; ++materialIdx)\r\n        {\r\n            for (int n = 0; n < Material::texCount; n++)\r\n            {\r\n                if (m_Textures[materialIdx * Material::texCount + n])\r\n                    m_Textures[materialIdx * Material::texCount + n]->Release();\r\n                m_Textures[materialIdx * Material::texCount + n] = nullptr;\r\n            }\r\n        }\r\n        delete [] m_Textures;\r\n    }\r\n    */\r\n}\r\n\r\nvoid Model::LoadTextures(void)\r\n{\r\n    ReleaseTextures();\r\n\r\n\tconst int numTexChannels = MaterialTexChannel_Count;\r\n\r\n    m_SRVs = new D3D12_CPU_DESCRIPTOR_HANDLE[m_Header.materialCount * numTexChannels];\r\n\r\n    const ManagedTexture* MatTextures[numTexChannels] = {};\r\n\r\n    for (uint32_t materialIdx = 0; materialIdx < m_Header.materialCount; ++materialIdx)\r\n    {\r\n        const Material& material = m_pMaterial[materialIdx];\r\n\t\tRenderMaterial& renderMat = m_pMaterialConstants[materialIdx];\r\n\t\t//renderMat.diffuse = material.diffuse;\r\n\t\t//renderMat.ambient = material.ambient;\r\n\t\t//renderMat.emissive = material.emissive;\r\n\t\t//renderMat.shininess = material.shininess;\r\n\t\t//renderMat.specular = material.specular;\r\n\t\tXMStoreFloat3(&renderMat.diffuse, material.diffuse);\r\n\t\tXMStoreFloat3(&renderMat.specular, material.specular);\r\n\t\tXMStoreFloat3(&renderMat.emissive, material.emissive);\r\n\t\trenderMat.shininess = material.shininess;\r\n\t\trenderMat.textureMask = 0;\r\n\r\n\r\n        // Load diffuse\r\n\t\tTextureManager::ReportLoadErrors(true);\r\n\t\tMatTextures[MaterialTexChannel_Diffuse] = TextureManager::LoadFromFile(material.texDiffusePath, true);\r\n\t\tTextureManager::ReportLoadErrors(false);\r\n\t\t\r\n\t\tif (!MatTextures[MaterialTexChannel_Diffuse]->IsValid()) {\r\n\t\t\tMatTextures[MaterialTexChannel_Diffuse] = TextureManager::LoadFromFile(\"default\", true);\r\n\t\t}\r\n\t\telse {\r\n\t\t\trenderMat.textureMask |= 1;\r\n\t\t}\r\n\r\n        // Load specular\r\n\t\tTextureManager::ReportLoadErrors(true);\r\n\t\tMatTextures[MaterialTexChannel_Specular] = TextureManager::LoadFromFile(material.texSpecularPath, true);\r\n\t\tTextureManager::ReportLoadErrors(false);\r\n\t\t\r\n\t\tif (!MatTextures[MaterialTexChannel_Specular]->IsValid())\r\n        {\r\n            MatTextures[MaterialTexChannel_Specular] = TextureManager::LoadFromFile(std::string(material.texDiffusePath) + \"_specular\", true);\r\n            if (!MatTextures[MaterialTexChannel_Specular]->IsValid())\r\n                MatTextures[MaterialTexChannel_Specular] = TextureManager::LoadFromFile(\"default_specular\", true);\r\n        }\r\n\t\telse {\r\n\t\t\trenderMat.textureMask |= 2;\r\n\t\t}\r\n\r\n        //// Load emissive\r\n        ////MatTextures[2] = TextureManager::LoadFromFile(pMaterial.texEmissivePath, true);\r\n\r\n        // Load normal\r\n\t\tTextureManager::ReportLoadErrors(true);\r\n\t\tMatTextures[MaterialTexChannel_Normal] = TextureManager::LoadFromFile(material.texNormalPath, false);\r\n\t\tprintf(\"Normal map: %s\\n\", material.texNormalPath);\r\n\t\tTextureManager::ReportLoadErrors(false);\r\n\t\tif (!MatTextures[MaterialTexChannel_Normal]->IsValid())\r\n        {\r\n            MatTextures[MaterialTexChannel_Normal] = TextureManager::LoadFromFile(std::string(material.texDiffusePath) + \"_normal\", false);\r\n            if (!MatTextures[MaterialTexChannel_Normal]->IsValid())\r\n                MatTextures[MaterialTexChannel_Normal] = TextureManager::LoadFromFile(\"default_normal\", false);\r\n        }\r\n\t\telse {\r\n\t\t\trenderMat.textureMask |= 4;\r\n\t\t}\r\n\t\tTextureManager::ReportLoadErrors(false);\r\n\r\n\t\tMatTextures[MaterialTexChannel_Opacity] = (ManagedTexture*) &TextureManager::GetWhiteTex2D(); // TextureManager::LoadFromFile(\"default\", true);\r\n\t\tif (material.hasMask) {\r\n\t\t\tprintf(\"Alpha mask: %s\\n\", material.texOpacityPath);\r\n\t\t\tTextureManager::ReportLoadErrors(true);\r\n\t\t\tauto manTex = TextureManager::LoadFromFile(material.texOpacityPath, false);\r\n\t\t\tTextureManager::ReportLoadErrors(false);\r\n\r\n\t\t\tif (manTex->IsValid()) {\r\n\t\t\t\tMatTextures[MaterialTexChannel_Opacity] = manTex;\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Load lightmap\r\n        //MatTextures[4] = TextureManager::LoadFromFile(pMaterial.texLightmapPath, true);\r\n\r\n        // Load reflection\r\n        //MatTextures[5] = TextureManager::LoadFromFile(pMaterial.texReflectionPath, true);\r\n\r\n\t\tconst int matBaseOffset = materialIdx * numTexChannels;\r\n\t\tm_SRVs[matBaseOffset + MaterialTexChannel_Diffuse] = MatTextures[MaterialTexChannel_Diffuse]->GetSRV();\r\n        m_SRVs[matBaseOffset + MaterialTexChannel_Specular] = MatTextures[MaterialTexChannel_Specular]->GetSRV();\r\n        m_SRVs[matBaseOffset + MaterialTexChannel_Emissive] = MatTextures[0]->GetSRV(); // yet unsupported\r\n        m_SRVs[matBaseOffset + MaterialTexChannel_Normal] = MatTextures[MaterialTexChannel_Normal]->GetSRV();\r\n\t\tm_SRVs[matBaseOffset + MaterialTexChannel_Lightmap] = MatTextures[0]->GetSRV();\r\n        m_SRVs[matBaseOffset + MaterialTexChannel_Reflection] = MatTextures[0]->GetSRV();\r\n\t\tm_SRVs[matBaseOffset + MaterialTexChannel_Opacity] = MatTextures[MaterialTexChannel_Opacity]->GetSRV();\r\n\t\t//m_SRVs[matBaseOffset + MaterialTexChannel_Constants] = m_MaterialConstants.GetSRV();\r\n\r\n\t}\r\n}\r\n"
  },
  {
    "path": "MiniEngine/Model/Model_VS17.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Profile|x64\">\r\n      <Configuration>Profile</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{5D3AEEFB-8789-48E5-9BD9-09C667052D09}</ProjectGuid>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <ProjectName>Model</ProjectName>\r\n    <RootNamespace>Model</RootNamespace>\r\n    <DefaultLanguage>en-US</DefaultLanguage>\r\n    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>\r\n    <ApplicationEnvironment>title</ApplicationEnvironment>\r\n    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Label=\"Configuration\">\r\n    <ConfigurationType>StaticLibrary</ConfigurationType>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\" />\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\" Label=\"PropertySheets\">\r\n    <Import Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Profile.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\r\n    <Import Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Release.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\r\n    <Import Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Debug.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup />\r\n  <ItemDefinitionGroup>\r\n    <ClCompile>\r\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeaderFile />\r\n      <RuntimeTypeInfo>true</RuntimeTypeInfo>\r\n    </ClCompile>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Platform)'=='X64'\">\r\n    <Link>\r\n      <AdditionalDependencies>d3d11.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <SubSystem>Windows</SubSystem>\r\n      <DataExecutionPrevention>true</DataExecutionPrevention>\r\n      <TargetMachine>MachineX64</TargetMachine>\r\n    </Link>\r\n    <Manifest>\r\n      <EnableDPIAwareness>true</EnableDPIAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"Model.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"Model.cpp\" />\r\n    <ClCompile Include=\"ModelH3D.cpp\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\" />\r\n</Project>\r\n"
  },
  {
    "path": "MiniEngine/Model/Model_VS17.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <ClCompile Include=\"Model.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ModelH3D.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{3e74f37f-1e1e-47ed-9c44-213389384278}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"Model.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n</Project>\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/CompileSM6Test.bat",
    "content": "dxc.exe /D_WAVE_OP /Zi /E\"main\" /Vn\"g_pModelViewerPS_SM6\" /Tps_6_0 /Fh\"ModelViewerPS_SM6.h\" /nologo Shaders/ModelViewerPS.hlsl\n\ncopy ModelViewerPS_SM6.h ..\\Build_VS14\\x64\\Debug\\Output\\ModelViewer\\CompiledShaders\ncopy ModelViewerPS_SM6.h ..\\Build_VS14\\x64\\Profile\\Output\\ModelViewer\\CompiledShaders\ncopy ModelViewerPS_SM6.h ..\\Build_VS14\\x64\\Release\\Output\\ModelViewer\\CompiledShaders\n\ndxc.exe /Zi /E\"main\" /Vn\"g_pModelViewerVS_SM6\" /Tvs_6_0 /Fh\"ModelViewerVS_SM6.h\" /nologo Shaders/ModelViewerVS.hlsl\n\ncopy ModelViewerVS_SM6.h ..\\Build_VS14\\x64\\Debug\\Output\\ModelViewer\\CompiledShaders\ncopy ModelViewerVS_SM6.h ..\\Build_VS14\\x64\\Profile\\Output\\ModelViewer\\CompiledShaders\ncopy ModelViewerVS_SM6.h ..\\Build_VS14\\x64\\Release\\Output\\ModelViewer\\CompiledShaders\n\ndxc.exe /Zi /E\"main\" /Vn\"g_pDepthViewerVS_SM6\" /Tvs_6_0 /Fh\"DepthViewerVS_SM6.h\" /nologo Shaders/DepthViewerVS.hlsl\n\ncopy DepthViewerVS_SM6.h ..\\Build_VS14\\x64\\Debug\\Output\\ModelViewer\\CompiledShaders\ncopy DepthViewerVS_SM6.h ..\\Build_VS14\\x64\\Profile\\Output\\ModelViewer\\CompiledShaders\ncopy DepthViewerVS_SM6.h ..\\Build_VS14\\x64\\Release\\Output\\ModelViewer\\CompiledShaders\n"
  },
  {
    "path": "MiniEngine/ModelViewer/ForwardPlusLighting.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Alex Nankervis\r\n//             James Stanard\r\n//\r\n\r\n#include \"ForwardPlusLighting.h\"\r\n#include \"PipelineState.h\"\r\n#include \"RootSignature.h\"\r\n#include \"CommandContext.h\"\r\n#include \"Camera.h\"\r\n#include \"BufferManager.h\"\r\n\r\n#include \"CompiledShaders/FillLightGridCS_8.h\"\r\n#include \"CompiledShaders/FillLightGridCS_16.h\"\r\n#include \"CompiledShaders/FillLightGridCS_24.h\"\r\n#include \"CompiledShaders/FillLightGridCS_32.h\"\r\n\r\n#include <algorithm>\r\n\r\nusing namespace Math;\r\nusing namespace Graphics;\r\n\r\n// must keep in sync with HLSL\r\nstruct LightData\r\n{\r\n    float pos[3];\r\n    float radiusSq;\r\n    float color[3];\r\n\r\n    uint32_t type;\r\n    float coneDir[3];\r\n    float coneAngles[2];\r\n\r\n    float shadowTextureMatrix[16];\r\n};\r\n\r\nenum { kMinLightGridDim = 8 };\r\n\r\nnamespace Lighting\r\n{\r\n    IntVar LightGridDim(\"Application/Forward+/Light Grid Dim\", 16, kMinLightGridDim, 32, 8 );\r\n\r\n    RootSignature m_FillLightRootSig;\r\n    ComputePSO m_FillLightGridCS_8;\r\n    ComputePSO m_FillLightGridCS_16;\r\n    ComputePSO m_FillLightGridCS_24;\r\n    ComputePSO m_FillLightGridCS_32;\r\n\r\n    LightData m_LightData[MaxLights];\r\n    StructuredBuffer m_LightBuffer;\r\n    ByteAddressBuffer m_LightGrid;\r\n\r\n    ByteAddressBuffer m_LightGridBitMask;\r\n    uint32_t m_FirstConeLight;\r\n    uint32_t m_FirstConeShadowedLight;\r\n\r\n    enum {shadowDim = 512};\r\n    ColorBuffer m_LightShadowArray;\r\n    ShadowBuffer m_LightShadowTempBuffer;\r\n    Matrix4 m_LightShadowMatrix[MaxLights];\r\n\r\n    void InitializeResources(void);\r\n    void CreateRandomLights(const Vector3 minBound, const Vector3 maxBound);\r\n    void FillLightGrid(GraphicsContext& gfxContext, const Camera& camera);\r\n    void Shutdown(void);\r\n}\r\n\r\nvoid Lighting::InitializeResources( void )\r\n{\r\n    m_FillLightRootSig.Reset(3, 0);\r\n    m_FillLightRootSig[0].InitAsConstantBuffer(0);\r\n    m_FillLightRootSig[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 2);\r\n    m_FillLightRootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 2);\r\n    m_FillLightRootSig.Finalize(L\"FillLightRS\");\r\n\r\n    m_FillLightGridCS_8.SetRootSignature(m_FillLightRootSig);\r\n    m_FillLightGridCS_8.SetComputeShader(g_pFillLightGridCS_8, sizeof(g_pFillLightGridCS_8));\r\n    m_FillLightGridCS_8.Finalize();\r\n\r\n    m_FillLightGridCS_16.SetRootSignature(m_FillLightRootSig);\r\n    m_FillLightGridCS_16.SetComputeShader(g_pFillLightGridCS_16, sizeof(g_pFillLightGridCS_16));\r\n    m_FillLightGridCS_16.Finalize();\r\n\r\n    m_FillLightGridCS_24.SetRootSignature(m_FillLightRootSig);\r\n    m_FillLightGridCS_24.SetComputeShader(g_pFillLightGridCS_24, sizeof(g_pFillLightGridCS_24));\r\n    m_FillLightGridCS_24.Finalize();\r\n\r\n    m_FillLightGridCS_32.SetRootSignature(m_FillLightRootSig);\r\n    m_FillLightGridCS_32.SetComputeShader(g_pFillLightGridCS_32, sizeof(g_pFillLightGridCS_32));\r\n    m_FillLightGridCS_32.Finalize();\r\n}\r\n\r\nvoid Lighting::CreateRandomLights( const Vector3 minBound, const Vector3 maxBound )\r\n{\r\n    Vector3 posScale = maxBound - minBound;\r\n    Vector3 posBias = minBound;\r\n\r\n\tfloat radScale = 0.45f * std::min<float>(posScale.GetX(), std::min<float>(posScale.GetY(), posScale.GetZ()));\r\n\r\n    // todo: replace this with MT\r\n    srand(12645);\r\n    auto randUint = []() -> uint32_t\r\n    {\r\n        return rand(); // [0, RAND_MAX]\r\n    };\r\n    auto randFloat = [randUint]() -> float\r\n    {\r\n        return randUint() * (1.0f / RAND_MAX); // convert [0, RAND_MAX] to [0, 1]\r\n    };\r\n    auto randVecUniform = [randFloat]() -> Vector3\r\n    {\r\n        return Vector3(randFloat(), randFloat(), randFloat());\r\n    };\r\n    auto randGaussian = [randFloat]() -> float\r\n    {\r\n        // polar box-muller\r\n        static bool gaussianPair = true;\r\n        static float y2;\r\n\r\n        if (gaussianPair)\r\n        {\r\n            gaussianPair = false;\r\n\r\n            float x1, x2, w;\r\n            do\r\n            {\r\n                x1 = 2 * randFloat() - 1;\r\n                x2 = 2 * randFloat() - 1;\r\n                w = x1 * x1 + x2 * x2;\r\n            } while (w >= 1);\r\n\r\n            w = sqrt(-2 * log(w) / w);\r\n            y2 = x2 * w;\r\n            return x1 * w;\r\n        }\r\n        else\r\n        {\r\n            gaussianPair = true;\r\n            return y2;\r\n        }\r\n    };\r\n    auto randVecGaussian = [randGaussian]() -> Vector3\r\n    {\r\n        return Normalize(Vector3(randGaussian(), randGaussian(), randGaussian()));\r\n    };\r\n\r\n    const float pi = 3.14159265359f;\r\n    for (uint32_t n = 0; n < MaxLights; n++)\r\n    {\r\n        Vector3 pos = randVecUniform() * posScale + posBias;\r\n        float lightRadius = randFloat() * radScale + 0.25f * radScale;\r\n\r\n        Vector3 color = randVecUniform();\r\n        float colorScale = randFloat() * .3f + .3f;\r\n        color = color * colorScale;\r\n\r\n        uint32_t type;\r\n        // force types to match 32-bit boundaries for the BIT_MASK_SORTED case\r\n        if (n < 32 * 1)\r\n            type = 0;\r\n        else if (n < 32 * 3)\r\n            type = 1;\r\n        else\r\n            type = 2;\r\n\r\n        Vector3 coneDir = randVecGaussian();\r\n        float coneInner = (randFloat() * .2f + .025f) * pi;\r\n        float coneOuter = coneInner + randFloat() * .1f * pi;\r\n\r\n        if (type == 1 || type == 2)\r\n        {\r\n            // emphasize cone lights\r\n            color = color * 5.0f;\r\n        }\r\n\r\n        Math::Camera shadowCamera;\r\n        shadowCamera.SetEyeAtUp(pos, pos + coneDir, Vector3(0, 1, 0));\r\n        shadowCamera.SetPerspectiveMatrix(coneOuter * 2, 1.0f, lightRadius * .05f, lightRadius * 1.0f);\r\n        shadowCamera.Update();\r\n        m_LightShadowMatrix[n] = shadowCamera.GetViewProjMatrix();\r\n        Matrix4 shadowTextureMatrix = Matrix4(AffineTransform(Matrix3::MakeScale( 0.5f, -0.5f, 1.0f ), Vector3(0.5f, 0.5f, 0.0f))) * m_LightShadowMatrix[n];\r\n\r\n        m_LightData[n].pos[0] = pos.GetX();\r\n        m_LightData[n].pos[1] = pos.GetY();\r\n        m_LightData[n].pos[2] = pos.GetZ();\r\n        m_LightData[n].radiusSq = lightRadius * lightRadius;\r\n        m_LightData[n].color[0] = color.GetX();\r\n        m_LightData[n].color[1] = color.GetY();\r\n        m_LightData[n].color[2] = color.GetZ();\r\n        m_LightData[n].type = type;\r\n        m_LightData[n].coneDir[0] = coneDir.GetX();\r\n        m_LightData[n].coneDir[1] = coneDir.GetY();\r\n        m_LightData[n].coneDir[2] = coneDir.GetZ();\r\n        m_LightData[n].coneAngles[0] = 1.0f / (cos(coneInner) - cos(coneOuter));\r\n        m_LightData[n].coneAngles[1] = cos(coneOuter);\r\n        std::memcpy(m_LightData[n].shadowTextureMatrix, &shadowTextureMatrix, sizeof(shadowTextureMatrix));\r\n        //*(Matrix4*)(m_LightData[n].shadowTextureMatrix) = shadowTextureMatrix;\r\n    }\r\n    // sort lights by type, needed for efficiency in the BIT_MASK approach\r\n    /*\t{\r\n    Matrix4 copyLightShadowMatrix[MaxLights];\r\n    memcpy(copyLightShadowMatrix, m_LightShadowMatrix, sizeof(Matrix4) * MaxLights);\r\n    LightData copyLightData[MaxLights];\r\n    memcpy(copyLightData, m_LightData, sizeof(LightData) * MaxLights);\r\n\r\n    uint32_t sortArray[MaxLights];\r\n    for (uint32_t n = 0; n < MaxLights; n++)\r\n    {\r\n    sortArray[n] = n;\r\n    }\r\n    std::sort(sortArray, sortArray + MaxLights,\r\n    [this](const uint32_t &a, const uint32_t &b) -> bool\r\n    {\r\n    return this->m_LightData[a].type < this->m_LightData[b].type;\r\n    });\r\n    for (uint32_t n = 0; n < MaxLights; n++)\r\n    {\r\n    m_LightShadowMatrix[n] = copyLightShadowMatrix[sortArray[n]];\r\n    m_LightData[n] = copyLightData[sortArray[n]];\r\n    }\r\n    }*/\r\n    for (uint32_t n = 0; n < MaxLights; n++)\r\n    {\r\n        if (m_LightData[n].type == 1)\r\n        {\r\n            m_FirstConeLight = n;\r\n            break;\r\n        }\r\n    }\r\n    for (uint32_t n = 0; n < MaxLights; n++)\r\n    {\r\n        if (m_LightData[n].type == 2)\r\n        {\r\n            m_FirstConeShadowedLight = n;\r\n            break;\r\n        }\r\n    }\r\n    m_LightBuffer.Create(L\"m_LightBuffer\", MaxLights, sizeof(LightData), m_LightData);\r\n\r\n    // todo: assumes max resolution of 1920x1080\r\n    uint32_t lightGridCells = Math::DivideByMultiple(1920, kMinLightGridDim) * Math::DivideByMultiple(1080, kMinLightGridDim);\r\n    uint32_t lightGridSizeBytes = lightGridCells * (4 + MaxLights * 4);\r\n    m_LightGrid.Create(L\"m_LightGrid\", lightGridSizeBytes, 1, nullptr);\r\n\r\n    uint32_t lightGridBitMaskSizeBytes = lightGridCells * 4 * 4;\r\n    m_LightGridBitMask.Create(L\"m_LightGridBitMask\", lightGridBitMaskSizeBytes, 1, nullptr);\r\n\r\n    m_LightShadowArray.CreateArray(L\"m_LightShadowArray\", shadowDim, shadowDim, MaxLights, DXGI_FORMAT_R16_UNORM);\r\n    m_LightShadowTempBuffer.Create(L\"m_LightShadowTempBuffer\", shadowDim, shadowDim);\r\n}\r\n\r\nvoid Lighting::Shutdown(void)\r\n{\r\n    m_LightBuffer.Destroy();\r\n    m_LightGrid.Destroy();\r\n    m_LightGridBitMask.Destroy();\r\n    m_LightShadowArray.Destroy();\r\n    m_LightShadowTempBuffer.Destroy();\r\n}\r\n\r\nvoid Lighting::FillLightGrid(GraphicsContext& gfxContext, const Camera& camera)\r\n{\r\n    ScopedTimer _prof(L\"FillLightGrid\", gfxContext);\r\n\r\n    ComputeContext& Context = gfxContext.GetComputeContext();\r\n\r\n    Context.SetRootSignature(m_FillLightRootSig);\r\n\r\n    switch ((int)LightGridDim)\r\n    {\r\n    case  8: Context.SetPipelineState(m_FillLightGridCS_8 ); break;\r\n    case 16: Context.SetPipelineState(m_FillLightGridCS_16); break;\r\n    case 24: Context.SetPipelineState(m_FillLightGridCS_24); break;\r\n    case 32: Context.SetPipelineState(m_FillLightGridCS_32); break;\r\n    default: ASSERT(false); break;\r\n    }\r\n\r\n    ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];\r\n\r\n    Context.TransitionResource(m_LightBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(m_LightGrid, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n    Context.TransitionResource(m_LightGridBitMask, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n\r\n    Context.SetDynamicDescriptor(1, 0, m_LightBuffer.GetSRV());\r\n    Context.SetDynamicDescriptor(1, 1, LinearDepth.GetSRV());\r\n    Context.SetDynamicDescriptor(2, 0, m_LightGrid.GetUAV());\r\n    Context.SetDynamicDescriptor(2, 1, m_LightGridBitMask.GetUAV());\r\n\r\n    // todo: assumes 1920x1080 resolution\r\n    uint32_t tileCountX = Math::DivideByMultiple(g_pSceneColorBuffer->GetWidth(), LightGridDim);\r\n    uint32_t tileCountY = Math::DivideByMultiple(g_pSceneColorBuffer->GetHeight(), LightGridDim);\r\n\r\n    float FarClipDist = camera.GetFarClip();\r\n    float NearClipDist = camera.GetNearClip();\r\n    const float RcpZMagic = NearClipDist / (FarClipDist - NearClipDist);\r\n\r\n    struct CSConstants\r\n    {\r\n        uint32_t ViewportWidth, ViewportHeight;\r\n        float InvTileDim;\r\n        float RcpZMagic;\r\n        uint32_t TileCount;\r\n        Matrix4 ViewProjMatrix;\r\n    } csConstants;\r\n    // todo: assumes 1920x1080 resolution\r\n    csConstants.ViewportWidth = g_pSceneColorBuffer->GetWidth();\r\n    csConstants.ViewportHeight = g_pSceneColorBuffer->GetHeight();\r\n    csConstants.InvTileDim = 1.0f / LightGridDim;\r\n    csConstants.RcpZMagic = RcpZMagic;\r\n    csConstants.TileCount = tileCountX;\r\n    csConstants.ViewProjMatrix = camera.GetViewProjMatrix();\r\n    Context.SetDynamicConstantBufferView(0, sizeof(CSConstants), &csConstants);\r\n\r\n    Context.Dispatch(tileCountX, tileCountY, 1);\r\n\r\n    Context.TransitionResource(m_LightGrid, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n    Context.TransitionResource(m_LightGridBitMask, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/ForwardPlusLighting.h",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Alex Nankervis\r\n//             James Stanard\r\n//\r\n\r\n#pragma once\r\n\r\n//using namespace Graphics;\r\n\r\n#include <cstdint>\r\n\r\nclass StructuredBuffer;\r\nclass ByteAddressBuffer;\r\nclass ColorBuffer;\r\nclass ShadowBuffer;\r\nclass GraphicsContext;\r\nclass IntVar;\r\nnamespace Math\r\n{\r\n    class Vector3;\r\n    class Matrix4;\r\n    class Camera;\r\n}\r\n\r\nnamespace Lighting\r\n{\r\n    extern IntVar LightGridDim;\r\n\r\n    enum { MaxLights = 128 };\r\n\r\n    //LightData m_LightData[MaxLights];\r\n    extern StructuredBuffer m_LightBuffer;\r\n    extern ByteAddressBuffer m_LightGrid;\r\n\r\n    extern ByteAddressBuffer m_LightGridBitMask;\r\n    extern std::uint32_t m_FirstConeLight;\r\n    extern std::uint32_t m_FirstConeShadowedLight;\r\n\r\n    extern ColorBuffer m_LightShadowArray;\r\n    extern ShadowBuffer m_LightShadowTempBuffer;\r\n    extern Math::Matrix4 m_LightShadowMatrix[MaxLights];\r\n\r\n    void InitializeResources(void);\r\n    void CreateRandomLights(const Math::Vector3 minBound, const Math::Vector3 maxBound);\r\n    void FillLightGrid(GraphicsContext& gfxContext, const Math::Camera& camera);\r\n    void Shutdown(void);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/ModelViewer.cpp",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  Alex Nankervis\r\n//             James Stanard\r\n//\r\n\r\n// Modified 2018, Intel Corporation\r\n// Added Checkerboard rendering paths\r\n\r\n#include \"Scene.h\"\r\n#include \"GameCore.h\"\r\n#include \"GraphicsCore.h\"\r\n#include \"CameraController.h\"\r\n#include \"BufferManager.h\"\r\n//#include \"Camera.h\"\r\n//#include \"Model.h\"\r\n#include \"GpuBuffer.h\"\r\n#include \"CommandContext.h\"\r\n#include \"SamplerManager.h\"\r\n#include \"TemporalEffects.h\"\r\n#include \"MotionBlur.h\"\r\n#include \"DepthOfField.h\"\r\n#include \"PostEffects.h\"\r\n#include \"SSAO.h\"\r\n#include \"FXAA.h\"\r\n#include \"SystemTime.h\"\r\n#include \"TextRenderer.h\"\r\n#include \"ShadowCamera.h\"\r\n#include \"ParticleEffectManager.h\"\r\n#include \"GameInput.h\"\r\n#include \"./ForwardPlusLighting.h\"\r\n\r\n#include \"ART/Animation/AnimatedValue.inl\"\r\n#include \"ART/Animation/AnimationController.h\"\r\n\r\n#include \"ART/GUI/GUICore.h\"\r\n#include \"ART/GUI/AnimationWidget.h\"\r\n#include \"ART/GUI/SequencerWidget.h\"\r\n\r\n#include \"ART/Sequencer/FrameSequencer.h\"\r\n\r\n// To enable wave intrinsics, uncomment this macro and #define DXIL in Core/GraphcisCore.cpp.\r\n// Run CompileSM6Test.bat to compile the relevant shaders with DXC.\r\n//#define _WAVE_OP\r\n\r\n#include \"CompiledShaders/DepthViewerVS.h\"\r\n#include \"CompiledShaders/DepthViewerPS.h\"\r\n#include \"CompiledShaders/ModelViewerVS.h\"\r\n#include \"CompiledShaders/ModelViewerPS.h\"\r\n#ifdef _WAVE_OP\r\n#include \"CompiledShaders/DepthViewerVS_SM6.h\"\r\n#include \"CompiledShaders/ModelViewerVS_SM6.h\"\r\n#include \"CompiledShaders/ModelViewerPS_SM6.h\"\r\n#endif\r\n#include \"CompiledShaders/WaveTileCountPS.h\"\r\n// shaders for MSAA\r\n#include \"CompiledShaders/MsaaColorResolveCS.h\"\r\n#include \"CompiledShaders/MsaaDepthResolveCS.h\"\r\n// shaders for Upsampling\r\n#include \"CompiledShaders/UpsampleColorResolveCS.h\"\r\n#include \"CompiledShaders/UpsampleDepthResolveCS.h\"\r\n// shaders for checkerboard rendering\r\n#include \"CompiledShaders/CheckerboardColorResolveCS.h\"\r\n#include \"CompiledShaders/CheckerboardDepthResolveCS.h\"\r\n#include \"CompiledShaders/ModelViewerPS_CBR.h\"\r\n#include \"CompiledShaders/ModelViewerPS_CBR_PP.h\"\r\n\r\n#include \"CompiledShaders/DepthViewerPS_CBR.h\"\r\n\r\n#include <shellapi.h>\r\n\r\nusing namespace GameCore;\r\nusing namespace Math;\r\nusing namespace Graphics;\r\nusing namespace ART;\r\n\r\nclass ModelViewer : public GameCore::IGameApp\r\n{\r\npublic:\r\n\r\n    ModelViewer(void) {}\r\n\r\n    virtual void Startup(void) override;\r\n    virtual void Cleanup(void) override;\r\n\r\n    virtual void Update(float deltaT) override;\r\n    virtual void RenderScene(void) override;\r\n\r\n    virtual bool IsDone(void) override\r\n    {\r\n        if (false == m_Loaded)\r\n            return true;\r\n\r\n        return GameInput::IsFirstPressed(GameInput::kKey_escape);\r\n    }\r\n\r\nprivate:\r\n\r\n    void RenderLightShadows(GraphicsContext& gfxContext);\r\n\r\n    enum eObjectFilter { kOpaque = 0x1, kCutout = 0x2, kTransparent = 0x4, kAll = 0xF, kNone = 0x0 };\r\n    void RenderObjects(GraphicsContext& Context, const Matrix4& ViewProjMat, eObjectFilter Filter = kAll);\r\n    void CreateParticleEffects();\r\n    void UpdatePlacedResources(GraphicsContext& context);\r\n    float RecalculateResolutionScale();\r\n    void SetFrameBuffers( GraphicsContext& context, int index, int alt_index, bool CbrWasEnabled, bool MsaaWasEnabled, int PrevMsaaMode );\r\n        \r\n    //Camera m_Camera;\r\n    std::auto_ptr<CameraController> m_CameraController;\r\n    Matrix4 m_ViewProjMatrix;\r\n    D3D12_VIEWPORT m_MainViewport;\r\n    D3D12_RECT m_MainScissor;\r\n\r\n    D3D12_VIEWPORT m_DownSizedViewport;\r\n    D3D12_RECT m_DownSizedScissor;\r\n\r\n    RootSignature m_RootSig;\r\n    GraphicsPSO m_DepthPSO;\r\n    GraphicsPSO m_DepthMsaaPSO;\r\n    GraphicsPSO m_CutoutDepthPSO;\r\n    GraphicsPSO m_CutoutDepthMsaaPSO;\r\n    GraphicsPSO m_ModelPSO;\r\n    GraphicsPSO m_ModelMsaaPSO;\r\n#ifdef _WAVE_OP\r\n    GraphicsPSO m_DepthWaveOpsPSO;\r\n    GraphicsPSO m_ModelWaveOpsPSO;\r\n#endif\r\n    GraphicsPSO m_CutoutModelPSO;\r\n    GraphicsPSO m_CutoutModelMsaaPSO;\r\n    GraphicsPSO m_ShadowPSO;\r\n    GraphicsPSO m_CutoutShadowPSO;\r\n    GraphicsPSO m_WaveTileCountPSO;\r\n\r\n    RootSignature m_MsaaResolveRootSig;\r\n    ComputePSO m_MsaaColorResolvePSO;\r\n    ComputePSO m_MsaaDepthResolvePSO;\r\n\r\n    RootSignature m_UpsampleResolveRootSig;\r\n    ComputePSO m_UpsampleColorResolvePSO;\r\n    ComputePSO m_UpsampleDepthResolvePSO;\r\n\r\n    RootSignature m_CheckerboardResolveRootSig;\r\n    ComputePSO m_CheckerboardColorResolvePSO;\r\n    ComputePSO m_CheckerboardDepthResolvePSO;\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_DefaultSampler;\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_ShadowSampler;\r\n\r\n    D3D12_CPU_DESCRIPTOR_HANDLE m_ExtraTextures[6];\r\n    std::vector<bool> m_pMaterialIsCutout;\r\n\r\n    Scene m_Scene;\r\n\r\n    Vector3 m_SunDirection;\r\n    ShadowCamera m_SunShadow;\r\n\r\n    SceneAnimation_ptr\t\tm_SceneAnimation;\r\n    AnimationController_ptr\tm_AnimationController;\r\n    FrameSequencer\t\t\tm_Sequencer;\r\n\r\n    XMFLOAT2 m_DownSizedFactor;\r\n    int m_FrameOffset;\r\n    bool m_Loaded;\r\n};\r\n\r\nCREATE_APPLICATION(ModelViewer)\r\n\r\nExpVar m_SunLightIntensity(\"Application/Lighting/Sun Light Intensity\", 4.0f, 0.0f, 16.0f, 0.1f);\r\nExpVar m_AmbientIntensity(\"Application/Lighting/Ambient Intensity\", 0.1f, -16.0f, 16.0f, 0.1f);\r\nNumVar m_SunOrientation(\"Application/Lighting/Sun Orientation\", -0.5f, -100.0f, 100.0f, 0.1f);\r\nNumVar m_SunInclination(\"Application/Lighting/Sun Inclination\", 0.75f, 0.0f, 1.0f, 0.01f);\r\nNumVar ShadowDimX(\"Application/Lighting/Shadow Dim X\", 5000, 10, 15000, 50);\r\nNumVar ShadowDimY(\"Application/Lighting/Shadow Dim Y\", 5000, 10, 15000, 50);\r\nNumVar ShadowDimZ(\"Application/Lighting/Shadow Dim Z\", 3000, 10, 10000, 50);\r\n\r\nBoolVar ShowWaveTileCounts(\"Application/Forward+/Show Wave Tile Counts\", false);\r\n\r\n// MSAA options\r\nBoolVar MsaaEnabled(\"Application/MSAA/MSAA Enable\", false);\r\nconst char* MsaaModeLabels[] = { \"2x\", \"4x\", \"8x\" };\r\nEnumVar MsaaMode(\"Application/MSAA/MSAA Mode\", 2, _countof(MsaaModeLabels), MsaaModeLabels);\r\nconst char* MsaaResolverLabels[] = { \"Auto\", \"Custom\" };\r\nEnumVar MsaaResolver(\"Application/MSAA/MSAA Resolver\", 1, _countof(MsaaResolverLabels), MsaaResolverLabels);\r\n\r\n// Checkerboard rendering options (CBR)\r\nBoolVar CbrEnabled(\"Checkerboard/Enable\", true);\r\nBoolVar CbrCheckShadingOcclusion(\"Checkerboard/Check Shading Occlusion\", true);\r\nBoolVar CbrRenderMotionVectors(\"Checkerboard/Show Derived Motion\", false);\r\nBoolVar CbrRenderMissingPixels(\"Checkerboard/Show Missing Pixels\", false);\r\nBoolVar CbrRenderObstructedPixels(\"Checkerboard/Show Occluded Pixels\", false);\r\nBoolVar CbrRenderPixelMotion(\"Checkerboard/Show Pixel Motion\", false);\r\nExpVar CbrDepthTolerance(\"Checkerboard/Depth Tolerance\", 0.1f, -4.0f, 512.0f, 0.1f);\r\n\r\nconst char* CbrRenderCheckerPatternLabels[] = { \"Both\", \"Odd\", \"Even\" };\r\nEnumVar CbrRenderCheckerPattern(\"Checkerboard/Show Checker Pattern\", 0, _countof(CbrRenderCheckerPatternLabels), CbrRenderCheckerPatternLabels);\r\n\r\n//DRR\r\nBoolVar DrrEnabled(\"DRR/Enable\", true);\r\nBoolVar DrrForceScale(\"DRR/Force Scale\", false);\r\nExpVar DrrResolutionIncrements(\"DRR/Resolution Increments\", .1f, log2(.01f), log2(1.0f));\r\nIntVar DrrDesiredFrameRate(\"DRR/Desired Frame Rate\", 60, 15, 360, 5 );\r\n\r\nExpVar DrrMinScale(\"DRR/Min Scale\", 0.7f, -3.0f, 0.0f, 0.1f);\r\nExpVar DrrFrameRateDeltaResolution(\"DRR/_Advanced/Frame Rate Delta Resolution\", .10f, log2(.001f), log2(1.0f) );\r\nExpVar DrrFrameRateLowPassFilter(\"DRR/_Advanced/Frame Rate Low Pass K\", 0.005f, log2(0.001f), log2(1.0f));\r\nExpVar DrrRateOfChange(\"DRR/_Advanced/Rate of Change\", .01f, log2(.01f), log2(1.0f) );\r\nExpVar DrrInternalScale(\"DRR/_Internal/Scale\", 1.0f);\r\nIntVar DrrInternalFrameRate(\"DRR/_Internal/Frame Rate\", 0);\r\n\r\n#ifdef _WAVE_OP\r\nBoolVar EnableWaveOps(\"Application/Forward+/Enable Wave Ops\", true);\r\n#endif\r\n\r\nbool FindScene(std::wstring *pScenePath, const wchar_t *pExecutableFolder, const wchar_t *pSceneName)\r\n{\r\n    // start at the executable folder and continue to move up folders\r\n    // until we can find a relative path matching pSceneName\r\n\r\n    wchar_t path[MAX_PATH];\r\n    wcsncpy_s(path, pExecutableFolder, _countof(path));\r\n\r\n    while (true)\r\n    {\r\n        wchar_t *pSlash = wcsrchr(path, '\\\\');\r\n        if (pSlash == NULL)\r\n            break;\r\n\r\n        *pSlash = 0;\r\n\r\n        wchar_t newPath[MAX_PATH];\r\n        _snwprintf_s(newPath, _countof(newPath), _TRUNCATE, L\"%s\\\\%s\", path, pSceneName);\r\n\r\n        DWORD result = GetFileAttributes(newPath);\r\n\r\n        if (INVALID_FILE_ATTRIBUTES != result &&\r\n            ERROR_FILE_NOT_FOUND != GetLastError())\r\n        {\r\n            *pScenePath = std::wstring(newPath);\r\n            return true;\r\n        }\r\n    }\r\n\r\n    return false;\r\n}\r\n\r\nvoid ModelViewer::Startup(void)\r\n{\r\n    SamplerDesc DefaultSamplerDesc;\r\n    DefaultSamplerDesc.MaxAnisotropy = 8;\r\n\r\n    m_RootSig.Reset(6, 2);\r\n    m_RootSig.InitStaticSampler(0, DefaultSamplerDesc, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    m_RootSig.InitStaticSampler(1, SamplerShadowDesc, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    m_RootSig[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_VERTEX);\r\n    m_RootSig[1].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    m_RootSig[2].InitAsConstantBuffer(1, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    m_RootSig[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, Model::kMaterialTexChannelCount(), D3D12_SHADER_VISIBILITY_PIXEL);\r\n    m_RootSig[4].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 64, 6, D3D12_SHADER_VISIBILITY_PIXEL);\r\n    m_RootSig[5].InitAsConstants(1, 2, D3D12_SHADER_VISIBILITY_VERTEX);\r\n    m_RootSig.Finalize(L\"ModelViewer\", D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);\r\n\r\n    m_MsaaResolveRootSig.Reset(3, 0);\r\n    m_MsaaResolveRootSig[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_ALL);\r\n    m_MsaaResolveRootSig[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1);\r\n    m_MsaaResolveRootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 1);\r\n    m_MsaaResolveRootSig.Finalize(L\"MsaaResolveRS\");\r\n\r\n    m_UpsampleResolveRootSig.Reset(3, 0);\r\n    m_UpsampleResolveRootSig[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_ALL);\r\n    m_UpsampleResolveRootSig[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1);\r\n    m_UpsampleResolveRootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 1);\r\n    m_UpsampleResolveRootSig.Finalize(L\"UpsampleResolveRS\");\r\n\r\n    m_CheckerboardResolveRootSig.Reset(3, 0);\r\n    m_CheckerboardResolveRootSig[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_ALL);\r\n    m_CheckerboardResolveRootSig[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 4);\r\n    m_CheckerboardResolveRootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 1);\r\n    m_CheckerboardResolveRootSig.Finalize(L\"CheckerboardResolveRS\");\r\n\r\n    DXGI_FORMAT ColorFormat = g_pSceneColorBuffer->GetFormat();\r\n    DXGI_FORMAT DepthFormat = g_pSceneDepthBuffer->GetFormat();\r\n    DXGI_FORMAT ShadowFormat = g_ShadowBuffer.GetFormat();\r\n\r\n    D3D12_INPUT_ELEMENT_DESC vertElem[] =\r\n    {\r\n         { \"POSITION\", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n         { \"TEXCOORD\", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n         { \"NORMAL\", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n         { \"TANGENT\", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n         { \"BITANGENT\", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }\r\n    };\r\n\r\n    // Depth-only\r\n    m_DepthPSO.SetRootSignature(m_RootSig);\r\n    m_DepthPSO.SetRasterizerState(RasterizerDefault);\r\n    m_DepthPSO.SetBlendState(BlendNoColorWrite);\r\n    m_DepthPSO.SetDepthStencilState(DepthStateReadWrite);\r\n    m_DepthPSO.SetInputLayout(_countof(vertElem), vertElem);\r\n    m_DepthPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);\r\n    m_DepthPSO.SetRenderTargetFormats(0, nullptr, DepthFormat);\r\n    m_DepthPSO.SetVertexShader(g_pDepthViewerVS, sizeof(g_pDepthViewerVS));\r\n    m_DepthPSO.Finalize();\r\n\r\n    m_DepthMsaaPSO = m_DepthPSO;\r\n    m_DepthMsaaPSO.SetRasterizerState(RasterizerDefaultMsaa);\r\n    m_DepthMsaaPSO.SetPixelShader(g_pDepthViewerPS_CBR, sizeof(g_pDepthViewerPS_CBR));\r\n    m_DepthMsaaPSO.Finalize();\r\n\r\n    // Depth-only shading but with alpha testing\r\n    m_CutoutDepthPSO = m_DepthPSO;\r\n    m_CutoutDepthPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS));\r\n    m_CutoutDepthPSO.SetRasterizerState(RasterizerTwoSided);\r\n    m_CutoutDepthPSO.Finalize();\r\n\r\n    m_CutoutDepthMsaaPSO = m_CutoutDepthPSO;\r\n    m_CutoutDepthMsaaPSO.SetRasterizerState(RasterizerTwoSidedMsaa);\r\n    m_CutoutDepthMsaaPSO.SetPixelShader(g_pDepthViewerPS_CBR, sizeof(g_pDepthViewerPS_CBR));\r\n    m_CutoutDepthMsaaPSO.Finalize();\r\n\r\n    // Depth-only but with a depth bias and/or render only backfaces\r\n    m_ShadowPSO = m_DepthPSO;\r\n    m_ShadowPSO.SetRasterizerState(RasterizerShadow);\r\n    m_ShadowPSO.SetRenderTargetFormats(0, nullptr, g_ShadowBuffer.GetFormat());\r\n    m_ShadowPSO.Finalize();\r\n\r\n    // Shadows with alpha testing\r\n    m_CutoutShadowPSO = m_ShadowPSO;\r\n    m_CutoutShadowPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS));\r\n    m_CutoutShadowPSO.SetRasterizerState(RasterizerShadowTwoSided);\r\n    m_CutoutShadowPSO.Finalize();\r\n\r\n    // Full color pass\r\n    m_ModelPSO = m_DepthPSO;\r\n    m_ModelPSO.SetBlendState(BlendDisable);\r\n    m_ModelPSO.SetDepthStencilState(DepthStateTestEqual);\r\n    m_ModelPSO.SetRenderTargetFormats(1, &ColorFormat, DepthFormat);\r\n    m_ModelPSO.SetVertexShader(g_pModelViewerVS, sizeof(g_pModelViewerVS));\r\n    m_ModelPSO.SetPixelShader(g_pModelViewerPS, sizeof(g_pModelViewerPS));\r\n    m_ModelPSO.Finalize();\r\n\r\n    m_ModelMsaaPSO = m_ModelPSO;\r\n    m_ModelMsaaPSO.SetRasterizerState(RasterizerDefaultMsaa);\r\n    m_ModelMsaaPSO.Finalize();\r\n\r\n#ifdef _WAVE_OP\r\n    m_DepthWaveOpsPSO = m_DepthPSO;\r\n    m_DepthWaveOpsPSO.SetVertexShader(g_pDepthViewerVS_SM6, sizeof(g_pDepthViewerVS_SM6));\r\n    m_DepthWaveOpsPSO.Finalize();\r\n\r\n    m_ModelWaveOpsPSO = m_ModelPSO;\r\n    m_ModelWaveOpsPSO.SetVertexShader(g_pModelViewerVS_SM6, sizeof(g_pModelViewerVS_SM6));\r\n    m_ModelWaveOpsPSO.SetPixelShader(g_pModelViewerPS_SM6, sizeof(g_pModelViewerPS_SM6));\r\n    m_ModelWaveOpsPSO.Finalize();\r\n#endif\r\n\r\n    m_CutoutModelPSO = m_ModelPSO;\r\n    m_CutoutModelPSO.SetRasterizerState(RasterizerTwoSided);\r\n    m_CutoutModelPSO.Finalize();\r\n\r\n    m_CutoutModelMsaaPSO = m_CutoutModelPSO;\r\n    m_CutoutModelMsaaPSO.SetRasterizerState(RasterizerTwoSidedMsaa);\r\n    m_CutoutModelMsaaPSO.Finalize();\r\n\r\n    // A debug shader for counting lights in a tile\r\n    m_WaveTileCountPSO = m_ModelPSO;\r\n    m_WaveTileCountPSO.SetPixelShader(g_pWaveTileCountPS, sizeof(g_pWaveTileCountPS));\r\n    m_WaveTileCountPSO.Finalize();\r\n\r\n    // Compute PSOs for MSAA depth and color resolve\r\n    m_MsaaColorResolvePSO.SetRootSignature(m_MsaaResolveRootSig);\r\n    m_MsaaColorResolvePSO.SetComputeShader(g_pMsaaColorResolveCS, sizeof(g_pMsaaColorResolveCS));\r\n    m_MsaaColorResolvePSO.Finalize();\r\n\r\n    m_MsaaDepthResolvePSO.SetRootSignature(m_MsaaResolveRootSig);\r\n    m_MsaaDepthResolvePSO.SetComputeShader(g_pMsaaDepthResolveCS, sizeof(g_pMsaaDepthResolveCS));\r\n    m_MsaaDepthResolvePSO.Finalize();\r\n\r\n    // Compute PSOs for Upsample dpeth and color resolve\r\n    m_UpsampleColorResolvePSO.SetRootSignature(m_UpsampleResolveRootSig);\r\n    m_UpsampleColorResolvePSO.SetComputeShader(g_pUpsampleColorResolveCS, sizeof(g_pUpsampleColorResolveCS));\r\n    m_UpsampleColorResolvePSO.Finalize();\r\n\r\n    m_UpsampleDepthResolvePSO.SetRootSignature(m_UpsampleResolveRootSig);\r\n    m_UpsampleDepthResolvePSO.SetComputeShader(g_pUpsampleDepthResolveCS, sizeof(g_pUpsampleDepthResolveCS));\r\n    m_UpsampleDepthResolvePSO.Finalize();\r\n\r\n    // Compute PSOs for Checkerboard depth and color resolve\r\n    m_CheckerboardColorResolvePSO.SetRootSignature(m_CheckerboardResolveRootSig);\r\n    m_CheckerboardColorResolvePSO.SetComputeShader(g_pCheckerboardColorResolveCS, sizeof(g_pCheckerboardColorResolveCS));\r\n    m_CheckerboardColorResolvePSO.Finalize();\r\n\r\n    m_CheckerboardDepthResolvePSO.SetRootSignature(m_CheckerboardResolveRootSig);\r\n    m_CheckerboardDepthResolvePSO.SetComputeShader(g_pCheckerboardDepthResolveCS, sizeof(g_pCheckerboardDepthResolveCS));\r\n    m_CheckerboardDepthResolvePSO.Finalize();\r\n\r\n    Lighting::InitializeResources();\r\n\r\n    m_ExtraTextures[0] = g_SSAOFullScreen.GetSRV();\r\n    m_ExtraTextures[1] = g_ShadowBuffer.GetSRV();\r\n\r\n    std::wstring wScenePath;\r\n\r\n    int nArgs = 0;\r\n    LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nArgs);\r\n\r\n    m_Loaded = false;\r\n\r\n    if (nArgs < 2)\r\n    {\r\n        bool result = FindScene(&wScenePath, argList[0], L\"Sponza\\\\sponza.scn\");\r\n\r\n        if (false == result)\r\n        {\r\n            Utility::Print(\"Expected: a scene file path as input argument 1, or Sponza\\\\sponza.scn in the parent directory structure.\\r\\n\");\r\n\r\n            MessageBox(GetForegroundWindow(),\r\n                L\"Expected: a scene file path as input argument 1, \"\r\n                L\"or Sponza\\\\sponza.scn in the parent directory structure.\",\r\n                L\"Could not find Scene\", MB_ICONERROR | MB_OK);\r\n\r\n            return;\r\n        }\r\n    }\r\n    else\r\n        wScenePath = std::wstring(argList[1]);\r\n\r\n    std::string scenepath(wScenePath.begin(), wScenePath.end());\r\n\r\n    LocalFree(argList);\r\n\r\n    ASSERT(m_Scene.LoadJson(scenepath.c_str()));\r\n    auto& model = m_Scene.GetModel();\r\n\r\n    // The caller of this function can override which materials are considered cutouts\r\n    m_pMaterialIsCutout.resize(model.m_Header.materialCount);\r\n    for (uint32_t i = 0; i < model.m_Header.materialCount; ++i)\r\n    {\r\n        const Model::Material& mat = model.m_pMaterial[i];\r\n        if (mat.hasMask)\r\n        {\r\n            m_pMaterialIsCutout[i] = true;\r\n        }\r\n        else\r\n        {\r\n            m_pMaterialIsCutout[i] = false;\r\n        }\r\n    }\r\n\r\n    //CreateParticleEffects();\r\n\r\n    float modelRadius = m_Scene.GetModelRadius();\r\n    m_CameraController.reset(new CameraController(m_Scene.GetCamera(), Vector3(kYUnitVector)));\r\n    m_CameraController->SetSpeed(0.25f * modelRadius);\r\n\r\n    const Vector3& sceneShadowDim = m_Scene.GetShadowDim();\r\n    if (sceneShadowDim.GetX() > 0.0f) ShadowDimX = sceneShadowDim.GetX();\r\n    if (sceneShadowDim.GetY() > 0.0f) ShadowDimY = sceneShadowDim.GetY();\r\n    if (sceneShadowDim.GetZ() > 0.0f) ShadowDimZ = sceneShadowDim.GetZ();\r\n\r\n    // KX: turn off motion blur, hdr, and ssao by default.\r\n    // KX: also turn off TAA by default to immediately show CB effects (image quality)\r\n    //MotionBlur::Enable = false;\r\n    //TemporalEffects::EnableTAA = false;\r\n    //FXAA::Enable = false;\r\n    PostEffects::EnableHDR = false;\r\n    //PostEffects::EnableAdaptation = false;\r\n    //SSAO::Enable = false;\r\n\r\n    // initialize DownSized Factors\r\n    m_DownSizedFactor.x = 1.f; m_DownSizedFactor.y = 1.f;\r\n\r\n    Lighting::CreateRandomLights(model.GetBoundingBox().min, model.GetBoundingBox().max);\r\n\r\n    m_ExtraTextures[2] = Lighting::m_LightBuffer.GetSRV();\r\n    m_ExtraTextures[3] = Lighting::m_LightShadowArray.GetSRV();\r\n    m_ExtraTextures[4] = Lighting::m_LightGrid.GetSRV();\r\n    m_ExtraTextures[5] = Lighting::m_LightGridBitMask.GetSRV();\r\n\r\n    m_AnimationController = std::make_shared<AnimationController>();\r\n    m_AnimationController->SetSceneAnimation(m_Scene.GetAnimation());\r\n    m_AnimationController->SetTargetCamera(&m_Scene.GetCamera());\r\n\r\n    m_AnimationController->AnimateFloatVar(&m_SunOrientation, \"SunOrientation\");\r\n    m_AnimationController->AnimateBoolVar(&ShowWaveTileCounts, \"ShowWaveTileCounts\");\r\n\r\n    // TODO: DRR - This might not work with our aliased placed resources\r\n    // If we care about running the sequencer this needs to be tested\r\n    m_Sequencer.SetSrcBuffer(Graphics::g_pSceneColorBuffer);\r\n    m_Sequencer.SetDstRootFolder(m_Scene.GetRootFolder());\r\n\r\n#ifdef ART_ENABLE_GUI\r\n    auto animWidget = ARTGUI::AnimationWidget::Create(m_AnimationController);\r\n    auto sequencerWidget = ARTGUI::SequencerWidget::Create(&m_Sequencer, m_AnimationController);\r\n    ARTGUI::AddWidget(animWidget);\r\n    ARTGUI::AddWidget(sequencerWidget);\r\n#endif\r\n\r\n    m_Loaded = true;\r\n\r\n    return;\r\n}\r\n\r\nvoid ModelViewer::Cleanup(void)\r\n{\r\n    if (m_Loaded)\r\n    {\r\n        m_Scene.SaveAnimation();\r\n        m_Scene.Cleanup();\r\n\r\n        Lighting::Shutdown();\r\n    }\r\n}\r\n\r\nnamespace Graphics\r\n{\r\n    extern EnumVar DebugZoom;\r\n}\r\n\r\nvoid ModelViewer::Update(float deltaT)\r\n{\r\n    {\t// setting downsize factors for jitter and viewport scaling\r\n        if (CbrEnabled) {\r\n            m_FrameOffset = Graphics::GetFrameCount() % 2;\r\n\r\n            // downsize to quarter resolution in CBR 2x and 4x (2x MSAA and 1xMSAA, respectively)\r\n            m_DownSizedFactor.x = 2.f; m_DownSizedFactor.y = 2.f;\r\n        }\r\n        else {\r\n            // reset to default\r\n            m_DownSizedFactor.x = 1.f; m_DownSizedFactor.y = 1.f;\r\n        }\r\n    }\r\n\r\n    ScopedTimer _prof(L\"Update State\");\r\n\r\n    if (GameInput::IsFirstPressed(GameInput::kLShoulder))\r\n        DebugZoom.Decrement();\r\n    else if (GameInput::IsFirstPressed(GameInput::kRShoulder))\r\n        DebugZoom.Increment();\r\n\r\n    // grab screenshot?\r\n    if (GameInput::IsFirstPressed(GameInput::kKey_sysrq)) {\r\n        Utility::Print(\"Capturing screenshot\\n\");\r\n        m_Sequencer.CaptureOne();\r\n    }\r\n\r\n    m_AnimationController->Update(deltaT);\r\n    if (m_AnimationController->IsDirty()) {\r\n        m_CameraController->Reset();\r\n        m_CameraController->Update(0);\r\n        m_AnimationController->SetDirty(false);\r\n    }\r\n    else\r\n        m_CameraController->Update(deltaT);\r\n\r\n    auto& camera = m_Scene.GetCamera();\r\n\r\n    m_ViewProjMatrix = camera.GetViewProjMatrix();\r\n\r\n    float costheta = cosf(m_SunOrientation);\r\n    float sintheta = sinf(m_SunOrientation);\r\n    float cosphi = cosf(m_SunInclination * 3.14159f * 0.5f);\r\n    float sinphi = sinf(m_SunInclination * 3.14159f * 0.5f);\r\n    m_SunDirection = Normalize(Vector3(costheta * cosphi, sinphi, sintheta * cosphi));\r\n}\r\n\r\nvoid ModelViewer::RenderObjects(GraphicsContext& gfxContext, const Matrix4& ViewProjMat, eObjectFilter Filter)\r\n{\r\n    struct VSConstants\r\n    {\r\n        Matrix4 modelToProjection;\r\n        Matrix4 modelToShadow;\r\n        XMFLOAT3 viewerPos;\r\n    } vsConstants;\r\n\r\n    vsConstants.modelToProjection = ViewProjMat;\r\n    vsConstants.modelToShadow = m_SunShadow.GetShadowMatrix();\r\n    XMStoreFloat3(&vsConstants.viewerPos, m_Scene.GetCamera().GetPosition());\r\n    gfxContext.SetDynamicConstantBufferView(0, sizeof(vsConstants), &vsConstants);\r\n\r\n    uint32_t materialIdx = 0xFFFFFFFFul;\r\n\r\n    auto& model = m_Scene.GetModel();\r\n\r\n    uint32_t VertexStride = model.m_VertexStride;\r\n\r\n    gfxContext.SetDynamicDescriptors(3, Model::kMaterialTexChannelCount() - 1, 1, &model.m_MaterialConstants.GetSRV());\r\n\r\n    for (uint32_t meshIndex = 0; meshIndex < model.m_Header.meshCount; meshIndex++)\r\n    {\r\n        const Model::Mesh& mesh = model.m_pMesh[meshIndex];\r\n\r\n        uint32_t indexCount = mesh.indexCount;\r\n        uint32_t startIndex = mesh.indexDataByteOffset / sizeof(uint16_t);\r\n        uint32_t baseVertex = mesh.vertexDataByteOffset / VertexStride;\r\n\r\n        if (mesh.materialIndex != materialIdx)\r\n        {\r\n            if (m_pMaterialIsCutout[mesh.materialIndex] && !(Filter & kCutout) ||\r\n                !m_pMaterialIsCutout[mesh.materialIndex] && !(Filter & kOpaque))\r\n                continue;\r\n\r\n            materialIdx = mesh.materialIndex;\r\n            gfxContext.SetDynamicDescriptors(3, 0, Model::kMaterialTexChannelCount() - 1, model.GetSRVs(materialIdx));\r\n            __declspec(align(16)) struct {\r\n                UINT32 vmaterialIdx;\r\n            } psMaterialConstants;\r\n            psMaterialConstants.vmaterialIdx = materialIdx;\r\n            gfxContext.SetDynamicConstantBufferView(2, sizeof(psMaterialConstants), &psMaterialConstants);\r\n        }\r\n\r\n        gfxContext.SetConstants(5, baseVertex, materialIdx);\r\n\r\n        gfxContext.DrawIndexed(indexCount, startIndex, baseVertex);\r\n    }\r\n}\r\n\r\nvoid ModelViewer::RenderLightShadows(GraphicsContext& gfxContext)\r\n{\r\n    using namespace Lighting;\r\n\r\n    ScopedTimer _prof(L\"RenderLightShadows\", gfxContext);\r\n\r\n    static uint32_t LightIndex = 0;\r\n    if (LightIndex >= MaxLights)\r\n        return;\r\n\r\n    m_LightShadowTempBuffer.BeginRendering(gfxContext);\r\n    {\r\n        gfxContext.SetPipelineState(m_ShadowPSO);\r\n        RenderObjects(gfxContext, m_LightShadowMatrix[LightIndex], kOpaque);\r\n        gfxContext.SetPipelineState(m_CutoutShadowPSO);\r\n        RenderObjects(gfxContext, m_LightShadowMatrix[LightIndex], kCutout);\r\n    }\r\n    m_LightShadowTempBuffer.EndRendering(gfxContext);\r\n\r\n    gfxContext.TransitionResource(m_LightShadowTempBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);\r\n    gfxContext.TransitionResource(m_LightShadowArray, D3D12_RESOURCE_STATE_COPY_DEST);\r\n\r\n    gfxContext.CopySubresource(m_LightShadowArray, LightIndex, m_LightShadowTempBuffer, 0);\r\n\r\n    gfxContext.TransitionResource(m_LightShadowArray, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n\r\n    ++LightIndex;\r\n}\r\n\r\nvoid ModelViewer::RenderScene(void)\r\n{\r\n    GraphicsContext& gfxContext = GraphicsContext::Begin(L\"Scene Render\");\r\n\r\n    UpdatePlacedResources( gfxContext );\r\n\r\n\r\n    // We use viewport offsets to jitter sample positions from frame to frame (for TAA.)\r\n    // D3D has a design quirk with fractional offsets such that the implicit scissor\r\n    // region of a viewport is floor(TopLeftXY) and floor(TopLeftXY + WidthHeight), so\r\n    // having a negative fractional top left, e.g. (-0.25, -0.25) would also shift the\r\n    // BottomRight corner up by a whole integer.  One solution is to pad your viewport\r\n    // dimensions with an extra pixel.  My solution is to only use positive fractional offsets,\r\n    // but that means that the average sample position is +0.5, which I use when I disable\r\n    // temporal AA.\r\n    TemporalEffects::GetJitterOffset(m_MainViewport.TopLeftX, m_MainViewport.TopLeftY);\r\n\r\n    m_MainViewport.Width = (float) g_pSceneColorBuffer->GetWidth();\r\n    m_MainViewport.Height = (float) g_pSceneColorBuffer->GetHeight();\r\n    m_MainViewport.MinDepth = 0.0f;\r\n    m_MainViewport.MaxDepth = 1.0f;\r\n\r\n    m_MainScissor.left = 0;\r\n    m_MainScissor.top = 0;\r\n    m_MainScissor.right = (LONG) m_MainViewport.Width;\r\n    m_MainScissor.bottom = (LONG) m_MainViewport.Height;\r\n\r\n    if (CbrEnabled) {\r\n        // scale viewport and jitter vectors\r\n        XMFLOAT2 Jitter;\r\n        TemporalEffects::GetJitterOffset(Jitter.x, Jitter.y);\r\n\r\n        m_DownSizedViewport.TopLeftX = Jitter.x / m_DownSizedFactor.x;\r\n        m_DownSizedViewport.TopLeftY = Jitter.y / m_DownSizedFactor.y;\r\n\r\n        m_DownSizedViewport.TopLeftX += .5f * m_FrameOffset;\r\n\r\n        m_DownSizedViewport.Width = (float) g_pSceneColorBuffer->GetWidth() / m_DownSizedFactor.x;\r\n        m_DownSizedViewport.Height = (float) g_pSceneColorBuffer->GetHeight() / m_DownSizedFactor.y;\r\n        m_DownSizedViewport.MinDepth = 0.0f;\r\n        m_DownSizedViewport.MaxDepth = 1.0f;\r\n\r\n        m_DownSizedScissor.left = 0;\r\n        m_DownSizedScissor.top = 0;\r\n        m_DownSizedScissor.right = (LONG) (g_pSceneColorBuffer->GetWidth() / m_DownSizedFactor.x);\r\n        m_DownSizedScissor.bottom = (LONG) (g_pSceneColorBuffer->GetHeight() / m_DownSizedFactor.y);\r\n    }\r\n\r\n\r\n\r\n    if (CbrEnabled) {\r\n        m_FrameOffset = Graphics::GetFrameCount() % 2;\r\n        m_DownSizedFactor.x = 2.f; m_DownSizedFactor.y = 2.f;\r\n    }\r\n\r\n    static bool s_ShowLightCounts = false;\r\n    if (ShowWaveTileCounts != s_ShowLightCounts)\r\n    {\r\n        static bool EnableHDR;\r\n        if (ShowWaveTileCounts)\r\n        {\r\n            EnableHDR = PostEffects::EnableHDR;\r\n            PostEffects::EnableHDR = false;\r\n        }\r\n        else\r\n        {\r\n            PostEffects::EnableHDR = EnableHDR;\r\n        }\r\n        s_ShowLightCounts = ShowWaveTileCounts;\r\n    }\r\n\r\n\r\n    ParticleEffects::Update(gfxContext.GetComputeContext(), Graphics::GetFrameTime());\r\n\r\n    uint32_t FrameIndex = TemporalEffects::GetFrameIndexMod2();\r\n\r\n    __declspec(align(16)) struct\r\n    {\r\n        Vector3 sunDirection;\r\n        Vector3 sunLight;\r\n        Vector3 ambientLight;\r\n        float ShadowTexelSize[4];\r\n\r\n        float InvTileDim[4];\r\n        uint32_t TileCount[4];\r\n        uint32_t FirstLightIndex[4];\r\n        float DownSizedFactors[4];\r\n\r\n    } psConstants;\r\n\r\n    unsigned int flags = 0;\r\n\r\n    if (m_FrameOffset)\r\n        flags |= 0x01;\r\n\r\n    if (Graphics::g_IntelIsGPU)\r\n        flags |= 0x02;\r\n\r\n    psConstants.sunDirection = m_SunDirection;\r\n    psConstants.sunLight = Vector3(1.0f, 1.0f, 1.0f) * m_SunLightIntensity;\r\n    psConstants.ambientLight = Vector3(1.0f, 1.0f, 1.0f) * m_AmbientIntensity;\r\n    psConstants.ShadowTexelSize[0] = 1.0f / g_ShadowBuffer.GetWidth();\r\n    psConstants.InvTileDim[0] = 1.0f / Lighting::LightGridDim;\r\n    psConstants.InvTileDim[1] = 1.0f / Lighting::LightGridDim;\r\n    psConstants.TileCount[0] = Math::DivideByMultiple(g_pSceneColorBuffer->GetWidth(), Lighting::LightGridDim);\r\n    psConstants.TileCount[1] = Math::DivideByMultiple(g_pSceneColorBuffer->GetHeight(), Lighting::LightGridDim);\r\n    psConstants.FirstLightIndex[0] = Lighting::m_FirstConeLight;\r\n    psConstants.FirstLightIndex[1] = Lighting::m_FirstConeShadowedLight;\r\n    psConstants.DownSizedFactors[0] = m_DownSizedFactor.x;\r\n    psConstants.DownSizedFactors[1] = m_DownSizedFactor.y;\r\n    psConstants.DownSizedFactors[2] = *(float *) (int *) &flags;\r\n\r\n    auto& model = m_Scene.GetModel();\r\n    auto& camera = m_Scene.GetCamera();\r\n\r\n    // Set the default state for command lists\r\n    auto& pfnSetupGraphicsState = [&](void)\r\n    {\r\n        gfxContext.SetRootSignature(m_RootSig);\r\n        gfxContext.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\r\n        gfxContext.SetIndexBuffer(model.m_IndexBuffer.IndexBufferView());\r\n        gfxContext.SetVertexBuffer(0, model.m_VertexBuffer.VertexBufferView());\r\n    };\r\n\r\n    pfnSetupGraphicsState();\r\n    RenderLightShadows(gfxContext);\r\n\r\n    // -- Depth prepass Normal,Upsampling,CBR\r\n    {\r\n        if (!CbrEnabled) {\r\n\r\n            ScopedTimer _prof(L\"Z PrePass\", gfxContext);\r\n            gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);\r\n            if (!MsaaEnabled)\r\n            {\r\n                {\r\n                    ScopedTimer _prof(L\"Opaque\", gfxContext);\r\n                    gfxContext.TransitionResource(*g_pSceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_WRITE, true);\r\n                    gfxContext.ClearDepth(*g_pSceneDepthBuffer);\r\n#ifdef _WAVE_OP\r\n                    gfxContext.SetPipelineState(EnableWaveOps ? m_DepthWaveOpsPSO : m_DepthPSO);\r\n#else\r\n                    gfxContext.SetPipelineState(m_DepthPSO);\r\n#endif\r\n                    gfxContext.SetDepthStencilTarget(g_pSceneDepthBuffer->GetDSV());\r\n\r\n                    gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);\r\n                    RenderObjects(gfxContext, m_ViewProjMatrix, kOpaque);\r\n                }\r\n\r\n                {\r\n                    ScopedTimer _prof(L\"Cutout\", gfxContext);\r\n                    gfxContext.SetPipelineState(m_CutoutDepthPSO);\r\n                    RenderObjects(gfxContext, m_ViewProjMatrix, kCutout);\r\n                }\r\n            }\r\n\r\n            if (MsaaEnabled) {\r\n                ScopedTimer _prof(L\"OpaqueMSAA\", gfxContext);\r\n\r\n                gfxContext.TransitionResource(*g_pMsaaDepth, D3D12_RESOURCE_STATE_DEPTH_WRITE, true);\r\n                gfxContext.ClearDepth(*g_pMsaaDepth);\r\n#ifdef _WAVE_OP\r\n                gfxContext.SetPipelineState(EnableWaveOps ? m_DepthWaveOpsPSO : m_DepthMsaaPSO);\r\n#else\r\n                m_DepthMsaaPSO.SetMsaaCount((UINT) std::pow((UINT) 2, (UINT) MsaaMode));\r\n                m_DepthMsaaPSO.Finalize();\r\n                gfxContext.SetPipelineState(m_DepthMsaaPSO);\r\n#endif\r\n                gfxContext.SetDepthStencilTarget((*g_pMsaaDepth).GetDSV());\r\n\r\n                gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);\r\n                RenderObjects(gfxContext, m_ViewProjMatrix, kOpaque);\r\n                {\r\n                    ScopedTimer _prof(L\"CutoutMSAA\", gfxContext);\r\n                    m_CutoutDepthMsaaPSO.SetMsaaCount((UINT) std::pow((UINT) 2, (UINT) MsaaMode));\r\n                    m_CutoutDepthMsaaPSO.Finalize();\r\n                    gfxContext.SetPipelineState(m_CutoutDepthMsaaPSO);\r\n                    RenderObjects(gfxContext, m_ViewProjMatrix, kCutout);\r\n                }\r\n            }\r\n\r\n            if (MsaaEnabled) {\r\n                // explicitly resolve MSAA depth\r\n                const float zMagic = (camera.GetFarClip() - camera.GetNearClip()) / camera.GetNearClip();\r\n                __declspec(align(16)) float cbData[] = {\r\n                    zMagic, (float) 1\r\n                };\r\n\r\n                uint32_t FrameIndex = TemporalEffects::GetFrameIndexMod2();\r\n                ColorBuffer *LinearDepth = &g_LinearDepth[Graphics::GetFrameCount() % 2];\r\n\r\n                ComputeContext& Context = gfxContext.GetComputeContext();\r\n                Context.SetRootSignature(m_MsaaResolveRootSig);\r\n                Context.SetPipelineState(m_MsaaDepthResolvePSO);\r\n                Context.TransitionResource(*g_pMsaaDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                Context.TransitionResource(*LinearDepth, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n                Context.SetDynamicConstantBufferView(0, sizeof(cbData), cbData);\r\n                Context.SetDynamicDescriptor(1, 0, (*g_pMsaaDepth).GetDepthSRV());\r\n                Context.SetDynamicDescriptor(2, 0, (*LinearDepth).GetUAV());\r\n                Context.Dispatch2D(g_pMsaaDepth->GetWidth(), g_pMsaaDepth->GetHeight());\r\n\r\n                // We convert linear depth here, but we still need SSAO to get ambient lighting\r\n                SSAO::ComputeLinearZ = false;\r\n            }\r\n            else {\r\n                SSAO::ComputeLinearZ = true;\r\n            }\r\n        }\r\n        else {\r\n            // render to downsized buffer and upsample using compute shader with checkerboard rendering\r\n            ScopedTimer _prof(L\"Z PrePass Checkerboard\", gfxContext);\r\n            gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);\r\n            {\r\n                ScopedTimer _prof(L\"Opaque Checkerboard\", gfxContext);\r\n                gfxContext.TransitionResource(*g_pCheckerboardDepths[m_FrameOffset], D3D12_RESOURCE_STATE_DEPTH_WRITE, true);\r\n                gfxContext.ClearDepth(*g_pCheckerboardDepths[m_FrameOffset]);\r\n#ifdef _WAVE_OP\r\n                gfxContext.SetPipelineState(EnableWaveOps ? m_DepthWaveOpsPSO : m_DepthMsaaPSO);\r\n#else\r\n                m_DepthMsaaPSO.SetMsaaCount(2);\t// 2x MSAA for CBR2x\r\n                m_DepthMsaaPSO.Finalize();\r\n                gfxContext.SetPipelineState(m_DepthMsaaPSO);\r\n#endif\r\n                gfxContext.SetDepthStencilTarget((*g_pCheckerboardDepths[m_FrameOffset]).GetDSV());\r\n                gfxContext.SetViewportAndScissor(m_DownSizedViewport, m_DownSizedScissor);\r\n                RenderObjects(gfxContext, m_ViewProjMatrix, kOpaque);\r\n\r\n                {\r\n                    ScopedTimer _prof(L\"Cutout Checkerboard\", gfxContext);\r\n                    m_CutoutDepthMsaaPSO.SetMsaaCount(2);\r\n                    m_CutoutDepthMsaaPSO.Finalize();\r\n                    gfxContext.SetPipelineState(m_CutoutDepthMsaaPSO);\r\n\r\n                    RenderObjects(gfxContext, m_ViewProjMatrix, kCutout);\r\n                }\r\n\r\n                {\r\n                    // Resolve the DownSized Depth to Full size depth buffer in linear space\r\n                    const float zMagic = (camera.GetFarClip() - camera.GetNearClip()) / camera.GetNearClip();\r\n                    __declspec(align(16)) float cbData[] = {\r\n                        zMagic, (float) m_FrameOffset\r\n                    };\r\n                    ColorBuffer *LinearDepth = &g_LinearDepth[Graphics::GetFrameCount() % 2];\r\n\r\n                    ComputeContext& Context = gfxContext.GetComputeContext();\r\n\r\n                    Context.SetRootSignature(m_CheckerboardResolveRootSig);\r\n                    Context.SetPipelineState(m_CheckerboardDepthResolvePSO);\r\n\r\n                    Context.TransitionResource(*g_pCheckerboardDepths[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                    Context.TransitionResource(*g_pCheckerboardDepths[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n                    Context.TransitionResource(*LinearDepth, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n                    Context.SetDynamicConstantBufferView(0, sizeof(cbData), cbData);\r\n\r\n                    // resolution just changed, our previous frame is invalid\r\n                    if ( TemporalEffects::TriggerReset )\r\n                    {\r\n                        Context.SetDynamicDescriptor(1, 0, (*g_pCheckerboardDepths[m_FrameOffset]).GetDepthSRV());\r\n                        Context.SetDynamicDescriptor(1, 1, (*g_pCheckerboardDepths[m_FrameOffset]).GetDepthSRV());\r\n                    }\r\n                    else\r\n                    {\r\n                        Context.SetDynamicDescriptor(1, 0, (*g_pCheckerboardDepths[0]).GetDepthSRV());\r\n                        Context.SetDynamicDescriptor(1, 1, (*g_pCheckerboardDepths[1]).GetDepthSRV());\r\n                    }\r\n\r\n                    Context.SetDynamicDescriptor(2, 0, (*LinearDepth).GetUAV());\r\n                    Context.Dispatch2D(LinearDepth->GetWidth(), LinearDepth->GetHeight());\r\n\r\n                    // We convert linear depth here, but we still need SSAO to get ambient lighting\r\n                    SSAO::ComputeLinearZ = false;\r\n                    gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    SSAO::Render(gfxContext, camera);\r\n\r\n    Lighting::FillLightGrid(gfxContext, camera);\r\n\r\n    // -- Primary shading pass Normal, Upsampling,CBR\r\n    {\r\n        if (!SSAO::DebugDraw)\r\n        {\r\n            ScopedTimer _prof(L\"Main Render\", gfxContext);\r\n\r\n            gfxContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET, true);\r\n            gfxContext.ClearColor(*g_pSceneColorBuffer);\r\n\r\n            pfnSetupGraphicsState();\r\n\r\n            {\r\n                ScopedTimer _prof(L\"Render Shadow Map\", gfxContext);\r\n\r\n                m_SunShadow.UpdateMatrix(-m_SunDirection, m_Scene.GetCenter() - m_SunDirection * 0.35f *m_Scene.GetModelRadius(), Vector3(ShadowDimX, ShadowDimY, ShadowDimZ),\r\n                    (uint32_t) g_ShadowBuffer.GetWidth(), (uint32_t) g_ShadowBuffer.GetHeight(), 16);\r\n                //m_SunShadow.UpdateMatrix(-m_SunDirection, Vector3(0, -500.0f, 0), Vector3(ShadowDimX, ShadowDimY, ShadowDimZ),\r\n                //\t(uint32_t)g_ShadowBuffer.GetWidth(), (uint32_t)g_ShadowBuffer.GetHeight(), 16);\r\n\r\n                g_ShadowBuffer.BeginRendering(gfxContext);\r\n                gfxContext.SetPipelineState(m_ShadowPSO);\r\n                RenderObjects(gfxContext, m_SunShadow.GetViewProjMatrix(), kOpaque);\r\n                gfxContext.SetPipelineState(m_CutoutShadowPSO);\r\n                RenderObjects(gfxContext, m_SunShadow.GetViewProjMatrix(), kCutout);\r\n                g_ShadowBuffer.EndRendering(gfxContext);\r\n            }\r\n\r\n            if (SSAO::AsyncCompute)\r\n            {\r\n                gfxContext.Flush();\r\n                pfnSetupGraphicsState();\r\n\r\n                // Make the 3D queue wait for the Compute queue to finish SSAO\r\n                g_CommandManager.GetGraphicsQueue().StallForProducer(g_CommandManager.GetComputeQueue());\r\n            }\r\n\r\n            {\r\n                ScopedTimer _prof(L\"Render Color\", gfxContext);\r\n                ScopedPipelineQuery _colorQuery(L\"ColorStats\", gfxContext);\r\n\r\n                gfxContext.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\r\n\r\n                gfxContext.SetDynamicDescriptors(4, 0, _countof(m_ExtraTextures), m_ExtraTextures);\r\n                gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);\r\n#ifdef _WAVE_OP\r\n                gfxContext.SetPipelineState(EnableWaveOps ? m_ModelWaveOpsPSO : m_ModelPSO);\r\n#else\r\n                m_ModelPSO.SetPixelShader(g_pModelViewerPS, sizeof(g_pModelViewerPS));\r\n                m_ModelPSO.Finalize();\r\n                gfxContext.SetPipelineState(ShowWaveTileCounts ? m_WaveTileCountPSO : m_ModelPSO);\r\n#endif\r\n                if (!CbrEnabled) {\r\n                    if (MsaaEnabled) {\r\n                        m_ModelMsaaPSO.SetMsaaCount((UINT) std::pow((UINT) 2, (UINT) MsaaMode));\r\n                        m_ModelMsaaPSO.SetPixelShader(g_pModelViewerPS, sizeof(g_pModelViewerPS));\r\n                        m_ModelMsaaPSO.Finalize();\r\n                        gfxContext.SetPipelineState(m_ModelMsaaPSO);\r\n                        if (ShowWaveTileCounts) {\r\n                            m_WaveTileCountPSO.SetMsaaCount((UINT) std::pow((UINT) 2, (UINT) MsaaMode));\r\n                            m_WaveTileCountPSO.SetRasterizerState(RasterizerDefaultMsaa);\r\n                            m_WaveTileCountPSO.Finalize();\r\n                            gfxContext.SetPipelineState(m_WaveTileCountPSO);\r\n                        }\r\n                        gfxContext.TransitionResource(*g_pMsaaColor, D3D12_RESOURCE_STATE_RENDER_TARGET, 1);\r\n                        gfxContext.ClearColor(*g_pMsaaColor);\r\n                        gfxContext.TransitionResource(*g_pMsaaDepth, D3D12_RESOURCE_STATE_DEPTH_READ);\r\n                        gfxContext.SetRenderTarget((*g_pMsaaColor).GetRTV(), (*g_pMsaaDepth).GetDSV_DepthReadOnly());\r\n                    }\r\n                    else {\r\n                        gfxContext.TransitionResource(*g_pSceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_READ);\r\n                        gfxContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);\r\n                        gfxContext.SetRenderTarget(g_pSceneColorBuffer->GetRTV(), g_pSceneDepthBuffer->GetDSV_DepthReadOnly());\r\n                    }\r\n\r\n                    gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);\r\n                }\r\n                else {\r\n                    m_ModelMsaaPSO.SetMsaaCount(2);\r\n                    m_ModelMsaaPSO.SetPixelShader(g_pModelViewerPS_CBR, sizeof(g_pModelViewerPS_CBR));\r\n                    m_ModelMsaaPSO.Finalize();\r\n                    gfxContext.SetPipelineState(m_ModelMsaaPSO);\r\n\r\n                    if (ShowWaveTileCounts) {\r\n                        m_WaveTileCountPSO.SetRasterizerState(RasterizerDefault);\r\n                        m_WaveTileCountPSO.Finalize();\r\n                        gfxContext.SetPipelineState(m_WaveTileCountPSO);\r\n                    }\r\n                    gfxContext.TransitionResource(*g_pCheckerboardColors[m_FrameOffset], D3D12_RESOURCE_STATE_RENDER_TARGET, 1);\r\n                    gfxContext.ClearColor(*g_pCheckerboardColors[m_FrameOffset]);\r\n                    gfxContext.TransitionResource(*g_pCheckerboardDepths[m_FrameOffset], D3D12_RESOURCE_STATE_DEPTH_READ);\r\n                    gfxContext.SetRenderTarget((*g_pCheckerboardColors[m_FrameOffset]).GetRTV(), (*g_pCheckerboardDepths[m_FrameOffset]).GetDSV_DepthReadOnly());\r\n                    gfxContext.SetViewportAndScissor(m_DownSizedViewport, m_DownSizedScissor);\r\n                }\r\n                // Shade the scene with color\r\n                RenderObjects(gfxContext, m_ViewProjMatrix, kOpaque);\r\n\r\n                if (!ShowWaveTileCounts)\t// shade cutout of scene with color\r\n                {\r\n                    if (!CbrEnabled) {\r\n                        if (MsaaEnabled) {\r\n                            m_CutoutModelMsaaPSO.SetMsaaCount((UINT) std::pow((UINT) 2, (UINT) MsaaMode));\r\n                            m_CutoutModelMsaaPSO.SetPixelShader(g_pModelViewerPS, sizeof(g_pModelViewerPS));\r\n                            m_CutoutModelMsaaPSO.Finalize();\r\n                            gfxContext.SetPipelineState(m_CutoutModelMsaaPSO);\r\n                        }\r\n                        else {\r\n                            m_CutoutModelPSO.SetPixelShader(g_pModelViewerPS, sizeof(g_pModelViewerPS));\r\n                            m_CutoutModelPSO.Finalize();\r\n                            gfxContext.SetPipelineState(m_CutoutModelPSO);\r\n                        }\r\n                    }\r\n                    else {\r\n                        m_CutoutModelMsaaPSO.SetMsaaCount(2);\r\n                        m_CutoutModelMsaaPSO.SetPixelShader(g_pModelViewerPS_CBR, sizeof(g_pModelViewerPS_CBR));\r\n                        m_CutoutModelMsaaPSO.Finalize();\r\n                        gfxContext.SetPipelineState(m_CutoutModelMsaaPSO);\r\n                    }\r\n                    RenderObjects(gfxContext, m_ViewProjMatrix, kCutout);\r\n                }\r\n\r\n                // Resolve color to output frame\r\n                if (!CbrEnabled) {\r\n                    if (MsaaEnabled) {\r\n                        if (MsaaResolver == 1) {\r\n                            // use MsaaColorResolveCS to resolve MSAA texture to non-MSAA texture\r\n                            ScopedTimer _prof(L\"MsaaColorResolve\", gfxContext);\r\n                            ComputeContext& Context = gfxContext.GetComputeContext();\r\n                            Context.SetRootSignature(m_MsaaResolveRootSig);\r\n                            Context.SetPipelineState(m_MsaaColorResolvePSO);\r\n                            Context.TransitionResource(*g_pMsaaColor, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                            Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                            Context.SetDynamicDescriptor(1, 0, (*g_pMsaaColor).GetSRV());\r\n                            Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n                            Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n                        }\r\n                        else {\r\n                            if (MsaaMode > 0) {\r\n                                gfxContext.TransitionResource(*g_pMsaaColor, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);\r\n                                gfxContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_RESOLVE_DEST);\r\n                                gfxContext.ResolveSubresource(*g_pSceneColorBuffer, 0, *g_pMsaaColor, 0, g_pSceneColorBuffer->GetFormat());\r\n                            }\r\n                            else {\r\n                                gfxContext.TransitionResource(*g_pMsaaColor, D3D12_RESOURCE_STATE_COPY_SOURCE);\r\n                                gfxContext.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_COPY_DEST);\r\n                                gfxContext.CopySubresource(*g_pSceneColorBuffer, 0, *g_pMsaaColor, 0);\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                else {\r\n                    static Matrix4 PrevInvViewProj = Math::Invert(camera.GetViewProjMatrix());\r\n                    static uint64_t FrameCount;\r\n\r\n                    struct __declspec(align(16)) CBData\r\n                    {\r\n                        float FrameOffset;\r\n                        float DepthTolerance;\r\n                        uint32_t Flags;\r\n                        float _Pad;\r\n                        float LinearZTransform[4];\r\n                        float CurrViewProj[16];\r\n                        float PrevInvViewProj[16];\r\n                    };\r\n\r\n                    // if our prev frame + 1 doesn't match the actual frame\r\n                    // then we've been skipped and we're now being toggled back on\r\n                    bool CbrToggledOn = (FrameCount + 1) != Graphics::GetFrameCount( );\r\n\r\n                    CBData cbData;\r\n                    cbData.DepthTolerance = CbrDepthTolerance;\r\n                    cbData.FrameOffset = (float) m_FrameOffset;\r\n                    cbData.Flags = 0;\r\n                    cbData.Flags |= CbrRenderMotionVectors ? 0x01 : 0;\r\n                    cbData.Flags |= CbrRenderMissingPixels ? 0x02 : 0;\r\n                    cbData.Flags |= CbrRenderPixelMotion ? 0x04 : 0;\r\n                    cbData.Flags |= (CbrRenderCheckerPattern == 1) ? 0x08 : 0;\r\n                    cbData.Flags |= (CbrRenderCheckerPattern == 2) ? 0x10 : 0;\r\n                    cbData.Flags |= CbrRenderObstructedPixels ? 0x20 : 0;\r\n                    cbData.Flags |= CbrCheckShadingOcclusion ? 0x40 : 0;\r\n                    cbData.Flags |= TemporalEffects::TriggerReset ? 0x80: 0;\r\n                    cbData.Flags |= CbrToggledOn ? 0x80: 0;\r\n\r\n                    FrameCount = Graphics::GetFrameCount( );\r\n\r\n                    std::memcpy(cbData.CurrViewProj, &Math::Transpose(camera.GetViewProjMatrix()), sizeof(cbData.CurrViewProj));\r\n                    std::memcpy(cbData.PrevInvViewProj, &Math::Transpose(PrevInvViewProj), sizeof(cbData.PrevInvViewProj));\r\n\r\n                    Math::Matrix4 InvViewProj = Math::Invert(camera.GetViewProjMatrix());\r\n                    cbData.LinearZTransform[0] = InvViewProj.GetZ().GetZ();\r\n                    cbData.LinearZTransform[1] = InvViewProj.GetW().GetZ();\r\n                    cbData.LinearZTransform[2] = InvViewProj.GetZ().GetW();\r\n                    cbData.LinearZTransform[3] = InvViewProj.GetW().GetW();\r\n\r\n                    PrevInvViewProj = Math::Invert(camera.GetViewProjMatrix());\r\n\r\n                    ScopedTimer _prof(L\"CheckerboardColorResolve\", gfxContext);\r\n                    ComputeContext& Context = gfxContext.GetComputeContext();\r\n                    Context.SetRootSignature(m_CheckerboardResolveRootSig);\r\n                    Context.SetPipelineState(m_CheckerboardColorResolvePSO);\r\n\r\n                    Context.TransitionResource(*g_pCheckerboardColors[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                    Context.TransitionResource(*g_pCheckerboardColors[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                    Context.TransitionResource(*g_pCheckerboardDepths[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n                    Context.TransitionResource(*g_pCheckerboardDepths[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);\r\n\r\n                    Context.TransitionResource(*g_pSceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\r\n                    Context.SetDynamicConstantBufferView(0, sizeof(cbData), &cbData);\r\n                    Context.SetDynamicDescriptor(1, 0, (*g_pCheckerboardColors[0]).GetSRV());\r\n                    Context.SetDynamicDescriptor(1, 1, (*g_pCheckerboardColors[1]).GetSRV());\r\n\r\n                    Context.SetDynamicDescriptor(1, 2, (*g_pCheckerboardDepths[0]).GetDepthSRV());\r\n                    Context.SetDynamicDescriptor(1, 3, (*g_pCheckerboardDepths[1]).GetDepthSRV());\r\n\r\n                    Context.SetDynamicDescriptor(2, 0, g_pSceneColorBuffer->GetUAV());\r\n                    Context.Dispatch2D(g_pSceneColorBuffer->GetWidth(), g_pSceneColorBuffer->GetHeight());\r\n\r\n                    gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);\r\n                }\r\n            }\r\n        }\r\n    }\r\n    // Some systems generate a per-pixel velocity buffer to better track dynamic and skinned meshes.  Everything\r\n    // is static in our scene, so we generate velocity from camera motion and the depth buffer.  A velocity buffer\r\n    // is necessary for all temporal effects (and motion blur).\t\r\n    // Set \"true\" to use Linear Z\r\n    MotionBlur::GenerateCameraVelocityBuffer(gfxContext, camera, true);\r\n\r\n    TemporalEffects::ResolveImage(gfxContext);\r\n\r\n    //ParticleEffects::Render(gfxContext, camera, *g_pSceneColorBuffer, *g_pSceneDepthBuffer,  g_LinearDepth[FrameIndex]);\r\n\r\n    // Until I work out how to couple these two, it's \"either-or\".\r\n    if (DepthOfField::Enable)\r\n        DepthOfField::Render(gfxContext, camera.GetNearClip(), camera.GetFarClip());\r\n    else\r\n        MotionBlur::RenderObjectBlur(gfxContext, g_VelocityBuffer);\r\n\r\n    gfxContext.Finish();\r\n\r\n    m_Sequencer.FinishFrame();\r\n\r\n}\r\n\r\nvoid ModelViewer::CreateParticleEffects()\r\n{\r\n    ParticleEffectProperties Effect = ParticleEffectProperties();\r\n    Effect.MinStartColor = Effect.MaxStartColor = Effect.MinEndColor = Effect.MaxEndColor = Color(1.0f, 1.0f, 1.0f, 0.0f);\r\n    Effect.TexturePath = L\"sparkTex.dds\";\r\n\r\n    Effect.TotalActiveLifetime = FLT_MAX;\r\n    Effect.Size = Vector4(4.0f, 8.0f, 4.0f, 8.0f);\r\n    Effect.Velocity = Vector4(20.0f, 200.0f, 50.0f, 180.0f);\r\n    Effect.LifeMinMax = XMFLOAT2(1.0f, 3.0f);\r\n    Effect.MassMinMax = XMFLOAT2(4.5f, 15.0f);\r\n    Effect.EmitProperties.Gravity = XMFLOAT3(0.0f, -100.0f, 0.0f);\r\n    Effect.EmitProperties.FloorHeight = -0.5f;\r\n    Effect.EmitProperties.EmitPosW = Effect.EmitProperties.LastEmitPosW = XMFLOAT3(-1200.0f, 185.0f, -445.0f);\r\n    Effect.EmitProperties.MaxParticles = 800;\r\n    Effect.EmitRate = 64.0f;\r\n    Effect.Spread.x = 20.0f;\r\n    Effect.Spread.y = 50.0f;\r\n    ParticleEffects::InstantiateEffect(Effect);\r\n\r\n    ParticleEffectProperties Smoke = ParticleEffectProperties();\r\n    Smoke.TexturePath = L\"smoke.dds\";\r\n\r\n    Smoke.TotalActiveLifetime = FLT_MAX;\r\n    Smoke.EmitProperties.MaxParticles = 25;\r\n    Smoke.EmitProperties.EmitPosW = Smoke.EmitProperties.LastEmitPosW = XMFLOAT3(1120.0f, 185.0f, -445.0f);\r\n    Smoke.EmitRate = 64.0f;\r\n    Smoke.LifeMinMax = XMFLOAT2(2.5f, 4.0f);\r\n    Smoke.Size = Vector4(60.0f, 108.0f, 30.0f, 208.0f);\r\n    Smoke.Velocity = Vector4(30.0f, 30.0f, 10.0f, 40.0f);\r\n    Smoke.MassMinMax = XMFLOAT2(1.0, 3.5);\r\n    Smoke.Spread.x = 60.0f;\r\n    Smoke.Spread.y = 70.0f;\r\n    Smoke.Spread.z = 20.0f;\r\n    ParticleEffects::InstantiateEffect(Smoke);\r\n\r\n    ParticleEffectProperties Fire = ParticleEffectProperties();\r\n    Fire.MinStartColor = Fire.MaxStartColor = Fire.MinEndColor = Fire.MaxEndColor = Color(8.0f, 8.0f, 8.0f, 0.0f);\r\n    Fire.TexturePath = L\"fire.dds\";\r\n\r\n    Fire.TotalActiveLifetime = FLT_MAX;\r\n    Fire.Size = Vector4(54.0f, 68.0f, 0.1f, 0.3f);\r\n    Fire.Velocity = Vector4(10.0f, 30.0f, 50.0f, 50.0f);\r\n    Fire.LifeMinMax = XMFLOAT2(1.0f, 3.0f);\r\n    Fire.MassMinMax = XMFLOAT2(10.5f, 14.0f);\r\n    Fire.EmitProperties.Gravity = XMFLOAT3(0.0f, 1.0f, 0.0f);\r\n    Fire.EmitProperties.EmitPosW = Fire.EmitProperties.LastEmitPosW = XMFLOAT3(1120.0f, 125.0f, 405.0f);\r\n    Fire.EmitProperties.MaxParticles = 25;\r\n    Fire.EmitRate = 64.0f;\r\n    Fire.Spread.x = 1.0f;\r\n    Fire.Spread.y = 60.0f;\r\n    ParticleEffects::InstantiateEffect(Fire);\r\n}\r\n\r\nvoid ModelViewer::UpdatePlacedResources(GraphicsContext& context)\r\n{\r\n    // At most refresh ~1 a second\r\n    const int FramesBetweenRefresh = (int) Graphics::GetFrameRate();\r\n    \r\n    static bool CbrWasEnabled = CbrEnabled;\r\n    static bool MsaaWasEnabled = MsaaEnabled;\r\n    static bool DrrWasEnabled = DrrEnabled;\r\n    static int PrevMsaaMode = MsaaMode;\r\n    static int PlacedResourceIndex;\r\n    static int FramesUntilSafeRefresh;\r\n    \r\n    // CBR (Checkerboard Rendering) uses every other resource\r\n    // This always leaves Resource N+1 available for DRR to \r\n    // jump to if it needs to change resoluiton\r\n    int CheckerAlternateIndex = (PlacedResourceIndex + 2) % NUM_CHECKER_BUFFERS;\r\n\r\n    // DRR is currently on\r\n    if (DrrEnabled) \r\n    {\r\n        bool DrrRefresh = false;\r\n\r\n        // force refresh if we are in a new mode\r\n        DrrRefresh |= CbrWasEnabled != CbrEnabled;\r\n        DrrRefresh |= MsaaWasEnabled != MsaaEnabled;\r\n        DrrRefresh |= (PrevMsaaMode - MsaaMode) != 0;\r\n\r\n        // toggle on render mode change \r\n        // so we can wait for gpu idle and force a refresh\r\n        if ( DrrRefresh )\r\n        {\r\n            g_CommandManager.IdleGPU();\r\n            FramesUntilSafeRefresh = 0;\r\n        }\r\n        else\r\n        {\r\n            FramesUntilSafeRefresh = FramesUntilSafeRefresh - 1;\r\n            FramesUntilSafeRefresh = FramesUntilSafeRefresh < 0 ? 0 : FramesUntilSafeRefresh;\r\n        }\r\n\r\n        if ( FramesUntilSafeRefresh == 0 )\r\n        {\r\n            g_ResolutionScale = RecalculateResolutionScale( );\r\n\r\n            // force 4 pixel alignment for checkerboarding\r\n            int drrWidth = ALIGN((int) (g_DisplayWidth * g_ResolutionScale), 4);\r\n            int drrHeight = ALIGN((int) (g_DisplayHeight * g_ResolutionScale), 4);\r\n\r\n            // amount of change in each resolution\r\n            // used for testing below - we won't change if it is less than N pixels difference\r\n            int diffX = g_pSceneColorBuffer->GetWidth() - drrWidth;\r\n            int diffY = g_pSceneColorBuffer->GetHeight() - drrHeight;\r\n\r\n            //only change if it's more than N pixels, prevents jittering\r\n            DrrRefresh |= abs(diffX) >= 4;\r\n            DrrRefresh |= abs(diffY) >= 4;\r\n        \r\n            if (DrrRefresh)\r\n            {\r\n                FramesUntilSafeRefresh = FramesBetweenRefresh;\r\n            \r\n                TemporalEffects::TriggerReset = true;\r\n\r\n                PlacedResourceIndex = (PlacedResourceIndex + 1) % NUM_SCENE_BUFFERS;\r\n\r\n                ScopedTimer recreate( L\"Recreated Placed Res\" );\r\n\r\n                if ( CbrEnabled )\r\n                {\r\n                    // CBR (Checkerboard Rendering) uses every other resource\r\n                    // This always leaves Resource N+1 available for DRR to \r\n                    // jump to if it needs to change resoluiton\r\n                    CheckerAlternateIndex = (PlacedResourceIndex + 2) % NUM_CHECKER_BUFFERS;\r\n                    Graphics::RecreateCBRBuffers( PlacedResourceIndex, CheckerAlternateIndex, drrWidth >> 1, drrHeight >> 1 );\r\n                }\r\n                else if ( MsaaEnabled )\r\n                    Graphics::RecreateMsaaBuffers( PlacedResourceIndex, MsaaMode, drrWidth, drrHeight );\r\n                else\r\n                    Graphics::RecreateSceneDepthBuffer( PlacedResourceIndex, drrWidth, drrHeight );\r\n\r\n                // every time because other types (cbr or msaa) will be resolved here\r\n                Graphics::RecreateSceneColorBuffer( PlacedResourceIndex, drrWidth, drrHeight );\r\n            }\r\n        }\r\n    }\r\n    // DRR was on last frame, is now off this frame\r\n    // we need to do this once each state change (on to off)\r\n    else if ( DrrWasEnabled )\r\n    {\r\n        // Drr is now disabled, recreate all our buffers at full resolution\r\n        g_CommandManager.IdleGPU();\r\n\r\n        Graphics::RecreateCBRBuffers( PlacedResourceIndex, CheckerAlternateIndex, g_DisplayWidth >> 1, g_DisplayHeight >> 1 );\r\n        \r\n        Graphics::RecreateMsaaBuffers( PlacedResourceIndex, 0, g_DisplayWidth, g_DisplayHeight );\r\n        Graphics::RecreateMsaaBuffers( PlacedResourceIndex, 1, g_DisplayWidth, g_DisplayHeight );\r\n        Graphics::RecreateMsaaBuffers( PlacedResourceIndex, 2, g_DisplayWidth, g_DisplayHeight );\r\n\r\n        Graphics::RecreateSceneDepthBuffer( PlacedResourceIndex, g_DisplayWidth, g_DisplayHeight );\r\n        Graphics::RecreateSceneColorBuffer( PlacedResourceIndex, g_DisplayWidth, g_DisplayHeight );\r\n\r\n        g_ResolutionScale = 1.0f;\r\n    }\r\n\r\n    SetFrameBuffers( context, PlacedResourceIndex, CheckerAlternateIndex, CbrWasEnabled, MsaaWasEnabled, PrevMsaaMode );\r\n\r\n    DrrWasEnabled = DrrEnabled;\r\n    CbrWasEnabled = CbrEnabled;\r\n    MsaaWasEnabled = MsaaEnabled;\r\n    PrevMsaaMode = MsaaMode;\r\n}\r\n\r\nfloat ModelViewer::RecalculateResolutionScale( )\r\n{\r\n    float ResolutionScale;\r\n\r\n    static float FilteredFrameRate = Graphics::GetFrameRate();\r\n\r\n    // filter noise out of the frame rate\r\n    FilteredFrameRate = FilteredFrameRate * (1 - DrrFrameRateLowPassFilter) + (Graphics::GetFrameRate() * DrrFrameRateLowPassFilter);\r\n\r\n    // loosely based on the original algorithm here: https://software.intel.com/en-us/articles/dynamic-resolution-rendering-article/\r\n    float TimeRatio = FilteredFrameRate / DrrDesiredFrameRate;\r\n\r\n    // round our time ratio based on nearest 10th, 100th, 1000th, whatever the user has set\r\n    // this allows some headroom in the framerate to prevent resolution popping \r\n    // when the time+perf combination is hovering on a threshold\r\n    TimeRatio = ((int) (TimeRatio * (1.0f / DrrFrameRateDeltaResolution))) * DrrFrameRateDeltaResolution - 1.0f;\r\n\r\n    // increment or decrement our DRR scale based on the rate of change and framerate delta\r\n    float Scale = DrrInternalScale + DrrInternalScale * TimeRatio * DrrRateOfChange;\r\n\r\n    // clamp at 1.0 resolution: we do not allow super sampling until a downscale algorithm is implemented\r\n    Scale = Math::Min( Math::Max( Scale, DrrMinScale ), 1 );\r\n\r\n    // actual rendered scale is our internal scale rounded up to the nearest user specified resolution increment\r\n    ResolutionScale = ((int) (((Scale + .05f) * (1.0f / DrrResolutionIncrements)))) * DrrResolutionIncrements;\r\n\r\n    if ( DrrForceScale )\r\n        ResolutionScale = DrrMinScale;\r\n\r\n    DrrInternalFrameRate = (int) FilteredFrameRate;\r\n    DrrInternalScale = Scale;\r\n\r\n    return ResolutionScale;\r\n}\r\n\r\nvoid ModelViewer::SetFrameBuffers( GraphicsContext& context, int index, int alt_index, bool CbrWasEnabled, bool MsaaWasEnabled, int PrevMsaaMode )\r\n{\r\n    // NULL out all pointers so we can catch an error later \r\n    // if one is used but that mode isn't set\r\n    g_pMsaaColor = NULL;\r\n    g_pMsaaDepth = NULL;\r\n    g_pSceneDepthBuffer = NULL;\r\n    g_pCheckerboardColors[0] = NULL;\r\n    g_pCheckerboardDepths[0] = NULL;\r\n    g_pCheckerboardColors[1] = NULL;\r\n    g_pCheckerboardDepths[1] = NULL;\r\n\r\n    if ( CbrEnabled )\r\n    {\r\n        g_pCheckerboardColors[0] = &g_SceneColorBuffersCB2x[index];\r\n        g_pCheckerboardDepths[0] = &g_SceneDepthBuffersCB2x[index];\r\n        g_pCheckerboardColors[1] = &g_SceneColorBuffersCB2x[alt_index];\r\n        g_pCheckerboardDepths[1] = &g_SceneDepthBuffersCB2x[alt_index];\r\n\r\n        if ( CbrWasEnabled == false )\r\n        {\r\n            // Before barrier can be NULL but miniengine API takes reference so \r\n            // there seems to be no harm by setting a before barrier\r\n            context.InsertAliasBarrier( *g_pCheckerboardColors[0], *g_pCheckerboardColors[0] );\r\n            context.InsertAliasBarrier( *g_pCheckerboardColors[1], *g_pCheckerboardColors[1] );\r\n            context.InsertAliasBarrier( *g_pCheckerboardDepths[0], *g_pCheckerboardDepths[0] );\r\n            context.InsertAliasBarrier( *g_pCheckerboardDepths[1], *g_pCheckerboardDepths[1] );\r\n        }\r\n    }\r\n    else if ( MsaaEnabled )\r\n    {\r\n        switch ( MsaaMode )\r\n        {\r\n        case 0 : \r\n            g_pMsaaColor = &g_SceneColorBuffers2x[index];\r\n            g_pMsaaDepth = &g_SceneDepthBuffers2x[index];\r\n            break;\r\n        case 1:\r\n            g_pMsaaColor = &g_SceneColorBuffers4x[index];\r\n            g_pMsaaDepth = &g_SceneDepthBuffers4x[index];\r\n            break;\r\n        case 2:\r\n            g_pMsaaColor = &g_SceneColorBuffers8x[index];\r\n            g_pMsaaDepth = &g_SceneDepthBuffers8x[index];\r\n            break;\r\n\r\n        default:\r\n            break;\r\n        }\r\n\r\n        if ( (MsaaWasEnabled == false || (PrevMsaaMode - MsaaMode) != 0) )\r\n        {\r\n            // Before barrier can be NULL but miniengine API takes reference so \r\n            // there seems to be no harm by setting a before barrier\r\n            context.InsertAliasBarrier( *g_pMsaaColor, *g_pMsaaColor );\r\n            context.InsertAliasBarrier( *g_pMsaaDepth, *g_pMsaaDepth );\r\n        }\r\n    }\r\n    else\r\n    {\r\n        g_pSceneDepthBuffer = &g_SceneDepthBuffers[index];\r\n\r\n        if ( CbrWasEnabled || MsaaWasEnabled )\r\n            // Before barrier can be NULL but miniengine API takes reference so \r\n            // there seems to be no harm by setting a before barrier\r\n            context.InsertAliasBarrier( *g_pSceneDepthBuffer, *g_pSceneDepthBuffer );\r\n    }\r\n\r\n    g_pSceneColorBuffer = &g_SceneColorBuffers[index];\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/ModelViewer_VS17.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.26430.16\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"ModelViewer\", \"ModelViewer_VS17.vcxproj\", \"{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}\"\r\nEndProject\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Core\", \"..\\Core\\Core_VS17.vcxproj\", \"{86A58508-0D6A-4786-A32F-01A301FDC6F3}\"\r\nEndProject\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Model\", \"..\\Model\\Model_VS17.vcxproj\", \"{5D3AEEFB-8789-48E5-9BD9-09C667052D09}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Windows = Debug|Windows\r\n\t\tProfile|Windows = Profile|Windows\r\n\t\tRelease|Windows = Release|Windows\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}.Debug|Windows.ActiveCfg = Debug|x64\r\n\t\t{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}.Debug|Windows.Build.0 = Debug|x64\r\n\t\t{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}.Profile|Windows.ActiveCfg = Profile|x64\r\n\t\t{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}.Profile|Windows.Build.0 = Profile|x64\r\n\t\t{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}.Release|Windows.ActiveCfg = Release|x64\r\n\t\t{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}.Release|Windows.Build.0 = Release|x64\r\n\t\t{86A58508-0D6A-4786-A32F-01A301FDC6F3}.Debug|Windows.ActiveCfg = Debug|x64\r\n\t\t{86A58508-0D6A-4786-A32F-01A301FDC6F3}.Debug|Windows.Build.0 = Debug|x64\r\n\t\t{86A58508-0D6A-4786-A32F-01A301FDC6F3}.Profile|Windows.ActiveCfg = Profile|x64\r\n\t\t{86A58508-0D6A-4786-A32F-01A301FDC6F3}.Profile|Windows.Build.0 = Profile|x64\r\n\t\t{86A58508-0D6A-4786-A32F-01A301FDC6F3}.Release|Windows.ActiveCfg = Release|x64\r\n\t\t{86A58508-0D6A-4786-A32F-01A301FDC6F3}.Release|Windows.Build.0 = Release|x64\r\n\t\t{5D3AEEFB-8789-48E5-9BD9-09C667052D09}.Debug|Windows.ActiveCfg = Debug|x64\r\n\t\t{5D3AEEFB-8789-48E5-9BD9-09C667052D09}.Debug|Windows.Build.0 = Debug|x64\r\n\t\t{5D3AEEFB-8789-48E5-9BD9-09C667052D09}.Profile|Windows.ActiveCfg = Profile|x64\r\n\t\t{5D3AEEFB-8789-48E5-9BD9-09C667052D09}.Profile|Windows.Build.0 = Profile|x64\r\n\t\t{5D3AEEFB-8789-48E5-9BD9-09C667052D09}.Release|Windows.ActiveCfg = Release|x64\r\n\t\t{5D3AEEFB-8789-48E5-9BD9-09C667052D09}.Release|Windows.Build.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/ModelViewer_VS17.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Profile|x64\">\r\n      <Configuration>Profile</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{1813BD6E-E2AF-4A3C-8C54-4E72119DA993}</ProjectGuid>\r\n    <ApplicationEnvironment>title</ApplicationEnvironment>\r\n    <DefaultLanguage>en-US</DefaultLanguage>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <ProjectName>ModelViewer</ProjectName>\r\n    <RootNamespace>ModelViewer</RootNamespace>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>\r\n    <TargetRuntime>Native</TargetRuntime>\r\n    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <PlatformToolset>v141</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\" />\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Debug.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Release.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n    <Import Project=\"..\\PropertySheets\\VS17.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Profile.props\" />\r\n    <Import Project=\"..\\PropertySheets\\Win32.props\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <ItemDefinitionGroup>\r\n    <ClCompile>\r\n      <AdditionalIncludeDirectories>..\\Model;..\\rapidjson-master\\include\\rapidjson;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ClCompile>\r\n    <Link Condition=\"'$(Configuration)'=='Debug'\">\r\n      <AdditionalOptions>/nodefaultlib:MSVCRT %(AdditionalOptions)</AdditionalOptions>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Platform)'=='x64'\">\r\n    <Link>\r\n      <AdditionalDependencies>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)\r\n\t  </AdditionalDependencies>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"ForwardPlusLighting.cpp\" />\r\n    <ClCompile Include=\"ModelViewer.cpp\" />\r\n    <ClCompile Include=\"Scene.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"../Core/Core_VS17.vcxproj\">\r\n      <Project>{86A58508-0D6A-4786-A32F-01A301FDC6F3}</Project>\r\n      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r\n    </ProjectReference>\r\n    <ProjectReference Include=\"..\\Model\\Model_VS17.vcxproj\">\r\n      <Project>{5d3aeefb-8789-48e5-9bd9-09c667052d09}</Project>\r\n    </ProjectReference>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"Logo.png\" />\r\n    <Image Include=\"SmallLogo.png\" />\r\n    <Image Include=\"SplashScreen.png\" />\r\n    <Image Include=\"StoreLogo.png\" />\r\n    <Image Include=\"Textures\\default.DDS\" />\r\n    <Image Include=\"Textures\\default_normal.DDS\" />\r\n    <Image Include=\"Textures\\default_specular.DDS\" />\r\n    <Image Include=\"Textures\\fire.dds\" />\r\n    <Image Include=\"Textures\\Models\\background.DDS\" />\r\n    <Image Include=\"Textures\\Models\\background_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\chain_texture.DDS\" />\r\n    <Image Include=\"Textures\\Models\\chain_texture_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\gi_flag.DDS\" />\r\n    <Image Include=\"Textures\\Models\\lion.DDS\" />\r\n    <Image Include=\"Textures\\Models\\lion_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\spnza_bricks_a.DDS\" />\r\n    <Image Include=\"Textures\\Models\\spnza_bricks_a_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\spnza_bricks_a_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_arch.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_arch_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_arch_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_ceiling_a.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_ceiling_a_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_a.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_a_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_a_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_b.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_b_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_b_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_c.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_c_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_column_c_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_curtain.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_curtain_blue.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_curtain_green.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_details.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_details_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_fabric.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_fabric_blue.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_fabric_green.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_fabric_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_flagpole.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_flagpole_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_floor_a.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_floor_a_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_roof.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_thorn.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_thorn_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\sponza_thorn_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_hanging.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_plant.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_plant_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_round.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_round_normal.DDS\" />\r\n    <Image Include=\"Textures\\Models\\vase_round_specular.DDS\" />\r\n    <Image Include=\"Textures\\Models\\white.DDS\" />\r\n    <Image Include=\"Textures\\smoke.dds\" />\r\n    <Image Include=\"Textures\\sparkTex.dds\" />\r\n    <Image Include=\"WideLogo.png\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"Models\\sponza.h3d\">\r\n      <DeploymentContent>true</DeploymentContent>\r\n    </None>\r\n    <None Include=\"Shaders\\DepthViewerPSHeader.hlsli\" />\r\n    <None Include=\"Shaders\\FillLightGridCS.hlsli\" />\r\n    <None Include=\"Shaders\\LightGrid.hlsli\" />\r\n    <None Include=\"Shaders\\ModelViewerPSHeader.hlsli\" />\r\n    <None Include=\"Shaders\\ModelViewerRS.hlsli\" />\r\n    <None Include=\"Shaders\\SamplePositions.hlsli\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <FxCompile Include=\"Shaders\\CheckerboardColorResolveCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CheckerboardDepthResolveCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DepthViewerPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DepthViewerPS_CBR.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DepthViewerVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_16.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_24.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_32.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_8.hlsl\" />\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS_CBR.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS_CBR_PP.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS_CPS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Pixel</ShaderType>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Pixel</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerVS.hlsl\">\r\n      <ShaderType>Vertex</ShaderType>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MsaaColorResolveCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MsaaDepthResolveCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\UpsampleColorResolveCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\UpsampleDepthResolveCS.hlsl\">\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Profile|x64'\">5.0</ShaderModel>\r\n      <ShaderType Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Compute</ShaderType>\r\n      <ShaderModel Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">5.0</ShaderModel>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\WaveTileCountPS.hlsl\">\r\n      <ShaderType>Pixel</ShaderType>\r\n    </FxCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"ForwardPlusLighting.h\" />\r\n    <ClInclude Include=\"Scene.h\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ItemDefinitionGroup>\r\n    <Link>\r\n      <AdditionalLibraryDirectories>..\\zlib-1.2.11\\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n      <AdditionalDependencies>zlibstat.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <AdditionalOptions>/nodefaultlib:LIBCMT %(AdditionalOptions)</AdditionalOptions>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ImportGroup Label=\"ExtensionTargets\" />\r\n</Project>"
  },
  {
    "path": "MiniEngine/ModelViewer/ModelViewer_VS17.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Resource Files\">\r\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\">\r\n      <UniqueIdentifier>{06dcf987-d5c3-489b-aa0a-88d547a323d5}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\LightPass\">\r\n      <UniqueIdentifier>{5deb19ec-a845-459c-9ca2-02e2bb35a35b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\ResolveCS\">\r\n      <UniqueIdentifier>{8509ac90-99aa-4e55-9f86-c12aaf69ab94}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\ModelViewer\">\r\n      <UniqueIdentifier>{53128894-7446-48eb-8153-ce3b7c8c90ee}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Shaders\\DepthViewer\">\r\n      <UniqueIdentifier>{3fcabe4b-4054-4c41-ba66-2514e6aa47bb}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"Logo.png\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"SmallLogo.png\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"SplashScreen.png\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"StoreLogo.png\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\default.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\default_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\default_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\background.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\background_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\chain_texture.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\chain_texture_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\gi_flag.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\lion.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\lion_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\spnza_bricks_a.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\spnza_bricks_a_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\spnza_bricks_a_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_arch.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_arch_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_arch_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_ceiling_a.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_ceiling_a_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_a.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_a_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_a_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_b.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_b_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_b_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_c.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_c_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_column_c_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_curtain.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_curtain_blue.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_curtain_green.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_details.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_details_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_fabric.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_fabric_blue.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_fabric_green.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_fabric_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_flagpole.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_flagpole_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_floor_a.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_floor_a_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_roof.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_thorn.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_thorn_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\sponza_thorn_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_hanging.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_plant.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_plant_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_round.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_round_normal.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\vase_round_specular.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\Models\\white.DDS\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"WideLogo.png\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\fire.dds\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\smoke.dds\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n    <Image Include=\"Textures\\sparkTex.dds\">\r\n      <Filter>Resource Files</Filter>\r\n    </Image>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"Models\\sponza.h3d\">\r\n      <Filter>Resource Files</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\FillLightGridCS.hlsli\">\r\n      <Filter>Shaders\\LightPass</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\LightGrid.hlsli\">\r\n      <Filter>Shaders\\LightPass</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\SamplePositions.hlsli\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ModelViewerPSHeader.hlsli\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\ModelViewerRS.hlsli\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </None>\r\n    <None Include=\"Shaders\\DepthViewerPSHeader.hlsli\">\r\n      <Filter>Shaders\\DepthViewer</Filter>\r\n    </None>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"ModelViewer.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ForwardPlusLighting.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Scene.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <FxCompile Include=\"Shaders\\WaveTileCountPS.hlsl\">\r\n      <Filter>Shaders</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_8.hlsl\">\r\n      <Filter>Shaders\\LightPass</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_16.hlsl\">\r\n      <Filter>Shaders\\LightPass</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_24.hlsl\">\r\n      <Filter>Shaders\\LightPass</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\FillLightGridCS_32.hlsl\">\r\n      <Filter>Shaders\\LightPass</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CheckerboardDepthResolveCS.hlsl\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MsaaColorResolveCS.hlsl\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\MsaaDepthResolveCS.hlsl\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\UpsampleColorResolveCS.hlsl\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\UpsampleDepthResolveCS.hlsl\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\CheckerboardColorResolveCS.hlsl\">\r\n      <Filter>Shaders\\ResolveCS</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS.hlsl\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS_CBR.hlsl\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS_CPS.hlsl\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerVS.hlsl\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DepthViewerVS.hlsl\">\r\n      <Filter>Shaders\\DepthViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DepthViewerPS.hlsl\">\r\n      <Filter>Shaders\\DepthViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\ModelViewerPS_CBR_PP.hlsl\">\r\n      <Filter>Shaders\\ModelViewer</Filter>\r\n    </FxCompile>\r\n    <FxCompile Include=\"Shaders\\DepthViewerPS_CBR.hlsl\">\r\n      <Filter>Shaders\\DepthViewer</Filter>\r\n    </FxCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"ForwardPlusLighting.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Scene.h\">\r\n      <Filter>Source Files</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "MiniEngine/ModelViewer/Scene.cpp",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n#define _ENABLE_EXTENDED_ALIGNED_STORAGE\r\n\r\n#include \"pch.h\"\r\n\r\n#include \"Scene.h\"\r\n\r\n#include \"document.h\"\r\n\r\n#include <iostream>\r\n#include <fstream>\r\n#include <sstream>\r\n#include <filesystem>\r\n\r\nusing namespace ART;\r\nusing namespace Math;\r\nusing namespace std::experimental;\r\n\r\n#define STRMATCH(x, y) (strcmp(x, y) == 0)\r\n\r\nbool Scene::LoadJson(const char* path) {\r\n\r\n\tstd::ifstream file;\r\n\tfile.open(path, std::ios::binary);\r\n\tif (!file) {\r\n\t\tstd::cout << \"Failed to open scene file: \" << path << std::endl;\r\n\t\treturn false;\r\n\t}\r\n\tstd::stringstream ss;\r\n\tss << file.rdbuf();\r\n\tfile.close();\r\n\r\n\tm_ShadowDim = Math::Vector3(0);\r\n\r\n\tfilesystem::path fullPath(filesystem::absolute( filesystem::path(path) ));\r\n\r\n\tfilesystem::path sceneRootDir = fullPath.remove_filename();\r\n\tm_Root = sceneRootDir.generic_string();\r\n\r\n\t//std::cout << \"Scene root dir: \" << sceneRootDir;\r\n\r\n\tfilesystem::path modelPath;\r\n\tfilesystem::path animPath;\r\n\tfilesystem::path textureRootPath = sceneRootDir / filesystem::path(\"Textures\");\r\n\r\n\t//bool hasCamera = false;\r\n\t//Camera sceneCam;\r\n\tbool hasAnimation = false;\r\n\r\n\trapidjson::Document doc;\r\n\tif (doc.Parse(ss.str().c_str()).HasParseError()) {\r\n\t\tstd::cout << \"Error parsing JSON: document not recognized as object.\" << std::endl;\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfor (rapidjson::Value::MemberIterator it = doc.MemberBegin(); it != doc.MemberEnd(); it++) {\r\n\r\n\t\tconst char* name = it->name.GetString();\r\n\t\trapidjson::Value& val = it->value;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tif (STRMATCH(name, \"ModelPath\")) {\r\n\t\t\t\tif (!val.IsString())\r\n\t\t\t\t\tthrow SerializationException(\"'ModelPath' : expected string\");\r\n\t\t\t\tmodelPath = val.GetString();\r\n\t\t\t\tif (modelPath.is_relative()) {\r\n\t\t\t\t\tmodelPath = sceneRootDir / modelPath;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"Animation\")) {\r\n\t\t\t\tif (!val.IsString())\r\n\t\t\t\t\tthrow SerializationException(\"'Animation' : expected string\");\r\n\t\t\t\tanimPath = val.GetString();\r\n\t\t\t\tif (animPath.is_relative()) {\r\n\t\t\t\t\tanimPath = sceneRootDir / animPath;\r\n\t\t\t\t}\r\n\t\t\t\thasAnimation = true;\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"TextureRoot\")) {\r\n\t\t\t\tif (!val.IsString())\r\n\t\t\t\t\tthrow SerializationException(\"'TextureRoot' : expected string\");\r\n\t\t\t\ttextureRootPath = val.GetString();\r\n\t\t\t\tif (textureRootPath.is_relative()) {\r\n\t\t\t\t\ttextureRootPath = sceneRootDir / textureRootPath;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"Camera\")) {\r\n\t\t\t\tif (!val.IsObject())\r\n\t\t\t\t\tthrow SerializationException(\"'Camera' : expected JSON object\");\r\n\t\t\t\t// To be supported in the future...\r\n\t\t\t}\r\n\t\t\telse if (STRMATCH(name, \"ShadowDim\")) {\r\n\t\t\t\tif (!val.IsArray() || val.Size() != 3)\r\n\t\t\t\t\tthrow SerializationException(\"'ShadowDim' : expected array of 3 floats\");\r\n\t\t\t\tm_ShadowDim.SetX((float)val[0].GetDouble());\r\n\t\t\t\tm_ShadowDim.SetY((float)val[1].GetDouble());\r\n\t\t\t\tm_ShadowDim.SetZ((float)val[2].GetDouble());\r\n\t\t\t}\r\n\t\t}\r\n\t\tcatch (SerializationException ex) {\r\n\t\t\tstd::stringstream msg;\r\n\t\t\tmsg << \"Error parsing scene: \" << ex.Message;\r\n\t\t\tUtility::Print(msg.str().c_str());\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tCleanup();\r\n\r\n\t// no real JSON load yet, just migrated the code from ModelViewer\r\n\tstd::cout << std::endl;\r\n\tstd::cout << \"Model path: \" << modelPath.generic_string() << std::endl;\r\n\tstd::cout << \"Texture root: \" << textureRootPath << std::endl;\r\n\r\n\tTextureManager::Initialize(textureRootPath.wstring() + L\"/\");\r\n\r\n\tbool success = m_Model.Load(modelPath.generic_string().c_str());\r\n\tASSERT(success, \"Failed to load model\");\r\n\tASSERT(m_Model.m_Header.meshCount > 0, \"Model contains no meshes\");\r\n\r\n\tauto box = m_Model.m_Header.boundingBox.max - m_Model.m_Header.boundingBox.min;\r\n\tstd::cout << \"BBox size: [\" << box.GetX() << \", \" << box.GetY() << \", \" << box.GetZ() << \"]\" << std::endl;\r\n\r\n\tm_ModelRadius = Length(m_Model.m_Header.boundingBox.max - m_Model.m_Header.boundingBox.min) * .5f;\r\n\tm_Center = (m_Model.m_Header.boundingBox.min + m_Model.m_Header.boundingBox.max) * .5f;\r\n\tconst Vector3 eye = (m_Model.m_Header.boundingBox.min + m_Model.m_Header.boundingBox.max) * .5f + Vector3(m_ModelRadius * .5f, 0.0f, 0.0f);\r\n\tm_Camera.SetEyeAtUp(eye, Vector3(kZero), Vector3(kYUnitVector));\r\n\tm_Camera.SetZRange(0.0001f * m_ModelRadius, 10.0f * m_ModelRadius);\r\n\r\n\tm_SceneAnimation = std::make_shared<SceneAnimation>();\r\n\t// set default animation if load fails\r\n\tif (!hasAnimation || !m_SceneAnimation->LoadJson(animPath.generic_string().c_str())) {\r\n\t\tm_SceneAnimation->SetTimeSpan(0, 5);\r\n\t\tm_SceneAnimation->SetTime(0);\r\n\t\tanimPath = sceneRootDir / \"default.anim\";\r\n\t}\r\n\r\n\tm_AnimationPath = animPath.generic_string();\r\n\tm_TextureRoot = textureRootPath.generic_string() + std::string(\"/\");\r\n\r\n\treturn success;\r\n}\r\n\r\nbool Scene::UpdateAnimation() {\r\n\t// attempt to load the animation file again\r\n\tauto newAnimation = std::make_shared<SceneAnimation>();\r\n\tif (newAnimation->LoadJson(m_AnimationPath.c_str())) {\r\n\t\tm_SceneAnimation = newAnimation;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Scene::SaveAnimation() {\r\n\tm_SceneAnimation->SaveJson(m_AnimationPath.c_str());\r\n}\r\n\r\nvoid Scene::Cleanup() {\r\n\tm_Model.Clear();\r\n\tm_SceneAnimation = nullptr;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Scene.h",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#pragma once\r\n\r\n#include \"Camera.h\"\r\n#include \"CameraController.h\"\r\n#include \"Model.h\"\r\n\r\n#include \"Art/Animation/SceneAnimation.h\"\r\n\r\n// Simple scene class to encapsulate animation and asset paths\r\n\r\nclass Scene {\r\n\r\npublic:\r\n\r\n\tScene() {};\r\n\r\n\tbool LoadJson(const char* path);\r\n\r\n\tvoid Cleanup();\r\n\r\n\t// reloads the animation file\r\n\tbool UpdateAnimation();\r\n\t\r\n\t// overwrites the animation file\r\n\tvoid SaveAnimation();\r\n\r\n\tconst std::string& GetName() const {\r\n\t\treturn m_Name;\r\n\t}\r\n\r\n\tModel& GetModel() { return m_Model; }\r\n\tART::SceneAnimation_ptr& GetAnimation() { return m_SceneAnimation; }\r\n\tMath::Camera& GetCamera() { return m_Camera; };\r\n\r\n\tconst std::string& GetTextureRoot() const {\r\n\t\treturn m_TextureRoot;\r\n\t}\r\n\r\n\tconst std::string& GetRootFolder() const {\r\n\t\treturn m_Root;\r\n\t}\r\n\r\n\tfloat GetModelRadius() const { return m_ModelRadius; }\r\n\tconst Math::Vector3& GetCenter()const { return m_Center; }\r\n\tconst Math::Vector3& GetShadowDim() const { return m_ShadowDim; }\r\n\r\nprotected:\r\n\r\n\tstd::string\t\t\t\t\tm_Name;\r\n\tstd::string\t\t\t\t\tm_AnimationPath;\r\n\tstd::string\t\t\t\t\tm_TextureRoot;\r\n\tstd::string\t\t\t\t\tm_Root;\r\n\r\n\tModel\t\t\t\t\t\tm_Model;\r\n\tfloat\t\t\t\t\t\tm_ModelRadius;\r\n\tMath::Vector3\t\t\t\tm_Center;\r\n\tMath::Vector3\t\t\t\tm_ShadowDim;\r\n\tART::SceneAnimation_ptr\t\tm_SceneAnimation;\r\n\tMath::Camera\t\t\t\tm_Camera;\r\n\r\n};\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/CheckerboardColorResolveCS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include \"SamplePositions.hlsli\"\r\n#include \"../../Core/Shaders/ShaderUtility.hlsli\"\r\n\r\n#define CheckerboardResolve_RootSig \\\r\n    \"RootFlags(0), \" \\\r\n    \"CBV(b0), \" \\\r\n    \"DescriptorTable(SRV(t0, numDescriptors = 4)),\" \\\r\n    \"DescriptorTable(UAV(u0, numDescriptors = 1))\"\r\n\r\nTexture2DMS<float4> DownSizedInColor2x0 : register(t0);\r\nTexture2DMS<float4> DownSizedInColor2x1 : register(t1);\r\nTexture2DMS<unorm float> DownSizedInDepth2x0 : register(t2);\r\nTexture2DMS<unorm float> DownSizedInDepth2x1 : register(t3);\r\nRWTexture2D<float4> OutColor : register(u0);\r\n\r\n#define Up\t\t0\r\n#define Down\t1\r\n#define Left\t2\r\n#define Right\t3\r\n\r\n//#define HALF_PRECISION;\r\n\r\n#ifdef HALF_PRECISION\r\n#define lpfloat min16float\r\n#define lpfloat2 min16float2\r\n#define lpfloat3 min16float3\r\n#define lpfloat4 min16float4\r\n#else\r\n#define lpfloat float\r\n#define lpfloat2 float2\r\n#define lpfloat3 float3\r\n#define lpfloat4 float4\r\n#endif\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n    float FrameOffset;\r\n    float DepthTolerance;\r\n    uint Flags;\r\n    float _Pad;\r\n    float4 LinearZTransform;\r\n    float4x4 CurrViewProj;\r\n    float4x4 PrevInvViewProj;\r\n}\r\n\r\n// Simple tonemap to invtonemap color blend\r\n// should be replaced by customized solution\r\nfloat3 hdrColorBlend(float3 a, float3 b, float3 c, float3 d)\r\n{\r\n    // Reinhard \r\n    float3 t_a = a / (a + 1);\r\n    float3 t_b = b / (b + 1);\r\n    float3 t_c = c / (c + 1);\r\n    float3 t_d = d / (d + 1);\r\n\r\n    float3 color = (t_a + t_b + t_c + t_d) * .25f;\r\n\r\n    // back to hdr\r\n    return -color / (color - 1);\r\n}\r\n\r\n// convert projected depth into projected pixel position \r\n// for frame N-1\r\nuint2 previousPixelPos(float2 pixel, float currDepth, float2 res)\r\n{\r\n    // no depth buffer information\r\n    if (currDepth <= 0.0)\r\n        return pixel;\r\n\r\n    uint2 old_pixel = floor(pixel);\r\n\r\n    // Projection is flipped from UV coords\r\n    pixel.y = res.y - pixel.y - 1;\r\n\r\n    float2 projected = pixel / res * 2.0 - 1;\r\n\r\n    float4 re_projected_pre_w_divide = float4(projected.x, projected.y, currDepth, 1.0);\r\n    float4 ws = mul(re_projected_pre_w_divide, PrevInvViewProj);\r\n    ws /= ws.w;\r\n\r\n    float4 ws_to_curr_projection = mul(ws, CurrViewProj);\r\n    ws_to_curr_projection = ws_to_curr_projection / ws_to_curr_projection.w;\r\n\r\n    float2 curr = ws_to_curr_projection.xy * (res / 2) + (res / 2);\r\n    curr.y = res.y - curr.y - 1;\r\n\r\n    uint2 new_pixel = floor(curr);\r\n    int2 delta = new_pixel - old_pixel;\r\n\r\n    return old_pixel - delta;\r\n}\r\n\r\nfloat4 readFromQuadrant(int2 pixel, int quadrant)\r\n{\r\n    if (0 == quadrant)\r\n        return DownSizedInColor2x0.Load(pixel, 1);\r\n    else if (1 == quadrant)\r\n        return DownSizedInColor2x1.Load(pixel + int2(1, 0), 1);\r\n    else if (2 == quadrant)\r\n        return DownSizedInColor2x1.Load(pixel, 0);\r\n    else //( 3 == quadrant )\r\n        return DownSizedInColor2x0.Load(pixel, 0);\r\n}\r\n\r\nfloat readDepthFromQuadrant(int2 pixel, int quadrant)\r\n{\r\n    if (0 == quadrant)\r\n        return DownSizedInDepth2x0.Load(pixel, 1);\r\n    else if (1 == quadrant)\r\n        return DownSizedInDepth2x1.Load(pixel + int2(1, 0), 1);\r\n    else if (2 == quadrant)\r\n        return DownSizedInDepth2x1.Load(pixel, 0);\r\n    else //( 3 == quadrant )\r\n        return DownSizedInDepth2x0.Load(pixel, 0);\r\n}\r\n\r\nfloat4 colorFromCardinalOffsets(uint2 qtr_res_pixel, int2 offsets[4], int quadrants[2])\r\n{\r\n    float4 color[4];\r\n\r\n    float2 w;\r\n\r\n    color[Up] = readFromQuadrant(qtr_res_pixel + offsets[Up], quadrants[0]);\r\n    color[Down] = readFromQuadrant(qtr_res_pixel + offsets[Down], quadrants[0]);\r\n    color[Left] = readFromQuadrant(qtr_res_pixel + offsets[Left], quadrants[1]);\r\n    color[Right] = readFromQuadrant(qtr_res_pixel + offsets[Right], quadrants[1]);\r\n\r\n    return float4(hdrColorBlend(color[Up].rgb, color[Down].rgb, color[Left].rgb, color[Right].rgb), 1);\r\n}\r\n\r\nvoid getCardinalOffsets(int quadrant, out int2 offsets[4], out int quadrants[2])\r\n{\r\n    if (quadrant == 0)\r\n    {\r\n        offsets[Up] = -int2(0, 1);\r\n        offsets[Down] = 0;\r\n        offsets[Left] = -int2(1, 0);\r\n        offsets[Right] = 0;\r\n\r\n        quadrants[0] = 2;\r\n        quadrants[1] = 1;\r\n    }\r\n    else if (quadrant == 1)\r\n    {\r\n        offsets[Up] = -int2(0, 1);\r\n        offsets[Down] = 0;\r\n        offsets[Left] = 0;\r\n        offsets[Right] = +int2(1, 0);\r\n\r\n        quadrants[0] = 3;\r\n        quadrants[1] = 0;\r\n    }\r\n    else if (quadrant == 2)\r\n    {\r\n        offsets[Up] = 0;\r\n        offsets[Down] = +int2(0, 1);\r\n        offsets[Left] = -int2(1, 0);\r\n        offsets[Right] = 0;\r\n\r\n        quadrants[0] = 0;\r\n        quadrants[1] = 3;\r\n    }\r\n    else // ( quadrant == 3 )\r\n    {\r\n        offsets[Up] = 0;\r\n        offsets[Down] = +int2(0, 1);\r\n        offsets[Left] = 0;\r\n        offsets[Right] = +int2(1, 0);\r\n\r\n        quadrants[0] = 1;\r\n        quadrants[1] = 2;\r\n    }\r\n}\r\n\r\nfloat projectedDepthToLinear(float depth)\r\n{\r\n    return (depth * LinearZTransform.x + LinearZTransform.y) / (depth * LinearZTransform.z + LinearZTransform.w);\r\n}\r\n\r\nfloat4 Resolve2xSampleTemporal(float FrameOffset, uint2 dispatchThreadId)\r\n{\r\n    uint2 full_res;\r\n    OutColor.GetDimensions(full_res.x, full_res.y);\r\n\r\n#define DEBUG_RENDER\r\n\r\n#ifdef DEBUG_RENDER\r\n    const bool render_motion_vectors = (Flags & 0x01) != 0;\r\n    const bool render_missing_pixels = (Flags & 0x02) != 0;\r\n    const bool render_qtr_motion_pixels = (Flags & 0x04) != 0;\r\n    const bool render_checker_pattern_odd = (Flags & 0x08) != 0;\r\n    const bool render_checker_pattern_even = (Flags & 0x10) != 0;\r\n    const bool render_obstructed_pixels = (Flags & 0x20) != 0;\r\n#endif\r\n\r\n    const bool check_shading_occlusion = (Flags & 0x40) != 0;\r\n    const bool render_resolution_changed = (Flags & 0x80) != 0;\r\n    const uint2 qtr_res = full_res * .5;\r\n    const uint2 full_res_pixel = dispatchThreadId.xy;\r\n    const uint2 qtr_res_pixel = floor(dispatchThreadId.xy * .5);\r\n    const uint quadrant = (dispatchThreadId.x & 0x1) + (dispatchThreadId.y & 0x1) * 2;\r\n    const float tolerance = DepthTolerance;\r\n\r\n    const uint frame_lookup[2][2] =\r\n    {\r\n       { 0, 3 },\r\n       { 1, 2 }\r\n    };\r\n\r\n    uint frame_quadrants[2];\r\n    frame_quadrants[0] = frame_lookup[FrameOffset][0];\r\n    frame_quadrants[1] = frame_lookup[FrameOffset][1];\r\n\r\n#ifdef DEBUG_RENDER\r\n    if (render_checker_pattern_odd + render_checker_pattern_even > 0)\r\n    {\r\n        if ((render_checker_pattern_even && (quadrant == 0 || quadrant == 3)) ||\r\n            (render_checker_pattern_odd && (quadrant == 1 || quadrant == 2)))\r\n            return readFromQuadrant(qtr_res_pixel, quadrant);\r\n        else\r\n            return float4(0, 0, 0, 1);\r\n    }\r\n#endif\r\n\r\n    // if the pixel we are writing to is in a MSAA quadrant which matches our latest CB frame\r\n    // then read it directly and we're done\r\n    if (frame_quadrants[0] == quadrant || frame_quadrants[1] == quadrant)\r\n        return readFromQuadrant(qtr_res_pixel, quadrant);\r\n    else\r\n    {\r\n        // We need to read from Frame N-1\r\n\r\n        int2 cardinal_offsets[4];\r\n        int cardinal_quadrants[2];\r\n\r\n        // Get the locations of the pixels in Frame N which surround\r\n        // our current pixel location\r\n        getCardinalOffsets(quadrant, cardinal_offsets, cardinal_quadrants);\r\n\r\n        bool missing_pixel = false;\r\n\r\n        // if the render resolution changed then last frame's data is invalid\r\n        // so ignore it entirely and early out\r\n        if (render_resolution_changed)\r\n            return colorFromCardinalOffsets(qtr_res_pixel, cardinal_offsets, cardinal_quadrants);\r\n\r\n        // What is the depth at this pixel which was written to by Frame N-1\r\n        float depth = readDepthFromQuadrant(qtr_res_pixel, quadrant);\r\n\r\n        // Project that through the matrices and get the screen space position\r\n        // this pixel was rendered in Frame N-1\r\n        uint2 prev_pixel_pos = previousPixelPos(full_res_pixel + .5f, depth, full_res);\r\n\r\n        int2 pixel_delta = floor((full_res_pixel + .5f) - prev_pixel_pos);\r\n        int2 qtr_res_pixel_delta = pixel_delta * .5f;\r\n\r\n        int2 prev_qtr_res_pixel = floor(prev_pixel_pos * .5f);\r\n\r\n        // Which MSAA quadrant was this pixel in when it was shaded in Frame N-1\r\n        uint quadrant_needed = (prev_pixel_pos.x & 0x1) + (prev_pixel_pos.y & 0x1) * 2;\r\n\r\n#ifdef DEBUG_RENDER\r\n        if (render_motion_vectors && (pixel_delta.x || pixel_delta.y))\r\n            return float4(1, 0, 0, 1);\r\n\r\n        if (render_qtr_motion_pixels && (qtr_res_pixel_delta.x || qtr_res_pixel_delta.y))\r\n            return float4(0, 1, 0, 1);\r\n#endif\r\n\r\n        // if it falls on this frame (Frame N)'s quadrant then the shading information is missing\r\n        // so extrapolate the color from the texels around us\r\n        if (frame_quadrants[0] == quadrant_needed || frame_quadrants[1] == quadrant_needed)\r\n            missing_pixel = true;\r\n        else if (qtr_res_pixel_delta.x || qtr_res_pixel_delta.y)\r\n        {\r\n            // Otherwise we might have the shading information,\r\n            // Now we check to see if it's obstructed\r\n\r\n            // If the user doesn't want to check for obstruction we just assume it's obstructed\r\n            // and this pixel will be an extrapolation of the Frame N pixels around it\r\n            // This generally saves on perf and isn't noticeable because the pixels are in motion anyway\r\n            if (false == check_shading_occlusion)\r\n                missing_pixel = true;\r\n            else\r\n            {\r\n                float4 current_depth = 0;\r\n                const int count = 4;\r\n\r\n                // Fetch the interpolated depth at this location in Frame N\r\n                current_depth.x = readDepthFromQuadrant(qtr_res_pixel + cardinal_offsets[Left], cardinal_quadrants[1]);\r\n                current_depth.y = readDepthFromQuadrant(qtr_res_pixel + cardinal_offsets[Right], cardinal_quadrants[1]);\r\n\r\n                current_depth.z = readDepthFromQuadrant(qtr_res_pixel + cardinal_offsets[Down], cardinal_quadrants[0]);\r\n                current_depth.w = readDepthFromQuadrant(qtr_res_pixel + cardinal_offsets[Up], cardinal_quadrants[0]);\r\n\r\n                float current_depth_avg = (projectedDepthToLinear(current_depth.x) +\r\n                    projectedDepthToLinear(current_depth.y) +\r\n                    projectedDepthToLinear(current_depth.z) +\r\n                    projectedDepthToLinear(current_depth.w)) * .25f;\r\n\r\n                // reach across the frame N-1 and grab the depth of the pixel we want\r\n                // then compare it to Frame N's depth at this pixel to see if it's within range\r\n                float prev_depth = readDepthFromQuadrant(prev_qtr_res_pixel, quadrant_needed);\r\n                prev_depth = projectedDepthToLinear(prev_depth);\r\n\r\n                // if the discrepancy is too large assume the pixel we need to \r\n                // fetch from the previous buffer is missing\r\n                float diff = prev_depth - current_depth_avg;\r\n                missing_pixel = abs(diff) >= tolerance;\r\n\r\n#ifdef DEBUG_RENDER\r\n                if (render_obstructed_pixels && missing_pixel)\r\n                    return float4(1, 0, 1, 1);\r\n#endif\r\n            }\r\n        }\r\n\r\n#ifdef DEBUG_RENDER\r\n        if (render_missing_pixels && missing_pixel)\r\n            return float4(1, 0, 0, 1);\r\n#endif\r\n\r\n        // If we've determined the pixel (i.e. shading information) is missing,\r\n        // then extrapolate the missing color by blending the \r\n        // current frame's up, down, left, right pixels\r\n        if (missing_pixel == true)\r\n            return colorFromCardinalOffsets(qtr_res_pixel, cardinal_offsets, cardinal_quadrants);\r\n        else\r\n            return readFromQuadrant(prev_qtr_res_pixel, quadrant_needed);\r\n    }\r\n}\r\n\r\n[RootSignature(CheckerboardResolve_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main(uint3 DTid : SV_DispatchThreadID)\r\n{\r\n    float4 Color = Resolve2xSampleTemporal(FrameOffset, DTid.xy);\r\n    OutColor[DTid.xy] = float4(Color.xyz, 1.0f);\r\n}"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/CheckerboardDepthResolveCS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include \"SamplePositions.hlsli\"\r\n\r\n#define CheckerboardResolve_RootSig \\\r\n    \"RootFlags(0), \" \\\r\n    \"CBV(b0), \" \\\r\n    \"DescriptorTable(SRV(t0, numDescriptors = 2)),\" \\\r\n    \"DescriptorTable(UAV(u0, numDescriptors = 1))\"\r\n\r\nTexture2DMS<float> DownSizedInDepth2x0 : register(t0);\r\nTexture2DMS<float> DownSizedInDepth2x1 : register(t1);\r\nRWTexture2D<float> OutDepth : register(u0);\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n\tfloat ZMagic;\t\t\t\t// (zFar - zNear) / zNear\r\n\tfloat FrameOffset;\r\n}\r\n\r\n[RootSignature(CheckerboardResolve_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main(uint3 DTid : SV_DispatchThreadID)\r\n{\r\n\tfloat Depth;\r\n\tfloat LinearZ;\r\n\r\n\tuint2 ID;\r\n\tuint SubSampleID;\r\n\tint Offset;\r\n\t\r\n\tID = DTid.xy * 0.5;\r\n\tSubSampleID = DTid.x % 2 + (DTid.y % 2) * 2;\r\n\r\n\tif (FrameOffset > 0) {\r\n\t\t// sample #1 and #2 is rendered, #0 and #3 need to be filled\r\n\t\tif (SubSampleID == 1 || SubSampleID == 2) {\r\n\t\t\tif (SubSampleID == 1)\tID.x = ID.x + 1;\r\n\t\t\tOffset = offset2[SubSampleID - 1];\r\n\t\t\tDepth = DownSizedInDepth2x1.Load(ID.xy, Offset);\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// simply copying the other (vertically) sample's depth \r\n\t\t\tif (SubSampleID == 3) ID.x = ID.x + 1;\r\n\t\t\tOffset = offset2[SubSampleID % 2];\r\n\t\t\tDepth = DownSizedInDepth2x1.Load(ID.xy, Offset);\r\n\t\t}\r\n\t}\r\n\telse {\r\n\t\t// sample #0 and #3 is rendered, #1 and #2 need to be filled\r\n\t\tif (SubSampleID == 0 || SubSampleID == 3) {\r\n\t\t\tOffset = offset2[SubSampleID % 2];\r\n\t\t\tDepth = DownSizedInDepth2x0.Load(ID.xy, Offset);\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// simply copying the other (vertically) sample's depth \r\n\t\t\tOffset = offset2[(SubSampleID +2)%4];\r\n\t\t\tDepth = DownSizedInDepth2x0.Load(ID.xy, Offset);\r\n\t\t}\r\n\t}\r\n\r\n\tLinearZ = 1.0 / (ZMagic * Depth + 1.0);\r\n\tOutDepth[DTid.xy] = LinearZ;\r\n}"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/DepthViewerPS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include \"DepthViewerPSHeader.hlsli\""
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/DepthViewerPSHeader.hlsli",
    "content": "// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author(s):\tJames Stanard\n//\n\n// Modified 2018, Intel Corporation\n// Added derivatives for customizable mip levels\n\n#include \"ModelViewerRS.hlsli\"\n\nstruct VSOutput\n{\n\tsample float4 pos : SV_Position;\n\tsample float2 uv : TexCoord0;\n};\n\nTexture2D<float4>\ttexDiffuse\t\t: register(t0);\nTexture2D<float>\ttexOpacity\t\t: register(t6);\nSamplerState\t\tsampler0\t\t: register(s0);\n\n[RootSignature(ModelViewer_RootSig)]\nvoid main(VSOutput vsOutput)\n{\n#ifdef DDXY_BIAS\n\tfloat2 tdx = ddx_fine(vsOutput.uv);\n\tfloat2 tdy = ddy_fine(vsOutput.uv);\n\n\tif (texOpacity.SampleGrad(sampler0, vsOutput.uv, tdx * DDXY_BIAS, tdy * DDXY_BIAS).x < 0.5)\n\t\tdiscard;\n#else\n\tif (texOpacity.Sample(sampler0, vsOutput.uv).x < 0.5)\n\t\tdiscard;\n#endif\n\n}\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/DepthViewerPS_CBR.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define DDXY_BIAS 0.5f\r\n\r\n#include \"DepthViewerPSHeader.hlsli\""
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/DepthViewerVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//             Alex Nankervis\r\n//\r\n\r\n#include \"ModelViewerRS.hlsli\"\r\n\r\ncbuffer VSConstants : register(b0)\r\n{\r\n    float4x4 modelToProjection;\r\n};\r\n\r\nstruct VSInput\r\n{\r\n    float3 position : POSITION;\r\n    float2 texcoord0 : TEXCOORD;\r\n    float3 normal : NORMAL;\r\n    float3 tangent : TANGENT;\r\n    float3 bitangent : BITANGENT;\r\n};\r\n\r\nstruct VSOutput\r\n{\r\n    float4 pos : SV_Position;\r\n    float2 uv : TexCoord0;\r\n};\r\n\r\n[RootSignature(ModelViewer_RootSig)]\r\nVSOutput main(VSInput vsInput)\r\n{\r\n    VSOutput vsOutput;\r\n    vsOutput.pos = mul(modelToProjection, float4(vsInput.position, 1.0));\r\n    vsOutput.uv = vsInput.texcoord0;\r\n    return vsOutput;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/FillLightGridCS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author(s):\tAlex Nankervis\n//\n\n#include \"LightGrid.hlsli\"\n\n// outdated warning about for-loop variable scope\n#pragma warning (disable: 3078)\n\n#define FLT_MIN         1.175494351e-38F        // min positive value\n#define FLT_MAX         3.402823466e+38F        // max value\n#define PI\t\t\t\t3.1415926535f\n#define TWOPI\t\t\t6.283185307f\n\n#define WORK_GROUP_THREADS (WORK_GROUP_SIZE_X * WORK_GROUP_SIZE_Y * WORK_GROUP_SIZE_Z)\n\n\ncbuffer CSConstants : register(b0)\n{\n    uint ViewportWidth, ViewportHeight;\n    float InvTileDim;\n    float RcpZMagic;\n    uint TileCountX;\n    float4x4 ViewProjMatrix;\n};\n\nStructuredBuffer<LightData> lightBuffer : register(t0);\nTexture2D<float> depthTex : register(t1);\nRWByteAddressBuffer lightGrid : register(u0);\nRWByteAddressBuffer lightGridBitMask : register(u1);\n\ngroupshared uint minDepthUInt;\ngroupshared uint maxDepthUInt;\n\ngroupshared uint tileLightCountSphere;\ngroupshared uint tileLightCountCone;\ngroupshared uint tileLightCountConeShadowed;\n\ngroupshared uint tileLightIndicesSphere[MAX_LIGHTS];\ngroupshared uint tileLightIndicesCone[MAX_LIGHTS];\ngroupshared uint tileLightIndicesConeShadowed[MAX_LIGHTS];\n\ngroupshared uint4 tileLightBitMask;\n\n#define _RootSig \\\n    \"RootFlags(0), \" \\\n    \"CBV(b0), \" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 2)),\" \\\n    \"DescriptorTable(UAV(u0, numDescriptors = 2))\"\n\n[RootSignature(_RootSig)]\n[numthreads(WORK_GROUP_SIZE_X, WORK_GROUP_SIZE_Y, WORK_GROUP_SIZE_Z)]\nvoid main(\n    uint3 globalID : SV_DispatchThreadID,\n    uint3 groupID : SV_GroupID,\n    uint3 threadID : SV_GroupThreadID,\n    uint threadIndex : SV_GroupIndex)\n{\n    // go ahead and fetch depth here\n    float depth = -1.0;\n    if (globalID.x >= ViewportWidth || globalID.y >= ViewportHeight)\n    {\n        // out of bounds\n    }\n    else\n    {\n        depth = depthTex[globalID.xy];\n    }\n    \n    // initialize shared data\n    if (threadIndex == 0)\n    {\n        tileLightCountSphere = 0;\n        tileLightCountCone = 0;\n        tileLightCountConeShadowed = 0;\n        tileLightBitMask = 0;\n        minDepthUInt = 0xffffffff;\n        maxDepthUInt = 0;\n    }\n    GroupMemoryBarrierWithGroupSync();\n\n    // determine min/max Z for tile\n    if (depth != -1.0)\n    {\n        uint depthUInt = asuint(depth);\n        \n        InterlockedMin(minDepthUInt, depthUInt);\n        InterlockedMax(maxDepthUInt, depthUInt);\n    }\n    GroupMemoryBarrierWithGroupSync();\n    //float tileMinDepth = asfloat(minDepthUInt);\n    //float tileMaxDepth = asfloat(maxDepthUInt);\n    float tileMinDepth = (rcp(asfloat(maxDepthUInt)) - 1.0) * RcpZMagic;\n    float tileMaxDepth = (rcp(asfloat(minDepthUInt)) - 1.0) * RcpZMagic;\n    float tileDepthRange = tileMaxDepth - tileMinDepth;\n    tileDepthRange = max(tileDepthRange, FLT_MIN); // don't allow a depth range of 0\n    float invTileDepthRange = rcp(tileDepthRange);\n    // TODO: near/far clipping planes seem to be falling apart at or near the max depth with infinite projections\n\n    // construct transform from world space to tile space (projection space constrained to tile area)\n    float2 invTileSize2X = float2(ViewportWidth, ViewportHeight) * InvTileDim;\n    // D3D-specific [0, 1] depth range ortho projection\n    // (but without negation of Z, since we already have that from the projection matrix)\n    float3 tileBias = float3(\n        -2.0 * float(groupID.x) + invTileSize2X.x - 1.0,\n        -2.0 * float(groupID.y) + invTileSize2X.y - 1.0,\n        -tileMinDepth * invTileDepthRange);\n    float4x4 projToTile = float4x4(\n        invTileSize2X.x, 0, 0, tileBias.x,\n        0, -invTileSize2X.y, 0, tileBias.y,\n        0, 0, invTileDepthRange, tileBias.z,\n        0, 0, 0, 1\n        );\n    float4x4 tileMVP = mul(projToTile, ViewProjMatrix);\n    \n    // extract frustum planes (these will be in world space)\n    float4 frustumPlanes[6];\n    frustumPlanes[0] = tileMVP[3] + tileMVP[0];\n    frustumPlanes[1] = tileMVP[3] - tileMVP[0];\n    frustumPlanes[2] = tileMVP[3] + tileMVP[1];\n    frustumPlanes[3] = tileMVP[3] - tileMVP[1];\n    frustumPlanes[4] = tileMVP[3] + tileMVP[2];\n    frustumPlanes[5] = tileMVP[3] - tileMVP[2];\n    for (int n = 0; n < 6; n++)\n    {\n        frustumPlanes[n] *= rsqrt(dot(frustumPlanes[n].xyz, frustumPlanes[n].xyz));\n    }\n\n    uint tileIndex = GetTileIndex(groupID.xy, TileCountX);\n    uint tileOffset = GetTileOffset(tileIndex);\n\n    // find set of lights that overlap this tile\n    for (uint lightIndex = threadIndex; lightIndex < MAX_LIGHTS; lightIndex += WORK_GROUP_THREADS)\n    {\n        LightData lightData = lightBuffer[lightIndex];\n        float3 lightWorldPos = lightData.pos;\n        float lightCullRadius = sqrt(lightData.radiusSq);\n\n        bool overlapping = true;\n        for (int n = 0; n < 6; n++)\n        {\n            float d = dot(lightWorldPos, frustumPlanes[n].xyz) + frustumPlanes[n].w;\n            if (d < -lightCullRadius)\n            {\n                overlapping = false;\n            }\n        }\n        \n        if (overlapping)\n        {\n            switch (lightData.type)\n            {\n            case 0: // sphere\n                {\n                    uint slot = 0;\n                    InterlockedAdd(tileLightCountSphere, 1, slot);\n                    tileLightIndicesSphere[slot] = lightIndex;\n                }\n                break;\n\n            case 1: // cone\n                {\n                    uint slot = 0;\n                    InterlockedAdd(tileLightCountCone, 1, slot);\n                    tileLightIndicesCone[slot] = lightIndex;\n                }\n                break;\n\n            case 2: // cone w/ shadow map\n                {\n                    uint slot = 0;\n                    InterlockedAdd(tileLightCountConeShadowed, 1, slot);\n                    tileLightIndicesConeShadowed[slot] = lightIndex;\n                }\n                break;\n            }\n\n            // update bitmask\n            switch (lightIndex / 32)\n            {\n            case 0:\n                InterlockedOr(tileLightBitMask.x, 1 << (lightIndex % 32));\n                break;\n            case 1:\n                InterlockedOr(tileLightBitMask.y, 1 << (lightIndex % 32));\n                break;\n            case 2:\n                InterlockedOr(tileLightBitMask.z, 1 << (lightIndex % 32));\n                break;\n            case 3:\n                InterlockedOr(tileLightBitMask.w, 1 << (lightIndex % 32));\n                break;\n            }\n        }\n    }\n\n    GroupMemoryBarrierWithGroupSync();\n\n    if (threadIndex == 0)\n    {\n        uint lightCount = \n            ((tileLightCountSphere & 0xff) << 0) |\n            ((tileLightCountCone & 0xff) << 8) |\n            ((tileLightCountConeShadowed & 0xff) << 16);\n        lightGrid.Store(tileOffset + 0, lightCount);\n\n        uint storeOffset = tileOffset + 4;\n        for (uint n = 0; n < tileLightCountSphere; n++)\n        {\n            lightGrid.Store(storeOffset, tileLightIndicesSphere[n]);\n            storeOffset += 4;\n        }\n        for (uint n = 0; n < tileLightCountCone; n++)\n        {\n            lightGrid.Store(storeOffset, tileLightIndicesCone[n]);\n            storeOffset += 4;\n        }\n        for (uint n = 0; n < tileLightCountConeShadowed; n++)\n        {\n            lightGrid.Store(storeOffset, tileLightIndicesConeShadowed[n]);\n            storeOffset += 4;\n        }\n\n        lightGridBitMask.Store4(tileIndex * 16, tileLightBitMask);\n    }\n}\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/FillLightGridCS_16.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define WORK_GROUP_SIZE_X 16\r\n#define WORK_GROUP_SIZE_Y 16\r\n#define WORK_GROUP_SIZE_Z 1\r\n\r\n#include \"FillLightGridCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/FillLightGridCS_24.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define WORK_GROUP_SIZE_X 24\r\n#define WORK_GROUP_SIZE_Y 24\r\n#define WORK_GROUP_SIZE_Z 1\r\n\r\n#include \"FillLightGridCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/FillLightGridCS_32.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define WORK_GROUP_SIZE_X 32\r\n#define WORK_GROUP_SIZE_Y 32\r\n#define WORK_GROUP_SIZE_Z 1\r\n\r\n#include \"FillLightGridCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/FillLightGridCS_8.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define WORK_GROUP_SIZE_X 8\r\n#define WORK_GROUP_SIZE_Y 8\r\n#define WORK_GROUP_SIZE_Z 1\r\n\r\n#include \"FillLightGridCS.hlsli\"\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/LightGrid.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author(s):\tAlex Nankervis\n//\n\n// keep in sync with C code\n#define MAX_LIGHTS 128\n#define TILE_SIZE (4 + MAX_LIGHTS * 4)\n\nstruct LightData\n{\n    float3 pos;\n    float radiusSq;\n\n    float3 color;\n    uint type;\n\n    float3 coneDir;\n    float2 coneAngles; // x = 1.0f / (cos(coneInner) - cos(coneOuter)), y = cos(coneOuter)\n\n    float4x4 shadowTextureMatrix;\n};\n\nuint2 GetTilePos(float2 pos, float2 invTileDim)\n{\n    return pos * invTileDim;\n}\nuint GetTileIndex(uint2 tilePos, uint tileCountX)\n{\n    return tilePos.y * tileCountX + tilePos.x;\n}\nuint GetTileOffset(uint tileIndex)\n{\n    return tileIndex * TILE_SIZE;\n}\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerPS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define CENTER_SHADING\r\n#define DDXY_BIAS 1.0f\r\n\r\n#include \"ModelViewerPSHeader.hlsli\""
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerPSHeader.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author(s):\tJames Stanard\n//\t\t\t\tAlex Nankervis\n//\n// Thanks to Michal Drobot for his feedback.\n\n// Modified 2018, Intel Corporation\n// This is now an implementation file which is called by\n// a ModelEviewerPS_* shader which sets the appropriate #defines\n\n#include \"ModelViewerRS.hlsli\"\n#include \"LightGrid.hlsli\"\n\n// outdated warning about for-loop variable scope\n#pragma warning (disable: 3078)\n// single-iteration loop\n#pragma warning (disable: 3557)\n\n#define ENABLE_LIGHT_GRID\n\n#ifdef SAMPLE_SHADING\nstruct VSOutput\n{\n    sample float4 position : SV_Position;\n    sample float3 worldPos : WorldPos;\n    sample float2 uv : TexCoord0;\n    sample float3 viewDir : TexCoord1;\n    sample float3 shadowCoord : TexCoord2;\n    sample float3 normal : Normal;\n    sample float3 tangent : Tangent;\n    sample float3 bitangent : Bitangent;\n    uint sampleIndex : SV_SampleIndex;\n};\n#endif\n\n#ifdef CENTROID_SHADING\nstruct VSOutput\n{\n\tcentroid float4 position : SV_Position;\n\tcentroid float3 worldPos : WorldPos;\n\tcentroid float2 uv : TexCoord0;\n\tcentroid float3 viewDir : TexCoord1;\n\tcentroid float3 shadowCoord : TexCoord2;\n\tcentroid float3 normal : Normal;\n\tcentroid float3 tangent : Tangent;\n\tcentroid float3 bitangent : Bitangent;\n};\n#endif\n\n#ifdef CENTER_SHADING\nstruct VSOutput\n{\n\tfloat4 position : SV_Position;\n\tfloat3 worldPos : WorldPos;\n\tfloat2 uv : TexCoord0;\n\tfloat3 viewDir : TexCoord1;\n\tfloat3 shadowCoord : TexCoord2;\n\tfloat3 normal : Normal;\n\tfloat3 tangent : Tangent;\n\tfloat3 bitangent : Bitangent;\n};\n#endif\n\nstruct MaterialConstants {\n\tfloat3 diffuse;\n\tfloat3 specular;\n\tfloat3 emissive;\n\tfloat shininess;\n\tuint textureMask;\n};\n\nTexture2D<float3> texDiffuse\t\t: register(t0);\nTexture2D<float3> texSpecular\t\t: register(t1);\n//Texture2D<float4> texEmissive\t\t: register(t2);\nTexture2D<float3> texNormal\t\t\t: register(t3);\n//Texture2D<float4> texLightmap\t\t: register(t4);\n//Texture2D<float4> texReflection\t: register(t5);\nStructuredBuffer<MaterialConstants>\tmaterialBuffer\t: register(t7);\nTexture2D<float> texSSAO\t\t\t: register(t64);\nTexture2D<float> texShadow\t\t\t: register(t65);\n\nStructuredBuffer<LightData> lightBuffer : register(t66);\nTexture2DArray<float> lightShadowArrayTex : register(t67);\nByteAddressBuffer lightGrid : register(t68);\nByteAddressBuffer lightGridBitMask : register(t69);\n\ncbuffer PSConstants : register(b0)\n{\n\tfloat3 SunDirection;\n\tfloat3 SunColor;\n\tfloat3 AmbientColor;\n\tfloat4 ShadowTexelSize;\n\tfloat4 InvTileDim;\n\tuint4 TileCount;\n\tuint4 FirstLightIndex;\n\tfloat3 DownSizedFactors;\t// the factors to compensate resolution upsampling\n\t\t\t\t\t\t\t\t// in color shading PS, if we downsample the viewport by x, the screenPosition must be compensated for fetching full screen like SSAO and lightCull indices\n\t\t\t\t\t\t\t\t// the third parameter is the frame offset for odd or even pixel look up in the ssao and light grids\n}\n\nSamplerState sampler0 : register(s0);\nSamplerComparisonState shadowSampler : register(s1);\n\ncbuffer PSMaterialConstants : register(b1) {\n\tuint MaterialIdx;\n}\n\nvoid AntiAliasSpecular(inout float3 texNormal, inout float gloss)\n{\n\tfloat normalLenSq = dot(texNormal, texNormal);\n\tfloat invNormalLen = rsqrt(normalLenSq);\n\ttexNormal *= invNormalLen;\n\tgloss = lerp(1, gloss, rcp(invNormalLen));\n}\n\n// Apply fresnel to modulate the specular albedo\nvoid FSchlick(inout float3 specular, inout float3 diffuse, float3 lightDir, float3 halfVec)\n{\n\tfloat fresnel = pow(1.0 - saturate(dot(lightDir, halfVec)), 5.0);\n\tspecular = lerp(specular, 1, fresnel);\n\tdiffuse = lerp(diffuse, 0, fresnel);\n}\n\nfloat3 ApplyAmbientLight(\n\tfloat3\tdiffuse,\t// Diffuse albedo\n\tfloat\tao,\t\t\t// Pre-computed ambient-occlusion\n\tfloat3\tlightColor\t// Radiance of ambient light\n)\n{\n\treturn ao * diffuse * lightColor;\n}\n\nfloat GetShadow(float3 ShadowCoord)\n{\n#ifdef SINGLE_SAMPLE\n\tfloat result = ShadowMap.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy, ShadowCoord.z);\n#else\n\tconst float Dilation = 2.0;\n\tfloat d1 = Dilation * ShadowTexelSize.x * 0.125;\n\tfloat d2 = Dilation * ShadowTexelSize.x * 0.875;\n\tfloat d3 = Dilation * ShadowTexelSize.x * 0.625;\n\tfloat d4 = Dilation * ShadowTexelSize.x * 0.375;\n\tfloat result = (\n\t\t2.0 * texShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy, ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(-d2, d1), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(-d1, -d2), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(d2, -d1), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(d1, d2), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(-d4, d3), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(-d3, -d4), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(d4, -d3), ShadowCoord.z) +\n\t\ttexShadow.SampleCmpLevelZero(shadowSampler, ShadowCoord.xy + float2(d3, d4), ShadowCoord.z)\n\t\t) / 10.0;\n#endif\n\treturn result * result;\n}\n\nfloat GetShadowConeLight(uint lightIndex, float3 shadowCoord)\n{\n\tfloat result = lightShadowArrayTex.SampleCmpLevelZero(\n\t\tshadowSampler, float3(shadowCoord.xy, lightIndex), shadowCoord.z);\n\treturn result * result;\n}\n\nfloat3 ApplyLightCommon(\n\tfloat3\tdiffuseColor,\t// Diffuse albedo\n\tfloat3\tspecularColor,\t// Specular albedo\n\tfloat\tspecularMask,\t// Where is it shiny or dingy?\n\tfloat\tgloss,\t\t\t// Specular power\n\tfloat3\tnormal,\t\t\t// World-space normal\n\tfloat3\tviewDir,\t\t// World-space vector from eye to point\n\tfloat3\tlightDir,\t\t// World-space vector from point to light\n\tfloat3\tlightColor\t\t// Radiance of directional light\n)\n{\n\tfloat3 halfVec = normalize(lightDir - viewDir);\n\tfloat nDotH = saturate(dot(halfVec, normal));\n\n\tFSchlick(diffuseColor, specularColor, lightDir, halfVec);\n\n\tfloat specularFactor = specularMask * pow(nDotH, gloss) * (gloss + 2) / 8;\n\n\tfloat nDotL = saturate(dot(normal, lightDir));\n\n\treturn nDotL * lightColor * (diffuseColor + specularFactor * specularColor);\n}\n\nfloat3 ApplyDirectionalLight(\n\tfloat3\tdiffuseColor,\t// Diffuse albedo\n\tfloat3\tspecularColor,\t// Specular albedo\n\tfloat\tspecularMask,\t// Where is it shiny or dingy?\n\tfloat\tgloss,\t\t\t// Specular power\n\tfloat3\tnormal,\t\t\t// World-space normal\n\tfloat3\tviewDir,\t\t// World-space vector from eye to point\n\tfloat3\tlightDir,\t\t// World-space vector from point to light\n\tfloat3\tlightColor,\t\t// Radiance of directional light\n\tfloat3\tshadowCoord\t\t// Shadow coordinate (Shadow map UV & light-relative Z)\n)\n{\n\tfloat shadow = GetShadow(shadowCoord);\n\n\treturn shadow * ApplyLightCommon(\n\t\tdiffuseColor,\n\t\tspecularColor,\n\t\tspecularMask,\n\t\tgloss,\n\t\tnormal,\n\t\tviewDir,\n\t\tlightDir,\n\t\tlightColor\n\t);\n}\n\nfloat3 ApplyPointLight(\n\tfloat3\tdiffuseColor,\t// Diffuse albedo\n\tfloat3\tspecularColor,\t// Specular albedo\n\tfloat\tspecularMask,\t// Where is it shiny or dingy?\n\tfloat\tgloss,\t\t\t// Specular power\n\tfloat3\tnormal,\t\t\t// World-space normal\n\tfloat3\tviewDir,\t\t// World-space vector from eye to point\n\tfloat3\tworldPos,\t\t// World-space fragment position\n\tfloat3\tlightPos,\t\t// World-space light position\n\tfloat\tlightRadiusSq,\n\tfloat3\tlightColor\t\t// Radiance of directional light\n)\n{\n\tfloat3 lightDir = lightPos - worldPos;\n\tfloat lightDistSq = dot(lightDir, lightDir);\n\tfloat invLightDist = rsqrt(lightDistSq);\n\tlightDir *= invLightDist;\n\n\t// modify 1/d^2 * R^2 to fall off at a fixed radius\n\t// (R/d)^2 - d/R = [(1/d^2) - (1/R^2)*(d/R)] * R^2\n\tfloat distanceFalloff = lightRadiusSq * (invLightDist * invLightDist);\n\tdistanceFalloff = max(0, distanceFalloff - rsqrt(distanceFalloff));\n\n\treturn distanceFalloff * ApplyLightCommon(\n\t\tdiffuseColor,\n\t\tspecularColor,\n\t\tspecularMask,\n\t\tgloss,\n\t\tnormal,\n\t\tviewDir,\n\t\tlightDir,\n\t\tlightColor\n\t);\n}\n\nfloat3 ApplyConeLight(\n\tfloat3\tdiffuseColor,\t// Diffuse albedo\n\tfloat3\tspecularColor,\t// Specular albedo\n\tfloat\tspecularMask,\t// Where is it shiny or dingy?\n\tfloat\tgloss,\t\t\t// Specular power\n\tfloat3\tnormal,\t\t\t// World-space normal\n\tfloat3\tviewDir,\t\t// World-space vector from eye to point\n\tfloat3\tworldPos,\t\t// World-space fragment position\n\tfloat3\tlightPos,\t\t// World-space light position\n\tfloat\tlightRadiusSq,\n\tfloat3\tlightColor,\t\t// Radiance of directional light\n\tfloat3\tconeDir,\n\tfloat2\tconeAngles\n)\n{\n\tfloat3 lightDir = lightPos - worldPos;\n\tfloat lightDistSq = dot(lightDir, lightDir);\n\tfloat invLightDist = rsqrt(lightDistSq);\n\tlightDir *= invLightDist;\n\n\t// modify 1/d^2 * R^2 to fall off at a fixed radius\n\t// (R/d)^2 - d/R = [(1/d^2) - (1/R^2)*(d/R)] * R^2\n\tfloat distanceFalloff = lightRadiusSq * (invLightDist * invLightDist);\n\tdistanceFalloff = max(0, distanceFalloff - rsqrt(distanceFalloff));\n\n\tfloat coneFalloff = dot(-lightDir, coneDir);\n\tconeFalloff = saturate((coneFalloff - coneAngles.y) * coneAngles.x);\n\n\treturn (coneFalloff * distanceFalloff) * ApplyLightCommon(\n\t\tdiffuseColor,\n\t\tspecularColor,\n\t\tspecularMask,\n\t\tgloss,\n\t\tnormal,\n\t\tviewDir,\n\t\tlightDir,\n\t\tlightColor\n\t);\n}\n\nfloat3 ApplyConeShadowedLight(\n\tfloat3\tdiffuseColor,\t// Diffuse albedo\n\tfloat3\tspecularColor,\t// Specular albedo\n\tfloat\tspecularMask,\t// Where is it shiny or dingy?\n\tfloat\tgloss,\t\t\t// Specular power\n\tfloat3\tnormal,\t\t\t// World-space normal\n\tfloat3\tviewDir,\t\t// World-space vector from eye to point\n\tfloat3\tworldPos,\t\t// World-space fragment position\n\tfloat3\tlightPos,\t\t// World-space light position\n\tfloat\tlightRadiusSq,\n\tfloat3\tlightColor,\t\t// Radiance of directional light\n\tfloat3\tconeDir,\n\tfloat2\tconeAngles,\n\tfloat4x4 shadowTextureMatrix,\n\tuint\tlightIndex\n)\n{\n\tfloat4 shadowCoord = mul(shadowTextureMatrix, float4(worldPos, 1.0));\n\tshadowCoord.xyz *= rcp(shadowCoord.w);\n\tfloat shadow = GetShadowConeLight(lightIndex, shadowCoord.xyz);\n\n\treturn shadow * ApplyConeLight(\n\t\tdiffuseColor,\n\t\tspecularColor,\n\t\tspecularMask,\n\t\tgloss,\n\t\tnormal,\n\t\tviewDir,\n\t\tworldPos,\n\t\tlightPos,\n\t\tlightRadiusSq,\n\t\tlightColor,\n\t\tconeDir,\n\t\tconeAngles\n\t);\n}\n\n// options for F+ variants and optimizations\n#ifdef _WAVE_OP // SM 6.0 (new shader compiler)\n\n// choose one of these:\n//# define BIT_MASK\n# define BIT_MASK_SORTED\n//# define SCALAR_LOOP\n//# define SCALAR_BRANCH\n\n// enable to amortize latency of vector read in exchange for additional VGPRs being held\n# define LIGHT_GRID_PRELOADING\n\n// configured for 32 sphere lights, 64 cone lights, and 32 cone shadowed lights\n# define POINT_LIGHT_GROUPS\t\t\t1\n# define SPOT_LIGHT_GROUPS\t\t\t2\n# define SHADOWED_SPOT_LIGHT_GROUPS\t1\n# define POINT_LIGHT_GROUPS_TAIL\t\t\tPOINT_LIGHT_GROUPS\n# define SPOT_LIGHT_GROUPS_TAIL\t\t\t\tPOINT_LIGHT_GROUPS_TAIL + SPOT_LIGHT_GROUPS\n# define SHADOWED_SPOT_LIGHT_GROUPS_TAIL\tSPOT_LIGHT_GROUPS_TAIL + SHADOWED_SPOT_LIGHT_GROUPS\n\n\nuint GetGroupBits(uint groupIndex, uint tileIndex, uint lightBitMaskGroups[4])\n{\n#ifdef LIGHT_GRID_PRELOADING\n\treturn lightBitMaskGroups[groupIndex];\n#else\n\treturn lightGridBitMask.Load(tileIndex * 16 + groupIndex * 4);\n#endif\n}\n\nuint64_t Ballot64(bool b)\n{\n\tuint4 ballots = WaveActiveBallot(b);\n\treturn (uint64_t)ballots.y << 32 | (uint64_t)ballots.x;\n}\n\n#endif // _WAVE_OP\n\n// Helper function for iterating over a sparse list of bits.  Gets the offset of the next\n// set bit, clears it, and returns the offset.\nuint PullNextBit(inout uint bits)\n{\n\tuint bitIndex = firstbitlow(bits);\n\tbits ^= 1 << bitIndex;\n\treturn bitIndex;\n}\n\n// Main Pixel Shader\n[RootSignature(ModelViewer_RootSig)]\nfloat3 main(VSOutput vsOutput) : SV_Target0\n{\n\tMaterialConstants matConstants = materialBuffer[MaterialIdx];\n\n\tuint2 pixelPos = vsOutput.position.xy * DownSizedFactors.xy;\n\n#ifdef SAMPLE_SHADING\n\tuint flags = asuint(DownSizedFactors.z);\n\n\t// pixePos is used for the full res light grid look up\n\t// we need to account for the frame jitter\n\tpixelPos.x -= (flags & 0x1);;\n\t\n\t// On Intel pixel pos is always sample index 0 (bottom right)\n\t// so we back it up if this is sample index 1\n\tif ( flags & 0x02 ) // INTEL \n\t{\n\t\tpixelPos.x -= (vsOutput.sampleIndex);\n\t\tpixelPos.y -= (vsOutput.sampleIndex);\n\t}\n#endif\n\n\t// Texture Coordinate manipulation for CB sampling\n\tfloat2 tex2D = vsOutput.uv;\n\tfloat2 tdx = ddx_fine(tex2D);\n\tfloat2 tdy = ddy_fine(tex2D);\n\n\tfloat3 diffuseAlbedo = matConstants.diffuse;\n\tif (matConstants.textureMask & 1)\n\t{\n\t\tdiffuseAlbedo = texDiffuse.SampleGrad(sampler0, vsOutput.uv, tdx * DDXY_BIAS, tdy * DDXY_BIAS);\n\t}\n\n\t//float3 colorSum = 0;\n\tfloat3 colorSum = matConstants.emissive;\n\t{\n\t\tfloat ao = texSSAO[pixelPos];\n\t\tcolorSum += ApplyAmbientLight(diffuseAlbedo, ao, AmbientColor);\n\t}\n\n\t//float gloss = 128.0;\n\tfloat gloss = matConstants.shininess;;\n\tfloat3 normal = normalize(vsOutput.normal);\n\tif (dot(vsOutput.tangent, vsOutput.tangent) > 0.f)\n\t{\n\t\tnormal = texNormal.SampleGrad(sampler0, vsOutput.uv, tdx * DDXY_BIAS, tdy * DDXY_BIAS) * 2.0 - 1.0;\n\t\tAntiAliasSpecular(normal, gloss);\n\n\t\tfloat3x3 tbn = float3x3(normalize(vsOutput.tangent), normalize(vsOutput.bitangent), normalize(vsOutput.normal));\n\n\t\tnormal = normalize(mul(normal, tbn));\n\t}\n\n\tfloat3 specularAlbedo = float3(0.56, 0.56, 0.56);\n\tfloat specularMask = texSpecular.SampleGrad(sampler0, vsOutput.uv, tdx * DDXY_BIAS, tdy * DDXY_BIAS).g;\n\t\n\tfloat3 viewDir = normalize(vsOutput.viewDir);\n\n\tfloat3 shadowCoord = vsOutput.shadowCoord;\n\tcolorSum += ApplyDirectionalLight(diffuseAlbedo, specularAlbedo, specularMask, gloss, normal, viewDir, SunDirection, SunColor, shadowCoord);\n\n#ifdef ENABLE_LIGHT_GRID\n\n\tuint2 tilePos = GetTilePos(pixelPos, InvTileDim.xy);\n\tuint tileIndex = GetTileIndex(tilePos, TileCount.x);\n\tuint tileOffset = GetTileOffset(tileIndex);\n\n\t// Light Grid Preloading setup\n\tuint lightBitMaskGroups[4] = { 0, 0, 0, 0 };\n#if defined(LIGHT_GRID_PRELOADING)\n\tuint4 lightBitMask = lightGridBitMask.Load4(tileIndex * 16);\n\n\tlightBitMaskGroups[0] = lightBitMask.x;\n\tlightBitMaskGroups[1] = lightBitMask.y;\n\tlightBitMaskGroups[2] = lightBitMask.z;\n\tlightBitMaskGroups[3] = lightBitMask.w;\n#endif\n\t\n\tfloat3 worldPos = vsOutput.worldPos;\n\n#define POINT_LIGHT_ARGS \\\n    diffuseAlbedo, \\\n    specularAlbedo, \\\n    specularMask, \\\n    gloss, \\\n    normal, \\\n    viewDir, \\\n    worldPos, \\\n\tlightData.pos, \\\n    lightData.radiusSq, \\\n    lightData.color\n\n\t//vsOutput.worldPos, \\\n\n#define CONE_LIGHT_ARGS \\\n    POINT_LIGHT_ARGS, \\\n    lightData.coneDir, \\\n    lightData.coneAngles\n\n#define SHADOWED_LIGHT_ARGS \\\n    CONE_LIGHT_ARGS, \\\n    lightData.shadowTextureMatrix, \\\n    lightIndex\n\n#if defined(BIT_MASK)\n\tuint64_t threadMask = Ballot64(tileIndex != ~0); // attempt to get starting exec mask\n\n\tfor (uint groupIndex = 0; groupIndex < 4; groupIndex++)\n\t{\n\t\t// combine across threads\n\t\tuint groupBits = WaveActiveBitOr(GetGroupBits(groupIndex, tileIndex, lightBitMaskGroups));\n\n\t\twhile (groupBits != 0)\n\t\t{\n\t\t\tuint bitIndex = PullNextBit(groupBits);\n\t\t\tuint lightIndex = 32 * groupIndex + bitIndex;\n\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\n\t\t\tif (lightIndex < FirstLightIndex.x) // sphere\n\t\t\t{\n\t\t\t\tcolorSum += ApplyPointLight(POINT_LIGHT_ARGS);\n\t\t\t}\n\t\t\telse if (lightIndex < FirstLightIndex.y) // cone\n\t\t\t{\n\t\t\t\tcolorSum += ApplyConeLight(CONE_LIGHT_ARGS);\n\t\t\t}\n\t\t\telse // cone w/ shadow map\n\t\t\t{\n\t\t\t\tcolorSum += ApplyConeShadowedLight(SHADOWED_LIGHT_ARGS);\n\t\t\t}\n\t\t}\n\t}\n\n#elif defined(BIT_MASK_SORTED)\n\n\t// Get light type groups - these can be predefined as compile time constants to enable unrolling and better scheduling of vector reads\n\tuint pointLightGroupTail = POINT_LIGHT_GROUPS_TAIL;\n\tuint spotLightGroupTail = SPOT_LIGHT_GROUPS_TAIL;\n\tuint spotShadowLightGroupTail = SHADOWED_SPOT_LIGHT_GROUPS_TAIL;\n\n\tuint groupBitsMasks[4] = { 0, 0, 0, 0 };\n\tfor (int i = 0; i < 4; i++)\n\t{\n\t\t// combine across threads\n\t\tgroupBitsMasks[i] = WaveActiveBitOr(GetGroupBits(i, tileIndex, lightBitMaskGroups));\n\t}\n\n\tfor (uint groupIndex = 0; groupIndex < pointLightGroupTail; groupIndex++)\n\t{\n\t\tuint groupBits = groupBitsMasks[groupIndex];\n\n\t\twhile (groupBits != 0)\n\t\t{\n\t\t\tuint bitIndex = PullNextBit(groupBits);\n\t\t\tuint lightIndex = 32 * groupIndex + bitIndex;\n\n\t\t\t// sphere\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyPointLight(POINT_LIGHT_ARGS);\n\t\t}\n\t}\n\n\tfor (uint groupIndex = pointLightGroupTail; groupIndex < spotLightGroupTail; groupIndex++)\n\t{\n\t\tuint groupBits = groupBitsMasks[groupIndex];\n\n\t\twhile (groupBits != 0)\n\t\t{\n\t\t\tuint bitIndex = PullNextBit(groupBits);\n\t\t\tuint lightIndex = 32 * groupIndex + bitIndex;\n\n\t\t\t// cone\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyConeLight(CONE_LIGHT_ARGS);\n\t\t}\n\t}\n\n\tfor (uint groupIndex = spotLightGroupTail; groupIndex < spotShadowLightGroupTail; groupIndex++)\n\t{\n\t\tuint groupBits = groupBitsMasks[groupIndex];\n\n\t\twhile (groupBits != 0)\n\t\t{\n\t\t\tuint bitIndex = PullNextBit(groupBits);\n\t\t\tuint lightIndex = 32 * groupIndex + bitIndex;\n\n\t\t\t// cone w/ shadow map\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyConeShadowedLight(SHADOWED_LIGHT_ARGS);\n\t\t}\n\t}\n\n#elif defined(SCALAR_LOOP)\n\tuint64_t threadMask = Ballot64(tileOffset != ~0); // attempt to get starting exec mask\n\tuint64_t laneBit = 1ull << WaveGetLaneIndex();\n\n\twhile ((threadMask & laneBit) != 0) // is this thread waiting to be processed?\n\t{ // exec is now the set of remaining threads\n\t  // grab the tile offset for the first active thread\n\t\tuint uniformTileOffset = WaveReadLaneFirst(tileOffset);\n\t\t// mask of which threads have the same tile offset as the first active thread\n\t\tuint64_t uniformMask = Ballot64(tileOffset == uniformTileOffset);\n\n\t\tif (any((uniformMask & laneBit) != 0)) // is this thread one of the current set of uniform threads?\n\t\t{\n\t\t\tuint tileLightCount = lightGrid.Load(uniformTileOffset + 0);\n\t\t\tuint tileLightCountSphere = (tileLightCount >> 0) & 0xff;\n\t\t\tuint tileLightCountCone = (tileLightCount >> 8) & 0xff;\n\t\t\tuint tileLightCountConeShadowed = (tileLightCount >> 16) & 0xff;\n\n\t\t\tuint tileLightLoadOffset = uniformTileOffset + 4;\n\n\t\t\t// sphere\n\t\t\tfor (uint n = 0; n < tileLightCountSphere; n++, tileLightLoadOffset += 4)\n\t\t\t{\n\t\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\t\tcolorSum += ApplyPointLight(POINT_LIGHT_ARGS);\n\t\t\t}\n\n\t\t\t// cone\n\t\t\tfor (uint n = 0; n < tileLightCountCone; n++, tileLightLoadOffset += 4)\n\t\t\t{\n\t\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\t\tcolorSum += ApplyConeLight(CONE_LIGHT_ARGS);\n\t\t\t}\n\n\t\t\t// cone w/ shadow map\n\t\t\tfor (uint n = 0; n < tileLightCountConeShadowed; n++, tileLightLoadOffset += 4)\n\t\t\t{\n\t\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\t\tcolorSum += ApplyConeShadowedLight(SHADOWED_LIGHT_ARGS);\n\t\t\t}\n\t\t}\n\n\t\t// strip the current set of uniform threads from the exec mask for the next loop iteration\n\t\tthreadMask &= ~uniformMask;\n\t}\n\n#elif defined(SCALAR_BRANCH)\n\n\tif (Ballot64(tileOffset == WaveReadLaneFirst(tileOffset)) == ~0ull)\n\t{\n\t\t// uniform branch\n\t\ttileOffset = WaveReadLaneFirst(tileOffset);\n\n\t\tuint tileLightCount = lightGrid.Load(tileOffset + 0);\n\t\tuint tileLightCountSphere = (tileLightCount >> 0) & 0xff;\n\t\tuint tileLightCountCone = (tileLightCount >> 8) & 0xff;\n\t\tuint tileLightCountConeShadowed = (tileLightCount >> 16) & 0xff;\n\n\t\tuint tileLightLoadOffset = tileOffset + 4;\n\n\t\t// sphere\n\t\tfor (uint n = 0; n < tileLightCountSphere; n++, tileLightLoadOffset += 4)\n\t\t{\n\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyPointLight(POINT_LIGHT_ARGS);\n\t\t}\n\n\t\t// cone\n\t\tfor (uint n = 0; n < tileLightCountCone; n++, tileLightLoadOffset += 4)\n\t\t{\n\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyConeLight(CONE_LIGHT_ARGS);\n\t\t}\n\n\t\t// cone w/ shadow map\n\t\tfor (uint n = 0; n < tileLightCountConeShadowed; n++, tileLightLoadOffset += 4)\n\t\t{\n\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyConeShadowedLight(SHADOWED_LIGHT_ARGS);\n\t\t}\n\t}\n\telse\n\t{\n\t\t// divergent branch\n\t\tuint tileLightCount = lightGrid.Load(tileOffset + 0);\n\t\tuint tileLightCountSphere = (tileLightCount >> 0) & 0xff;\n\t\tuint tileLightCountCone = (tileLightCount >> 8) & 0xff;\n\t\tuint tileLightCountConeShadowed = (tileLightCount >> 16) & 0xff;\n\n\t\tuint tileLightLoadOffset = tileOffset + 4;\n\n\t\t// sphere\n\t\tfor (uint n = 0; n < tileLightCountSphere; n++, tileLightLoadOffset += 4)\n\t\t{\n\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyPointLight(POINT_LIGHT_ARGS);\n\t\t}\n\n\t\t// cone\n\t\tfor (uint n = 0; n < tileLightCountCone; n++, tileLightLoadOffset += 4)\n\t\t{\n\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyConeLight(CONE_LIGHT_ARGS);\n\t\t}\n\n\t\t// cone w/ shadow map\n\t\tfor (uint n = 0; n < tileLightCountConeShadowed; n++, tileLightLoadOffset += 4)\n\t\t{\n\t\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\t\tLightData lightData = lightBuffer[lightIndex];\n\t\t\tcolorSum += ApplyConeShadowedLight(SHADOWED_LIGHT_ARGS);\n\t\t}\n\t}\n\n#else // SM 5.0 (no wave intrinsics)\n\n\tuint tileLightCount = lightGrid.Load(tileOffset + 0);\n\tuint tileLightCountSphere = (tileLightCount >> 0) & 0xff;\n\tuint tileLightCountCone = (tileLightCount >> 8) & 0xff;\n\tuint tileLightCountConeShadowed = (tileLightCount >> 16) & 0xff;\n\n\tuint tileLightLoadOffset = tileOffset + 4;\n\n\t// sphere\n\tfor (uint n = 0; n < tileLightCountSphere; n++, tileLightLoadOffset += 4)\n\t{\n\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\tLightData lightData = lightBuffer[lightIndex];\n\t\tcolorSum += ApplyPointLight(POINT_LIGHT_ARGS);\n\t}\n\n\t// cone\n\tfor (uint n = 0; n < tileLightCountCone; n++, tileLightLoadOffset += 4)\n\t{\n\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\tLightData lightData = lightBuffer[lightIndex];\n\t\tcolorSum += ApplyConeLight(CONE_LIGHT_ARGS);\n\t}\n\n\t// cone w/ shadow map\n\tfor (uint n = 0; n < tileLightCountConeShadowed; n++, tileLightLoadOffset += 4)\n\t{\n\t\tuint lightIndex = lightGrid.Load(tileLightLoadOffset);\n\t\tLightData lightData = lightBuffer[lightIndex];\n\t\tcolorSum += ApplyConeShadowedLight(SHADOWED_LIGHT_ARGS);\n\t}\n#endif\n\n#endif // enable light grid\n\n\t//return specularMask;\n\t//return diffuseAlbedo;\n\treturn colorSum;\n}\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerPS_CBR.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define SAMPLE_SHADING\r\n#define DDXY_BIAS 0.5f\r\n\r\n#include \"ModelViewerPSHeader.hlsli\""
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerPS_CBR_PP.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define CENTER_SHADING\r\n#define DDXY_BIAS 0.5f\r\n\r\n#include \"ModelViewerPSHeader.hlsli\""
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerPS_CPS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n//#define CENTROID_SHADING\r\n// centroid sampling makes derivative undefined... We couldn't downsample the texture with LOD under centroid\r\n// Forced to use Center_shading unless we have a downsampling method without derivative \r\n// May lead to extrapolation on geometry edges (fine for now).\r\n#define CENTER_SHADING\r\n#define DDXY_BIAS 0.5f\r\n\r\n#include \"ModelViewerPSHeader.hlsli\""
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerRS.hlsli",
    "content": "//\n// Copyright (c) Microsoft. All rights reserved.\n// This code is licensed under the MIT License (MIT).\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\n//\n// Developed by Minigraph\n//\n// Author:  James Stanard \n//\n\n#define ModelViewer_RootSig \\\n    \"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), \" \\\n    \"CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), \" \\\n    \"CBV(b0, visibility = SHADER_VISIBILITY_PIXEL), \" \\\n    \"CBV(b1, visibility = SHADER_VISIBILITY_PIXEL), \" \\\n    \"DescriptorTable(SRV(t0, numDescriptors = 8), visibility = SHADER_VISIBILITY_PIXEL),\" \\\n    \"DescriptorTable(SRV(t64, numDescriptors = 6), visibility = SHADER_VISIBILITY_PIXEL),\" \\\n    \"RootConstants(b1, num32BitConstants = 2, visibility = SHADER_VISIBILITY_VERTEX), \" \\\n    \"StaticSampler(s0, maxAnisotropy = 8, visibility = SHADER_VISIBILITY_PIXEL),\" \\\n    \"StaticSampler(s1, visibility = SHADER_VISIBILITY_PIXEL,\" \\\n        \"addressU = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressV = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"addressW = TEXTURE_ADDRESS_CLAMP,\" \\\n        \"comparisonFunc = COMPARISON_GREATER_EQUAL,\" \\\n        \"filter = FILTER_MIN_MAG_LINEAR_MIP_POINT)\"\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/ModelViewerVS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):  James Stanard\r\n//             Alex Nankervis\r\n//\r\n\r\n#include \"ModelViewerRS.hlsli\"\r\n\r\ncbuffer VSConstants : register(b0)\r\n{\r\n    float4x4 modelToProjection;\r\n    float4x4 modelToShadow;\r\n    float3 ViewerPos;\r\n};\r\n\r\nstruct VSInput\r\n{\r\n    float3 position : POSITION;\r\n    float2 texcoord0 : TEXCOORD;\r\n    float3 normal : NORMAL;\r\n    float3 tangent : TANGENT;\r\n    float3 bitangent : BITANGENT;\r\n};\r\n\r\nstruct VSOutput\r\n{\r\n    float4 position : SV_Position;\r\n    float3 worldPos : WorldPos;\r\n    float2 texCoord : TexCoord0;\r\n    float3 viewDir : TexCoord1;\r\n    float3 shadowCoord : TexCoord2;\r\n    float3 normal : Normal;\r\n    float3 tangent : Tangent;\r\n    float3 bitangent : Bitangent;\r\n};\r\n\r\n[RootSignature(ModelViewer_RootSig)]\r\nVSOutput main(VSInput vsInput)\r\n{\r\n    VSOutput vsOutput;\r\n\r\n    vsOutput.position = mul(modelToProjection, float4(vsInput.position, 1.0));\r\n    vsOutput.worldPos = vsInput.position;\r\n    vsOutput.texCoord = vsInput.texcoord0;\r\n    vsOutput.viewDir = vsInput.position - ViewerPos;\r\n    vsOutput.shadowCoord = mul(modelToShadow, float4(vsInput.position, 1.0)).xyz;\r\n\r\n    vsOutput.normal = vsInput.normal;\r\n    vsOutput.tangent = vsInput.tangent;\r\n    vsOutput.bitangent = vsInput.bitangent;\r\n\r\n    return vsOutput;\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/MsaaColorResolveCS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define MsaaResolve_RootSig \\\r\n    \"RootFlags(0), \" \\\r\n    \"CBV(b0), \" \\\r\n    \"DescriptorTable(SRV(t0, numDescriptors = 1)),\" \\\r\n    \"DescriptorTable(UAV(u0, numDescriptors = 1))\"\r\n\r\nTexture2DMS<float4> MsaaInColor : register(t0);\r\nRWTexture2D<float4> OutColor : register(u0);\r\n//\r\n//cbuffer CB0 : register(b0)\r\n//{\r\n//\tfloat ZMagic;\t\t\t\t// (zFar - zNear) / zNear\r\n//\tfloat DepthMode;\t\t\t// 0: average depth, 1: minDepth\r\n//}\r\n\r\n[RootSignature(MsaaResolve_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main( uint3 DTid : SV_DispatchThreadID )\r\n{\r\n\tfloat4 Color = float4(0,0,0,0);\r\n\tuint Width, Height, SampleCount;\r\n\r\n\tMsaaInColor.GetDimensions(Width, Height, SampleCount);\r\n\tfor (uint i = 0; i < SampleCount; i++) {\r\n\t\tColor += MsaaInColor.Load(DTid.xy, i);\r\n\t}\r\n\tOutColor[DTid.xy] = Color / (float)SampleCount;\r\n}"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/MsaaDepthResolveCS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#define MsaaResolve_RootSig \\\r\n    \"RootFlags(0), \" \\\r\n    \"CBV(b0), \" \\\r\n    \"DescriptorTable(SRV(t0, numDescriptors = 1)),\" \\\r\n    \"DescriptorTable(UAV(u0, numDescriptors = 1))\"\r\n\r\n//\"RootConstants(b0, num32BitConstants = 4), \" \\\r\n\r\nTexture2DMS<float> MsaaInDepth : register(t0);\r\nRWTexture2D<float> OutDepth : register(u0);\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n\tfloat ZMagic;\t\t\t\t// (zFar - zNear) / zNear\r\n\tfloat DepthMode;\t\t\t// 0: average depth, 1: minDepth\r\n}\r\n\r\n[RootSignature(MsaaResolve_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main(uint3 DTid : SV_DispatchThreadID)\r\n{\r\n\tfloat Depth = 0.f;\r\n\tuint Width, Height, SampleCount;\r\n\tfloat LinearZ; \r\n\tMsaaInDepth.GetDimensions(Width, Height, SampleCount);\r\n\tif (DepthMode > 0) {\t// find the minDepth of those samples\r\n\t\tDepth = 100.f;\r\n\t\tfor (uint i = 0; i < SampleCount; i++) {\r\n\t\t\tLinearZ = 1.0 / (ZMagic * MsaaInDepth.Load(DTid.xy, i) + 1.0);\r\n\t\t\tif (Depth > LinearZ) Depth = LinearZ;\r\n\t\t}\r\n\t\tOutDepth[DTid.xy] = Depth;\r\n\t}\r\n\telse {\t// Compute an average depth of all samples\r\n\t\tfor (uint i = 0; i < SampleCount; i++) {\r\n\t\t\tLinearZ = 1.0 / (ZMagic * MsaaInDepth.Load(DTid.xy, i) + 1.0);\r\n\t\t\tDepth += LinearZ;\r\n\t\t}\r\n\t\tOutDepth[DTid.xy] = Depth / (float)SampleCount;\r\n\t}\r\n}"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/SamplePositions.hlsli",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Copyright (c) 2018, Intel Corporation\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \n// the Software.\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \n// SOFTWARE.\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nstatic const int offset2[] = {\n\t1, 0\n};\nstatic const int offset4[] = {\n\t0, 1, 2, 3\n};\nstatic const int offset8[] = {\n\t5, 3, 0, 7, 4, 1, 6, 2\n};\n\nstatic const float2 pos2[] = {\n\t{ 4.0 / 16.0,  4.0 / 16.0 },{ -4.0 / 16.0, -4.0 / 16.0 },\n};\n\nstatic const float2 pos4[] = {\n\t{ -2.0 / 16.0, -6.0 / 16.0 },{ 6.0 / 16.0, -2.0 / 16.0 },{ -6.0 / 16.0,  2.0 / 16.0 },{ 2.0 / 16.0,  6.0 / 16.0 },\n};\n\nstatic const float2 pos8[] = {\n\t{ 1.0 / 16.0, -3.0 / 16.0 },{ -1.0 / 16.0,  3.0 / 16.0 },{ 5.0 / 16.0,  1.0 / 16.0 },{ -3.0 / 16.0, -5.0 / 16.0 },\n\t{ -5.0 / 16.0,  5.0 / 16.0 },{ -7.0 / 16.0, -1.0 / 16.0 },{ 3.0 / 16.0,  7.0 / 16.0 },{ 7.0 / 16.0, -7.0 / 16.0 },\n};"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/UpsampleColorResolveCS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include \"SamplePositions.hlsli\"\r\n\r\n#define UpsampleResolve_RootSig \\\r\n    \"RootFlags(0), \" \\\r\n    \"CBV(b0), \" \\\r\n    \"DescriptorTable(SRV(t0, numDescriptors = 1)),\" \\\r\n    \"DescriptorTable(UAV(u0, numDescriptors = 1))\"\r\n\r\nTexture2DMS<float4> DownSizedInColor : register(t0);\r\nRWTexture2D<float4> OutColor : register(u0);\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n\tfloat ZMagic;\t\t\t\t// (zFar - zNear) / zNear\r\n\tfloat2 UpsampleFactor;\t\t\r\n}\r\n\r\n[RootSignature(UpsampleResolve_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main(uint3 DTid : SV_DispatchThreadID)\r\n{\r\n\tuint Width, Height, SampleCount;\r\n\tfloat4 Color;\r\n\tDownSizedInColor.GetDimensions(Width, Height, SampleCount);\r\n\tuint2 ID;\r\n\tID.x = DTid.x / UpsampleFactor.x;\r\n\tID.y = DTid.y / UpsampleFactor.y;\r\n\r\n\tint Temp = (DTid.x % (uint)UpsampleFactor.x) + (DTid.y % (uint)UpsampleFactor.y) * UpsampleFactor.x;\r\n\tint Offset;\r\n\tif (SampleCount == 2) Offset = offset2[Temp];\r\n\telse if (SampleCount == 4) Offset = offset4[Temp];\r\n\telse if (SampleCount == 8) Offset = offset8[Temp];\r\n\telse if (SampleCount == 1) Offset = 0;\r\n\r\n\tColor = DownSizedInColor.Load(ID.xy, Offset);\r\n\r\n\tOutColor[DTid.xy] = Color;\r\n\r\n\t//--------\r\n\t// Offset and SamplePosition Validation\r\n\r\n\t/*float2 SamplePosition = DownSizedInColor.GetSamplePosition(Offset);\r\n\tColor = float4(0, 0, 0, 1);\r\n\r\n\tif (SampleCount == 2) {\r\n\t\tif ((DTid.x % 2) == 0)\r\n\t\t\tColor += float4(pos2[1], 0, 0);\r\n\t\telse\r\n\t\t\tColor += float4(pos2[0], 0, 0);\r\n\t}\r\n\telse if (SampleCount == 4) {\r\n\t\tif ((DTid.y % 2) == 0) {\r\n\t\t\tif ((DTid.x%2) == 0)\r\n\t\t\t\tColor += float4(pos4[0], 0, 0);\r\n\t\t\telse\r\n\t\t\t\tColor += float4(pos4[1], 0, 0);\r\n\t\t}\r\n\t\telse {\r\n\t\t\tif ((DTid.x%2) == 0)\r\n\t\t\t\tColor += float4(pos4[2], 0, 0);\r\n\t\t\telse\r\n\t\t\t\tColor += float4(pos4[3], 0, 0);\r\n\t\t}\r\n\t}\r\n\telse if (SampleCount == 8) {\r\n\t\t\tif ((DTid.y % 2) == 0) {\r\n\t\t\t\tif ((DTid.x % 4) == 0)\r\n\t\t\t\t\tColor += float4(pos8[5], 0, 0);\r\n\t\t\t\telse if ((DTid.x % 4) ==1)\r\n\t\t\t\t\tColor += float4(pos8[3], 0, 0);\r\n\t\t\t\telse if ((DTid.x %4) == 2)\r\n\t\t\t\t\tColor += float4(pos8[0], 0, 0);\r\n\t\t\t\telse\r\n\t\t\t\t\tColor += float4(pos8[7], 0, 0);\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tif ((DTid.x % 4) == 0)\r\n\t\t\t\t\tColor += float4(pos8[4], 0, 0);\r\n\t\t\t\telse if ((DTid.x % 4) == 1)\r\n\t\t\t\t\tColor += float4(pos8[1], 0, 0);\r\n\t\t\t\telse if ((DTid.x % 4) == 2)\r\n\t\t\t\t\tColor += float4(pos8[6], 0, 0);\r\n\t\t\t\telse\r\n\t\t\t\t\tColor += float4(pos8[2], 0, 0);\r\n\t\t\t}\r\n\t}\r\n\r\n\tColor -= float4(SamplePosition, 0, 0);\r\n\r\n\tOutColor[DTid.xy] = Color;\r\n*/\r\n\t// Standard sample patterns\r\n\r\n\t//\t+static const tSamplePos pos1[] = {\r\n\t//\t+{ 0.0 / 16.0,  0.0 / 16.0 },\r\n\t//\t+};\r\n\t//+\r\n\t//\t+    // standard sample positions for 2, 4, 8, and 16 samples.\r\n\t//\t+static const tSamplePos pos2[] = {\r\n\t//\t+{ 4.0 / 16.0,  4.0 / 16.0 },{ -4.0 / 16.0, -4.0 / 16.0 },\r\n\t//\t+};\r\n\t//+\r\n\t//\t+static const tSamplePos pos4[] = {\r\n\t//\t+{-2.0 / 16.0, -6.0 / 16.0 },{ 6.0 / 16.0, -2.0 / 16.0 },{ -6.0 / 16.0,  2.0 / 16.0 },{ 2.0 / 16.0,  6.0 / 16.0 },\r\n\t//\t+};\r\n\t//+\r\n\t//\t+static const tSamplePos pos8[] = {\r\n\t//\t+{ 1.0 / 16.0, -3.0 / 16.0 },{ -1.0 / 16.0,  3.0 / 16.0 },{ 5.0 / 16.0,  1.0 / 16.0 },{ -3.0 / 16.0, -5.0 / 16.0 },\r\n\t//\t+{-5.0 / 16.0,  5.0 / 16.0 },{ -7.0 / 16.0, -1.0 / 16.0 },{ 3.0 / 16.0,  7.0 / 16.0 },{ 7.0 / 16.0, -7.0 / 16.0 },\r\n\t//\t+};\r\n\t//+\r\n\t//\t+static const tSamplePos pos16[] = {\r\n\t//\t+{ 1.0 / 16.0,  1.0 / 16.0 },{ -1.0 / 16.0, -3.0 / 16.0 },{ -3.0 / 16.0,  2.0 / 16.0 },{ 4.0 / 16.0, -1.0 / 16.0 },\r\n\t//\t+{-5.0 / 16.0, -2.0 / 16.0 },{ 2.0 / 16.0,  5.0 / 16.0 },{ 5.0 / 16.0,  3.0 / 16.0 },{ 3.0 / 16.0, -5.0 / 16.0 },\r\n\t//\t+{-2.0 / 16.0,  6.0 / 16.0 },{ 0.0 / 16.0, -7.0 / 16.0 },{ -4.0 / 16.0, -6.0 / 16.0 },{ -6.0 / 16.0,  4.0 / 16.0 },\r\n\t//\t+{-8.0 / 16.0,  0.0 / 16.0 },{ 7.0 / 16.0, -4.0 / 16.0 },{ 6.0 / 16.0,  7.0 / 16.0 },{ -7.0 / 16.0, -8.0 / 16.0 },\r\n\t//\t+};\r\n\r\n}"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/UpsampleDepthResolveCS.hlsl",
    "content": "///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n// Copyright (c) 2018, Intel Corporation\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \r\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation \r\n// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of \r\n// the Software.\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r\n// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \r\n// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r\n// SOFTWARE.\r\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n#include \"SamplePositions.hlsli\"\r\n\r\n#define UpsampleResolve_RootSig \\\r\n    \"RootFlags(0), \" \\\r\n    \"CBV(b0), \" \\\r\n    \"DescriptorTable(SRV(t0, numDescriptors = 1)),\" \\\r\n    \"DescriptorTable(UAV(u0, numDescriptors = 1))\"\r\n\r\nTexture2DMS<float> DownSizedInDepth : register(t0);\r\nRWTexture2D<float> OutDepth : register(u0);\r\n\r\ncbuffer CB0 : register(b0)\r\n{\r\n\tfloat ZMagic;\t\t\t\t// (zFar - zNear) / zNear\r\n\tfloat2 UpsampleFactor;\t\t\r\n}\r\n\r\n[RootSignature(UpsampleResolve_RootSig)]\r\n[numthreads(8, 8, 1)]\r\nvoid main(uint3 DTid : SV_DispatchThreadID)\r\n{\r\n\tuint Width, Height, SampleCount;\r\n\tfloat Depth;\r\n\tfloat LinearZ;\r\n\tDownSizedInDepth.GetDimensions(Width, Height, SampleCount);\r\n\r\n\tuint2 ID;\r\n\tID.x = DTid.x / UpsampleFactor.x;\r\n\tID.y = DTid.y / UpsampleFactor.y;\r\n\r\n\t/*uint Offset;\r\n\tOffset = (DTid.x % (uint)UpsampleFactor.x) + (DTid.y % (uint)UpsampleFactor.y) * UpsampleFactor.x;\r\n\t*/\r\n\tint Temp = (DTid.x % (uint)UpsampleFactor.x) + (DTid.y % (uint)UpsampleFactor.y) * UpsampleFactor.x;\r\n\tint Offset;\r\n\tif (SampleCount == 2) Offset = offset2[Temp];\r\n\telse if (SampleCount == 4) Offset = offset4[Temp];\r\n\telse if (SampleCount == 8) Offset = offset8[Temp];\r\n\telse if (SampleCount == 1) Offset = 0;\r\n\r\n\tDepth = DownSizedInDepth.Load(ID.xy, Offset);\r\n\r\n\tLinearZ = 1.0 / (ZMagic * Depth + 1.0);\r\n\r\n\tOutDepth[DTid.xy] = LinearZ;\r\n}"
  },
  {
    "path": "MiniEngine/ModelViewer/Shaders/WaveTileCountPS.hlsl",
    "content": "//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n// Developed by Minigraph\r\n//\r\n// Author(s):\tAlex Nankervis\r\n//\r\n\r\n#include \"ModelViewerRS.hlsli\"\r\n#include \"LightGrid.hlsli\"\r\n\r\nstruct VSOutput\r\n{\r\n    sample float4 position : SV_Position;\r\n    sample float3 worldPos : worldPos;\r\n    sample float2 texcoord0 : texcoord0;\r\n    sample float3 viewDir : texcoord1;\r\n    sample float3 shadowCoord : texcoord2;\r\n    sample float3 normal : normal;\r\n    sample float3 tangent : tangent;\r\n    sample float3 bitangent : bitangent;\r\n};\r\n\r\nTexture2D<float3> texDiffuse\t\t: register(t0);\r\nTexture2D<float3> texSpecular\t\t: register(t1);\r\n//Texture2D<float4> texEmissive\t\t: register(t2);\r\nTexture2D<float3> texNormal\t\t\t: register(t3);\r\n//Texture2D<float4> texLightmap\t\t: register(t4);\r\n//Texture2D<float4> texReflection\t: register(t5);\r\nTexture2D<float> texSSAO\t\t\t: register(t64);\r\nTexture2D<float> texShadow\t\t\t: register(t65);\r\n\r\nStructuredBuffer<LightData> lightBuffer : register(t66);\r\nTexture2DArray<float> lightShadowArrayTex : register(t67);\r\nByteAddressBuffer lightGrid : register(t68);\r\n\r\ncbuffer PSConstants : register(b0)\r\n{\r\n    float3 SunDirection;\r\n    float3 SunColor;\r\n    float3 AmbientColor;\r\n    float4 ShadowTexelSize;\r\n\r\n    float4 InvTileDim;\r\n    uint4 TileCount;\r\n    uint4 FirstLightIndex;\r\n\tfloat2 UpsamplingFactors;\t// the factors to compensate resolution upsampling\r\n\t\t\t\t\t\t\t\t// in color shading PS, if we downsample the viewport by x, the screenPosition must be compensated for fetching full screen like SSAO and lightCull indices\r\n\r\n}\r\n\r\nSamplerState sampler0 : register(s0);\r\nSamplerComparisonState shadowSampler : register(s1);\r\n\r\n[RootSignature(ModelViewer_RootSig)]\r\nfloat3 main(VSOutput vsOutput) : SV_Target0\r\n{\r\n    uint2 tilePos = GetTilePos(vsOutput.position.xy * UpsamplingFactors, InvTileDim.xy);\r\n    uint tileIndex = GetTileIndex(tilePos, TileCount.x);\r\n    uint tileOffset = GetTileOffset(tileIndex);\r\n\r\n    // There are three counts in one UINT\r\n    uint tileLightCount = lightGrid.Load(tileOffset + 0);\r\n    tileLightCount = (tileLightCount & 0xFF) + ((tileLightCount >> 8) & 0xFF) + ((tileLightCount >> 16) & 0xFF);\r\n\r\n    return lerp(float3(0, 1, 0), float3(1, 0, 0), tileLightCount / 32.0);\r\n}\r\n"
  },
  {
    "path": "MiniEngine/ModelViewer/UWP.appxmanifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Package xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\" xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\" xmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\" IgnorableNamespaces=\"uap mp\">\n  <Identity Name=\"202a44d8-54a7-4efd-83fe-ab27a027219c\" Publisher=\"CN=Microsoft\" Version=\"1.0.5.0\" />\n  <mp:PhoneIdentity PhoneProductId=\"202a44d8-54a7-4efd-83fe-ab27a027219c\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\" />\n  <Properties>\n    <DisplayName>ModelViewer</DisplayName>\n    <PublisherDisplayName>Microsoft</PublisherDisplayName>\n    <Logo>StoreLogo.png</Logo>\n  </Properties>\n  <Dependencies>\n    <TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10586.0\" MaxVersionTested=\"10.0.14393.0\" />\n  </Dependencies>\n  <Resources>\n    <Resource Language=\"x-generate\" />\n  </Resources>\n  <Applications>\n    <Application Id=\"App\" Executable=\"$targetnametoken$.exe\" EntryPoint=\"ModelViewer.App\">\n      <uap:VisualElements DisplayName=\"ModelViewer\" Square150x150Logo=\"Logo.png\" Square44x44Logo=\"Logo44.png\" Description=\"ModelViewer\" BackgroundColor=\"transparent\">\n        <uap:DefaultTile Wide310x150Logo=\"WideLogo.png\" />\n        <uap:SplashScreen Image=\"SplashScreen.png\" />\n      </uap:VisualElements>\n    </Application>\n  </Applications>\n</Package>"
  },
  {
    "path": "MiniEngine/ModelViewer/engineTuning.txt",
    "content": "   + Application ...\n        + CPS_Emulation ...\n             CPS Mode 0:  All On\n             Enable:  on\n             Sampling Bias:  1.000000\n        + CPS_MSAA ...\n             Enable:  off\n             LOD NoBias:  off\n             Set Samples as Grid:  off\n             Set-Sample Supported:  off\n        + Checkerboard ...\n             Debug:  off\n             Enable:  off\n             Mode:  2x\n        + Forward+ ...\n             Light Grid Dim:  16\n             Show Wave Tile Counts:  off\n        + Lighting ...\n             Ambient Intensity:  0.857418\n             Shadow Dim X:  40.000000\n             Shadow Dim Y:  40.000000\n             Shadow Dim Z:  35.000000\n             Sun Inclination:  0.670000\n             Sun Light Intensity:  2.297396\n             Sun Orientation:  7.299995\n        + MSAA ...\n             Depth Resolve Enable:  off\n             MSAA Depth Resolve Mode:  Min\n             MSAA Enable:  off\n             MSAA Mode:  4x\n             MSAA Resolver:  Custom\n        + Upsampling ...\n             Enable:  off\n             Mode:  1x\n   Display Frame Rate:  on\n   Display Performance Graph:  off\n   Display Profiler:  off\n   + Graphics ...\n        + AA ...\n             + FXAA ...\n                  Always Recompute Log-Luma:  off\n                  Contrast Threshold:  0.175000\n                  Debug:  off\n                  Enable:  off\n                  Subpixel Removal:  0.500000\n             + TAA ...\n                  Bicubic Filtering:  on\n                  Blue Noise:  on\n                  CPSWeight Mode:  Gaussian\n                  Disocclusion Visual:  off\n                  Enable:  on\n                  NumSamples:  8.000000\n                  Reset:  off\n                  Sharpness:  0.000000\n                  Silhouette Threshold Factor:  0.400000\n                  Silhouette Visual in Motion:  off\n                  Speed Limit:  32.000000\n                  Temporal Acc Modifier:  0.000000\n                  Variance Extension:  3.000000\n        + Bloom ...\n             Enable:  off\n             High Quality:  off\n             Scatter:  0.650000\n             Strength:  0.100000\n             Threshold:  4.000000\n        + Depth of Field ...\n             AntiSparkle:  1.000000\n             Debug Mode:  Off\n             Debug Tiles:  off\n             Enable:  off\n             FG Range:  100.000000\n             Focal Center:  0.100000\n             Focal Radius:  0.100000\n             Force Fast Path:  off\n             Force Slow Path:  off\n             Median Alpha:  off\n             Median Filter:  on\n             PreFilter:  on\n        + Display ...\n             Bicubic Filter Weight:  -0.750000\n             HDR Debug Mode:  HDR\n             Magnify Pixels:  Off\n             Native Resolution:  1920x1080\n             Paper White (nits):  200.000000\n             Peak Brightness (nits):  1000.000000\n             Sharpness Sample Rotation:  45.000000\n             Sharpness Sample Spread:  1.000000\n             Sharpness Strength:  0.100000\n             Upsample Filter:  Sharpening\n        + HDR ...\n             Adaptation Rate:  0.050000\n             Adaptive Exposure:  off\n             Draw Histogram:  off\n             Enable:  off\n             Exposure:  2.000000\n             Key:  0.080000\n             Max Exposure:  64.000000\n             Min Exposure:  0.015625\n        + Motion Blur ...\n             Enable:  off\n        + Particle Effects ...\n             Dynamic Resolution Cutoff:  0.000000\n             Enable:  off\n             Mip Bias:  0.000000\n             Pause Simulation:  off\n             Sort Sprites:  on\n             Tiled Rendering:  on\n             Tiled Sample Rate:  Dynamic\n        + SSAO ...\n             Accentuation:  0.700000\n             Always Linearize Z:  on\n             Async Compute:  off\n             Blur Tolerance (log10):  -5.000000\n             Debug Draw:  off\n             Enable:  on\n             Hierarchy Depth:  3\n             Noise Filter Threshold (log10):  -3.000000\n             Quality Level:  High\n             Rejection Falloff (rcp):  2.500000\n             Upsample Tolerance (log10):  -7.000000\n   + Timing ...\n        Drop Random Frames:  off\n        Limit To 30Hz:  off\n        VSync:  on\n"
  },
  {
    "path": "MiniEngine/ModelViewer/perfreport.csv",
    "content": "Analyze depth volumes, 0.61952, 0.620544, 0.623648, 0.626656, 0.620544, 0.622592, 0.622592, 0.621568, 0.624608, 0.623584, 0.627712, 0.625664, 0.626688, 0.6216, 0.622592, 0.622592, 0.627712, 0.626688, 0.62672, 0.61952, 0.628704, 0.625664, 0.627744, 0.619552, 0.622592, 0.620512, 0.627712, 0.620544, 0.623584, 0.624672, 0.62768, 0.624608, 0.6216, 0.623584, 0.626656, 0.625664, 0.627744, 0.622624, 0.621568, 0.62464, 0.622592, 0.626688, 0.6216, 0.619488, 0.627712, 0.61952, 0.62464, 0.619552, 0.627712, 0.620544, 0.628768, 0.620576, 0.626688, 0.623584, 0.628704, 0.62464, 0.622592, 0.625696, 0.627712, 0.62672, 0.622592, 0.618496, 0.626688, 0.626688, 0.62464, 0.622592, 0.64512, 0.62464, 0.622592, 0.625696, 0.62672, 0.644096, 0.62464, 0.61952, 0.618464, 0.62464, 0.627712, 0.62672, 0.627712, 0.62464, 0.626656, 0.669696, 0.625664, 0.625696, 0.62672, 0.62464, 0.627744, 0.619488, 0.625632, 0.620544, 0.658464, 0.625696, 0.622592, 0.621536, 0.627712, 0.685056, 0.626656, 0.627712, 0.62464, 0.621568, 0.642016, 0.627712, 0.621568, 0.626688, 0.621568, 0.640992, 0.62672, 0.618528, 0.620512, 0.623616, 0.627712, 0.620544, 0.620512, 0.625664, 0.64208, 0.627744, 0.62672, 0.619552, 0.628704, 0.684064, 0.62464, 0.627712, 0.623584, 0.626688, 0.627712, 0.623584, 0.626656, 0.625696, 0.62464, 0.625664, 0.625664, 0.61952, 0.625664, 0.625664, 0.623584, 0.622592, 0.62256, 0.621536, 0.671776, 0.632832, 0.620576, 0.625664, 0.620544, 0.647168, 0.622592, 0.625664, 0.62672, 0.62464, 0.65744, 0.624608, 0.627712, 0.626688, 0.625696, 0.62464, 0.62464, 0.620544, 0.619552, 0.625664, 0.628704, 0.61952, 0.623584, 0.622592, 0.626656, 0.63488, 0.620544, 0.620512, 0.623648, 0.628768, 0.627712, 0.61952, 0.625632, 0.627744, 0.674816, 0.623616, 0.62464, 0.62464, 0.618464, 0.651232, 0.622592, 0.62672, 0.628704, 0.627712, 0.62464, 0.619552, 0.635904, 0.625696, 0.652288, 0.625664, 0.628736, 0.62464, 0.626688, 0.624608, 0.62464, 0.620544, 0.625632, 0.620512, 0.65024, 0.626688, 0.627712, 0.625664, 0.627712, 0.625664, 0.622624, 0.618464, 0.625696, 0.64512, 0.626688, 0.623584, 0.627712, 0.626656, 0.62672, 0.62464, 0.618528, 0.624608, 0.623584, 0.625664, 0.623648, 0.62464, 0.62672, 0.62672, 0.630816, 0.624608, 0.620544, 0.61952, 0.626656, 0.65024, 0.623616, 0.625664, 0.62672, 0.62464, 0.625632, 0.623648, 0.627712, 0.625664, 0.62768, 0.625632, 0.61952, 0.620544, 0.625696, 0.623584, 0.626656, 0.62464, 0.625632, 0.621536, 0.627712, 0.623616, 0.636928, 0.623648, 0.620512, 0.62672, 0.625664, 0.62464, 0.622592, 0.624672, 0.625664, 0.622624, 0.62464, 0.62672, 0.630752, 0.626688, 0.623584, 0.625632, 0.62464, 0.62976, 0.625664, 0.624672, 0.626656, 0.62464, 0.627712, 0.626656, 0.623584, 0.625664, 0.626656, 0.625632, 0.626656, 0.624672, 0.62464, 0.65024, 0.627712, 0.620544, 0.626656, 0.623584, 0.627712, 0.623584, 0.623584, 0.625696, 0.625696, 0.627712, 0.627712, 0.625664, 0.623584, 0.621536, 0.62672, 0.623648, 0.622592, 0.625632, 0.628768, 0.63488, 0.62768, 0.62464, 0.625664, 0.623648, 0.62672, 0.626688, 0.632832, 0.622592, 0.66048, 0.625664, 0.623616, 0.625664, 0.623584, 0.626688, 0.62464, 0.627712, 0.621536, 0.617472, 0.625632, 0.62672, 0.626688, 0.625696, 0.625696, 0.690176, 0.623648, 0.64208, 0.6216, 0.655328, 0.623584, 0.620544, 0.62976, 0.620576, 0.642048, 0.627712, 0.620544, 0.61952, 0.62464, 0.693216, 0.62672, 0.62464, 0.627712, 0.620512, 0.625696, 0.61952, 0.622592, 0.620544, 0.626656, 0.657408, 0.627744, 0.625632, 0.622592, 0.685088, 0.625664, 0.61952, 0.628768, 0.617472, 0.623648, 0.626688, 0.623584, 0.625664, 0.627712, 0.62464, 0.625664, 0.622592, 0.625696, 0.627712, 0.640992, 0.62464, 0.62464, 0.626688, 0.6216, 0.677888, 0.62672, 0.619552, 0.622592, 0.626656, 0.62672, 0.625696, 0.629792, 0.626656, 0.627744, 0.625664, 0.621536, 0.626688, 0.61952, 0.62672, 0.627744, 0.6216, 0.619488, 0.628768, 0.626656, 0.625696, 0.620512, 0.62464, 0.618464, 0.623616, 0.625696, 0.618464, 0.62672, 0.624608, 0.625696, 0.619552, 0.62464, 0.618464, 0.669696, 0.625632, 0.622592, 0.618464, 0.627744, 0.656352, 0.62672, 0.622592, 0.62672, 0.62464, 0.656352, 0.625664, 0.61952, 0.620544, 0.62672, 0.62464, 0.631776, 0.620544, 0.621536, 0.627744, 0.627712, 0.626688, 0.61952, 0.625664, 0.625664, 0.625632, 0.620512, 0.61952, 0.622592, 0.626656, 0.625632, 0.619552, 0.619552, 0.625632, 0.626688, 0.625664, 0.626656, 0.62464, 0.618528, 0.62672, 0.626688, 0.625696, 0.622592, 0.642048, 0.625664, 0.61952, 0.627712, 0.61952, 0.626688, 0.627712, 0.620544, 0.61952, 0.627712, 0.625664, 0.627712, 0.61952, 0.627712, 0.621536, 0.644064, 0.623648, 0.620512, 0.627712, 0.622592, 0.625632, 0.627712, 0.619552, 0.620576, 0.627712, 0.62464, 0.625696, 0.628704, 0.621536, 0.62976, 0.625664, 0.625632, 0.62464, 0.622592, 0.626656, 0.631808, 0.62672, 0.626656, 0.626688, 0.627712, 0.626688, 0.634848, 0.625632, 0.618496, 0.627712, 0.623648, 0.621536, 0.623584, 0.626688, 0.625696, 0.6216, 0.620512, 0.61952, 0.625664, 0.627712, 0.618528, 0.622592, 0.623584, 0.626656, 0.623584, 0.6216, 0.61952, 0.622592, 0.629792, 0.625664, 0.625632, 0.626656, 0.618464, 0.625664, 0.627712, 0.618528, 0.62672, 0.674816, 0.625696, 0.620576, 0.623584, 0.626688, 0.62464, 0.625632, 0.618464, 0.621568, 0.623648, 0.623648, 0.626688, 0.626688, 0.62464, 0.632864, 0.627712, 0.62976, 0.6216, 0.620512, 0.62768, 0.625664, 0.63696, 0.622592, 0.626688, 0.642048, \nBlur and upsample, 0.877536, 0.88064, 0.879584, 0.881696, 0.873472, 0.878592, 0.87248, 0.8776, 0.873472, 0.886816, 0.878592, 0.881632, 0.87856, 0.876576, 0.878592, 0.876544, 0.878592, 0.885792, 0.882656, 0.873472, 0.87248, 0.871392, 0.886784, 0.881632, 0.879584, 0.8776, 0.878592, 0.874464, 0.873472, 0.879584, 0.883712, 0.881696, 0.878592, 0.876576, 0.87552, 0.8888, 0.878592, 0.880608, 0.873472, 0.876576, 0.874528, 0.874496, 0.876544, 0.882688, 0.87552, 0.879648, 0.878592, 0.8704, 0.87552, 0.87552, 0.877536, 0.88064, 0.871424, 0.881696, 0.879648, 0.882688, 0.870368, 0.884704, 0.883712, 0.868352, 0.876512, 0.87552, 0.881664, 0.880608, 0.883712, 0.88064, 0.980992, 0.883712, 0.879584, 0.885792, 0.878592, 0.885728, 0.879616, 0.879584, 0.874496, 0.87552, 0.924704, 0.88064, 0.87552, 0.884704, 0.882688, 0.946176, 0.88064, 0.869344, 0.876544, 0.88064, 0.881664, 0.874528, 0.879616, 0.879584, 0.93696, 0.881632, 0.877536, 0.878624, 0.883744, 0.989184, 0.891936, 0.88272, 0.8776, 0.875552, 0.883744, 0.88064, 0.8776, 0.876544, 0.878592, 0.937984, 0.879584, 0.872416, 0.87552, 0.882656, 0.87552, 0.872448, 0.879648, 0.874464, 0.886752, 0.880608, 0.878592, 0.877568, 0.868352, 0.883712, 0.881632, 0.871392, 0.87248, 0.879648, 0.88064, 0.899072, 0.88272, 0.877536, 0.88064, 0.883712, 0.887808, 0.873472, 0.88272, 0.88576, 0.881696, 0.874528, 0.876544, 0.873472, 0.900064, 0.882688, 0.874496, 0.877568, 0.871456, 0.941056, 0.884768, 0.878592, 0.877536, 0.873472, 0.925696, 0.881696, 0.871424, 0.876544, 0.872416, 0.880608, 0.88576, 0.874464, 0.873472, 0.883712, 0.886784, 0.87552, 0.876544, 0.873472, 0.947232, 0.909344, 0.87856, 0.8776, 0.879584, 0.887808, 0.88064, 0.871424, 0.879648, 0.880608, 0.879584, 0.88368, 0.87552, 0.8704, 0.875552, 0.88784, 0.882688, 0.883712, 0.875552, 0.920576, 0.880608, 0.872448, 0.879648, 0.87552, 0.922624, 0.887808, 0.875488, 0.875552, 0.880608, 0.884768, 0.883712, 0.871456, 0.871424, 0.874528, 0.903168, 0.881632, 0.876544, 0.8704, 0.876512, 0.883712, 0.878624, 0.873472, 0.877536, 0.957472, 0.880608, 0.881696, 0.872448, 0.88064, 0.882688, 0.883712, 0.874464, 0.872448, 0.879648, 0.88064, 0.898048, 0.876576, 0.872448, 0.873472, 0.901088, 0.881696, 0.874528, 0.87552, 0.873472, 0.909344, 0.882656, 0.874464, 0.878592, 0.882656, 0.883712, 0.873472, 0.87552, 0.881696, 0.927776, 0.88272, 0.8776, 0.8776, 0.878592, 0.891904, 0.883712, 0.884768, 0.883712, 0.8776, 0.88576, 0.88368, 0.869344, 0.878592, 0.880672, 0.932864, 0.882688, 0.873472, 0.884768, 0.931808, 0.88576, 0.875488, 0.8704, 0.874464, 0.91648, 0.881664, 0.88064, 0.87552, 0.870368, 0.892896, 0.883712, 0.873472, 0.874528, 0.8776, 0.882688, 0.881696, 0.8776, 0.87856, 0.871456, 0.891936, 0.893952, 0.873472, 0.871424, 0.88272, 0.881696, 0.876512, 0.87248, 0.879648, 0.918528, 0.879648, 0.872448, 0.876544, 0.875488, 0.922592, 0.883712, 0.878592, 0.876576, 0.8776, 0.925696, 0.886784, 0.874528, 0.878592, 0.879584, 0.905248, 0.878592, 0.875552, 0.873472, 0.881632, 0.884704, 0.871424, 0.88576, 0.874464, 0.980992, 0.88064, 0.877568, 0.873472, 0.871456, 0.886784, 0.879648, 0.883712, 0.87552, 0.877568, 0.88064, 0.878592, 0.876544, 0.871424, 0.875488, 0.95536, 0.886752, 0.87856, 0.87552, 0.968736, 0.884768, 0.87552, 0.874464, 0.872416, 0.967712, 0.883712, 0.87552, 0.873472, 0.88576, 0.97488, 0.88576, 0.877536, 0.879584, 0.88272, 0.883712, 0.883712, 0.876576, 0.87248, 0.879648, 0.954368, 0.880608, 0.87552, 0.878592, 0.953344, 0.882688, 0.886816, 0.877568, 0.876544, 0.884704, 0.88576, 0.87552, 0.881696, 0.882688, 0.891904, 0.882656, 0.877568, 0.873472, 0.876544, 0.904224, 0.8776, 0.877536, 0.867296, 0.876512, 0.884768, 0.886752, 0.877536, 0.872448, 0.919584, 0.88368, 0.88064, 0.886752, 0.876576, 0.888832, 0.878592, 0.876576, 0.87248, 0.88064, 0.886752, 0.886784, 0.878592, 0.878624, 0.8704, 0.884768, 0.88272, 0.876544, 0.873472, 0.879648, 0.880608, 0.892896, 0.8776, 0.87552, 0.952352, 0.881664, 0.874528, 0.884768, 0.877568, 0.887776, 0.892928, 0.87552, 0.87248, 0.877536, 0.925728, 0.884704, 0.874464, 0.878592, 0.880672, 0.924704, 0.88064, 0.879584, 0.876576, 0.869344, 0.881664, 0.879648, 0.8776, 0.873504, 0.927712, 0.881664, 0.877568, 0.875552, 0.877568, 0.883712, 0.878592, 0.871424, 0.875488, 0.874464, 0.881696, 0.884768, 0.874464, 0.879584, 0.881696, 0.884768, 0.878592, 0.876576, 0.87248, 0.874464, 0.926688, 0.879584, 0.88064, 0.88576, 0.888832, 0.906272, 0.873472, 0.876544, 0.876576, 0.88272, 0.88576, 0.877536, 0.876544, 0.883712, 0.883712, 0.88576, 0.877536, 0.875552, 0.87552, 0.944128, 0.879584, 0.872448, 0.877568, 0.8776, 0.910368, 0.8776, 0.874464, 0.872416, 0.88576, 0.878592, 0.882656, 0.881664, 0.88064, 0.88576, 0.883744, 0.879648, 0.876544, 0.882656, 0.895008, 0.882656, 0.881632, 0.883712, 0.8776, 0.883712, 0.884704, 0.88064, 0.878592, 0.87552, 0.89904, 0.88368, 0.878592, 0.881664, 0.884768, 0.881664, 0.879584, 0.88064, 0.874528, 0.948224, 0.884768, 0.877536, 0.876576, 0.881696, 0.88576, 0.88784, 0.881632, 0.874496, 0.879584, 0.886752, 0.878592, 0.881664, 0.871456, 0.87552, 0.884768, 0.898048, 0.877536, 0.8704, 0.88272, 0.879584, 0.891904, 0.8776, 0.873472, 0.884736, 0.878592, 0.879648, 0.877536, 0.878592, 0.892928, 0.883712, 0.883712, 0.884768, 0.872416, 0.88064, 0.902112, 0.876512, 0.878592, 0.879648, 0.88064, 0.892928, 0.878624, 0.879648, 0.886816, \nCopy texture to memory, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0, 0.810016, 0, 0, 0, 0, 0.838656, 0, 0, 0, 0, 0.75472, 0, 0, 0, 0, 0.821248, 0, 0, 0, 0.75776, 0, 0, 0, 0, 0.755712, 0, 0, 0, 0, 0.7936, 0, 0, 0, 0, 0.75776, 0, 0, 0, 0, 0.784416, 0, 0, 0, 0.834528, 0, 0, 0, 0, 0.771072, 0, 0, 0, 0, 0.804832, 0, 0, 0, 0, 0.867328, 0, 0, 0, 0, 0.75776, 0, 0, 0, 0.797696, 0, 0, 0, 0, 0.799744, 0, 0, 0, 0, 0.789504, 0, 0, 0, 0, 0.75776, 0, 0, 0, 0, 0.75776, 0, 0, 0, 0.813056, 0, 0, 0, 0, 0.801824, 0, 0, 0, 0, 0.777216, 0, 0, 0, 0, 0.905184, 0, 0, 0, 0, 0.755712, 0, 0, 0, 0.75472, 0, 0, 0, 0, 0.789472, 0, 0, 0, 0, 0.811008, 0, 0, 0, 0, 0.835584, 0, 0, 0, 0, 0.78848, 0, 0, 0, 0.893952, 0, 0, 0, 0, 0.794592, 0, 0, 0, 0, 0.771072, 0, 0, 0, 0, 0.762848, 0, 0, 0, 0, 0.891936, 0, 0, 0, 1.12947, 0, 0, 0, 0, 0.84784, 0, 0, 0, 0, 0.83248, 0, 0, 0, 0, 0.797696, 0, 0, 0, 0, 0.761824, 0, 0, 0, 0.754656, 0, 0, 0, 0, 0.792576, 0, 0, 0, 0, 0.838656, 0, 0, 0, 0, 0.81408, 0, 0, 0, 0, 0.817152, 0, 0, 0, 0.95744, 0, 0, 0, 0, 0.84992, 0, 0, 0, 0, 0.754656, 0, 0, 0, 0, 0.755712, 0, 0, 0, 0, 0.758816, 0, 0, 0, 0.79152, 0, 0, 0, 0, 0.753632, 0, 0, 0, 0, 0.77616, 0, 0, 0, 0, 0.753664, 0, 0, 0, 0, 0.753632, 0, 0, 0, 0.763872, 0, 0, 0, 0, 0.794592, 0, 0, 0, 0, 0.76592, 0, 0, 0, 0, 0.864224, 0, 0, 0, 0, 0.792576, 0, 0, 0, 0.78128, 0, 0, 0, 0, 0.750592, 0, 0, 0, 0, 0.818176, 0, 0, 0, 0, 0.75776, 0, 0, 0, 0, 0.937984, 0, 0, 0, 0.75776, 0, 0, 0, 0, 0.790528, 0, 0, 0, 0, 0.761888, 0, 0, 0, 0, 0.777216, 0, 0, 0, 0, 0.812, 0, 0, 0, 0.792576, 0, 0, 0, 0, 0.7936, 0, 0, 0, 0, 0.813056, 0, 0, 0, 0, 0.812, 0, 0, 0, 0, 0.736224, 0, 0, 0, 0.750592, 0, 0, 0, 0, 0.792576, 0, 0, 0, 0, 0.764928, 0, 0, 0, 0, 0.775168, 0, 0, 0, 0, 0.754688, 0, 0, 0, 0.75776, 0, 0, 0, 0, 0.754656, 0, 0, 0, 0, 0.748576, 0, 0, 0, 0, 0.764896, 0, 0, 0, 0, 0.758816, 0, 0, 0, 0.964608, 0, 0, 0, 0, 0.787456, 0, 0, 0, 0, 0.815104, 0, 0, 0, 0, 0.79872, 0, 0, 0, 0, 0.794656, 0, 0, 0, 0.86528, 0, 0, 0, 0, 0.804864, 0, 0, 0, 0, 0.813056, 0, 0, 0, 0, 0.790528, 0, 0, 0, 0, 0.988192, 0, 0, 0, 0.78848, 0, 0, 0, 0, 0.777184, 0, 0, 0, 0, 0.83248, 0, 0, 0, 0, 0.84688, 0, 0, 0, 0, 0.777248, 0, 0, 0, 0.78848, \nCutout, 0.062464, 0.062464, 0.062464, 0.062464, 0.062432, 0.063488, 0.062464, 0.061408, 0.061472, 0.061472, 0.062464, 0.062496, 0.062464, 0.063488, 0.062464, 0.061472, 0.062464, 0.061408, 0.062464, 0.061472, 0.063456, 0.063456, 0.062464, 0.062464, 0.061408, 0.062464, 0.062464, 0.062464, 0.062496, 0.06352, 0.063456, 0.061472, 0.062464, 0.061408, 0.062464, 0.061472, 0.062464, 0.062464, 0.062464, 0.061408, 0.061472, 0.061472, 0.062464, 0.062464, 0.062464, 0.063456, 0.062464, 0.062496, 0.061472, 0.061472, 0.062464, 0.061472, 0.063488, 0.06352, 0.062464, 0.06144, 0.06352, 0.06144, 0.062464, 0.062464, 0.06352, 0.06448, 0.063456, 0.061472, 0.06144, 0.061408, 0.063488, 0.062432, 0.062464, 0.062496, 0.062464, 0.063488, 0.063488, 0.063488, 0.064512, 0.065536, 0.080896, 0.064544, 0.063456, 0.062464, 0.061472, 0.066592, 0.061408, 0.058368, 0.059392, 0.057344, 0.057344, 0.057376, 0.058368, 0.059392, 0.059392, 0.060416, 0.059424, 0.059424, 0.062464, 0.061408, 0.062464, 0.062464, 0.062464, 0.063488, 0.067584, 0.062464, 0.06448, 0.062464, 0.065536, 0.064512, 0.06352, 0.06448, 0.06448, 0.063488, 0.061472, 0.058368, 0.053248, 0.051168, 0.049152, 0.045024, 0.046048, 0.045056, 0.045056, 0.045056, 0.041952, 0.040992, 0.039904, 0.04096, 0.039936, 0.037888, 0.036832, 0.034848, 0.036832, 0.037888, 0.037856, 0.03888, 0.037888, 0.03888, 0.037888, 0.036896, 0.036864, 0.035808, 0.034816, 0.034816, 0.03376, 0.036864, 0.034816, 0.035808, 0.033824, 0.034816, 0.034816, 0.034784, 0.034816, 0.03376, 0.034816, 0.034816, 0.03584, 0.034816, 0.034848, 0.034816, 0.035808, 0.03584, 0.034848, 0.034816, 0.034816, 0.035808, 0.035808, 0.03584, 0.03584, 0.032768, 0.03376, 0.034816, 0.032768, 0.032768, 0.034816, 0.03376, 0.033824, 0.03376, 0.032768, 0.0328, 0.0328, 0.03376, 0.034816, 0.034816, 0.035808, 0.03584, 0.036832, 0.036864, 0.035808, 0.035808, 0.034816, 0.032768, 0.035808, 0.036864, 0.035872, 0.035872, 0.03584, 0.036864, 0.037888, 0.037888, 0.04096, 0.038944, 0.039936, 0.039936, 0.039936, 0.039936, 0.03888, 0.037888, 0.036864, 0.037888, 0.036832, 0.036864, 0.037888, 0.03888, 0.037888, 0.037888, 0.037888, 0.039936, 0.038944, 0.040928, 0.040992, 0.039936, 0.038944, 0.034784, 0.031744, 0.031776, 0.032768, 0.033824, 0.036832, 0.039936, 0.041952, 0.044032, 0.044, 0.044, 0.045056, 0.045056, 0.046048, 0.047104, 0.046112, 0.04608, 0.047104, 0.047104, 0.04608, 0.046048, 0.046048, 0.047072, 0.049184, 0.048096, 0.050176, 0.049184, 0.046048, 0.04608, 0.045056, 0.041984, 0.036832, 0.032768, 0.031712, 0.032768, 0.034784, 0.033824, 0.035872, 0.038944, 0.040928, 0.044, 0.046048, 0.044, 0.04912, 0.054272, 0.0584, 0.05936, 0.066528, 0.060416, 0.068576, 0.066528, 0.0696, 0.074784, 0.074752, 0.073696, 0.079872, 0.07888, 0.080896, 0.084992, 0.083936, 0.073728, 0.072704, 0.065536, 0.062496, 0.061408, 0.058368, 0.057312, 0.057344, 0.058336, 0.057376, 0.055328, 0.056352, 0.057376, 0.055296, 0.055296, 0.055296, 0.055296, 0.055296, 0.055296, 0.056352, 0.057344, 0.057344, 0.058368, 0.059392, 0.060416, 0.062464, 0.065536, 0.072672, 0.077824, 0.084992, 0.087008, 0.084992, 0.084, 0.08192, 0.081952, 0.071648, 0.060416, 0.063488, 0.062464, 0.070624, 0.070656, 0.077824, 0.089088, 0.09424, 0.09728, 0.095232, 0.094176, 0.095232, 0.09216, 0.089056, 0.08704, 0.105472, 0.102432, 0.106528, 0.106528, 0.107488, 0.125984, 0.115712, 0.116704, 0.121824, 0.120832, 0.124928, 0.124928, 0.12288, 0.120864, 0.118816, 0.135168, 0.11776, 0.11568, 0.113632, 0.128, 0.113664, 0.110592, 0.110592, 0.111584, 0.110592, 0.109536, 0.111616, 0.109568, 0.110592, 0.110592, 0.109568, 0.110592, 0.110592, 0.108512, 0.111648, 0.108576, 0.106464, 0.108512, 0.107488, 0.109536, 0.10752, 0.106528, 0.108512, 0.109536, 0.108576, 0.10752, 0.106464, 0.106528, 0.10752, 0.106528, 0.106528, 0.105472, 0.106528, 0.106496, 0.106528, 0.105472, 0.106528, 0.105472, 0.108544, 0.106528, 0.106464, 0.105472, 0.106528, 0.106464, 0.106496, 0.106528, 0.105472, 0.110592, 0.109568, 0.10752, 0.10752, 0.108576, 0.10752, 0.10752, 0.107552, 0.106464, 0.10752, 0.10752, 0.10752, 0.107488, 0.10752, 0.10752, 0.109536, 0.107552, 0.10752, 0.108544, 0.1096, 0.112608, 0.109536, 0.108544, 0.108544, 0.111648, 0.11264, 0.109568, 0.114688, 0.107552, 0.111584, 0.110592, 0.111584, 0.110592, 0.109568, 0.111584, 0.109536, 0.1096, 0.1096, 0.109536, 0.11264, 0.110592, 0.108544, 0.109536, 0.109568, 0.11056, 0.110592, 0.110592, 0.110592, 0.111648, 0.110592, 0.108544, 0.110592, 0.11056, 0.116768, 0.111584, 0.110592, 0.108576, 0.110592, 0.113696, 0.110592, 0.110592, 0.110592, 0.1096, 0.114656, 0.110592, 0.11056, 0.110592, 0.110592, 0.110592, 0.111584, 0.109536, 0.110592, 0.110592, 0.111648, 0.109536, 0.110592, 0.110592, 0.11264, 0.110592, 0.110592, 0.108512, 0.1096, 0.11264, 0.110592, 0.109568, 0.11056, 0.109536, 0.113664, 0.110592, 0.110592, 0.11056, 0.111648, 0.113664, 0.109568, 0.109568, 0.110592, 0.112608, 0.111648, 0.109536, 0.110592, 0.110592, 0.112672, 0.111584, 0.110592, 0.110592, 0.111584, 0.113696, 0.110592, 0.11056, 0.110592, 0.1096, 0.113696, 0.110592, 0.110592, 0.109536, 0.111584, 0.113632, 0.111584, 0.110592, 0.110592, 0.113632, 0.111648, 0.108512, 0.111648, 0.110592, 0.112608, 0.111584, 0.1096, 0.109568, 0.110592, 0.113664, 0.111648, 0.110592, 0.110592, 0.112608, 0.111648, 0.110592, 0.109536, 0.109568, 0.110592, 0.110592, 0.110592, 0.11056, 0.109568, 0.113696, \nDecompress and downsample, 0.610304, 0.610336, 0.616416, 0.610304, 0.60928, 0.608224, 0.612352, 0.610304, 0.613408, 0.622592, 0.612352, 0.611328, 0.614432, 0.608224, 0.613408, 0.611296, 0.6144, 0.612352, 0.615392, 0.612352, 0.618528, 0.613408, 0.615424, 0.607232, 0.615456, 0.61136, 0.613408, 0.608288, 0.611328, 0.611296, 0.61648, 0.611296, 0.611296, 0.609312, 0.613408, 0.612352, 0.615424, 0.61232, 0.615424, 0.610304, 0.624608, 0.615424, 0.612352, 0.613408, 0.614432, 0.612352, 0.610304, 0.610272, 0.613344, 0.612352, 0.613344, 0.609248, 0.612352, 0.613376, 0.615424, 0.606176, 0.612352, 0.612352, 0.6144, 0.612352, 0.615424, 0.610336, 0.615424, 0.612352, 0.614368, 0.608288, 0.62464, 0.607232, 0.61136, 0.611296, 0.613344, 0.612352, 0.6144, 0.608288, 0.613376, 0.613344, 0.686048, 0.615392, 0.612352, 0.61136, 0.6144, 0.610304, 0.622592, 0.612352, 0.613344, 0.614368, 0.612352, 0.611328, 0.61648, 0.612352, 0.616416, 0.610304, 0.612352, 0.612352, 0.614368, 0.615456, 0.613408, 0.611296, 0.613376, 0.611296, 0.62976, 0.610272, 0.609248, 0.611296, 0.611296, 0.614432, 0.611296, 0.611328, 0.61136, 0.61136, 0.615424, 0.608288, 0.61648, 0.613408, 0.688128, 0.607232, 0.6144, 0.611296, 0.614432, 0.612352, 0.61136, 0.612352, 0.613408, 0.611296, 0.617472, 0.615456, 0.615456, 0.613344, 0.612352, 0.613408, 0.612352, 0.612352, 0.614368, 0.613408, 0.615424, 0.611296, 0.613376, 0.61136, 0.6144, 0.6216, 0.6144, 0.612352, 0.613344, 0.61136, 0.625632, 0.611296, 0.6144, 0.61136, 0.615392, 0.610336, 0.615392, 0.609248, 0.613344, 0.61136, 0.613344, 0.612352, 0.612352, 0.610336, 0.621568, 0.611296, 0.614432, 0.61136, 0.615456, 0.623584, 0.612352, 0.612352, 0.612352, 0.615424, 0.60928, 0.611296, 0.615424, 0.625664, 0.615424, 0.613408, 0.610304, 0.612384, 0.615424, 0.618528, 0.614432, 0.611296, 0.613408, 0.6144, 0.620576, 0.611296, 0.612352, 0.610304, 0.616416, 0.625632, 0.614432, 0.610304, 0.615424, 0.612352, 0.625696, 0.611296, 0.615424, 0.613376, 0.61952, 0.615392, 0.612352, 0.610304, 0.613376, 0.60928, 0.615424, 0.61136, 0.615424, 0.618464, 0.61648, 0.610304, 0.615424, 0.613408, 0.613344, 0.612352, 0.615424, 0.610336, 0.6144, 0.613408, 0.615424, 0.611296, 0.613344, 0.611328, 0.614368, 0.611328, 0.615392, 0.613376, 0.615456, 0.626656, 0.61648, 0.60928, 0.6144, 0.615456, 0.623648, 0.611296, 0.614432, 0.61136, 0.613376, 0.613408, 0.614368, 0.611296, 0.615392, 0.613408, 0.625696, 0.612352, 0.613376, 0.61136, 0.615456, 0.62464, 0.614432, 0.610272, 0.613376, 0.65024, 0.615456, 0.61136, 0.6144, 0.64816, 0.620576, 0.609248, 0.614368, 0.613344, 0.615424, 0.611296, 0.613408, 0.61136, 0.61136, 0.656416, 0.62464, 0.60928, 0.615456, 0.611296, 0.617472, 0.620576, 0.613408, 0.612352, 0.616448, 0.614432, 0.618528, 0.610272, 0.6144, 0.620512, 0.6144, 0.60928, 0.6144, 0.612352, 0.610272, 0.623648, 0.6144, 0.612352, 0.610304, 0.6656, 0.613344, 0.610304, 0.615424, 0.611328, 0.620512, 0.613344, 0.613344, 0.609312, 0.6144, 0.612352, 0.613376, 0.611296, 0.613344, 0.612352, 0.612352, 0.632832, 0.613408, 0.61136, 0.643072, 0.611328, 0.612352, 0.60928, 0.612352, 0.614368, 0.614368, 0.610272, 0.613408, 0.610304, 0.628768, 0.60928, 0.614432, 0.614368, 0.611296, 0.67072, 0.616416, 0.611296, 0.6144, 0.682016, 0.612352, 0.611296, 0.614432, 0.614368, 0.646112, 0.607232, 0.6144, 0.610304, 0.6144, 0.68608, 0.612352, 0.608288, 0.613408, 0.61136, 0.614368, 0.610304, 0.612352, 0.611296, 0.615424, 0.684064, 0.626656, 0.610304, 0.613408, 0.68304, 0.626688, 0.610304, 0.626656, 0.610304, 0.613344, 0.612352, 0.610304, 0.610304, 0.615424, 0.612352, 0.612352, 0.60928, 0.6144, 0.613408, 0.672768, 0.611296, 0.61136, 0.614432, 0.612352, 0.635936, 0.615392, 0.606176, 0.610304, 0.630816, 0.611296, 0.61232, 0.615392, 0.612352, 0.616416, 0.60928, 0.6144, 0.625664, 0.610272, 0.616448, 0.631776, 0.608224, 0.612352, 0.613344, 0.6144, 0.613344, 0.609312, 0.620544, 0.613376, 0.612384, 0.6144, 0.612352, 0.613344, 0.613408, 0.619488, 0.612352, 0.614368, 0.608256, 0.65536, 0.619552, 0.612352, 0.613408, 0.614368, 0.628768, 0.612352, 0.613408, 0.613344, 0.612352, 0.630816, 0.60928, 0.61136, 0.60928, 0.615392, 0.60928, 0.620576, 0.611328, 0.615456, 0.636896, 0.620576, 0.609248, 0.627712, 0.62256, 0.617504, 0.623648, 0.613408, 0.610304, 0.608288, 0.613408, 0.61648, 0.608224, 0.613344, 0.61136, 0.615424, 0.610272, 0.60928, 0.612352, 0.613376, 0.65024, 0.61136, 0.613344, 0.612352, 0.615424, 0.617472, 0.611296, 0.613408, 0.608256, 0.618464, 0.61136, 0.611328, 0.610304, 0.615424, 0.612352, 0.616416, 0.61136, 0.61744, 0.60928, 0.6728, 0.610304, 0.614432, 0.628768, 0.613344, 0.689184, 0.612352, 0.60928, 0.614368, 0.610336, 0.621536, 0.610304, 0.613408, 0.607232, 0.61648, 0.612352, 0.6144, 0.609312, 0.612352, 0.613408, 0.620544, 0.610272, 0.6144, 0.612352, 0.616448, 0.61136, 0.613408, 0.612384, 0.611296, 0.61952, 0.612352, 0.608288, 0.613408, 0.617472, 0.616416, 0.612352, 0.610304, 0.616416, 0.616448, 0.60928, 0.611296, 0.60928, 0.613408, 0.667648, 0.610336, 0.606208, 0.61136, 0.60928, 0.618464, 0.610336, 0.612352, 0.613408, 0.61136, 0.669696, 0.620576, 0.613344, 0.613344, 0.662528, 0.621536, 0.610304, 0.60928, 0.620544, 0.61952, 0.618528, 0.612352, 0.608256, 0.611296, 0.713696, 0.613376, 0.610304, 0.6144, 0.612352, 0.616416, 0.623648, 0.612352, 0.610304, 0.613376, 0.610336, 0.618464, 0.608256, 0.613376, 0.674784, \nFillLightGrid, 2.1504, 2.20259, 2.15347, 2.16064, 2.15146, 2.16989, 2.14934, 2.17187, 2.14835, 2.16576, 2.16064, 2.15965, 2.15446, 2.16061, 2.15859, 2.16781, 2.15552, 2.15446, 2.15146, 2.21898, 2.15242, 2.16573, 2.16269, 2.21594, 2.1576, 2.16883, 2.15245, 2.16477, 2.14938, 2.17091, 2.15658, 2.16675, 2.15754, 2.16778, 2.1576, 2.16477, 2.1473, 2.20262, 2.16266, 2.17088, 2.15859, 2.17699, 2.15856, 2.16682, 2.14934, 2.16573, 2.17293, 2.20672, 2.15654, 2.17085, 2.15146, 2.1719, 2.15658, 2.16166, 2.15245, 2.16781, 2.16576, 2.16064, 2.16163, 2.16675, 2.20061, 2.16272, 2.15453, 2.16576, 2.15347, 2.1647, 2.15446, 2.16477, 2.15757, 2.16675, 2.15856, 2.16682, 2.14627, 2.16166, 2.14835, 2.16678, 2.15347, 2.16678, 2.16067, 2.1617, 2.16067, 2.17187, 2.15552, 2.1719, 2.16163, 2.16886, 2.15757, 2.176, 2.16272, 2.16883, 2.17392, 2.16579, 2.17194, 2.18314, 2.1647, 2.17293, 2.16064, 2.1688, 2.15651, 2.15958, 2.1463, 2.15347, 2.1463, 2.16477, 2.14323, 2.16166, 2.15248, 2.16166, 2.14019, 2.15555, 2.14528, 2.20157, 2.14323, 2.16269, 2.15658, 2.16682, 2.1391, 2.16371, 2.14528, 2.16064, 2.14736, 2.15446, 2.15139, 2.15958, 2.14736, 2.15757, 2.1504, 2.15658, 2.15142, 2.16675, 2.14326, 2.15958, 2.1473, 2.15651, 2.15142, 2.17187, 2.1504, 2.16989, 2.18218, 2.17088, 2.15347, 2.17088, 2.1473, 2.17395, 2.15347, 2.16781, 2.15965, 2.16371, 2.17088, 2.16266, 2.1576, 2.16781, 2.15248, 2.16269, 2.14323, 2.16477, 2.14733, 2.17293, 2.16374, 2.17501, 2.1473, 2.16266, 2.15549, 2.16166, 2.15142, 2.16678, 2.15347, 2.16576, 2.16477, 2.16272, 2.1473, 2.1617, 2.16272, 2.16166, 2.14224, 2.16371, 2.14733, 2.15552, 2.14218, 2.15757, 2.1504, 2.15962, 2.16064, 2.15037, 2.14115, 2.15446, 2.14736, 2.16477, 2.14736, 2.15552, 2.13712, 2.15651, 2.13811, 2.1463, 2.13712, 2.14531, 2.1463, 2.1576, 2.1391, 2.15139, 2.1463, 2.15859, 2.1473, 2.16576, 2.14323, 2.20157, 2.14323, 2.15142, 2.14326, 2.14736, 2.14118, 2.15139, 2.14736, 2.1463, 2.14218, 2.1647, 2.14426, 2.15859, 2.14938, 2.14835, 2.14835, 2.1504, 2.14118, 2.15654, 2.13606, 2.16883, 2.12483, 2.14019, 2.12787, 2.12995, 2.11763, 2.13606, 2.11558, 2.12688, 2.11046, 2.12886, 2.11251, 2.12374, 2.10637, 2.12582, 2.11152, 2.12784, 2.1033, 2.12374, 2.11046, 2.12378, 2.11354, 2.1289, 2.11658, 2.12989, 2.11354, 2.13811, 2.12272, 2.13094, 2.1248, 2.13299, 2.12378, 2.13405, 2.13299, 2.14323, 2.13402, 2.13712, 2.12586, 2.14118, 2.12582, 2.18211, 2.1391, 2.14528, 2.12582, 2.14426, 2.12787, 2.17808, 2.13197, 2.14525, 2.12582, 2.14115, 2.13094, 2.1504, 2.13914, 2.15552, 2.12787, 2.14835, 2.14019, 2.1473, 2.13402, 2.15347, 2.13712, 2.15043, 2.12992, 2.14934, 2.13402, 2.14934, 2.13706, 2.14422, 2.17395, 2.14736, 2.13402, 2.14835, 2.13299, 2.14422, 2.13917, 2.1463, 2.1289, 2.1391, 2.13402, 2.14122, 2.1647, 2.14941, 2.12682, 2.14733, 2.12989, 2.1504, 2.12682, 2.13811, 2.1289, 2.14323, 2.11763, 2.14118, 2.12275, 2.13299, 2.12275, 2.13504, 2.12278, 2.14118, 2.11149, 2.14934, 2.11149, 2.12685, 2.1033, 2.11766, 2.11248, 2.11968, 2.1545, 2.1504, 2.11354, 2.1207, 2.11146, 2.13712, 2.1207, 2.13811, 2.1176, 2.13402, 2.1473, 2.12886, 2.11251, 2.15757, 2.12685, 2.13914, 2.11558, 2.13917, 2.11459, 2.13709, 2.11661, 2.13194, 2.12582, 2.13814, 2.16883, 2.13606, 2.12582, 2.13811, 2.12685, 2.17494, 2.13094, 2.12992, 2.12989, 2.1391, 2.11971, 2.13507, 2.1207, 2.14118, 2.13302, 2.13094, 2.1207, 2.14323, 2.12074, 2.13811, 2.13712, 2.12682, 2.13811, 2.13504, 2.12477, 2.14934, 2.12483, 2.13507, 2.13094, 2.14016, 2.11866, 2.14221, 2.12374, 2.14422, 2.12995, 2.14013, 2.11971, 2.14941, 2.12483, 2.13706, 2.12784, 2.14016, 2.13504, 2.13402, 2.1207, 2.13402, 2.13405, 2.14835, 2.16675, 2.1463, 2.1279, 2.14422, 2.11763, 2.17805, 2.12582, 2.13709, 2.12477, 2.132, 2.11866, 2.13606, 2.12275, 2.13811, 2.12275, 2.14934, 2.12378, 2.14224, 2.12886, 2.13811, 2.12992, 2.1279, 2.1217, 2.13712, 2.12688, 2.13405, 2.1207, 2.13914, 2.12787, 2.1617, 2.1248, 2.12989, 2.12272, 2.15658, 2.15654, 2.14016, 2.1207, 2.13402, 2.11971, 2.13914, 2.11453, 2.15654, 2.12685, 2.14016, 2.12992, 2.14118, 2.16982, 2.12989, 2.12381, 2.14934, 2.12477, 2.14118, 2.12275, 2.14429, 2.13094, 2.13299, 2.12176, 2.12582, 2.12173, 2.13501, 2.11862, 2.13712, 2.11965, 2.13405, 2.11971, 2.13194, 2.13094, 2.12688, 2.12074, 2.13402, 2.12477, 2.14013, 2.12477, 2.12886, 2.11971, 2.13504, 2.12893, 2.12173, 2.14016, 2.13094, 2.16576, 2.14221, 2.14013, 2.1207, 2.13299, 2.12995, 2.12278, 2.17296, 2.12992, 2.16166, 2.13299, 2.17805, 2.16166, 2.13501, 2.13402, 2.12275, 2.12995, 2.13402, 2.11555, 2.13606, 2.13706, 2.15958, 2.17392, 2.12995, 2.1207, 2.13504, 2.13712, 2.11965, 2.12893, 2.13094, 2.12477, 2.17706, 2.13296, 2.16269, 2.12582, 2.12374, 2.1217, 2.12582, 2.13606, 2.12378, 2.13606, 2.18218, 2.11354, 2.12989, 2.12477, 2.14013, 2.12784, 2.1289, 2.11664, 2.13507, 2.132, 2.13507, 2.12173, 2.13094, 2.1289, 2.13197, 2.13501, 2.13706, \nGenerate Bloom, 0.44848, 0.44848, 0.454656, 0.45264, 0.459808, 0.45056, 0.452576, 0.452608, 0.451584, 0.451616, 0.454656, 0.458752, 0.451584, 0.451552, 0.45264, 0.451584, 0.454688, 0.449536, 0.450528, 0.453664, 0.456704, 0.449536, 0.455648, 0.45264, 0.451616, 0.453632, 0.451584, 0.451584, 0.455648, 0.45776, 0.44848, 0.451584, 0.452576, 0.45056, 0.459776, 0.45264, 0.460832, 0.446464, 0.45264, 0.455712, 0.449536, 0.451616, 0.450528, 0.456704, 0.451552, 0.454656, 0.453664, 0.447488, 0.451584, 0.445472, 0.455648, 0.449536, 0.456704, 0.450592, 0.445472, 0.453632, 0.451584, 0.4536, 0.455712, 0.448544, 0.45264, 0.455712, 0.453664, 0.455648, 0.453632, 0.454624, 0.449536, 0.446464, 0.44752, 0.455712, 0.447456, 0.444416, 0.466944, 0.446464, 0.44752, 0.452576, 0.449504, 0.448512, 0.454624, 0.446464, 0.445472, 0.451584, 0.465888, 0.448544, 0.447456, 0.440288, 0.449536, 0.44752, 0.44848, 0.446432, 0.445408, 0.45264, 0.450592, 0.45264, 0.449568, 0.443392, 0.452608, 0.449504, 0.448512, 0.444416, 0.456736, 0.448544, 0.451584, 0.44752, 0.448512, 0.445472, 0.455648, 0.462848, 0.452608, 0.448544, 0.445408, 0.450592, 0.452608, 0.452608, 0.445472, 0.443424, 0.449504, 0.452608, 0.446464, 0.444416, 0.449536, 0.44848, 0.451584, 0.446432, 0.45872, 0.447488, 0.450592, 0.446432, 0.448512, 0.44752, 0.448544, 0.44848, 0.451584, 0.438304, 0.452608, 0.449536, 0.44848, 0.449536, 0.458784, 0.442368, 0.450528, 0.45056, 0.450592, 0.448512, 0.452576, 0.452608, 0.448512, 0.4536, 0.447456, 0.449536, 0.461824, 0.460768, 0.44752, 0.442368, 0.44752, 0.461824, 0.459808, 0.447456, 0.452608, 0.449536, 0.45056, 0.44752, 0.445408, 0.447488, 0.451552, 0.449536, 0.45776, 0.445408, 0.454688, 0.447456, 0.460768, 0.466944, 0.447456, 0.448512, 0.451584, 0.445408, 0.446464, 0.450592, 0.445472, 0.445472, 0.450592, 0.445472, 0.449536, 0.444416, 0.442368, 0.449536, 0.451584, 0.453632, 0.448544, 0.452608, 0.444416, 0.451616, 0.45264, 0.451584, 0.449504, 0.449536, 0.451584, 0.450592, 0.448512, 0.450528, 0.450592, 0.444416, 0.449536, 0.447488, 0.453632, 0.445472, 0.447488, 0.452576, 0.447488, 0.450592, 0.454656, 0.455712, 0.448544, 0.451584, 0.453664, 0.448512, 0.45264, 0.44848, 0.454656, 0.450528, 0.447488, 0.446464, 0.459776, 0.450592, 0.448544, 0.444448, 0.449504, 0.452608, 0.449536, 0.442368, 0.455712, 0.451584, 0.449568, 0.44848, 0.459776, 0.450528, 0.460768, 0.447456, 0.450528, 0.447488, 0.446496, 0.446464, 0.450592, 0.450592, 0.448512, 0.44752, 0.454656, 0.448512, 0.4536, 0.445472, 0.450528, 0.446496, 0.449536, 0.455712, 0.44848, 0.447456, 0.450592, 0.45264, 0.454624, 0.450592, 0.446464, 0.449568, 0.451616, 0.465888, 0.449536, 0.451584, 0.45568, 0.449536, 0.449536, 0.448512, 0.449536, 0.450528, 0.447488, 0.445408, 0.444384, 0.445472, 0.454624, 0.44848, 0.449536, 0.446464, 0.453664, 0.457696, 0.453632, 0.445408, 0.449536, 0.445408, 0.456704, 0.449536, 0.445408, 0.449536, 0.450528, 0.452576, 0.447488, 0.444416, 0.447456, 0.448544, 0.448512, 0.443392, 0.455648, 0.44848, 0.453632, 0.444384, 0.44752, 0.452576, 0.456704, 0.450528, 0.456704, 0.45264, 0.448544, 0.450592, 0.448512, 0.449568, 0.457696, 0.445408, 0.446464, 0.450528, 0.454656, 0.447456, 0.452608, 0.446464, 0.450528, 0.45872, 0.453632, 0.454688, 0.45776, 0.443392, 0.445472, 0.451584, 0.449536, 0.444384, 0.44848, 0.450592, 0.454688, 0.456704, 0.456704, 0.448512, 0.464896, 0.44848, 0.452608, 0.445408, 0.45056, 0.450592, 0.452576, 0.44752, 0.450528, 0.447488, 0.449536, 0.456704, 0.450592, 0.462816, 0.451584, 0.450592, 0.447488, 0.449536, 0.45568, 0.447488, 0.448512, 0.451616, 0.44752, 0.448512, 0.449504, 0.449536, 0.452608, 0.449536, 0.445472, 0.45056, 0.449536, 0.452576, 0.447456, 0.461824, 0.450528, 0.454656, 0.450528, 0.443392, 0.45264, 0.450528, 0.453632, 0.453632, 0.452608, 0.450528, 0.456704, 0.449536, 0.455648, 0.44848, 0.451584, 0.454656, 0.45056, 0.451584, 0.45264, 0.449536, 0.448544, 0.449536, 0.459776, 0.447488, 0.451616, 0.450528, 0.457728, 0.44752, 0.459744, 0.45872, 0.449536, 0.460768, 0.445408, 0.454656, 0.457696, 0.455648, 0.446464, 0.448512, 0.449536, 0.45264, 0.449536, 0.454656, 0.443424, 0.452608, 0.453664, 0.447488, 0.4536, 0.445472, 0.449536, 0.451584, 0.449536, 0.442368, 0.453632, 0.451584, 0.446496, 0.451584, 0.44752, 0.450592, 0.456704, 0.444416, 0.450528, 0.449504, 0.453632, 0.446464, 0.449536, 0.453664, 0.44848, 0.4536, 0.454656, 0.45264, 0.44752, 0.454656, 0.457728, 0.451584, 0.451616, 0.447488, 0.454656, 0.44752, 0.452576, 0.452576, 0.454624, 0.454656, 0.449536, 0.453664, 0.452576, 0.445472, 0.456704, 0.454688, 0.453632, 0.455648, 0.451616, 0.453632, 0.457728, 0.449536, 0.454688, 0.446464, 0.44848, 0.451584, 0.452608, 0.44032, 0.451584, 0.451584, 0.4536, 0.451584, 0.443424, 0.451552, 0.460832, 0, 0.423936, 0.429056, 0.42288, 0.420864, 0.421856, 0.421888, 0.425984, 0.419808, 0.420896, 0.420864, 0.419872, 0.427008, 0.421888, 0.419808, 0.42496, 0.427008, 0.422944, 0.423936, 0.423936, 0.420832, 0.42704, 0.419808, 0.423968, 0.42288, 0.419872, 0.427008, 0.41776, 0.420864, 0.421888, 0.425984, 0.426016, 0.41776, 0.423936, 0.421888, 0.41984, 0.427008, 0.417824, 0.423936, 0.41984, 0.426016, 0.42288, 0.420864, 0.420832, 0.419808, 0.42496, 0.420864, 0.420896, 0.41984, 0.423968, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \nGenerate Camera Velocity, 0.690176, 0.716768, 0.692224, 0.691232, 0.728064, 0.722944, 0.68912, 0.730112, 0.692256, 0.728064, 0.693216, 0.691168, 0.691168, 0.690176, 0.692224, 0.7096, 0.728064, 0.691168, 0.727072, 0.719872, 0.729088, 0.714752, 0.690176, 0.705536, 0.712704, 0.728064, 0.710688, 0.705568, 0.72912, 0.727072, 0.712704, 0.690176, 0.705536, 0.735232, 0.690176, 0.729056, 0.722944, 0.723936, 0.728064, 0.691232, 0.728064, 0.691168, 0.690176, 0.722944, 0.728064, 0.690176, 0.728064, 0.72912, 0.705536, 0.728064, 0.748512, 0.729056, 0.711712, 0.763872, 0.691168, 0.705536, 0.690176, 0.72704, 0.738304, 0.690176, 0.719872, 0.706528, 0.690176, 0.722944, 0.740352, 0.691168, 0.713696, 0.7096, 0.729056, 0.691232, 0.730112, 0.690176, 0.727072, 0.689184, 0.691232, 0.707552, 0.711712, 0.690176, 0.728096, 0.72912, 0.732128, 0.701408, 0.690176, 0.70864, 0.730112, 0.713696, 0.705536, 0.723936, 0.692224, 0.737248, 0.712704, 0.729056, 0.706528, 0.723936, 0.691168, 0.705536, 0.689184, 0.690176, 0.722944, 0.729088, 0.691168, 0.712704, 0.745472, 0.712704, 0.731104, 0.690176, 0.690176, 0.689184, 0.691232, 0.691232, 0.707584, 0.745472, 0.691232, 0.730112, 0.690176, 0.691168, 0.733184, 0.706528, 0.71168, 0.690176, 0.690176, 0.716768, 0.746528, 0.691168, 0.731104, 0.690176, 0.712704, 0.72912, 0.710656, 0.70448, 0.719872, 0.731168, 0.724992, 0.690176, 0.691168, 0.690176, 0.72912, 0.72912, 0.72704, 0.724992, 0.705536, 0.727008, 0.690176, 0.691168, 0.690176, 0.720896, 0.691168, 0.688096, 0.6912, 0.691232, 0.690176, 0.690176, 0.691232, 0.690176, 0.691168, 0.688128, 0.690176, 0.690176, 0.735232, 0.68912, 0.705536, 0.691232, 0.713696, 0.68912, 0.69328, 0.692192, 0.690176, 0.690176, 0.715776, 0.704512, 0.690176, 0.72704, 0.704512, 0.730112, 0.70864, 0.727072, 0.728032, 0.691232, 0.690176, 0.749568, 0.706592, 0.690176, 0.719872, 0.687104, 0.708576, 0.690176, 0.731104, 0.728064, 0.713728, 0.72912, 0.691168, 0.720864, 0.712704, 0.711712, 0.745472, 0.726016, 0.71376, 0.6912, 0.68912, 0.72704, 0.691168, 0.690176, 0.707584, 0.734176, 0.690176, 0.68912, 0.705568, 0.728064, 0.713696, 0.72912, 0.696352, 0.705536, 0.6912, 0.726016, 0.68912, 0.690176, 0.728064, 0.68912, 0.719904, 0.707584, 0.690176, 0.728032, 0.714752, 0.722944, 0.691232, 0.690176, 0.690176, 0.7352, 0.690176, 0.6912, 0.713728, 0.741376, 0.690176, 0.690176, 0.691168, 0.691168, 0.6912, 0.691168, 0.69328, 0.690176, 0.691232, 0.6912, 0.691232, 0.759808, 0.732192, 0.71376, 0.736224, 0.690176, 0.732192, 0.714784, 0.6912, 0.690176, 0.738304, 0.713728, 0.690176, 0.691168, 0.71472, 0.690176, 0.691232, 0.736224, 0.690176, 0.689184, 0.711712, 0.691168, 0.691168, 0.731104, 0.736224, 0.69328, 0.690176, 0.690176, 0.734208, 0.725024, 0.6912, 0.68912, 0.715808, 0.6912, 0.735232, 0.690144, 0.71376, 0.692192, 0.723968, 0.690176, 0.691232, 0.737312, 0.735232, 0.71376, 0.691232, 0.712704, 0.690176, 0.735232, 0.731136, 0.715776, 0.691168, 0.73424, 0.690176, 0.701408, 0.715776, 0.690176, 0.703456, 0.690176, 0.691168, 0.704512, 0.715808, 0.689184, 0.73216, 0.73424, 0.71376, 0.692192, 0.689184, 0.692224, 0.693248, 0.691168, 0.690176, 0.690176, 0.690176, 0.735264, 0.736224, 0.690208, 0.735264, 0.690176, 0.691232, 0.692224, 0.735264, 0.715776, 0.735264, 0.705536, 0.691168, 0.731136, 0.7168, 0.755712, 0.736256, 0.689184, 0.735232, 0.716768, 0.737312, 0.6912, 0.691232, 0.692256, 0.691168, 0.69328, 0.6912, 0.689184, 0.753696, 0.714784, 0.691232, 0.691168, 0.724, 0.68912, 0.73424, 0.736256, 0.712704, 0.690208, 0.712704, 0.73216, 0.690176, 0.713728, 0.736224, 0.690176, 0.734176, 0.692256, 0.709664, 0.733184, 0.71472, 0.756768, 0.691232, 0.73424, 0.68912, 0.690176, 0.731104, 0.68912, 0.68912, 0.700416, 0.692192, 0.691168, 0.690176, 0.730112, 0.73424, 0.691232, 0.692224, 0.691168, 0.691232, 0.692224, 0.6912, 0.692256, 0.690176, 0.691168, 0.691168, 0.691232, 0.690176, 0.691232, 0.690176, 0.690176, 0.6912, 0.690176, 0.691168, 0.691168, 0.690176, 0.713696, 0.713728, 0.691168, 0.735232, 0.712704, 0.731168, 0.732128, 0.751584, 0.735264, 0.71472, 0.691232, 0.708608, 0.731104, 0.72704, 0.692256, 0.692224, 0.725984, 0.772128, 0.733184, 0.718816, 0.689184, 0.713696, 0.731168, 0.722944, 0.69424, 0.689152, 0.691168, 0.693248, 0.691232, 0.690176, 0.690176, 0.690176, 0.716768, 0.712704, 0.70864, 0.711712, 0.734176, 0.730112, 0.691168, 0.705536, 0.710656, 0.690176, 0.718816, 0.705568, 0.713696, 0.690176, 0.715776, 0.713728, 0.691168, 0.691232, 0.736256, 0.691168, 0.689152, 0.71376, 0.6912, 0.692224, 0.69424, 0.691168, 0.691168, 0.690176, 0.68912, 0.735232, 0.687104, 0.6912, 0.6912, 0.692224, 0.735232, 0.692224, 0.68912, 0.730112, 0.690176, 0.6912, 0.730112, 0.691168, 0.6912, 0.690176, 0.692224, 0.693248, 0.690176, 0.690176, 0.691232, 0.690176, 0.690176, 0.731136, 0.687104, 0.713696, 0.711712, 0.690176, 0.692224, 0.702464, 0.692224, 0.72192, 0.6912, 0.690176, 0.735232, 0.715776, 0.715808, 0.737248, 0.691232, 0.692224, 0.693248, 0.691168, 0.71376, 0.73936, 0.713728, 0.71472, 0.713696, 0.690176, 0.690176, 0.690176, 0.692224, 0.692224, 0.68816, 0.690176, 0.690176, 0.71376, 0.733184, 0.690176, 0.68912, 0.690176, 0.691232, 0.6912, 0.68912, 0.68912, 0.691168, 0.690176, 0.734176, 0.712704, 0.777216, 0.71984, 0.690176, 0.733152, 0.715808, 0.73424, 0.691232, 0.690176, 0.691232, 0.690176, 0.71168, 0.73936, 0.690176, 0.69936, 0.734176, 0.731168, 0.691232, \nGenerate SSAO, 2.10736, 2.11152, 2.11965, 2.11866, 2.1033, 2.10941, 2.10742, 2.10947, 2.11149, 2.13299, 2.11866, 2.11862, 2.11971, 2.10739, 2.11459, 2.11043, 2.1207, 2.12483, 2.12477, 2.10534, 2.11971, 2.11149, 2.12995, 2.10842, 2.11763, 2.10947, 2.11971, 2.1033, 2.10838, 2.11658, 2.12787, 2.11763, 2.11149, 2.10947, 2.11558, 2.12682, 2.12176, 2.11555, 2.11046, 2.11152, 2.12173, 2.11661, 2.1105, 2.11558, 2.11766, 2.11152, 2.11354, 2.10022, 2.11658, 2.10842, 2.11965, 2.11046, 2.11046, 2.11866, 2.12381, 2.1135, 2.10531, 2.12374, 2.12582, 2.10742, 2.11453, 2.10534, 2.12378, 2.11965, 2.12272, 2.11152, 2.25075, 2.11558, 2.11354, 2.12378, 2.11866, 2.14218, 2.11866, 2.10739, 2.10637, 2.1135, 2.23846, 2.12275, 2.11558, 2.1207, 2.12374, 2.22618, 2.1289, 2.10739, 2.11661, 2.11965, 2.12278, 2.10534, 2.12275, 2.11248, 2.21184, 2.11763, 2.11248, 2.11251, 2.12582, 2.2897, 2.132, 2.12173, 2.11562, 2.10845, 2.15552, 2.11862, 2.10842, 2.11453, 2.11146, 2.19341, 2.1176, 2.10227, 2.10739, 2.11763, 2.11866, 2.10128, 2.11664, 2.11354, 2.21795, 2.11558, 2.11971, 2.10842, 2.11149, 2.18013, 2.11763, 2.11149, 2.10947, 2.11763, 2.12582, 2.13811, 2.12483, 2.11658, 2.11763, 2.12278, 2.12582, 2.10538, 2.12378, 2.12483, 2.1207, 2.10842, 2.11248, 2.10637, 2.18624, 2.13712, 2.10947, 2.11558, 2.10534, 2.19958, 2.13299, 2.11555, 2.11866, 2.10947, 2.19853, 2.11664, 2.11453, 2.11248, 2.11146, 2.11661, 2.12374, 2.10736, 2.10538, 2.11971, 2.13706, 2.10634, 2.11456, 2.10742, 2.18934, 2.16781, 2.11146, 2.11046, 2.11558, 2.132, 2.11763, 2.10224, 2.1207, 2.13402, 2.16982, 2.1207, 2.11046, 2.10842, 2.10944, 2.1576, 2.11971, 2.12173, 2.11766, 2.16269, 2.12582, 2.1033, 2.1279, 2.11251, 2.19235, 2.1391, 2.11866, 2.1105, 2.12272, 2.12173, 2.13405, 2.1033, 2.11248, 2.10941, 2.17293, 2.12374, 2.11661, 2.10637, 2.1176, 2.11866, 2.11766, 2.1033, 2.11965, 2.22106, 2.12378, 2.11558, 2.11558, 2.1207, 2.12275, 2.1207, 2.10842, 2.10739, 2.11763, 2.11971, 2.13811, 2.11251, 2.11251, 2.11152, 2.1463, 2.11763, 2.11046, 2.10842, 2.11558, 2.18624, 2.12275, 2.10941, 2.11971, 2.12275, 2.13299, 2.10941, 2.11766, 2.1207, 2.16883, 2.12176, 2.11149, 2.10944, 2.11968, 2.1289, 2.13606, 2.12176, 2.12272, 2.1105, 2.12893, 2.13194, 2.1207, 2.11251, 2.11456, 2.20982, 2.12381, 2.10947, 2.12176, 2.20464, 2.132, 2.10736, 2.10941, 2.11453, 2.16269, 2.11968, 2.11763, 2.11251, 2.10637, 2.17907, 2.13501, 2.10742, 2.11664, 2.11354, 2.12787, 2.12893, 2.11459, 2.11658, 2.11459, 2.132, 2.13914, 2.10845, 2.11046, 2.15446, 2.12381, 2.10634, 2.11354, 2.11558, 2.15651, 2.12688, 2.11046, 2.11459, 2.11248, 2.21594, 2.12477, 2.11456, 2.11558, 2.11046, 2.17293, 2.12378, 2.11046, 2.11354, 2.12275, 2.15248, 2.11965, 2.11149, 2.11248, 2.11763, 2.12378, 2.13094, 2.132, 2.10842, 2.28458, 2.11862, 2.11354, 2.10842, 2.10739, 2.12784, 2.11866, 2.1217, 2.11046, 2.10534, 2.13504, 2.11459, 2.11766, 2.11149, 2.11248, 2.31626, 2.12682, 2.13194, 2.11152, 2.30608, 2.1207, 2.10736, 2.11866, 2.10736, 2.25587, 2.11866, 2.11046, 2.1033, 2.1248, 2.35418, 2.12483, 2.11046, 2.1207, 2.11459, 2.12378, 2.11354, 2.11152, 2.10432, 2.12173, 2.29584, 2.13603, 2.11146, 2.11459, 2.32346, 2.13504, 2.11664, 2.13299, 2.10435, 2.1217, 2.1248, 2.10941, 2.11766, 2.12582, 2.1289, 2.1207, 2.10944, 2.11357, 2.11766, 2.21798, 2.11354, 2.11354, 2.10842, 2.11046, 2.19958, 2.12886, 2.1033, 2.10534, 2.17706, 2.1217, 2.11866, 2.13197, 2.11558, 2.13299, 2.11354, 2.11251, 2.12483, 2.11146, 2.12992, 2.1463, 2.10842, 2.11046, 2.11251, 2.12582, 2.12275, 2.10637, 2.11866, 2.11149, 2.11661, 2.13299, 2.10842, 2.11558, 2.19037, 2.12685, 2.10742, 2.12378, 2.10429, 2.21286, 2.13811, 2.11046, 2.10435, 2.11965, 2.21085, 2.12378, 2.11046, 2.11866, 2.11766, 2.21187, 2.11558, 2.11046, 2.1064, 2.11146, 2.11558, 2.132, 2.10947, 2.11152, 2.19235, 2.12995, 2.11354, 2.12378, 2.12579, 2.12688, 2.12787, 2.10534, 2.10531, 2.10534, 2.12176, 2.12688, 2.10224, 2.11248, 2.11869, 2.12688, 2.11453, 2.11251, 2.10947, 2.10736, 2.20365, 2.11763, 2.11968, 2.1207, 2.1463, 2.14941, 2.10429, 2.11766, 2.10435, 2.12787, 2.12483, 2.10941, 2.10637, 2.12688, 2.12272, 2.12989, 2.10842, 2.1207, 2.10634, 2.26099, 2.11354, 2.10842, 2.13405, 2.11354, 2.22618, 2.11766, 2.1033, 2.10736, 2.1248, 2.12477, 2.11866, 2.1248, 2.10941, 2.132, 2.12176, 2.11968, 2.1105, 2.1176, 2.13507, 2.13501, 2.11866, 2.12477, 2.11664, 2.12787, 2.12275, 2.12992, 2.11661, 2.10534, 2.14627, 2.11968, 2.10842, 2.11866, 2.12893, 2.12378, 2.11354, 2.11146, 2.11046, 2.19034, 2.12176, 2.10736, 2.10845, 2.11869, 2.18006, 2.12176, 2.10947, 2.10538, 2.11146, 2.13501, 2.11459, 2.11965, 2.11152, 2.10534, 2.18013, 2.14634, 2.10941, 2.11046, 2.22006, 2.12682, 2.12278, 2.11046, 2.1207, 2.12893, 2.12275, 2.11046, 2.10736, 2.11453, 2.23027, 2.12378, 2.1207, 2.12381, 2.11763, 2.12477, 2.15552, 2.11046, 2.10941, 2.1207, 2.11664, 2.14835, 2.10947, 2.11971, 2.20365, \nHDR Tone Mapping, 1.02195, 0.999424, 1.00253, 0.980992, 0.99024, 1.00144, 1.00352, 1.00454, 0.980992, 1.02294, 0.984064, 0.98816, 0.980992, 0.979968, 1.00458, 0.996352, 0.98512, 0.977888, 0.978944, 0.982048, 1.01376, 0.987104, 0.984064, 1.0271, 0.981024, 0.991232, 1.02195, 0.979936, 1.00758, 0.987168, 0.976896, 0.979936, 0.981984, 0.999424, 1.02912, 0.99536, 1.01171, 1.01475, 0.983072, 0.984064, 0.978944, 0.981024, 0.980992, 0.985056, 1.00253, 0.983072, 0.982016, 0.999424, 1.00355, 0.977952, 0.986112, 1.02294, 0.992224, 1.00147, 0.97488, 0.98304, 1.00246, 1.024, 0.98512, 0.999424, 0.982048, 1.00765, 0.984064, 0.985056, 1.01069, 0.984032, 0.978944, 0.976896, 0.999456, 0.989184, 0.97792, 0.973824, 0.997344, 1.01683, 0.977952, 1.00246, 0.979936, 0.978944, 1.01168, 0.999456, 0.997408, 0.980992, 0.996352, 0.977952, 0.978944, 0.970752, 1.0025, 1.00765, 0.979968, 0.976896, 0.975872, 1.00454, 0.983072, 1.00765, 0.980992, 0.973824, 0.983008, 0.979936, 0.996352, 0.993312, 0.987136, 1.00147, 1.00458, 0.99328, 0.977888, 0.977952, 0.985056, 0.992256, 0.984064, 0.98, 0.975872, 0.981024, 0.984064, 1.01373, 0.976928, 0.97488, 0.980992, 0.984064, 0.999424, 0.974848, 0.98096, 0.979936, 0.98512, 0.977888, 0.9912, 0.978944, 0.980992, 1.00042, 1.00458, 0.977952, 1.00048, 0.980992, 0.98512, 0.970784, 0.986144, 0.980992, 1.00454, 0.98304, 0.993312, 0.97488, 0.983008, 1.00246, 0.984064, 0.979936, 0.986112, 0.988128, 0.984064, 1.0199, 0.98304, 0.983072, 0.9984, 0.996352, 0.98512, 0.977952, 0.980992, 0.997408, 0.991232, 0.977888, 0.98512, 0.98, 0.980992, 0.978944, 0.975872, 0.98, 0.982016, 0.98, 0.98816, 0.97584, 0.98816, 0.979936, 0.991232, 0.9984, 0.977888, 0.978944, 1.00454, 0.975872, 0.97792, 0.982016, 0.975872, 0.999456, 1.02195, 0.975904, 0.986112, 0.975872, 0.974816, 0.989216, 0.983008, 0.98512, 1.00147, 0.983072, 0.97488, 0.98512, 0.989184, 0.982016, 0.979936, 0.98, 0.98304, 0.98, 1.00147, 0.983008, 0.980992, 0.97584, 0.992288, 0.989184, 0.986112, 0.975904, 0.978944, 1.00147, 1.00147, 1.00048, 0.987136, 1.03219, 1.02195, 0.99536, 0.987168, 0.98304, 0.989184, 0.982016, 0.992256, 0.983008, 0.982016, 0.98, 0.992288, 0.983072, 1.00048, 0.97488, 1.01888, 1.024, 0.992256, 0.971776, 1.00864, 0.980992, 0.97792, 0.999424, 0.989184, 0.980992, 0.991232, 0.977888, 0.981984, 0.977888, 0.975904, 0.976896, 0.997408, 0.981024, 0.978976, 1.00352, 0.986112, 1.01581, 0.994304, 0.975872, 0.982016, 0.976896, 1.00147, 0.986144, 0.978944, 0.97792, 1.00253, 0.983072, 0.98304, 1.00147, 0.975872, 0.98, 1.00253, 0.995296, 0.98, 1.00246, 0.984064, 0.98, 0.978944, 0.977952, 0.978944, 0.979968, 0.978944, 0.973824, 0.989152, 0.997408, 0.984032, 0.976896, 0.98, 0.975904, 0.983072, 0.98816, 0.98304, 0.996352, 0.977952, 0.986112, 1.00765, 0.978944, 0.973824, 0.98, 1.00352, 0.981984, 0.975904, 0.972832, 1.0025, 0.98512, 0.977888, 0.971744, 0.985056, 0.999424, 0.98512, 0.9728, 0.975872, 1.00352, 0.986112, 1.00246, 0.986112, 0.983072, 0.976896, 0.98, 0.97792, 0.98, 0.999392, 0.974816, 1.024, 0.98096, 0.984064, 0.97792, 0.982016, 0.976896, 1.02195, 0.988128, 1.00762, 0.98512, 1.01171, 0.97488, 0.978944, 1.00659, 0.984064, 0.974848, 0.978944, 1.00765, 1.00458, 1.01376, 0.991232, 0.978944, 0.994304, 0.978944, 0.983008, 0.973824, 0.979936, 1.02192, 0.984064, 0.976928, 0.999424, 0.976896, 0.978944, 0.986144, 1.00352, 0.991232, 0.981024, 0.978944, 0.976896, 0.978912, 0.987168, 0.991264, 0.976864, 0.98, 0.97792, 0.97792, 0.978944, 0.978976, 0.982016, 1.00147, 0.9728, 1.00147, 0.977952, 1.00352, 0.996352, 0.989184, 1.00147, 1.00451, 0.979936, 0.972768, 1.00458, 0.979936, 0.98304, 0.98304, 0.982016, 0.979936, 0.98512, 0.978944, 0.986112, 0.976896, 0.981984, 0.984064, 0.979936, 0.979936, 0.980992, 0.977952, 0.977952, 0.977888, 0.989184, 0.975904, 0.981024, 0.978944, 0.986144, 0.973824, 1.01069, 0.988128, 0.997344, 0.9912, 0.974816, 1.00659, 1.00864, 1.0025, 0.9984, 0.97792, 0.977888, 0.982048, 0.978944, 0.984064, 0.971776, 1.02294, 0.997408, 0.976896, 0.984064, 0.973824, 0.980992, 1.00352, 0.996352, 0.970784, 0.981984, 0.981984, 0.975904, 0.98, 0.976896, 0.978944, 0.985088, 0.993248, 0.98096, 0.97792, 0.996352, 0.975872, 0.992288, 0.980992, 0.977888, 1.00966, 1.02608, 1.00352, 0.9984, 0.983072, 1.00867, 0.98, 1.00355, 0.976896, 0.983072, 0.998432, 0.980992, 0.98304, 0.983072, 0.985056, 0.978944, 0.983072, 0.981984, 0.973824, 0.986112, 0.98304, 0.982048, 0.984064, 0.981024, 0.98304, 0.986112, 1.00147, 0.98304, 0.975872, 0.976896, 0.979936, 0.981024, 0.968704, 0.98096, 0.98, 0.982016, 0.980992, 0.971776, 0.979936, 0.99024, 0.979936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.976928, 0.982016, 0.999456, 0.98, 0.979936, 0.987104, 0.980992, 0.980992, 1.00762, 0.997408, 0.972832, 1.00246, 0.984064, 0.99328, 0.974816, \nMain Render, 33.6363, 33.833, 32.51, 32.4557, 32.4178, 32.4679, 32.4311, 32.5028, 32.4536, 32.4526, 32.4823, 32.427, 32.3758, 32.425, 32.4004, 32.4977, 32.3994, 32.3973, 32.4505, 32.4342, 32.4045, 32.4741, 32.4168, 32.4731, 32.3922, 32.4372, 32.429, 32.4157, 32.4516, 32.4423, 32.4137, 32.4198, 32.3902, 32.468, 32.4239, 32.4444, 32.3984, 32.4188, 32.4148, 32.3871, 32.3768, 32.4352, 32.4147, 32.4526, 32.4117, 32.4526, 32.4291, 32.4423, 32.3994, 32.4291, 32.3973, 32.4588, 32.4229, 32.4106, 32.4076, 32.4679, 32.4055, 32.4014, 32.4404, 32.4823, 32.3707, 32.4413, 32.3901, 32.4383, 32.4076, 32.4281, 32.3953, 32.5315, 32.4137, 32.299, 32.3052, 32.2898, 32.3185, 32.471, 32.7014, 32.6001, 32.7792, 32.6236, 32.2396, 32.1249, 32.1669, 32.1526, 32.9308, 33.4981, 33.6323, 34.091, 34.8426, 35.6966, 36.1011, 36.6009, 36.0274, 36.2486, 36.3387, 35.7684, 35.4376, 34.5231, 33.2636, 31.5515, 31.0272, 30.6074, 30.1179, 30.1404, 30.5971, 30.9985, 31.485, 31.3692, 31.5105, 31.7635, 31.873, 31.5443, 31.4757, 31.3805, 31.532, 31.57, 31.4726, 31.3958, 31.5044, 31.3897, 31.2167, 30.7528, 30.5326, 30.3371, 30.3913, 30.4937, 30.2254, 30.2418, 29.9213, 29.9735, 30.2203, 30.6678, 31.0343, 31.1921, 31.0589, 31.0211, 31.3375, 31.6949, 31.8392, 31.7102, 31.4255, 31.4194, 31.4409, 31.5996, 31.6119, 31.6744, 31.7143, 31.2884, 31.1368, 31.0712, 31.1398, 30.8777, 30.6278, 30.4343, 30.3196, 30.1138, 29.8885, 29.7943, 29.8373, 29.9653, 30.1353, 29.8721, 29.6919, 29.5598, 29.4861, 29.314, 29.2393, 29.2332, 29.1676, 29.2874, 29.2792, 29.2679, 29.1308, 29.0078, 28.8748, 28.802, 28.8399, 28.716, 28.5174, 28.3095, 28.0791, 28.0064, 27.9122, 27.8517, 27.8036, 27.5538, 27.5118, 27.4729, 27.3541, 27.2292, 26.9947, 26.8288, 26.6414, 26.4551, 26.3311, 26.1427, 26.1693, 26.2717, 26.5246, 26.8329, 26.9486, 27.0541, 27.1442, 27.1769, 27.2118, 27.22, 27.4033, 27.4238, 27.7084, 27.7391, 27.906, 27.9961, 28.1262, 28.2204, 28.3249, 28.6013, 28.8461, 28.8369, 28.7969, 28.6822, 28.587, 28.6331, 28.7375, 28.7447, 28.7836, 28.6413, 28.4508, 27.8896, 27.2169, 26.4397, 25.8293, 25.2774, 25.0368, 24.7624, 24.4664, 24.2565, 24.1879, 24.0507, 23.9585, 23.9729, 24.0128, 23.9636, 24.0476, 23.9739, 24.0261, 24.0681, 24.108, 24.1142, 23.935, 23.9155, 23.9985, 24.0763, 24.2893, 24.5729, 25.1239, 25.2242, 25.1996, 25.2027, 25.3123, 25.4085, 25.4822, 25.5161, 25.5314, 25.5836, 25.3737, 25.4004, 25.428, 25.4556, 25.5673, 25.3532, 25.3358, 25.3338, 25.4075, 25.5477, 25.6491, 25.7567, 25.8109, 25.8345, 25.9133, 25.9758, 25.772, 25.7721, 25.7423, 25.7095, 25.5334, 25.387, 25.3245, 25.2221, 25.1771, 25.0316, 25.0634, 24.9897, 24.9856, 24.9713, 25.0092, 25.0798, 25.2344, 25.2129, 25.1402, 25.0655, 25.0501, 24.9457, 24.9405, 24.9303, 24.8771, 24.7982, 24.789, 24.8719, 24.7491, 24.7695, 24.5985, 24.4337, 24.3764, 24.3016, 24.1982, 24.1582, 24.1152, 24.1756, 24.1337, 24.3466, 24.6272, 24.8699, 24.8576, 24.832, 24.6692, 24.7142, 24.4726, 24.3016, 24.192, 24.0712, 24.0405, 24.1223, 24.5084, 24.6354, 24.8166, 24.9876, 25.3665, 25.8212, 26.4458, 26.9035, 26.8421, 26.9619, 26.8852, 26.8718, 26.7899, 26.8472, 26.8483, 26.9711, 26.9752, 26.9886, 27.1175, 27.1749, 27.1944, 27.2701, 27.3193, 27.3828, 27.4914, 27.4637, 27.4811, 27.4032, 27.5046, 27.4677, 27.5005, 27.4944, 27.5702, 27.521, 27.5558, 27.4852, 27.5825, 27.478, 27.4668, 27.5067, 27.4268, 27.393, 27.3961, 27.393, 27.3859, 27.3817, 27.3254, 27.3152, 27.2763, 27.2323, 27.2589, 27.2517, 27.2835, 27.2773, 27.2835, 27.2927, 27.262, 27.2896, 27.2466, 27.2046, 27.1555, 27.1258, 27.0828, 27.0715, 27.0356, 27.0469, 27.0091, 27.0111, 27.0366, 27.0223, 27.0694, 27.0889, 27.1001, 27.0971, 27.0603, 27.1063, 27.1974, 27.1636, 27.2026, 27.1944, 27.2752, 27.1954, 27.4248, 27.3244, 27.308, 27.307, 27.4043, 27.3265, 27.3295, 27.4074, 27.3695, 27.3521, 27.3111, 27.3603, 27.2865, 27.4186, 27.4381, 27.3459, 27.3951, 27.3818, 27.3982, 27.4258, 27.4043, 27.3766, 27.3572, 27.4842, 27.4207, 27.4698, 27.4606, 27.5026, 27.5456, 27.5016, 27.4852, 27.4555, 27.4883, 27.479, 27.5384, 27.5487, 27.4985, 27.5486, 27.5098, 27.5466, 27.5394, 27.5733, 27.562, 27.5989, 27.5302, 27.5476, 27.5732, 27.645, 27.5937, 27.5886, 27.5426, 27.562, 27.5467, 27.5907, 27.5425, 27.5722, 27.5517, 27.5456, 27.5036, 27.5343, 27.52, 27.5579, 27.5211, 27.5067, 27.4914, 27.4975, 4.62746, 4.63872, 4.62435, 4.61517, 4.63773, 4.652, 4.62848, 4.62336, 4.6377, 4.62954, 4.66019, 4.63869, 4.652, 4.63357, 4.65206, 4.62435, 4.62746, 4.61005, 4.61418, 4.6377, 4.63053, 4.63971, 4.63152, 4.64282, 4.63363, 4.63158, 4.62848, 4.6193, 4.61619, 4.6377, 4.62848, 4.62538, 4.60592, 4.63158, 4.65507, 4.63258, 4.62848, 4.608, 4.63974, 4.62538, 4.6377, 4.61213, 4.61213, 4.63565, 4.63766, 4.63158, 4.652, 4.60694, 4.63158, 27.5323, 27.4862, 27.52, 27.5118, 27.5241, 27.5241, 27.5128, 27.4852, 27.5231, 27.5077, 27.5077, 27.5517, 27.5016, 27.5681, 27.5128, \nMotionBlur, 0.782336, 0.780288, 1.19811, 0.782336, 0.782368, 0.781312, 0.782304, 0.782304, 0.782368, 0.78128, 0.781312, 0.782368, 0.782368, 0.78128, 0.781312, 0.78128, 0.782336, 0.779296, 0.784352, 0.78336, 0.782336, 0.780288, 0.782304, 0.781312, 0.782304, 0.780288, 0.78336, 0.782336, 0.782304, 0.780288, 0.78128, 0.782336, 0.78128, 0.78128, 0.781312, 0.78336, 0.779232, 0.780288, 0.78336, 0.781312, 0.78336, 0.782368, 0.78336, 0.780288, 0.78128, 0.78336, 0.78336, 0.781344, 0.78336, 0.783392, 0.782304, 0.778272, 0.780288, 0.780288, 0.78544, 0.779232, 0.782304, 0.780288, 0.782368, 0.784416, 0.78336, 0.782304, 0.784384, 0.782304, 0.782368, 0.782368, 0.78336, 1.13254, 1.15811, 1.18374, 1.2073, 1.22166, 1.24112, 1.2544, 1.2728, 1.28925, 1.29946, 1.31789, 1.33123, 1.34758, 1.35475, 1.36394, 1.3711, 1.36701, 1.37011, 1.36707, 1.36499, 1.36701, 1.36602, 1.37008, 1.37523, 1.37117, 1.36602, 1.364, 1.37014, 1.37213, 1.37315, 1.37114, 1.36605, 1.36496, 1.35782, 1.3537, 1.34758, 1.34352, 1.34042, 1.33018, 1.32202, 1.31376, 1.30461, 1.2872, 1.27587, 1.25949, 1.24726, 1.2247, 1.19805, 1.32611, 1.31382, 1.31584, 1.28413, 1.28202, 1.28618, 1.29434, 1.29949, 1.30352, 1.3056, 1.3056, 1.31584, 1.32198, 1.33424, 1.3343, 1.3312, 1.3343, 1.32506, 1.31382, 1.3353, 1.30765, 1.29942, 1.28406, 1.27901, 1.22061, 1.22774, 1.22678, 1.23494, 1.24006, 1.24723, 1.2544, 1.2585, 1.26358, 1.26976, 1.26877, 1.27798, 1.27901, 1.28307, 1.28512, 1.28922, 1.28922, 1.29642, 1.29536, 1.29744, 1.29434, 1.29334, 1.29024, 1.28618, 1.28307, 1.27795, 1.2687, 1.25952, 1.24723, 1.24006, 1.2216, 1.20525, 1.19398, 1.18269, 1.16429, 1.14688, 1.12234, 1.11414, 1.11312, 1.11619, 1.12538, 1.13565, 1.14483, 1.15402, 1.17453, 1.17453, 1.16122, 1.15302, 1.152, 1.15504, 1.16842, 1.17965, 1.18883, 1.20016, 1.21242, 1.2247, 1.23798, 1.24826, 1.24928, 1.25747, 1.2657, 1.27901, 1.29232, 1.30154, 1.3087, 1.31894, 1.32406, 1.33322, 1.34352, 1.36598, 1.37834, 1.38954, 1.39165, 1.38547, 1.3824, 1.38138, 1.38342, 1.38138, 1.37322, 1.36394, 1.35475, 1.3455, 1.3312, 1.30864, 1.28307, 1.25642, 1.2247, 1.18886, 1.15818, 1.12637, 1.10384, 1.08749, 1.07517, 1.0783, 1.07824, 1.08541, 1.10285, 1.12128, 1.13565, 1.1551, 1.16534, 1.18272, 1.18992, 1.20112, 1.20829, 1.21853, 1.22877, 1.23088, 1.23702, 1.24317, 1.24928, 1.25642, 1.26157, 1.27693, 1.27594, 1.28, 1.28611, 1.29024, 1.29328, 1.29843, 1.30154, 1.30048, 1.30461, 1.30154, 1.30563, 1.30666, 1.30659, 1.30666, 1.30659, 1.30253, 1.30358, 1.30045, 1.30048, 1.30253, 1.29946, 1.35066, 1.30048, 1.30253, 1.29536, 1.29536, 1.29328, 1.2913, 1.28717, 1.28822, 1.19088, 1.18787, 1.18166, 1.17555, 1.17453, 1.17149, 1.16528, 1.16224, 1.15712, 1.15299, 1.14589, 1.13664, 1.12845, 1.12131, 1.11312, 1.09875, 1.0967, 1.10282, 1.13254, 1.17453, 1.21754, 1.24928, 1.26467, 1.28099, 1.30659, 1.3271, 1.34038, 1.35677, 1.38138, 1.39773, 1.40493, 1.41517, 1.41517, 1.41619, 1.41418, 1.41312, 1.41411, 1.41411, 1.40899, 1.41616, 1.41213, 1.4121, 1.41206, 1.41517, 1.4152, 1.41213, 1.41619, 1.41616, 1.41312, 1.41619, 1.41517, 1.41616, 1.41616, 1.41008, 1.408, 1.4049, 1.39165, 1.37114, 1.3609, 1.34042, 1.32714, 1.31376, 1.30352, 1.28819, 1.26666, 1.25235, 1.24006, 1.22982, 1.20835, 1.18374, 1.16118, 1.13152, 1.06496, 1.02198, 1.00659, 0.992288, 0.98, 0.966656, 0.949216, 0.935936, 0.910304, 0.89296, 0.881696, 0.868352, 0.856064, 0.84688, 0.83152, 0.825344, 0.817184, 0.809952, 0.800768, 0.800736, 0.794656, 0.785408, 0.781312, 0.781312, 0.78336, 0.782368, 0.782336, 0.783328, 0.783328, 0.780288, 0.782336, 0.784352, 0.780288, 0.783328, 0.780288, 0.780288, 0.781312, 0.782368, 0.782368, 0.782304, 0.782304, 0.779296, 0.78128, 0.784416, 0.782336, 0.78128, 0.78336, 0.785408, 0.783392, 0.78544, 0.789504, 0.791584, 0.794592, 0.79664, 0.794656, 0.794656, 0.794656, 0.797696, 0.794656, 0.794656, 0.795648, 0.79872, 0.79872, 0.796672, 0.799712, 0.798752, 0.79872, 0.794592, 0.795648, 0.79664, 0.792576, 0.792576, 0.789536, 0.789504, 0.787488, 0.787456, 0.78544, 0.785408, 0.784352, 0.784416, 0.785408, 0.782304, 0.782336, 0.781344, 0.782336, 0.781344, 0.782336, 0.78336, 0.782304, 0.779296, 0.779296, 0.785376, 0.783328, 0.78128, 0.780288, 0.78128, 0.78128, 0.782304, 0.784416, 0.781312, 0.782336, 0.782368, 0.780288, 0.78128, 0.781344, 0.780288, 0.782368, 0.782336, 0.780288, 0.784352, 0.780256, 0.78336, 0.781344, 0.779296, 0.782304, 0.784352, 0.782304, 0.781312, 0.782304, 0.782336, 0.780288, 0.781344, 0.789536, 0.782336, 0.782336, 0.782336, 0.782368, 0.783392, 0.779296, 0.782304, 0.781312, 0.78128, 0.782304, 0.782336, 0.780256, 0.782336, 0.779296, 0.780288, 0.78128, 0.78336, 0.780288, 0.781312, 0.780288, 0.780288, 0.779296, 0.781344, 0.78336, 0.782336, 0.78336, 0.782368, 0.780288, 0.783328, 0.78336, 0.785408, 0.781312, 0.782368, 0.782336, 0.780288, 0.781344, 0.784384, 0.781312, 0.781344, 0.782336, 0.782368, 0.780256, 0.782304, 0.78336, 0.780256, 0.78128, 0.782336, 0.78128, 0.781312, 0.78336, 0.78128, 0.781344, 0.78128, 0.780288, 0.783392, 0.783328, 0.782336, 0.782368, 0.779296, 0.78336, 0.781312, 0.782368, 0.780288, 0.782368, \nOpaque, 0.511008, 0.508896, 0.514048, 0.504864, 0.513056, 0.504864, 0.512992, 0.512, 0.512992, 0.509952, 0.515072, 0.5048, 0.512992, 0.504864, 0.520192, 0.5048, 0.513024, 0.505888, 0.51408, 0.505824, 0.513056, 0.504832, 0.51712, 0.505824, 0.513056, 0.504832, 0.514016, 0.504832, 0.514048, 0.504832, 0.513024, 0.504832, 0.519168, 0.504832, 0.514048, 0.505824, 0.512992, 0.504864, 0.513056, 0.504832, 0.52016, 0.505824, 0.514048, 0.505824, 0.514048, 0.50384, 0.51408, 0.5048, 0.512992, 0.505824, 0.515072, 0.505824, 0.514048, 0.50688, 0.512, 0.505824, 0.512, 0.504864, 0.51408, 0.504832, 0.520192, 0.504832, 0.513024, 0.504832, 0.513024, 0.505888, 0.514048, 0.515104, 0.516064, 0.502752, 0.509952, 0.500768, 0.507936, 0.489472, 0.4936, 0.480256, 0.480288, 0.465888, 0.46288, 0.450528, 0.462848, 0.449536, 0.463872, 0.456704, 0.469024, 0.463872, 0.475104, 0.469984, 0.48128, 0.475136, 0.490496, 0.480224, 0.488416, 0.477152, 0.482336, 0.469024, 0.472064, 0.463872, 0.477184, 0.475104, 0.492544, 0.492544, 0.502784, 0.501792, 0.517088, 0.509952, 0.524288, 0.511008, 0.525344, 0.50688, 0.49968, 0.482272, 0.488416, 0.468, 0.469024, 0.453632, 0.45056, 0.433184, 0.438272, 0.423936, 0.431104, 0.410592, 0.407584, 0.390176, 0.397312, 0.375776, 0.380928, 0.372704, 0.38096, 0.367584, 0.38096, 0.366592, 0.372736, 0.36048, 0.36864, 0.352224, 0.364544, 0.347136, 0.357344, 0.350176, 0.358432, 0.34608, 0.356352, 0.34512, 0.356352, 0.344064, 0.353248, 0.345088, 0.362496, 0.356352, 0.358432, 0.349184, 0.356352, 0.347104, 0.364512, 0.351232, 0.361472, 0.367584, 0.369632, 0.354304, 0.364512, 0.354304, 0.364544, 0.367616, 0.361472, 0.351232, 0.362528, 0.349184, 0.365536, 0.35024, 0.358432, 0.346112, 0.366592, 0.35536, 0.360448, 0.348128, 0.368608, 0.353312, 0.367584, 0.35328, 0.362496, 0.356352, 0.36864, 0.352288, 0.366592, 0.356352, 0.371712, 0.357408, 0.3656, 0.355296, 0.369664, 0.351232, 0.3768, 0.342016, 0.34816, 0.336928, 0.346112, 0.343008, 0.344064, 0.335872, 0.342048, 0.330784, 0.34304, 0.33792, 0.343072, 0.34, 0.34816, 0.336896, 0.34816, 0.332832, 0.347136, 0.353312, 0.350176, 0.339936, 0.347136, 0.337952, 0.347136, 0.330784, 0.33584, 0.321568, 0.332832, 0.3256, 0.333824, 0.321504, 0.326656, 0.311296, 0.313344, 0.296928, 0.307232, 0.29696, 0.309248, 0.293888, 0.298016, 0.28672, 0.300032, 0.285696, 0.300064, 0.287776, 0.292864, 0.277536, 0.285696, 0.268288, 0.27952, 0.275488, 0.278528, 0.270336, 0.287776, 0.268288, 0.278528, 0.26112, 0.273408, 0.25904, 0.27136, 0.262176, 0.278528, 0.256992, 0.265184, 0.251872, 0.259072, 0.249888, 0.257024, 0.24576, 0.251936, 0.242656, 0.25088, 0.237568, 0.24064, 0.236544, 0.249888, 0.231424, 0.243712, 0.227328, 0.23552, 0.22736, 0.238592, 0.2304, 0.236544, 0.226304, 0.2376, 0.22224, 0.231424, 0.224288, 0.24064, 0.226336, 0.23552, 0.219168, 0.22736, 0.220192, 0.23344, 0.221184, 0.234464, 0.219104, 0.230432, 0.21712, 0.228352, 0.22528, 0.230368, 0.219104, 0.233472, 0.220192, 0.229408, 0.219104, 0.234464, 0.218112, 0.228352, 0.220128, 0.229408, 0.218144, 0.233472, 0.221184, 0.23248, 0.223232, 0.25296, 0.228352, 0.242688, 0.244768, 0.26112, 0.257024, 0.275488, 0.273408, 0.294944, 0.298016, 0.322528, 0.315424, 0.327648, 0.325632, 0.344064, 0.33488, 0.349184, 0.357376, 0.388128, 0.395232, 0.416768, 0.421888, 0.450592, 0.459776, 0.480224, 0.477184, 0.48128, 0.477184, 0.4936, 0.4936, 0.505824, 0.504832, 0.512992, 0.50688, 0.520192, 0.514048, 0.526368, 0.531424, 0.53552, 0.524288, 0.541696, 0.534528, 0.540672, 0.538656, 0.541696, 0.535584, 0.546816, 0.537632, 0.549888, 0.539648, 0.549888, 0.541728, 0.558048, 0.54576, 0.557056, 0.538656, 0.561152, 0.538656, 0.551968, 0.54064, 0.548896, 0.539648, 0.55088, 0.540704, 0.548896, 0.54272, 0.550944, 0.543712, 0.55088, 0.539648, 0.54784, 0.543744, 0.551936, 0.546816, 0.552928, 0.540704, 0.557056, 0.54272, 0.559104, 0.541696, 0.547808, 0.553984, 0.557056, 0.547808, 0.552992, 0.541696, 0.55296, 0.541696, 0.554016, 0.5376, 0.55088, 0.544768, 0.551936, 0.543776, 0.548896, 0.538624, 0.555008, 0.549888, 0.548896, 0.536544, 0.556064, 0.54272, 0.548832, 0.54064, 0.54784, 0.543744, 0.552992, 0.541696, 0.55088, 0.54576, 0.55296, 0.539648, 0.54784, 0.536576, 0.546848, 0.54064, 0.550944, 0.536576, 0.54576, 0.538656, 0.546816, 0.54576, 0.543744, 0.535584, 0.54576, 0.543776, 0.541696, 0.535584, 0.540672, 0.535552, 0.547808, 0.53248, 0.540704, 0.533472, 0.542688, 0.531456, 0.54064, 0.530432, 0.54064, 0.533536, 0.540672, 0.53248, 0.539648, 0.531424, 0.542752, 0.54064, 0.539648, 0.530432, 0.541696, 0.53552, 0.538656, 0.54576, 0.539648, 0.53552, 0.542752, 0.530464, 0.544768, 0.533536, 0.542688, 0.531456, 0.539648, 0.530464, 0.543712, 0.546816, 0.543776, 0.529408, 0.54064, 0.531424, 0.542752, 0.530432, 0.539648, 0.530464, 0.540704, 0.543712, 0.538624, 0.531488, 0.538592, 0.531456, 0.54272, 0.529408, 0.546816, 0.541696, 0.562176, 0.530464, 0.549856, 0.5376, 0.543744, 0.536608, 0.546816, 0.5376, 0.539648, 0.5304, 0.541664, 0.530432, 0.538624, 0.5304, 0.544768, 0.534528, 0.540704, 0.530464, 0.538656, 0.531488, 0.564256, 0.529408, 0.539648, 0.530432, 0.555008, 0.530432, 0.543712, 0.536576, 0.541696, 0.534528, 0.539648, 0.530432, 0.5448, 0.529408, 0.541696, 0.530464, 0.539648, 0.531456, 0.55088, 0.54064, 0.538656, 0.531488, 0.538624, 0.533472, 0.542752, 0.530432, 0.539648, 0.53248, \nPost Effects, 1.02294, 1.00042, 1.00352, 0.980992, 0.991232, 1.00246, 1.00451, 1.00454, 0.982048, 1.024, 0.985056, 0.989184, 0.980992, 0.98096, 1.00458, 0.996352, 0.986112, 0.978944, 0.979936, 0.983072, 1.01482, 0.98816, 0.985056, 1.0271, 0.981024, 0.991232, 1.02294, 0.980992, 1.00864, 0.988192, 0.977888, 0.980992, 0.983008, 0.999424, 1.03018, 0.99536, 1.01277, 1.01578, 0.984064, 0.98512, 0.979936, 0.983008, 0.980992, 0.985056, 1.00352, 0.984064, 0.983072, 0.999424, 1.00355, 0.977952, 0.987136, 1.02294, 0.99328, 1.00253, 0.975872, 0.984064, 1.00352, 1.024, 0.98512, 0.999424, 0.98304, 1.00765, 0.98512, 0.986112, 1.01069, 0.984064, 0.98, 0.977888, 1.00045, 0.989184, 0.978944, 0.97488, 0.9984, 1.01782, 0.978944, 1.00246, 0.979936, 0.979936, 1.0127, 1.00048, 0.9984, 0.982048, 0.996352, 0.978944, 0.979936, 0.970752, 1.00253, 1.00864, 0.982048, 0.977888, 0.976896, 1.0056, 0.984064, 1.00864, 0.982048, 0.974816, 0.98304, 0.980992, 0.997344, 0.994304, 0.989216, 1.00147, 1.00458, 0.99328, 0.978944, 0.977952, 0.986112, 0.993248, 0.985056, 0.980992, 0.976896, 0.982016, 0.98512, 1.01373, 0.976928, 0.975872, 0.980992, 0.985056, 1.00042, 0.975904, 0.982016, 0.979936, 0.98512, 0.978944, 0.9912, 0.978944, 0.982048, 1.00042, 1.00458, 0.977952, 1.00048, 0.982016, 0.98512, 0.970784, 0.986144, 0.982048, 1.00454, 0.98304, 0.993312, 0.975904, 0.984064, 1.00352, 0.98512, 0.980992, 0.987104, 0.988128, 0.984064, 1.0209, 0.984064, 0.983072, 0.999456, 0.996352, 0.986112, 0.977952, 0.982048, 0.9984, 0.992288, 0.978944, 0.98512, 0.98, 0.981984, 0.98, 0.976864, 0.981024, 0.982016, 0.980992, 0.98816, 0.976896, 0.99024, 0.980992, 0.991232, 0.9984, 0.97792, 0.978944, 1.00454, 0.975872, 0.978944, 0.982016, 0.976896, 0.999456, 1.02301, 0.976896, 0.987136, 0.976928, 0.975872, 0.99024, 0.984064, 0.986112, 1.00253, 0.984064, 0.975872, 0.986144, 0.99024, 0.983072, 0.980992, 0.98, 0.984096, 0.980992, 1.00147, 0.983008, 0.982048, 0.975872, 0.993312, 0.990176, 0.986112, 0.976896, 0.98, 1.00246, 1.00246, 1.00147, 0.988128, 1.03325, 1.02301, 0.996352, 0.988192, 0.984064, 0.989184, 0.983008, 0.992256, 0.983008, 0.982016, 0.980992, 0.992288, 0.984064, 1.00147, 0.975872, 1.01888, 1.024, 0.993248, 0.972768, 1.00963, 0.982048, 0.978944, 1.00042, 0.990176, 0.982016, 0.991232, 0.978944, 0.981984, 0.978944, 0.976896, 0.976896, 0.9984, 0.982016, 0.981024, 1.00454, 0.986112, 1.01683, 0.995296, 0.976928, 0.982016, 0.977952, 1.0025, 0.987136, 0.979968, 0.978944, 1.00355, 0.983072, 0.98304, 1.00253, 0.976896, 0.980992, 1.00355, 0.996352, 0.980992, 1.00352, 0.98512, 0.981024, 0.979936, 0.977952, 0.98, 0.98096, 0.978944, 0.974848, 0.990208, 0.997408, 0.985056, 0.977888, 0.981024, 0.976896, 0.984064, 0.989184, 0.98304, 0.997376, 0.977952, 0.987104, 1.00864, 0.978944, 0.974816, 0.98, 1.00451, 0.981984, 0.976896, 0.973824, 1.00355, 0.986112, 0.978944, 0.9728, 0.98608, 1.00042, 0.98512, 0.973824, 0.976928, 1.00454, 0.987104, 1.00246, 0.987168, 0.984064, 0.977952, 0.980992, 0.978912, 0.980992, 1.00045, 0.975872, 1.02499, 0.98096, 0.985056, 0.978912, 0.982016, 0.977888, 1.02294, 0.989184, 1.00762, 0.98512, 1.01277, 0.97488, 0.978944, 1.00758, 0.985056, 0.976896, 0.979968, 1.00864, 1.00656, 1.01482, 0.992224, 0.978944, 0.995296, 0.979936, 0.984064, 0.974816, 0.980992, 1.02192, 0.984064, 0.976928, 1.00042, 0.977888, 0.98, 0.987136, 1.00352, 0.992224, 0.981024, 0.98, 0.977952, 0.978944, 0.987168, 0.991264, 0.976864, 0.981024, 0.97792, 0.978944, 0.979936, 0.980992, 0.983008, 1.00253, 0.973856, 1.00147, 0.978944, 1.00352, 0.997344, 0.99024, 1.00246, 1.00557, 0.98096, 0.973824, 1.0056, 0.980992, 0.983072, 0.984064, 0.982016, 0.980992, 0.986112, 0.979936, 0.987136, 0.977888, 0.981984, 0.984064, 0.980992, 0.980992, 0.982048, 0.978944, 0.977952, 0.978944, 0.989184, 0.976896, 0.982016, 0.979936, 0.986144, 0.97488, 1.01168, 0.989184, 0.9984, 0.9912, 0.97584, 1.00758, 1.00963, 1.0025, 0.9984, 0.97792, 0.978944, 0.982048, 0.979936, 0.984064, 0.972832, 1.02294, 0.9984, 0.976896, 0.985056, 0.973824, 0.980992, 1.00352, 0.997344, 0.971776, 0.981984, 0.981984, 0.975904, 0.981024, 0.976896, 0.978944, 0.986112, 0.994304, 0.98096, 0.978944, 0.996352, 0.976864, 0.99328, 0.982016, 0.978944, 1.01066, 1.02707, 1.00352, 0.999456, 0.984064, 1.00966, 0.980992, 1.00355, 0.977888, 0.984064, 0.999424, 0.982016, 0.984064, 0.984064, 0.986112, 0.98, 0.984064, 0.98304, 0.973824, 0.987168, 0.984064, 0.98304, 0.985056, 0.981024, 0.984096, 0.987136, 1.00147, 0.984096, 0.976928, 0.977888, 0.980992, 0.982016, 0.969728, 0.98096, 0.981984, 0.983008, 0.981984, 0.973824, 0.979936, 0.991232, 0.980992, 0.843776, 0.847872, 0.841728, 0.840704, 0.840704, 0.839712, 0.845824, 0.838656, 0.840704, 0.840704, 0.837632, 0.844832, 0.840704, 0.837632, 0.843776, 0.847872, 0.84176, 0.84272, 0.843744, 0.839648, 0.845824, 0.838624, 0.843776, 0.841696, 0.837632, 0.845824, 0.836576, 0.839712, 0.840704, 0.845824, 0.845824, 0.834528, 0.842752, 0.839712, 0.838656, 0.844768, 0.837664, 0.842752, 0.838656, 0.844832, 0.840704, 0.839712, 0.839648, 0.838624, 0.844768, 0.839648, 0.838656, 0.838656, 0.842784, 0.976928, 0.982016, 1.00045, 0.98, 0.980992, 0.98816, 0.982016, 0.982048, 1.00762, 0.9984, 0.972832, 1.00352, 0.985088, 0.99328, 0.975872, \nPresent, 0.664608, 0.563232, 0.695296, 0.6144, 0.664576, 0.670688, 0.664576, 0.685056, 0.416768, 0.683008, 0.644128, 0.622592, 0.448544, 0.476192, 0.664576, 0.519136, 0.696352, 0.561184, 0.695296, 0.52736, 0.689152, 0.702464, 0.679936, 0.688128, 0.68608, 0.5888, 0.684064, 0.674816, 0.651232, 0.596992, 0.496608, 0.482272, 0.683008, 0.619488, 0.720896, 0.65024, 0.548832, 0.672768, 0.652288, 0.4936, 0.500704, 0.638976, 0.61952, 0.61952, 0.678944, 0.444416, 0.43312, 0.666592, 0.661472, 0.670752, 0.69424, 0.646112, 0.702464, 0.605184, 0.487424, 0.676832, 0.6984, 0.701472, 0.555008, 0.671712, 0.64512, 0.698368, 0.674816, 0.490528, 0.6912, 0.443424, 0.492544, 0.683008, 0.681984, 0.674816, 0.485376, 0.419872, 0.5192, 0.688096, 0.67584, 0.690176, 0.58576, 0.51504, 0.534528, 0.6656, 0.681984, 0.475168, 0.474112, 0.68816, 0.478176, 0.533504, 0.667648, 0.717824, 0.465888, 0.589824, 0.474112, 0.662528, 0.67072, 0.524256, 0.413696, 0.436224, 0.569344, 0.429024, 0.684, 0.674784, 0.420864, 0.622592, 0.66352, 0.651296, 0.626688, 0.423936, 0.479232, 0.480224, 0.423936, 0.437248, 0.686112, 0.685056, 0.67584, 0.65024, 0.463872, 0.528352, 0.451552, 0.515072, 0.686048, 0.504832, 0.446464, 0.664544, 0.647168, 0.492576, 0.493536, 0.516064, 0.506848, 0.63792, 0.672768, 0.474112, 0.693216, 0.640992, 0.50688, 0.410656, 0.672768, 0.51504, 0.678944, 0.479232, 0.530464, 0.566272, 0.671776, 0.66352, 0.666592, 0.576512, 0.455648, 0.509984, 0.656416, 0.6984, 0.434176, 0.409632, 0.497632, 0.48128, 0.458784, 0.753664, 0.444416, 0.483296, 0.46592, 0.490464, 0.438304, 0.460768, 0.67376, 0.409632, 0.436224, 0.475136, 0.626688, 0.63488, 0.652288, 0.493536, 0.690176, 0.635936, 0.415776, 0.696352, 0.433184, 0.525312, 0.652256, 0.672768, 0.492512, 0.503808, 0.50176, 0.622624, 0.66352, 0.52224, 0.677888, 0.542752, 0.551936, 0.672768, 0.420864, 0.66048, 0.6656, 0.696352, 0.407584, 0.432128, 0.673824, 0.413696, 0.508928, 0.451584, 0.497664, 0.468992, 0.626656, 0.62768, 0.476192, 0.760832, 0.67072, 0.562176, 0.677888, 0.407584, 0.445472, 0.626688, 0.647168, 0.658432, 0.50176, 0.679936, 0.684064, 0.64512, 0.414752, 0.434176, 0.69328, 0.6584, 0.661472, 0.474112, 0.454656, 0.638976, 0.484352, 0.593888, 0.620544, 0.428, 0.706592, 0.68608, 0.646144, 0.505888, 0.646112, 0.62672, 0.468992, 0.630784, 0.434176, 0.497696, 0.454656, 0.647168, 0.413696, 0.482304, 0.528416, 0.563168, 0.642048, 0.620544, 0.41984, 0.669696, 0.539648, 0.682016, 0.690176, 0.49152, 0.415744, 0.672768, 0.633888, 0.63488, 0.633824, 0.624672, 0.6656, 0.630816, 0.54272, 0.622592, 0.43312, 0.626688, 0.646176, 0.548832, 0.698368, 0.676864, 0.514048, 0.52528, 0.440288, 0.647168, 0.498656, 0.677888, 0.607232, 0.431104, 0.628704, 0.68096, 0.631808, 0.432128, 0.672768, 0.677888, 0.64, 0.468, 0.466944, 0.640992, 0.628704, 0.64512, 0.684032, 0.43216, 0.449536, 0.68608, 0.659424, 0.525344, 0.459808, 0.54064, 0.650208, 0.687136, 0.683008, 0.428, 0.679936, 0.676832, 0.449536, 0.437248, 0.428, 0.459776, 0.534528, 0.685056, 0.512992, 0.610304, 0.54576, 0.637952, 0.492512, 0.410656, 0.676864, 0.410656, 0.585728, 0.670688, 0.4936, 0.40752, 0.440288, 0.526336, 0.675808, 0.492544, 0.677888, 0.642048, 0.658464, 0.418816, 0.62976, 0.679936, 0.472064, 0.537568, 0.751616, 0.702464, 0.67584, 0.683008, 0.71984, 0.508928, 0.518112, 0.43312, 0.42288, 0.431072, 0.41264, 0.695296, 0.661472, 0.551904, 0.642048, 0.518176, 0.544768, 0.451584, 0.581664, 0.428, 0.505824, 0.450528, 0.65024, 0.435168, 0.43312, 0.597984, 0.464928, 0.52528, 0.52736, 0.51504, 0.56112, 0.68912, 0.507904, 0.671744, 0.438304, 0.664544, 0.411648, 0.805888, 0.630752, 0.504832, 0.714752, 0.640992, 0.683008, 0.426016, 0.654336, 0.531488, 0.540704, 0.50688, 0.471072, 0.62976, 0.414752, 0.468, 0.602112, 0.428064, 0.45568, 0.434176, 0.435168, 0.42288, 0.956416, 0.42288, 0.436224, 0.47824, 0.417824, 0.421888, 0.451584, 0.487424, 0.445472, 0.47824, 0.66864, 0.426016, 0.755712, 0.66352, 1.10182, 0.622592, 0.666592, 0.63696, 0.646112, 0.519168, 0.468, 0.67584, 0.548832, 0.423936, 0.43824, 0.687104, 0.67072, 0.668704, 0.705504, 0.42288, 0.533536, 0.6656, 0.6728, 0.536576, 0.510944, 0.475104, 0.518176, 0.475168, 0.420864, 0.441344, 0.424992, 0.502784, 0.66048, 0.41472, 0.675808, 0.643072, 0.711648, 0.52224, 0.441344, 0.690176, 0.691168, 0.626688, 0.64816, 0.428064, 0.626688, 0.484352, 0.654368, 0.434176, 0.647136, 0.639008, 0.450592, 0.686048, 0.427008, 0.64208, 0.568288, 0.504832, 0.51712, 0.439296, 0.635936, 0.459776, 0.556064, 0.63488, 0.414752, 0.607232, 0.47312, 0.679936, 0.6144, 0.426016, 0.494592, 0.47312, 0.448544, 0.488416, 0.546816, 0.495616, 0.511008, 0.495648, 1.26669, 0.49664, 0.51712, 0.48128, 0.423936, 0.413696, 0.526336, 0.423936, 0.718816, 0.622624, 0.470048, 0.62464, 0.657408, 0.661504, 0.67072, 0.531488, 0.546816, 0.615456, 0.525344, 0.557056, 0.603104, 0.620512, 0.436224, 0.472064, 0.586784, 0.665632, 0.632832, 0.580608, 0.564256, 0.978944, 0.47104, 0.6656, 0.406528, 0.405504, 0.418816, 0.41472, 0.463872, 0.490528, 0.636928, 0.520192, 0.649184, 0.694272, 0.639008, 0.463872, 0.674848, 0.650272, 0.679936, 0.560128, 0.499712, 0.428, 0.614432, 0.649216, 0.666656, 0.440352, 0.50176, 0.73008, 0.420896, 0.427008, 0.556, 0.450528, 0.62976, 0.66352, 0.679936, 0.430112, 0.630784, 0.64816, 0.603104, 0.557056, \nRender Color, 29.6089, 29.7984, 28.4744, 28.4221, 28.3893, 28.4365, 28.3986, 28.4744, 28.4221, 28.4088, 28.4611, 28.3945, 28.3444, 28.3966, 28.373, 28.4611, 28.3679, 28.3638, 28.417, 28.4037, 28.3761, 28.4426, 28.3832, 28.4396, 28.3577, 28.4098, 28.3955, 28.3832, 28.4293, 28.4119, 28.3843, 28.3852, 28.3607, 28.4364, 28.3986, 28.4099, 28.3638, 28.3863, 28.3894, 28.3576, 28.3515, 28.4006, 28.3832, 28.4232, 28.3781, 28.4221, 28.4037, 28.4109, 28.3648, 28.4058, 28.3658, 28.4273, 28.3924, 28.375, 28.3771, 28.4426, 28.37, 28.3689, 28.4078, 28.4436, 28.3402, 28.4129, 28.3576, 28.4109, 28.3792, 28.3781, 28.3505, 28.4938, 28.3833, 28.2604, 28.2757, 28.2542, 28.2818, 28.4487, 28.6709, 28.5512, 28.7355, 28.5829, 28.2102, 28.1006, 28.1344, 28.1088, 28.8953, 29.4676, 29.5967, 30.0483, 30.7968, 31.6641, 32.0707, 32.5366, 31.9836, 32.2069, 32.3021, 31.7348, 31.3999, 30.4742, 29.2209, 27.518, 26.9865, 26.5513, 26.0711, 26.0874, 26.5544, 26.9599, 27.4196, 27.3121, 27.4637, 27.7156, 27.8118, 27.4944, 27.4196, 27.3357, 27.4913, 27.5128, 27.4196, 27.3449, 27.4678, 27.3459, 27.1555, 26.6947, 26.4776, 26.2892, 26.3475, 26.4417, 26.1724, 26.1796, 25.8683, 25.9205, 26.1673, 26.6046, 26.9701, 27.1462, 27.009, 26.9506, 27.2712, 27.6429, 27.7821, 27.6306, 27.3531, 27.349, 27.3858, 27.5426, 27.5415, 27.6009, 27.647, 27.2282, 27.0715, 26.9906, 27.0705, 26.8114, 26.5656, 26.3711, 26.24, 26.0352, 25.8171, 25.7331, 25.7587, 25.8929, 26.0598, 25.81, 25.6276, 25.4709, 25.4004, 25.2345, 25.1668, 25.1648, 25.0983, 25.2027, 25.1996, 25.1852, 25.0501, 24.918, 24.79, 24.7183, 24.7654, 24.6364, 24.4265, 24.2248, 23.9964, 23.9288, 23.8223, 23.7639, 23.7158, 23.4772, 23.4332, 23.3667, 23.2571, 23.1322, 22.914, 22.7471, 22.5587, 22.354, 22.2341, 22.0631, 22.0857, 22.1665, 22.4225, 22.7369, 22.8639, 22.9673, 23.0543, 23.0758, 23.1127, 23.1281, 23.296, 23.3134, 23.6022, 23.6421, 23.81, 23.9022, 24.0199, 24.1142, 24.2279, 24.4992, 24.7265, 24.7276, 24.6928, 24.5832, 24.4879, 24.5063, 24.6272, 24.6313, 24.6825, 24.5463, 24.3364, 23.7814, 23.1065, 22.3427, 21.7068, 21.1702, 20.9244, 20.6602, 20.3602, 20.1554, 20.0704, 19.9424, 19.8523, 19.8687, 19.8953, 19.8543, 19.9373, 19.8687, 19.9229, 19.9496, 19.9884, 20.0028, 19.8298, 19.8154, 19.8768, 19.9588, 20.1759, 20.4677, 21.0022, 21.1077, 21.0862, 21.1005, 21.2081, 21.2869, 21.3658, 21.4036, 21.4313, 21.4764, 21.2562, 21.2838, 21.3125, 21.3494, 21.4631, 21.2295, 21.2214, 21.2255, 21.3023, 21.4241, 21.5255, 21.6433, 21.7016, 21.7355, 21.7948, 21.8604, 21.6587, 21.6709, 21.6392, 21.6033, 21.4221, 21.2808, 21.2234, 21.1241, 21.0627, 20.9234, 20.9541, 20.8957, 20.8896, 20.8548, 20.8968, 20.9725, 21.1333, 21.118, 21.0452, 20.9562, 20.948, 20.8558, 20.8343, 20.8281, 20.7728, 20.7063, 20.7032, 20.7636, 20.6561, 20.6746, 20.5127, 20.3428, 20.2762, 20.2087, 20.1052, 20.0766, 20.0305, 20.0622, 20.0448, 20.2629, 20.5496, 20.7924, 20.7646, 20.7421, 20.5855, 20.6418, 20.3776, 20.2199, 20.1144, 20.0018, 19.969, 20.0396, 20.4268, 20.5609, 20.7575, 20.9275, 21.3043, 21.7508, 22.3815, 22.8434, 22.784, 22.8915, 22.8239, 22.8065, 22.7379, 22.7963, 22.7983, 22.9233, 22.9263, 22.9479, 23.0564, 23.1219, 23.1414, 23.2274, 23.2837, 23.3318, 23.4445, 23.4312, 23.4568, 23.382, 23.4926, 23.4588, 23.4997, 23.5161, 23.595, 23.5561, 23.5909, 23.5325, 23.636, 23.5602, 23.5325, 23.5868, 23.5264, 23.51, 23.5121, 23.5264, 23.5275, 23.5438, 23.5039, 23.4998, 23.4629, 23.4384, 23.4803, 23.4905, 23.5213, 23.5428, 23.5551, 23.5889, 23.5735, 23.6022, 23.5735, 23.5489, 23.5223, 23.51, 23.4578, 23.4742, 23.4507, 23.4793, 23.4527, 23.4721, 23.5223, 23.5069, 23.5407, 23.5275, 23.5325, 23.508, 23.467, 23.4988, 23.5715, 23.51, 23.5438, 23.5223, 23.595, 23.4967, 23.7046, 23.594, 23.5571, 23.5551, 23.6288, 23.5305, 23.5223, 23.5756, 23.5192, 23.51, 23.4496, 23.4865, 23.4066, 23.5192, 23.5315, 23.4291, 23.4711, 23.4394, 23.4394, 23.4537, 23.4291, 23.3984, 23.3687, 23.4824, 23.3912, 23.4455, 23.4352, 23.4681, 23.4895, 23.4384, 23.424, 23.3933, 23.3984, 23.3851, 23.4455, 23.4588, 23.3964, 23.4291, 23.3922, 23.4189, 23.4117, 23.4251, 23.4087, 23.4291, 23.3656, 23.3892, 23.4045, 23.4629, 23.4168, 23.4199, 23.3871, 23.4097, 23.3912, 23.424, 23.381, 23.4199, 23.3984, 23.4076, 23.3667, 23.4086, 23.3994, 23.424, 23.3984, 23.3912, 23.3892, 23.381, 0.511008, 0.513056, 0.510976, 0.512, 0.534528, 0.52736, 0.512, 0.510944, 0.534528, 0.533536, 0.53552, 0.512992, 0.534528, 0.533472, 0.531456, 0.510944, 0.512, 0.510944, 0.512, 0.512, 0.512, 0.531424, 0.533472, 0.535584, 0.512, 0.509984, 0.513024, 0.51712, 0.519136, 0.513056, 0.512, 0.513024, 0.50992, 0.531456, 0.53552, 0.512, 0.512, 0.511008, 0.514048, 0.509952, 0.523232, 0.511008, 0.511008, 0.513056, 0.513024, 0.513056, 0.556, 0.512992, 0.513056, 23.4158, 23.3728, 23.4137, 23.4045, 23.4045, 23.3973, 23.3984, 23.378, 23.4138, 23.3799, 23.3892, 23.4373, 23.3943, 23.4424, 23.3994, \nRender Shadow Map, 4.01818, 4.02435, 4.02534, 4.0233, 4.01818, 4.02122, 4.0223, 4.01917, 4.02125, 4.03354, 4.01098, 4.02224, 4.02125, 4.01814, 4.01715, 4.0264, 4.02125, 4.0233, 4.0233, 4.02125, 4.01917, 4.02125, 4.0233, 4.0233, 4.02429, 4.01718, 4.0233, 4.02227, 4.012, 4.02026, 4.01917, 4.02435, 4.02026, 4.02125, 4.01616, 4.02534, 4.02435, 4.0223, 4.0151, 4.02019, 4.01514, 4.02432, 4.02125, 4.0192, 4.0233, 4.02125, 4.0151, 4.02125, 4.02538, 4.01411, 4.02125, 4.02122, 4.02019, 4.02538, 4.02125, 4.01616, 4.02534, 4.0223, 4.0223, 4.02941, 4.02125, 4.01818, 4.02227, 4.01818, 4.01818, 4.03661, 4.03152, 4.02739, 4.01923, 4.02941, 4.02022, 4.02534, 4.0264, 4.01206, 4.02125, 4.03558, 4.03459, 4.03149, 4.0192, 4.01405, 4.0223, 4.03149, 4.02634, 4.02019, 4.02534, 4.03357, 4.03555, 4.02227, 4.02022, 4.05094, 4.03354, 4.03149, 4.02634, 4.0233, 4.02742, 4.03658, 4.03248, 4.02429, 4.03046, 4.04275, 4.03658, 4.04278, 4.03354, 4.02842, 4.052, 4.04378, 4.03658, 4.03763, 4.0479, 4.03971, 4.04582, 4.03558, 4.03046, 4.04381, 4.04272, 4.0407, 4.02739, 4.03354, 4.04787, 4.04477, 4.04477, 4.0376, 4.03354, 4.04176, 4.04275, 4.052, 4.04275, 4.04272, 4.04272, 4.05094, 4.05402, 4.03558, 4.03971, 4.05712, 4.05603, 4.04275, 4.04688, 4.0663, 4.05914, 4.06013, 4.04582, 4.04784, 4.05712, 4.06323, 4.05706, 4.04995, 4.05606, 4.06736, 4.0591, 4.0561, 4.052, 4.05299, 4.0663, 4.06835, 4.06118, 4.05091, 4.06528, 4.06218, 4.06426, 4.05194, 4.05405, 4.07453, 4.07242, 4.06938, 4.06224, 4.05814, 4.05914, 4.07139, 4.06938, 4.07248, 4.0704, 4.07453, 4.07453, 4.0735, 4.06426, 4.06934, 4.07754, 4.07142, 4.07248, 4.0673, 4.07658, 4.07453, 4.07757, 4.06634, 4.06835, 4.09194, 4.08371, 4.08675, 4.0704, 4.07146, 4.07248, 4.08778, 4.08678, 4.06934, 4.07344, 4.09194, 4.08883, 4.08678, 4.07453, 4.07654, 4.07962, 4.0888, 4.08989, 4.08166, 4.09398, 4.10013, 4.09498, 4.08675, 4.08579, 4.08371, 4.09296, 4.09699, 4.08675, 4.09194, 4.10624, 4.096, 4.09392, 4.08883, 4.0888, 4.11344, 4.09805, 4.10314, 4.09088, 4.08573, 4.10112, 4.09699, 4.10112, 4.08678, 4.10928, 4.09395, 4.10317, 4.09293, 4.096, 4.09194, 4.10419, 4.09907, 4.096, 4.09494, 4.10419, 4.09907, 4.10006, 4.096, 4.0929, 4.10518, 4.10624, 4.1001, 4.096, 4.08989, 4.10829, 4.10525, 4.10317, 4.09494, 4.10829, 4.10627, 4.10211, 4.09194, 4.09398, 4.11242, 4.10317, 4.10218, 4.09091, 4.09699, 4.10416, 4.10317, 4.10522, 4.09494, 4.09395, 4.11034, 4.10115, 4.09805, 4.096, 4.11341, 4.10829, 4.10112, 4.10013, 4.08883, 4.10525, 4.10218, 4.10211, 4.09187, 4.09398, 4.096, 4.09805, 4.096, 4.09091, 4.08784, 4.1001, 4.09501, 4.09907, 4.08374, 4.08579, 4.10314, 4.09907, 4.09805, 4.09088, 4.08474, 4.0847, 4.096, 4.09293, 4.08064, 4.096, 4.0919, 4.09395, 4.08272, 4.07552, 4.09494, 4.08272, 4.0847, 4.07555, 4.08166, 4.08682, 4.08368, 4.08272, 4.07242, 4.07453, 4.09904, 4.07859, 4.07347, 4.0673, 4.0673, 4.07962, 4.07965, 4.07446, 4.06224, 4.08163, 4.07142, 4.06733, 4.06016, 4.06122, 4.06941, 4.07142, 4.06531, 4.04989, 4.04989, 4.052, 4.05811, 4.05405, 4.04992, 4.0479, 4.06016, 4.05094, 4.05501, 4.04176, 4.0417, 4.0407, 4.0376, 4.03866, 4.03043, 4.0479, 4.04272, 4.04272, 4.03254, 4.02534, 4.03763, 4.03664, 4.0223, 4.01411, 4.01101, 4.00176, 3.99565, 3.99053, 3.96906, 3.96493, 3.95571, 3.95165, 3.94243, 3.93626, 3.90861, 3.9209, 3.90758, 3.89018, 3.87277, 3.87075, 3.85328, 3.84819, 3.82771, 3.8113, 3.80518, 3.80006, 3.78365, 3.76934, 3.75094, 3.7489, 3.72429, 3.71811, 3.69354, 3.67818, 3.67718, 3.6608, 3.64547, 3.62394, 3.6055, 3.61062, 3.58704, 3.57475, 3.55741, 3.54301, 3.52563, 3.50518, 3.50518, 3.51949, 3.54813, 3.55734, 3.57888, 3.58301, 3.5983, 3.61677, 3.64029, 3.64954, 3.66288, 3.67002, 3.68842, 3.70685, 3.72019, 3.73965, 3.7417, 3.76426, 3.78266, 3.79805, 3.82157, 3.83696, 3.83181, 3.8513, 3.86352, 3.87072, 3.88915, 3.89325, 3.90758, 3.9137, 3.93216, 3.94547, 3.95882, 3.9649, 3.968, 3.97824, 3.99158, 4.01613, 4.01408, 4.0151, 4.02534, 4.04272, 4.04989, 4.05094, 4.05296, 4.07658, 4.08064, 4.08269, 4.07965, 4.09296, 4.10624, 4.10525, 4.11747, 4.11747, 4.13798, 4.1431, 4.15642, 4.15437, 4.14928, 4.1585, 4.1687, 4.16771, 4.15846, 4.14618, 4.1431, 4.14618, 4.15642, 4.15235, 4.14208, 4.14006, 4.12464, 4.12675, 4.11546, 4.11037, 4.11955, 4.10928, 4.10525, 4.09194, 4.10314, 4.10317, 4.11235, 4.10314, 4.09395, 4.09395, 4.11136, 4.1032, 4.10218, 4.0929, 4.08576, 4.11136, 4.11242, 4.10723, 4.08989, 4.1073, 4.10013, 4.10522, 4.08886, 4.09194, 4.11235, 4.10525, 4.09805, 4.08784, 4.09699, 4.10829, 4.10826, 4.10621, 4.0919, 4.08682, 4.11136, 4.10314, 4.10214, 4.08576, 4.08989, 4.10624, 4.10829, 4.10723, 4.08781, 4.11235, 4.10211, 4.10422, 4.09088, 4.09088, 4.10931, 4.11235, 4.10829, 4.08682, 4.08371, 4.10518, 4.10314, 4.10317, 4.096, 4.09706, 4.10624, 4.11341, 4.10416, 4.09699, 4.09904, 4.11446, 4.10525, 4.10416, 4.09702, 4.11546, 4.1001, \nRender UI, 0.018432, 0.011296, 0.017408, 0.011232, 0.017408, 0.011232, 0.017408, 0.012288, 0.017408, 0.012288, 0.017376, 0.012288, 0.018464, 0.011296, 0.018464, 0.012288, 0.017408, 0.012288, 0.017408, 0.011232, 0.017408, 0.011232, 0.018464, 0.011232, 0.018432, 0.01232, 0.018464, 0.012288, 0.0184, 0.012256, 0.017408, 0.012256, 0.0184, 0.012256, 0.017408, 0.01232, 0.017408, 0.011296, 0.017408, 0.01024, 0.017408, 0.01232, 0.018464, 0.011296, 0.017408, 0.012288, 0.017408, 0.012288, 0.018432, 0.012288, 0.017376, 0.012256, 0.017408, 0.012288, 0.017376, 0.011296, 0.017408, 0.011232, 0.016416, 0.012256, 0.01744, 0.012288, 0.017408, 0.012256, 0.018432, 0.012288, 0.012288, 0.011264, 0.018432, 0.011232, 0.018432, 0.013312, 0.017408, 0.012288, 0.018464, 0.012288, 0.01328, 0.011232, 0.017408, 0.01232, 0.0184, 0.012288, 0.018464, 0.012288, 0.016384, 0.012288, 0.0184, 0.012288, 0.018432, 0.012288, 0.012288, 0.011296, 0.0184, 0.012288, 0.017376, 0.011264, 0.018432, 0.011232, 0.017408, 0.012288, 0.012288, 0.011232, 0.017408, 0.012288, 0.01744, 0.012288, 0.021536, 0.012288, 0.018464, 0.012288, 0.01744, 0.012256, 0.018432, 0.012288, 0.012288, 0.011296, 0.017408, 0.011296, 0.017408, 0.012288, 0.018432, 0.011296, 0.018464, 0.011232, 0.012288, 0.011296, 0.018464, 0.011232, 0.017408, 0.011232, 0.017408, 0.012288, 0.018464, 0.012256, 0.017408, 0.011232, 0.018432, 0.012288, 0.012256, 0.012288, 0.017408, 0.011232, 0.017408, 0.013312, 0.0184, 0.012256, 0.018432, 0.012288, 0.013312, 0.012288, 0.02048, 0.011296, 0.017408, 0.012256, 0.017376, 0.011296, 0.018464, 0.011232, 0.017408, 0.011232, 0.0184, 0.01232, 0.01328, 0.01232, 0.018432, 0.012288, 0.017408, 0.011296, 0.018464, 0.011232, 0.0184, 0.012288, 0.012288, 0.012256, 0.0184, 0.011264, 0.018432, 0.013344, 0.017408, 0.012288, 0.018464, 0.011264, 0.017408, 0.011232, 0.018432, 0.01232, 0.012288, 0.012288, 0.018464, 0.012288, 0.018432, 0.012288, 0.018464, 0.011232, 0.017408, 0.012288, 0.011232, 0.011296, 0.0184, 0.012288, 0.017408, 0.012256, 0.018432, 0.011264, 0.0184, 0.012288, 0.017408, 0.012256, 0.018432, 0.012288, 0.012288, 0.011232, 0.018464, 0.011264, 0.017408, 0.012288, 0.017408, 0.011296, 0.017408, 0.012288, 0.011232, 0.012288, 0.018432, 0.011264, 0.01744, 0.01232, 0.017408, 0.012288, 0.017408, 0.011296, 0.017408, 0.011296, 0.016416, 0.012288, 0.012256, 0.011296, 0.017408, 0.012288, 0.018432, 0.012256, 0.018464, 0.011232, 0.017376, 0.012256, 0.012288, 0.011264, 0.017408, 0.01232, 0.018432, 0.013312, 0.017408, 0.012288, 0.019488, 0.012288, 0.018432, 0.011296, 0.017376, 0.011296, 0.011232, 0.011296, 0.017408, 0.011264, 0.017408, 0.012288, 0.0184, 0.012288, 0.019456, 0.011296, 0.012288, 0.012288, 0.017408, 0.012256, 0.017408, 0.012288, 0.017408, 0.011296, 0.018432, 0.012288, 0.017408, 0.012256, 0.017408, 0.011296, 0.012288, 0.012288, 0.018432, 0.012288, 0.018432, 0.011296, 0.0184, 0.011296, 0.017408, 0.012288, 0.012288, 0.011296, 0.017408, 0.012288, 0.017408, 0.012288, 0.018464, 0.012288, 0.018464, 0.012288, 0.017408, 0.012288, 0.018464, 0.011232, 0.012288, 0.012256, 0.0184, 0.012288, 0.018432, 0.012288, 0.018432, 0.011296, 0.0184, 0.011264, 0.011232, 0.01024, 0.017408, 0.012288, 0.017408, 0.012288, 0.017408, 0.011296, 0.017408, 0.013312, 0.017408, 0.012288, 0.017408, 0.012288, 0.012288, 0.012256, 0.017408, 0.012288, 0.019488, 0.013344, 0.017408, 0.011232, 0.017408, 0.011232, 0.012288, 0.012288, 0.018464, 0.012288, 0.0184, 0.012256, 0.017408, 0.012288, 0.017408, 0.011232, 0.018432, 0.012288, 0.017408, 0.011232, 0.01232, 0.012288, 0.017408, 0.011296, 0.018432, 0.01232, 0.018432, 0.012288, 0.016416, 0.011232, 0.01232, 0.011232, 0.017408, 0.012288, 0.0184, 0.011232, 0.017408, 0.012288, 0.017408, 0.012288, 0.017408, 0.011232, 0.017408, 0.011296, 0.011296, 0.012288, 0.017408, 0.012288, 0.019424, 0.01232, 0.017408, 0.011232, 0.018432, 0.012288, 0.012288, 0.011232, 0.018432, 0.012256, 0.018432, 0.012256, 0.016352, 0.012288, 0.017408, 0.013344, 0.018432, 0.011232, 0.018464, 0.01232, 0.011296, 0.012256, 0.0184, 0.012288, 0.018432, 0.012288, 0.017408, 0.012288, 0.017408, 0.01232, 0.01232, 0.011232, 0.017408, 0.011264, 0.017408, 0.012288, 0.018464, 0.011232, 0.0184, 0.013312, 0.018432, 0.012288, 0.017376, 0.012288, 0.012256, 0.011264, 0.017408, 0.011232, 0.017408, 0.012288, 0.017408, 0.011232, 0.017408, 0.012288, 0.012288, 0.011232, 0.0184, 0.012288, 0.018464, 0.012288, 0.017408, 0.011264, 0.0184, 0.012288, 0.0184, 0.011232, 0.017408, 0.012288, 0.012288, 0.012256, 0.017408, 0.011296, 0.017408, 0.01232, 0.018464, 0.011232, 0.017408, 0.012256, 0.012288, 0.01232, 0.016416, 0.011296, 0.018432, 0.011264, 0.017408, 0.012288, 0.017376, 0.01232, 0.017408, 0.011296, 0.017408, 0.01232, 0.01232, 0.011232, 0.018464, 0.010208, 0.018464, 0.012288, 0.017408, 0.011296, 0.018432, 0.012256, 0.012288, 0.012288, 0.017408, 0.012288, 0.018464, 0.012288, 0.0184, 0.011232, 0.0184, 0.012288, 0.018464, 0.012256, 0.017408, 0.012288, 0.011296, 0.012288, 0.018432, 0.012288, 0.017408, 0.012288, 0.017408, 0.012288, 0.017408, 0.011264, 0.013312, 0.012288, 0.017408, 0.011296, 0.018432, 0.01232, 0.018464, 0.012288, 0.018432, 0.012288, 0.017408, 0.012288, 0.017408, 0.01232, 0.012288, 0.012288, 0.018464, 0.012288, 0.01744, 0.011232, 0.017408, 0.011296, 0.017408, 0.011232, 0.012288, 0.011232, 0.017408, 0.011232, 0.0184, 0.012288, 0.017408, 0.012288, 0.017408, 0.012288, \nRenderLightShadows, 0, 0, 0, 0.001024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.2e-05, 0, 0, 0, 3.2e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.2e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \nResolve Image, 1.4889, 1.50525, 1.55446, 1.4633, 1.51043, 1.49299, 1.48381, 1.52576, 1.50733, 1.47149, 1.50224, 1.47866, 1.49917, 1.4817, 1.50019, 1.5104, 1.5073, 1.48483, 1.48483, 1.50118, 1.50221, 1.50019, 1.47661, 1.47453, 1.5104, 1.4807, 1.50218, 1.46842, 1.52371, 1.4735, 1.50013, 1.47866, 1.50115, 1.50528, 1.48477, 1.492, 1.50016, 1.48275, 1.5063, 1.48173, 1.49606, 1.47664, 1.50019, 1.47146, 1.50323, 1.49398, 1.50118, 1.51347, 1.48477, 1.50835, 1.51453, 1.48378, 1.51242, 1.49398, 1.49507, 1.52781, 1.4991, 1.49507, 1.52064, 1.49504, 1.52883, 1.47664, 1.48483, 1.4807, 1.50013, 1.46742, 1.52477, 1.56365, 1.56675, 1.59024, 1.54931, 1.52682, 1.54624, 1.51965, 1.57693, 1.57904, 1.5544, 1.55139, 1.52678, 1.54928, 1.5473, 1.52989, 1.54416, 1.54624, 1.56771, 1.5473, 1.52064, 1.54525, 1.54931, 1.57491, 1.54419, 1.56675, 1.56266, 1.54013, 1.52989, 1.52576, 1.52778, 1.52682, 1.5503, 1.54726, 1.55136, 1.56877, 1.54211, 1.52675, 1.56778, 1.54832, 1.5288, 1.52675, 1.52678, 1.53187, 1.5503, 1.53187, 1.57389, 1.57184, 1.53805, 1.54624, 1.53187, 1.55037, 1.54931, 1.52371, 1.57693, 1.5657, 1.52266, 1.55136, 1.52678, 1.55238, 1.55955, 1.58106, 1.51862, 1.54419, 1.54419, 1.5104, 1.56266, 1.54112, 1.53805, 1.54112, 1.53494, 1.536, 1.54314, 1.54115, 1.55136, 1.58413, 1.56163, 1.54218, 1.53805, 1.55648, 1.55651, 1.53088, 1.58822, 1.52266, 1.54525, 1.54317, 1.55136, 1.54624, 1.55549, 1.52989, 1.54624, 1.54931, 1.54419, 1.51552, 1.54211, 1.54624, 1.54931, 1.52682, 1.54419, 1.55034, 1.55542, 1.5247, 1.54419, 1.55341, 1.55443, 1.55853, 1.54006, 1.52886, 1.54211, 1.55546, 1.53296, 1.54829, 1.55853, 1.57696, 1.52576, 1.5473, 1.57082, 1.54518, 1.55136, 1.51859, 1.52368, 1.56669, 1.51552, 1.54624, 1.54422, 1.54218, 1.52368, 1.5616, 1.52163, 1.56877, 1.54826, 1.5391, 1.56365, 1.53395, 1.54419, 1.54317, 1.54211, 1.54419, 1.54211, 1.51965, 1.51962, 1.54218, 1.5647, 1.54522, 1.54518, 1.5391, 1.51958, 1.5391, 1.5176, 1.56058, 1.53494, 1.51146, 1.52982, 1.52682, 1.50835, 1.52778, 1.51248, 1.51142, 1.52883, 1.54218, 1.53293, 1.52269, 1.52678, 1.54218, 1.52576, 1.5288, 1.52371, 1.52682, 1.55242, 1.55037, 1.55238, 1.52784, 1.55648, 1.56774, 1.52166, 1.52163, 1.53494, 1.54723, 1.52064, 1.54112, 1.54624, 1.51958, 1.51958, 1.51859, 1.54723, 1.57187, 1.56976, 1.5657, 1.52163, 1.52576, 1.55341, 1.5657, 1.52883, 1.5647, 1.54218, 1.54211, 1.52269, 1.5391, 1.55446, 1.54829, 1.52371, 1.54931, 1.52163, 1.54518, 1.54624, 1.56365, 1.54624, 1.52682, 1.56877, 1.5544, 1.56672, 1.52371, 1.57082, 1.55446, 1.56774, 1.52682, 1.55136, 1.56774, 1.54931, 1.55341, 1.55034, 1.55446, 1.55853, 1.53194, 1.52576, 1.55235, 1.52272, 1.54931, 1.54624, 1.55136, 1.57082, 1.54723, 1.57699, 1.56976, 1.53501, 1.53194, 1.5503, 1.52982, 1.56259, 1.52269, 1.5616, 1.5473, 1.52064, 1.54624, 1.55341, 1.53088, 1.55341, 1.55235, 1.54624, 1.56874, 1.54422, 1.54317, 1.52368, 1.55034, 1.54928, 1.54522, 1.54726, 1.54627, 1.54211, 1.52064, 1.54934, 1.56976, 1.52266, 1.55341, 1.52576, 1.5247, 1.56058, 1.5217, 1.57082, 1.55549, 1.55136, 1.5575, 1.55139, 1.55235, 1.55034, 1.56464, 1.54518, 1.56976, 1.52982, 1.53501, 1.57389, 1.52986, 1.57693, 1.54522, 1.54419, 1.53699, 1.53187, 1.53296, 1.52781, 1.56365, 1.58314, 1.55341, 1.59949, 1.56157, 1.58822, 1.55242, 1.59747, 1.57389, 1.61382, 1.59334, 1.55546, 1.54931, 1.61075, 1.56058, 1.58006, 1.55958, 1.58211, 1.62, 1.60355, 1.59334, 1.57693, 1.54416, 1.56982, 1.52477, 1.56672, 1.5473, 1.54934, 1.53805, 1.5247, 1.5063, 1.536, 1.52266, 1.51555, 1.50528, 1.52064, 1.51859, 1.54624, 1.51555, 1.54317, 1.54218, 1.52883, 1.5647, 1.55958, 1.54218, 1.52576, 1.5247, 1.5616, 1.5401, 1.52682, 1.53088, 1.54525, 1.55136, 1.55952, 1.54829, 1.54832, 1.55034, 1.55549, 1.52678, 1.55235, 1.52682, 1.57904, 1.52675, 1.55037, 1.54317, 1.55235, 1.54934, 1.52678, 1.52477, 1.55235, 1.52982, 1.5329, 1.52477, 1.53088, 1.56061, 1.536, 1.52675, 1.55238, 1.54934, 1.55549, 1.52678, 1.52982, 1.54928, 1.52576, 1.55136, 1.53088, 1.53805, 1.56573, 1.55037, 1.54624, 1.51859, 1.54317, 1.55747, 1.5391, 1.55037, 1.54829, 1.50634, 1.51654, 1.50736, 1.50835, 1.49405, 1.492, 1.47046, 1.51248, 1.47354, 1.54522, 1.47658, 1.50013, 1.5176, 1.48989, 1.47971, 1.53194, 1.50634, 1.51446, 1.49094, 1.51555, 1.50627, 1.50323, 1.47664, 1.50323, 1.47453, 1.49914, 1.47046, 1.48582, 1.46534, 1.48483, 1.45514, 1.48582, 1.46227, 1.48275, 1.46538, 1.46435, 1.47354, 1.47354, 1.46022, 1.48582, 1.4633, 1.52064, 1.47046, 1.52477, 1.49914, 1.4807, 1.46534, 1.4664, 1.46019, 1.50733, 1.48886, 1.49098, 1.45306, 1.46534, 1.50528, 1.48176, 1.4776, 1.48688, 1.45613, 1.47766, 1.4633, 1.47354, 1.4449, 1.48995, 1.4633, 1.46637, 1.47558, 1.47558, 1.45206, 1.4633, 1.46538, 1.48582, 1.45923, 1.46742, 1.48582, 1.49094, 1.4879, 1.50531, 1.50938, 1.54006, 1.49811, 1.49405, 1.48272, 1.4817, 1.49194, 1.49811, 1.48374, 1.49094, 1.47254, 1.49808, 1.4817, \nSDR Processing, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0, 0.84272, 0.847872, 0.840704, 0.840704, 0.83968, 0.838656, 0.8448, 0.837632, 0.839712, 0.839712, 0.83664, 0.844832, 0.839712, 0.836576, 0.84272, 0.84688, 0.840704, 0.841696, 0.842752, 0.839648, 0.844832, 0.837632, 0.842784, 0.840704, 0.83664, 0.844768, 0.835584, 0.838688, 0.839712, 0.844768, 0.844832, 0.833536, 0.841696, 0.838656, 0.837664, 0.844768, 0.836608, 0.842752, 0.8376, 0.843776, 0.840704, 0.838656, 0.839648, 0.838624, 0.843776, 0.838656, 0.837632, 0.837664, 0.842784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \nScene Render, 42.37, 42.6639, 41.7761, 41.2099, 41.2406, 41.2856, 41.1822, 41.3604, 41.2314, 41.2754, 41.2805, 41.1965, 41.1648, 41.1761, 41.2017, 41.3327, 41.2375, 41.1668, 41.2713, 41.2938, 41.2314, 41.2887, 41.2119, 41.303, 41.2119, 41.2436, 41.2416, 41.1781, 41.2836, 41.2468, 41.2323, 41.1976, 41.1884, 41.2989, 41.1955, 41.2805, 41.2119, 41.257, 41.2477, 41.1638, 41.2047, 41.2201, 41.1976, 41.2508, 41.2396, 41.2252, 41.2692, 41.2989, 41.1925, 41.2621, 41.2641, 41.2621, 41.2406, 41.2682, 41.1874, 41.2979, 41.1874, 41.2252, 41.3143, 41.2559, 41.2652, 41.2191, 41.1771, 41.2498, 41.2528, 41.1822, 41.3604, 41.7567, 41.6768, 41.5877, 41.6021, 41.5754, 41.6369, 41.7229, 42.0148, 41.9635, 42.2523, 41.9523, 41.5785, 41.4924, 41.5642, 41.6102, 42.2799, 42.8462, 43.0377, 43.4606, 44.1876, 45.1236, 45.4667, 46.0329, 45.5383, 45.6765, 45.7411, 45.1779, 44.8113, 44.075, 42.6342, 40.9201, 40.4327, 40.0128, 39.5377, 39.5643, 40.0199, 40.3927, 40.918, 40.8259, 40.8771, 41.1065, 41.2006, 40.875, 40.7962, 40.7388, 40.8105, 40.8802, 40.7675, 40.705, 40.8146, 40.6794, 40.4675, 40.0343, 39.7885, 39.596, 39.6401, 39.7169, 39.4763, 39.4557, 39.1587, 39.2407, 39.4281, 39.8991, 40.2791, 40.4019, 40.2924, 40.2022, 40.5452, 40.8484, 41.0071, 40.8617, 40.6794, 40.5524, 40.534, 40.7562, 40.6907, 40.8566, 40.8136, 40.4244, 40.2514, 40.1582, 40.3978, 39.982, 39.7497, 39.5509, 39.4394, 39.2386, 39.0318, 38.9059, 38.958, 39.1342, 39.3502, 38.9827, 38.8393, 38.6837, 38.7113, 38.487, 38.3498, 38.3396, 38.2782, 38.3775, 38.3989, 38.3355, 38.1809, 38.1133, 37.9884, 37.845, 37.8338, 37.7129, 37.5009, 37.3084, 37.0483, 37.0667, 36.9019, 36.8845, 36.8865, 36.5415, 36.5558, 36.4523, 36.4615, 36.3121, 35.9936, 35.8758, 35.666, 35.5236, 35.4007, 35.201, 35.2502, 35.3792, 35.6874, 35.927, 36.0561, 36.1718, 36.2558, 36.2926, 36.3612, 36.4114, 36.5455, 36.7124, 36.8783, 36.9418, 37.1559, 37.2552, 37.3565, 37.4702, 37.5296, 37.848, 38.0467, 38.0949, 38.0734, 37.8676, 37.8081, 37.8153, 37.9197, 37.9351, 37.9156, 37.7569, 37.5122, 37.0063, 36.183, 35.4089, 34.7259, 34.1514, 33.9282, 33.6538, 33.2933, 33.0977, 33.0906, 32.9278, 32.8428, 32.8581, 32.9339, 32.9308, 32.9851, 32.9083, 32.9676, 33.108, 33.111, 33.1244, 32.98, 32.8775, 33.0066, 33.1612, 33.282, 33.5903, 34.2077, 34.3593, 34.219, 34.1985, 34.3521, 34.4576, 34.5559, 34.6204, 34.5631, 34.5989, 34.3982, 34.4945, 34.4935, 34.5815, 34.6583, 34.4012, 34.3788, 34.388, 34.4996, 34.6911, 34.69, 34.8006, 34.9707, 34.8775, 35.0136, 35.0525, 34.8724, 34.8171, 34.8047, 34.7085, 34.601, 34.3747, 34.2599, 34.1474, 34.0705, 34.0531, 33.9527, 33.9046, 33.8924, 33.879, 33.9149, 33.9999, 34.1094, 34.0788, 34.0295, 33.9261, 33.92, 33.7705, 33.7592, 33.792, 33.7971, 33.7388, 33.8391, 33.8821, 34.0019, 33.8258, 33.6486, 33.5206, 33.4787, 33.451, 33.366, 33.3281, 33.2708, 33.3967, 33.3558, 33.5196, 33.8514, 34.0623, 34.0818, 34.2825, 33.9825, 34.0285, 33.7725, 33.7766, 33.4653, 33.3968, 33.3066, 33.4612, 33.9958, 33.9507, 34.2518, 34.3695, 34.8171, 35.4744, 35.8554, 36.3356, 36.2639, 36.3776, 36.2895, 36.2967, 36.2445, 36.2465, 36.1912, 36.5364, 36.3888, 36.2957, 36.4811, 36.7565, 36.5117, 36.5364, 36.5834, 36.6305, 36.6796, 36.6418, 36.6766, 36.478, 36.6612, 36.5466, 36.5978, 36.6019, 36.6469, 36.6019, 36.693, 36.5353, 36.5332, 36.4043, 36.4851, 36.521, 36.4135, 36.2936, 36.2957, 36.4042, 36.3244, 36.3387, 36.2885, 36.1667, 36.181, 36.0714, 36.1298, 36.1247, 36.1349, 36.139, 36.1605, 36.1206, 36.0898, 36.1155, 36.0919, 36.0397, 35.9957, 35.9669, 35.9239, 35.9311, 35.9117, 35.8943, 35.8523, 35.9865, 35.9495, 35.8605, 35.9629, 35.9394, 36.1164, 36.0325, 36.0048, 36.009, 36.0858, 36.1319, 36.0971, 36.1595, 36.1789, 36.0652, 36.3961, 36.2128, 36.2527, 36.1923, 36.3151, 36.1922, 36.2342, 36.3356, 36.2691, 36.3121, 36.1831, 36.2127, 36.1728, 36.2681, 36.2967, 36.2015, 36.2404, 36.2608, 36.2547, 36.2937, 36.2916, 36.2916, 36.2414, 36.3131, 36.2813, 36.3643, 36.309, 36.3776, 36.3756, 36.4411, 36.3499, 36.3295, 36.352, 36.353, 36.4114, 36.4329, 36.3346, 36.3971, 36.4359, 36.3531, 36.3428, 36.3848, 36.3827, 36.4124, 36.3387, 36.3295, 36.439, 36.4062, 36.5803, 36.3622, 36.3223, 36.4473, 36.3295, 36.4851, 36.4053, 36.3479, 36.3407, 36.3879, 36.3284, 36.3244, 36.3131, 36.3356, 36.3366, 36.3049, 36.2834, 36.267, 13.6079, 13.6305, 13.6663, 13.5598, 13.6704, 13.6325, 13.6704, 13.6161, 13.6458, 13.5936, 13.6602, 13.6305, 13.6346, 13.6653, 13.7114, 13.6755, 13.7411, 13.6479, 13.6407, 13.6048, 13.6827, 13.6161, 13.6878, 13.6509, 13.6396, 13.6745, 13.609, 13.6417, 13.6325, 13.614, 13.6438, 13.5793, 13.5998, 13.5772, 13.6448, 13.6806, 13.6796, 13.6059, 13.6069, 13.7411, 13.6448, 13.5537, 13.57, 13.6069, 13.6489, 13.6294, 13.6418, 13.7185, 13.6428, 36.4257, 36.3531, 36.351, 36.3868, 36.3079, 36.3264, 36.3448, 36.2742, 36.3244, 36.3602, 36.2905, 36.3858, 36.3049, 36.4278, 36.3838, \nSharpen or Copy Image, 0.940064, 0.941056, 0.97072, 0.967648, 0.971744, 0.971808, 0.963584, 0.963584, 0.96048, 0.971808, 0.963584, 0.970752, 0.9656, 0.960544, 0.970752, 0.988192, 0.967712, 0.9656, 0.970752, 0.962528, 0.964608, 0.973824, 0.9728, 0.975872, 0.962592, 0.971776, 0.967712, 0.969728, 0.96256, 0.966656, 0.962592, 0.97488, 0.957472, 0.964608, 0.96464, 0.971776, 0.966656, 0.964608, 0.965632, 0.971744, 0.957472, 0.972768, 0.96256, 0.971776, 0.970784, 0.960544, 0.964576, 0.957408, 0.970752, 0.9656, 0.971776, 0.961536, 0.968704, 0.968704, 0.956384, 0.967712, 0.962592, 0.968704, 0.967648, 0.961536, 0.963584, 0.973824, 0.9728, 0.9728, 0.970752, 0.969696, 0.959488, 0.961568, 0.959488, 0.966656, 0.960512, 0.972768, 0.967648, 0.964608, 0.958496, 0.96048, 0.953376, 0.949248, 0.95024, 0.946176, 0.954368, 0.948224, 0.932896, 0.930816, 0.930816, 0.92976, 0.940064, 0.980992, 0.931808, 0.931872, 0.942048, 0.935904, 0.93488, 0.949216, 0.94512, 0.9544, 0.952352, 0.963584, 0.953344, 0.956416, 0.956416, 0.960544, 0.96464, 0.966656, 0.956416, 0.957408, 0.966656, 0.972832, 0.966624, 0.975872, 0.960544, 0.976928, 0.964576, 0.987104, 0.97488, 0.963584, 0.975872, 0.965632, 0.964576, 0.97488, 0.963584, 0.963584, 0.970752, 0.967712, 0.975872, 0.955392, 0.955392, 0.954368, 0.956416, 0.953344, 0.960512, 0.962528, 0.939008, 0.954368, 0.963584, 0.94512, 0.940064, 0.943104, 0.943104, 0.951296, 0.952352, 0.948224, 0.947168, 0.953344, 0.9472, 0.941056, 0.941056, 0.950304, 0.942112, 0.951296, 0.942048, 0.939008, 0.936928, 0.941056, 0.94, 0.94512, 0.936928, 0.937984, 0.931808, 0.940064, 0.944128, 0.93488, 0.930816, 0.94, 0.93488, 0.932896, 0.939008, 0.946176, 0.937984, 0.940064, 0.936992, 0.949248, 0.953376, 0.946176, 0.950304, 0.937952, 0.949216, 0.94512, 0.938976, 0.93904, 0.954336, 0.93488, 0.945184, 0.938016, 0.936992, 0.949248, 0.952352, 0.941056, 0.946176, 0.942048, 0.943072, 0.951296, 0.9472, 0.942112, 0.952352, 0.943104, 0.945152, 0.95024, 0.956416, 0.956416, 0.951296, 0.941056, 0.951296, 0.958464, 0.9472, 0.954336, 0.958464, 0.948192, 0.959488, 0.9656, 0.94928, 0.95024, 0.963584, 0.964608, 0.965632, 0.959456, 0.960512, 0.968672, 0.96976, 0.97584, 0.978944, 0.975872, 0.976896, 0.975872, 0.968704, 0.953312, 0.949248, 0.961536, 0.9544, 0.941056, 0.959456, 0.960544, 0.956416, 0.963584, 0.946176, 0.950272, 0.9472, 0.961504, 0.95024, 0.964608, 0.962528, 0.965632, 0.95952, 0.965632, 0.963584, 0.950304, 0.963584, 0.958464, 0.958464, 0.957472, 0.94928, 0.953312, 0.950304, 0.946176, 0.956416, 0.960544, 0.946176, 0.960544, 0.958464, 0.943072, 0.943072, 0.939008, 0.95536, 0.941024, 0.943072, 0.952352, 0.960512, 0.943104, 0.955424, 0.943104, 0.954368, 0.956384, 0.942112, 0.949248, 0.941056, 0.935936, 0.936928, 0.950272, 0.93488, 0.946176, 0.932832, 0.94, 0.936928, 0.928768, 0.923648, 0.930816, 0.941056, 0.933856, 0.921632, 0.94208, 0.946176, 0.945152, 0.943104, 0.949216, 0.933888, 0.943136, 0.937984, 0.933888, 0.948192, 0.933888, 0.951296, 0.95024, 0.931872, 0.953344, 0.948256, 0.952288, 0.944128, 0.945152, 0.954368, 0.943136, 0.943104, 0.95952, 0.946176, 0.951296, 0.949216, 0.9472, 0.946176, 0.949216, 0.964608, 0.948192, 0.960544, 0.964576, 0.9472, 0.953312, 0.963584, 0.960544, 0.94512, 0.948224, 0.953344, 0.943104, 0.946176, 0.951296, 0.933888, 0.94512, 0.928768, 0.928768, 0.92464, 0.93184, 0.928768, 0.92672, 0.929824, 0.942112, 0.926752, 0.927744, 0.940064, 0.939008, 0.925696, 0.940064, 0.928768, 0.938016, 0.929824, 0.941056, 0.932896, 0.937984, 0.939008, 0.922624, 0.922592, 0.923648, 0.920576, 0.928768, 0.92464, 0.935936, 0.922592, 0.940032, 0.921568, 0.932832, 0.941056, 0.940064, 0.928768, 0.944128, 0.970752, 0.941024, 0.930816, 0.92976, 0.942112, 0.933888, 0.941056, 0.942112, 0.930816, 0.941056, 0.93488, 0.930784, 0.935936, 0.93184, 0.945184, 0.947232, 0.927776, 0.928768, 0.941056, 0.94208, 0.94512, 0.94416, 0.932864, 0.944096, 0.936992, 0.930816, 0.942048, 0.93184, 0.92976, 0.92976, 0.945184, 0.945184, 0.931808, 0.939008, 0.942048, 0.946176, 0.930816, 0.927744, 0.924704, 0.944128, 0.931808, 0.932832, 0.922592, 0.940064, 0.939008, 0.93696, 0.9216, 0.940064, 0.925696, 0.944128, 0.930816, 0.925696, 0.935936, 0.94, 0.927776, 0.936992, 0.935936, 0.93488, 0.939008, 0.926688, 0.93696, 0.934944, 0.925664, 0.925696, 0.922592, 0.93184, 0.93392, 0.92672, 0.93184, 0.92672, 0.932832, 0.920608, 0.928736, 0.922624, 0.936928, 0.93696, 0.923648, 0.922656, 0.924672, 0.94, 0.92672, 0.92672, 0.926752, 0.927712, 0.936992, 0.93696, 0.937952, 0.93696, 0.933888, 0.937952, 0.929824, 0.937984, 0.92368, 0.923616, 0.932896, 0.934912, 0.92464, 0.920544, 0.920576, 0.935936, 0.922624, 0.922656, 0.919584, 0.941056, 0.923648, 0.932864, 0.921568, 0.94, 1.13354, 1.13766, 1.1264, 1.13763, 1.13459, 1.13866, 1.13664, 1.13357, 1.13971, 1.13664, 1.13254, 1.1377, 1.12848, 1.13152, 1.13459, 1.13766, 1.13664, 1.13459, 1.13866, 1.13459, 1.13254, 1.12947, 1.13149, 1.13053, 1.13149, 1.13251, 1.13152, 1.13459, 1.13254, 1.14077, 1.13558, 1.13251, 1.13558, 1.13766, 1.13664, 1.13046, 1.13971, 1.13664, 1.13459, 1.13866, 1.13869, 1.13357, 1.13462, 1.13664, 1.13459, 1.12947, 1.13046, 1.13667, 1.13462, 0.928736, 0.944128, 0.921568, 0.917536, 0.9216, 0.930784, 0.932896, 0.943136, 0.928768, 0.94208, 0.933888, 0.931872, 0.931808, 0.946176, 0.928768, \nTemporal Resolve, 2.42896, 2.44634, 2.52518, 2.43094, 2.48218, 2.4648, 2.44739, 2.48938, 2.46781, 2.4433, 2.46582, 2.44941, 2.46477, 2.44224, 2.47094, 2.49859, 2.47501, 2.45043, 2.45658, 2.46371, 2.46682, 2.47402, 2.44941, 2.4504, 2.47398, 2.45248, 2.46989, 2.43814, 2.48627, 2.44016, 2.46272, 2.45354, 2.45965, 2.46989, 2.44941, 2.46378, 2.46682, 2.44736, 2.47194, 2.45347, 2.45354, 2.44941, 2.46275, 2.44323, 2.47402, 2.45453, 2.46576, 2.47088, 2.45552, 2.47395, 2.4863, 2.44531, 2.48112, 2.46272, 2.45146, 2.49552, 2.4617, 2.46477, 2.48829, 2.45658, 2.49242, 2.45046, 2.45763, 2.4535, 2.47088, 2.43712, 2.48426, 2.52522, 2.52624, 2.5569, 2.50982, 2.49958, 2.51389, 2.48525, 2.53542, 2.53952, 2.50778, 2.50064, 2.47702, 2.49546, 2.50166, 2.47811, 2.47706, 2.47706, 2.49853, 2.47706, 2.4607, 2.52624, 2.48112, 2.50781, 2.48624, 2.50266, 2.49754, 2.48934, 2.47501, 2.48016, 2.48013, 2.4904, 2.50365, 2.50368, 2.50778, 2.52931, 2.50675, 2.49341, 2.52419, 2.50573, 2.49546, 2.49958, 2.49341, 2.50774, 2.51085, 2.5088, 2.53846, 2.55894, 2.51293, 2.50982, 2.50774, 2.516, 2.51389, 2.49958, 2.54051, 2.52928, 2.49341, 2.51907, 2.50266, 2.50778, 2.51494, 2.53542, 2.47504, 2.49754, 2.5047, 2.47293, 2.50166, 2.49549, 2.50163, 2.48624, 2.47501, 2.4791, 2.48624, 2.49446, 2.50371, 2.53235, 2.5088, 2.49651, 2.48525, 2.49754, 2.49757, 2.48118, 2.53034, 2.47395, 2.4873, 2.48218, 2.48829, 2.4873, 2.49549, 2.47501, 2.48317, 2.4873, 2.476, 2.45558, 2.48624, 2.48112, 2.48013, 2.46682, 2.47907, 2.48323, 2.49443, 2.47088, 2.48218, 2.49347, 2.49142, 2.50778, 2.49344, 2.47606, 2.49242, 2.49341, 2.48218, 2.49341, 2.4975, 2.516, 2.4801, 2.48218, 2.516, 2.4832, 2.48835, 2.46784, 2.47606, 2.50774, 2.4617, 2.48829, 2.4873, 2.49347, 2.47088, 2.5047, 2.47398, 2.51286, 2.49341, 2.48934, 2.52006, 2.49037, 2.49549, 2.48422, 2.49341, 2.50266, 2.48931, 2.47398, 2.47808, 2.49037, 2.52419, 2.51082, 2.49446, 2.48934, 2.48317, 2.50371, 2.48323, 2.52003, 2.49546, 2.48013, 2.49958, 2.50266, 2.4873, 2.50467, 2.48938, 2.4873, 2.49754, 2.49549, 2.48218, 2.48422, 2.48118, 2.48323, 2.48522, 2.48934, 2.48013, 2.4904, 2.49859, 2.50064, 2.49958, 2.48934, 2.50672, 2.53235, 2.48419, 2.48829, 2.49446, 2.5129, 2.48422, 2.49242, 2.50982, 2.47805, 2.47805, 2.47606, 2.49651, 2.52518, 2.52006, 2.51187, 2.47805, 2.4863, 2.49958, 2.52624, 2.4873, 2.50778, 2.48525, 2.48112, 2.47805, 2.48013, 2.49754, 2.50064, 2.48422, 2.49242, 2.47706, 2.48829, 2.50061, 2.52003, 2.48934, 2.47606, 2.50982, 2.49034, 2.50365, 2.47398, 2.5057, 2.50064, 2.50058, 2.46682, 2.48829, 2.49651, 2.47296, 2.48422, 2.49139, 2.48832, 2.48016, 2.47402, 2.47194, 2.4975, 2.46582, 2.49853, 2.48013, 2.4945, 2.5088, 2.48112, 2.52518, 2.50365, 2.4863, 2.48218, 2.48218, 2.48317, 2.51085, 2.47498, 2.50573, 2.49245, 2.47501, 2.48938, 2.49651, 2.4904, 2.49958, 2.50365, 2.49549, 2.51594, 2.4904, 2.49238, 2.48829, 2.49853, 2.50982, 2.50986, 2.49446, 2.49958, 2.5057, 2.48118, 2.49446, 2.51798, 2.476, 2.49651, 2.47194, 2.476, 2.49446, 2.46682, 2.49958, 2.48426, 2.476, 2.48934, 2.48016, 2.47907, 2.48016, 2.50675, 2.47194, 2.4975, 2.46989, 2.47402, 2.49958, 2.47094, 2.5057, 2.48323, 2.47402, 2.47805, 2.46477, 2.47094, 2.46682, 2.48627, 2.50573, 2.47706, 2.52006, 2.49034, 2.51286, 2.48835, 2.52006, 2.51392, 2.53539, 2.52618, 2.49651, 2.48938, 2.53952, 2.5047, 2.55082, 2.50061, 2.51293, 2.54976, 2.54566, 2.52723, 2.51798, 2.48627, 2.50064, 2.46582, 2.5016, 2.4791, 2.48627, 2.46989, 2.46989, 2.45354, 2.46378, 2.45245, 2.45661, 2.44736, 2.46576, 2.46275, 2.4791, 2.45965, 2.48016, 2.47299, 2.47088, 2.49654, 2.48934, 2.47194, 2.47094, 2.46989, 2.49341, 2.48013, 2.46886, 2.47706, 2.47706, 2.4791, 2.48422, 2.49242, 2.48013, 2.48317, 2.47808, 2.46685, 2.49136, 2.46378, 2.50064, 2.46682, 2.47606, 2.4873, 2.48317, 2.47504, 2.46272, 2.46477, 2.48013, 2.46682, 2.46883, 2.45965, 2.46989, 2.4873, 2.47296, 2.46269, 2.47805, 2.47504, 2.47808, 2.45866, 2.46374, 2.476, 2.4576, 2.47808, 2.46371, 2.45866, 2.49446, 2.47299, 2.48317, 2.45555, 2.46682, 2.48013, 2.46378, 2.49037, 2.47501, 2.43306, 2.4433, 2.43507, 2.44534, 2.43101, 2.42995, 2.40742, 2.44637, 2.41149, 2.47504, 2.41456, 2.42483, 2.44224, 2.42278, 2.41462, 2.45658, 2.42688, 2.43504, 2.42688, 2.43818, 2.42893, 2.42282, 2.4177, 2.42688, 2.40739, 2.4207, 2.41046, 2.61936, 2.60301, 2.61123, 2.59277, 2.62042, 2.60093, 2.61939, 2.59894, 2.60406, 2.61018, 2.60608, 2.59792, 2.6143, 2.59482, 2.65523, 2.60813, 2.66141, 2.63373, 2.61936, 2.59994, 2.59894, 2.58966, 2.63882, 2.61939, 2.62246, 2.58557, 2.59686, 2.63987, 2.6143, 2.61837, 2.62246, 2.58864, 2.61325, 2.60096, 2.61018, 2.57536, 2.62966, 2.59994, 2.60096, 2.61424, 2.61427, 2.58563, 2.59792, 2.60202, 2.62042, 2.5887, 2.59789, 2.6225, 2.62557, 2.41664, 2.44944, 2.43094, 2.4576, 2.41971, 2.42483, 2.41562, 2.42483, 2.4207, 2.44118, 2.41763, 2.42282, 2.40435, 2.44429, 2.41046, \nUpdate Exposure, 0.088064, 0.065536, 0.062464, 0.044, 0.045056, 0.065504, 0.065536, 0.066592, 0.044, 0.084992, 0.044064, 0.045056, 0.045056, 0.043008, 0.066592, 0.059392, 0.04608, 0.044, 0.044064, 0.044032, 0.071648, 0.052224, 0.043008, 0.089088, 0.044064, 0.053248, 0.086016, 0.044, 0.066528, 0.044032, 0.044064, 0.043008, 0.045056, 0.06448, 0.084992, 0.058368, 0.066528, 0.083936, 0.045056, 0.044, 0.044064, 0.045056, 0.045056, 0.044, 0.066592, 0.044064, 0.044, 0.067584, 0.066592, 0.047136, 0.044032, 0.088064, 0.051168, 0.066528, 0.044064, 0.044064, 0.066528, 0.084992, 0.044064, 0.065536, 0.044064, 0.067584, 0.045056, 0.044, 0.072704, 0.045056, 0.044, 0.04608, 0.067584, 0.048128, 0.045056, 0.045056, 0.045056, 0.086016, 0.04608, 0.065536, 0.045024, 0.045088, 0.072704, 0.067584, 0.067584, 0.045056, 0.045056, 0.045056, 0.04608, 0.045024, 0.067552, 0.074784, 0.046048, 0.046112, 0.045056, 0.067552, 0.047136, 0.070656, 0.046048, 0.045088, 0.046048, 0.04608, 0.063488, 0.064544, 0.045056, 0.068576, 0.06864, 0.060384, 0.045024, 0.047104, 0.045056, 0.045056, 0.046112, 0.046112, 0.045056, 0.04608, 0.047104, 0.076768, 0.046112, 0.046112, 0.047136, 0.047104, 0.068608, 0.045024, 0.04608, 0.047104, 0.048128, 0.046048, 0.047072, 0.046112, 0.046048, 0.069632, 0.071712, 0.04608, 0.067584, 0.04816, 0.049184, 0.047136, 0.049184, 0.047104, 0.070656, 0.04816, 0.050176, 0.04816, 0.048128, 0.066528, 0.04912, 0.047104, 0.049184, 0.051168, 0.050176, 0.080896, 0.051232, 0.050176, 0.051168, 0.051232, 0.052256, 0.051232, 0.04912, 0.051232, 0.047072, 0.04608, 0.04816, 0.046112, 0.045088, 0.045056, 0.046112, 0.04816, 0.04608, 0.046112, 0.045056, 0.04608, 0.04912, 0.048128, 0.046112, 0.047104, 0.045056, 0.04608, 0.068608, 0.047104, 0.047104, 0.047072, 0.046048, 0.06864, 0.087008, 0.045056, 0.051232, 0.047104, 0.047104, 0.055328, 0.047072, 0.048128, 0.068576, 0.046112, 0.046112, 0.04816, 0.052192, 0.045024, 0.04608, 0.046112, 0.046048, 0.045088, 0.068608, 0.047072, 0.046048, 0.047072, 0.057344, 0.057344, 0.048128, 0.04608, 0.046048, 0.064544, 0.06864, 0.064544, 0.047136, 0.092128, 0.088064, 0.059424, 0.049152, 0.050176, 0.052192, 0.049184, 0.052192, 0.048128, 0.049184, 0.049184, 0.04816, 0.048128, 0.067584, 0.04608, 0.056352, 0.085984, 0.058368, 0.045056, 0.066592, 0.045056, 0.044, 0.066592, 0.045056, 0.045056, 0.045056, 0.04608, 0.045056, 0.045056, 0.045056, 0.04608, 0.062464, 0.04608, 0.045056, 0.070624, 0.046048, 0.08192, 0.055296, 0.045056, 0.045056, 0.045056, 0.066528, 0.045056, 0.046112, 0.046112, 0.066592, 0.045056, 0.045056, 0.066528, 0.044, 0.04608, 0.06656, 0.045056, 0.045056, 0.066528, 0.044, 0.045056, 0.044064, 0.045088, 0.044, 0.045088, 0.046048, 0.044032, 0.058336, 0.067584, 0.044, 0.044064, 0.045056, 0.045056, 0.04608, 0.045056, 0.045056, 0.066592, 0.044064, 0.056352, 0.066592, 0.044064, 0.043008, 0.046112, 0.06864, 0.044, 0.044064, 0.044064, 0.069632, 0.052224, 0.044, 0.043008, 0.045056, 0.066592, 0.044064, 0.045056, 0.044, 0.066592, 0.044064, 0.067584, 0.044, 0.045088, 0.044032, 0.044064, 0.044064, 0.045056, 0.057344, 0.045056, 0.092192, 0.04608, 0.044064, 0.045056, 0.045056, 0.04608, 0.086048, 0.045056, 0.069632, 0.04608, 0.068608, 0.046112, 0.048128, 0.069632, 0.046112, 0.045056, 0.046112, 0.072704, 0.065536, 0.072704, 0.048128, 0.045056, 0.045056, 0.045056, 0.045056, 0.044064, 0.044, 0.084992, 0.047136, 0.044032, 0.06352, 0.045056, 0.044, 0.044064, 0.067584, 0.044064, 0.044064, 0.044, 0.044, 0.043008, 0.045056, 0.059424, 0.044, 0.044032, 0.045056, 0.044032, 0.043008, 0.045056, 0.044064, 0.067584, 0.042976, 0.066592, 0.044064, 0.066592, 0.063488, 0.043008, 0.066592, 0.065504, 0.045056, 0.044, 0.066592, 0.044, 0.044064, 0.044032, 0.045056, 0.045056, 0.044064, 0.044064, 0.046112, 0.044064, 0.045056, 0.045056, 0.045024, 0.044, 0.044, 0.044064, 0.045056, 0.044, 0.044064, 0.044064, 0.044064, 0.044064, 0.044064, 0.041952, 0.066592, 0.044, 0.063456, 0.04608, 0.044, 0.066592, 0.065536, 0.062496, 0.066592, 0.044064, 0.043008, 0.045056, 0.044064, 0.044, 0.043008, 0.084992, 0.0584, 0.045056, 0.045056, 0.044, 0.046048, 0.066528, 0.061472, 0.043008, 0.044, 0.045056, 0.044064, 0.04304, 0.043008, 0.044, 0.044032, 0.06448, 0.045024, 0.044032, 0.058368, 0.045056, 0.0584, 0.044, 0.044, 0.071712, 0.087072, 0.065504, 0.066528, 0.043008, 0.066592, 0.044064, 0.066592, 0.044064, 0.044064, 0.066592, 0.04304, 0.046112, 0.043008, 0.044, 0.044, 0.045056, 0.045056, 0.044, 0.044, 0.044, 0.043008, 0.044064, 0.045056, 0.044032, 0.044032, 0.066592, 0.044, 0.044, 0.044064, 0.042976, 0.044064, 0.044032, 0.044, 0.044064, 0.044064, 0.044064, 0.044, 0.044, 0.044064, 0.044, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.045024, 0.044064, 0.066592, 0.044064, 0.044, 0.044, 0.044064, 0.045056, 0.066528, 0.058368, 0.045056, 0.066528, 0.045056, 0.046112, 0.044, \nUpdate State, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \nZ PrePass, 0.573472, 0.57136, 0.576512, 0.567328, 0.575488, 0.568352, 0.575456, 0.573408, 0.575456, 0.571424, 0.577536, 0.567296, 0.575456, 0.568352, 0.582656, 0.566272, 0.575488, 0.567296, 0.576544, 0.567296, 0.576512, 0.568288, 0.579584, 0.568288, 0.574464, 0.567296, 0.57648, 0.567296, 0.576544, 0.568352, 0.57648, 0.566304, 0.581632, 0.56624, 0.576512, 0.567296, 0.575456, 0.567328, 0.57552, 0.56624, 0.581632, 0.567296, 0.576512, 0.568288, 0.576512, 0.567296, 0.576544, 0.567296, 0.574464, 0.567296, 0.577536, 0.567296, 0.577536, 0.5704, 0.574464, 0.567296, 0.57552, 0.566304, 0.576544, 0.567296, 0.583712, 0.569312, 0.57648, 0.566304, 0.574464, 0.567296, 0.577536, 0.577536, 0.578528, 0.566272, 0.572416, 0.564256, 0.571424, 0.55296, 0.558112, 0.545792, 0.561184, 0.530432, 0.526336, 0.512992, 0.52432, 0.516128, 0.52528, 0.515072, 0.528416, 0.521216, 0.532448, 0.52736, 0.539648, 0.534528, 0.549888, 0.54064, 0.54784, 0.536576, 0.5448, 0.530432, 0.534528, 0.526336, 0.539648, 0.539616, 0.560128, 0.555008, 0.567296, 0.564256, 0.582656, 0.574464, 0.587808, 0.575488, 0.589824, 0.570368, 0.561152, 0.54064, 0.541664, 0.519168, 0.518176, 0.498656, 0.496608, 0.47824, 0.483328, 0.468992, 0.473056, 0.451584, 0.447488, 0.431136, 0.437248, 0.413664, 0.41776, 0.407552, 0.417792, 0.405472, 0.418816, 0.405472, 0.410624, 0.39936, 0.406528, 0.38912, 0.401408, 0.382944, 0.39216, 0.384992, 0.392192, 0.382944, 0.391168, 0.380928, 0.390176, 0.37888, 0.388064, 0.379872, 0.397312, 0.390112, 0.393248, 0.384, 0.392192, 0.38192, 0.39936, 0.386048, 0.39728, 0.403424, 0.40448, 0.38912, 0.399328, 0.390112, 0.400352, 0.403456, 0.397344, 0.384, 0.396288, 0.384, 0.398304, 0.383008, 0.393248, 0.379872, 0.400416, 0.38912, 0.393216, 0.380928, 0.401408, 0.387072, 0.4024, 0.388096, 0.398304, 0.392192, 0.405472, 0.389152, 0.4024, 0.39216, 0.406528, 0.390176, 0.401408, 0.39216, 0.405536, 0.387104, 0.41264, 0.37888, 0.386048, 0.374816, 0.387072, 0.381952, 0.384, 0.375808, 0.381984, 0.37072, 0.381952, 0.375808, 0.379936, 0.377888, 0.384992, 0.37376, 0.386048, 0.371712, 0.385024, 0.3912, 0.388064, 0.379872, 0.38608, 0.37888, 0.388128, 0.37072, 0.374784, 0.356352, 0.364576, 0.357376, 0.366592, 0.355328, 0.363488, 0.351232, 0.355296, 0.34096, 0.351232, 0.34096, 0.354304, 0.338944, 0.344064, 0.333824, 0.347168, 0.331776, 0.347168, 0.33488, 0.338944, 0.323584, 0.331776, 0.31536, 0.328704, 0.323584, 0.328704, 0.31952, 0.333824, 0.314368, 0.323584, 0.303104, 0.31024, 0.291808, 0.303072, 0.294944, 0.313312, 0.290816, 0.301056, 0.290816, 0.301024, 0.294912, 0.303072, 0.28976, 0.301056, 0.296928, 0.30928, 0.296928, 0.307168, 0.29696, 0.318464, 0.297952, 0.313312, 0.302112, 0.310272, 0.301056, 0.318464, 0.310272, 0.317472, 0.311296, 0.321536, 0.295968, 0.304128, 0.289824, 0.303136, 0.287744, 0.293888, 0.27648, 0.284704, 0.278528, 0.290816, 0.276512, 0.290816, 0.27648, 0.285728, 0.272416, 0.283648, 0.280576, 0.285664, 0.2744, 0.289824, 0.277536, 0.286752, 0.277472, 0.293856, 0.278528, 0.290816, 0.285664, 0.30208, 0.295968, 0.318464, 0.308192, 0.317472, 0.307232, 0.33488, 0.310304, 0.314336, 0.305184, 0.324608, 0.319488, 0.346112, 0.344064, 0.372768, 0.387104, 0.416768, 0.412704, 0.42288, 0.419808, 0.439296, 0.42704, 0.43824, 0.444416, 0.4936, 0.497664, 0.523296, 0.528416, 0.55808, 0.58576, 0.595936, 0.593888, 0.603104, 0.598016, 0.618528, 0.61952, 0.628704, 0.625696, 0.631808, 0.642048, 0.637952, 0.62976, 0.64, 0.659424, 0.649184, 0.63488, 0.652288, 0.646112, 0.651264, 0.648192, 0.653344, 0.645152, 0.657408, 0.648224, 0.659456, 0.65024, 0.66048, 0.65024, 0.669696, 0.654336, 0.66352, 0.647168, 0.66864, 0.648192, 0.659488, 0.647168, 0.657408, 0.649184, 0.659456, 0.648224, 0.656384, 0.649248, 0.658464, 0.65024, 0.657408, 0.64512, 0.654368, 0.65024, 0.658464, 0.652288, 0.659456, 0.646176, 0.6656, 0.649248, 0.665568, 0.647168, 0.654336, 0.660448, 0.663552, 0.654336, 0.658464, 0.652288, 0.662528, 0.649216, 0.661536, 0.646176, 0.659424, 0.652288, 0.66048, 0.65024, 0.656416, 0.646144, 0.662528, 0.657376, 0.656416, 0.644064, 0.6656, 0.651296, 0.656352, 0.649184, 0.65744, 0.656352, 0.662528, 0.65024, 0.659424, 0.657408, 0.6656, 0.649216, 0.662528, 0.644128, 0.658432, 0.651232, 0.662528, 0.647168, 0.656352, 0.65024, 0.656352, 0.65536, 0.653344, 0.64512, 0.6584, 0.654368, 0.65024, 0.64512, 0.65024, 0.646112, 0.6584, 0.643072, 0.651296, 0.64512, 0.65328, 0.64, 0.651232, 0.640992, 0.657408, 0.64512, 0.651264, 0.641056, 0.65024, 0.64512, 0.653344, 0.651232, 0.65024, 0.641024, 0.656352, 0.646112, 0.649216, 0.656352, 0.65024, 0.646112, 0.654336, 0.64, 0.65536, 0.64512, 0.654336, 0.640992, 0.65024, 0.642048, 0.656352, 0.657408, 0.654368, 0.63792, 0.65024, 0.644064, 0.653344, 0.64, 0.65024, 0.64, 0.654368, 0.654304, 0.649216, 0.642048, 0.65024, 0.64512, 0.652288, 0.64, 0.657408, 0.654304, 0.673824, 0.64, 0.66048, 0.648192, 0.656416, 0.648192, 0.65744, 0.648192, 0.651232, 0.644096, 0.652256, 0.640992, 0.649216, 0.64, 0.658464, 0.64512, 0.651296, 0.64, 0.65024, 0.64512, 0.67584, 0.64, 0.65024, 0.644064, 0.666656, 0.638944, 0.65536, 0.647168, 0.654304, 0.646112, 0.649248, 0.64, 0.655392, 0.643072, 0.653344, 0.641056, 0.65024, 0.644064, 0.662528, 0.651232, 0.648192, 0.641056, 0.649216, 0.644064, 0.653344, 0.640992, 0.649216, 0.646176, \n"
  },
  {
    "path": "MiniEngine/PropertySheets/Debug.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>false</MinimalRebuild>\n      <Optimization>Disabled</Optimization>\n      <BufferSecurityCheck>true</BufferSecurityCheck>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <OptimizeReferences>false</OptimizeReferences>\n      <UACExecutionLevel>AsInvoker</UACExecutionLevel>\n    </Link>\n    <FxCompile>\n      <EnableDebuggingInformation>true</EnableDebuggingInformation>\n      <DisableOptimizations>false</DisableOptimizations>\n    </FxCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/PropertySheets/OrganizedBuild.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup />\n  <ItemDefinitionGroup />\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/PropertySheets/Profile.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>NDEBUG;PROFILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\n      <Optimization>MaxSpeed</Optimization>\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n      <BasicRuntimeChecks>Default</BasicRuntimeChecks>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <OptimizeReferences>false</OptimizeReferences>\n      <UACExecutionLevel>AsInvoker</UACExecutionLevel>\n    </Link>\n    <FxCompile>\n      <EnableDebuggingInformation>true</EnableDebuggingInformation>\n      <DisableOptimizations>false</DisableOptimizations>\n    </FxCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/PropertySheets/Release.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <LinkIncremental>false</LinkIncremental>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>NDEBUG;RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\n      <Optimization>MaxSpeed</Optimization>\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n      <BasicRuntimeChecks>Default</BasicRuntimeChecks>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>false</GenerateDebugInformation>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n    <FxCompile>\n      <EnableDebuggingInformation>false</EnableDebuggingInformation>\n      <DisableOptimizations>false</DisableOptimizations>\n    </FxCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/PropertySheets/UWP.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <GenerateManifest>false</GenerateManifest>\n  </PropertyGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ApplicationEnvironment>title</ApplicationEnvironment>\n    <DefaultLanguage>en-US</DefaultLanguage>\n    <PlatformToolset>v140</PlatformToolset>\n    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\n\t<Keyword>StaticLibrary</Keyword>\n    <AppContainerApplication>true</AppContainerApplication>\n    <ApplicationType>Windows Store</ApplicationType>\n    <WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>\n    <WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>\n    <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\n\t<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>\n\t<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>\n  </PropertyGroup>\n  <PropertyGroup Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n  </PropertyGroup>\n  \n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <CompileAsWinRT>false</CompileAsWinRT>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>\n      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>\n    </Link>\n  </ItemDefinitionGroup>\n  \n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/PropertySheets/VS17.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <OutDir>$(SolutionDir)..\\Build_VS17\\$(Platform)\\$(Configuration)\\Output\\$(ProjectName)\\</OutDir>\n    <IntDir>$(SolutionDir)..\\Build_VS17\\$(Platform)\\$(Configuration)\\Intermediate\\$(ProjectName)\\</IntDir>\n    <IncludePath>$(SolutionDir)..\\Build_VS17\\$(Platform)\\$(Configuration)\\Output\\$(ProjectName);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <AdditionalIncludeDirectories>..\\Core</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <WarningLevel>Level3</WarningLevel>\n      <ExceptionHandling>Sync</ExceptionHandling>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <FloatingPointModel>Fast</FloatingPointModel>\n    </ClCompile>\n    <Link>\n      <LargeAddressAware>true</LargeAddressAware>\n      <RandomizedBaseAddress>true</RandomizedBaseAddress>\n      <DataExecutionPrevention>true</DataExecutionPrevention>\n      <SubSystem>Console</SubSystem>\n    </Link>\n    <Lib>\n      <AdditionalOptions>/IGNORE:4221 %(AdditionalOptions)</AdditionalOptions>\n    </Lib>\n    <FxCompile>\n      <ShaderType>Compute</ShaderType>\n      <ShaderModel>5.0</ShaderModel>\n      <VariableName>g_p%(Filename)</VariableName>\n      <HeaderFileOutput>$(SolutionDir)..\\Build_VS17\\$(Platform)\\$(Configuration)\\Output\\$(ProjectName)\\CompiledShaders\\%(Filename).h</HeaderFileOutput>\n\t  <ObjectFileOutput>$(SolutionDir)..\\Build_VS17\\$(Platform)\\$(Configuration)\\Output\\$(ProjectName)\\Shaders\\%(Filename).cso</ObjectFileOutput>\n    </FxCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/PropertySheets/Win32.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\" />\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <GenerateManifest>true</GenerateManifest>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>_WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup />\n</Project>"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/allocators.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ALLOCATORS_H_\r\n#define RAPIDJSON_ALLOCATORS_H_\r\n\r\n#include \"rapidjson.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Allocator\r\n\r\n/*! \\class rapidjson::Allocator\r\n    \\brief Concept for allocating, resizing and freeing memory block.\r\n    \r\n    Note that Malloc() and Realloc() are non-static but Free() is static.\r\n    \r\n    So if an allocator need to support Free(), it needs to put its pointer in \r\n    the header of memory block.\r\n\r\n\\code\r\nconcept Allocator {\r\n    static const bool kNeedFree;    //!< Whether this allocator needs to call Free().\r\n\r\n    // Allocate a memory block.\r\n    // \\param size of the memory block in bytes.\r\n    // \\returns pointer to the memory block.\r\n    void* Malloc(size_t size);\r\n\r\n    // Resize a memory block.\r\n    // \\param originalPtr The pointer to current memory block. Null pointer is permitted.\r\n    // \\param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)\r\n    // \\param newSize the new size in bytes.\r\n    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);\r\n\r\n    // Free a memory block.\r\n    // \\param pointer to the memory block. Null pointer is permitted.\r\n    static void Free(void *ptr);\r\n};\r\n\\endcode\r\n*/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// CrtAllocator\r\n\r\n//! C-runtime library allocator.\r\n/*! This class is just wrapper for standard C library memory routines.\r\n    \\note implements Allocator concept\r\n*/\r\nclass CrtAllocator {\r\npublic:\r\n    static const bool kNeedFree = true;\r\n    void* Malloc(size_t size) { \r\n        if (size) //  behavior of malloc(0) is implementation defined.\r\n            return std::malloc(size);\r\n        else\r\n            return NULL; // standardize to returning NULL.\r\n    }\r\n    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {\r\n        (void)originalSize;\r\n        if (newSize == 0) {\r\n            std::free(originalPtr);\r\n            return NULL;\r\n        }\r\n        return std::realloc(originalPtr, newSize);\r\n    }\r\n    static void Free(void *ptr) { std::free(ptr); }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// MemoryPoolAllocator\r\n\r\n//! Default memory allocator used by the parser and DOM.\r\n/*! This allocator allocate memory blocks from pre-allocated memory chunks. \r\n\r\n    It does not free memory blocks. And Realloc() only allocate new memory.\r\n\r\n    The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.\r\n\r\n    User may also supply a buffer as the first chunk.\r\n\r\n    If the user-buffer is full then additional chunks are allocated by BaseAllocator.\r\n\r\n    The user-buffer is not deallocated by this allocator.\r\n\r\n    \\tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.\r\n    \\note implements Allocator concept\r\n*/\r\ntemplate <typename BaseAllocator = CrtAllocator>\r\nclass MemoryPoolAllocator {\r\npublic:\r\n    static const bool kNeedFree = false;    //!< Tell users that no need to call Free() with this allocator. (concept Allocator)\r\n\r\n    //! Constructor with chunkSize.\r\n    /*! \\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.\r\n        \\param baseAllocator The allocator for allocating memory chunks.\r\n    */\r\n    MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : \r\n        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)\r\n    {\r\n    }\r\n\r\n    //! Constructor with user-supplied buffer.\r\n    /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.\r\n\r\n        The user buffer will not be deallocated when this allocator is destructed.\r\n\r\n        \\param buffer User supplied buffer.\r\n        \\param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).\r\n        \\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.\r\n        \\param baseAllocator The allocator for allocating memory chunks.\r\n    */\r\n    MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :\r\n        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)\r\n    {\r\n        RAPIDJSON_ASSERT(buffer != 0);\r\n        RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));\r\n        chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);\r\n        chunkHead_->capacity = size - sizeof(ChunkHeader);\r\n        chunkHead_->size = 0;\r\n        chunkHead_->next = 0;\r\n    }\r\n\r\n    //! Destructor.\r\n    /*! This deallocates all memory chunks, excluding the user-supplied buffer.\r\n    */\r\n    ~MemoryPoolAllocator() {\r\n        Clear();\r\n        RAPIDJSON_DELETE(ownBaseAllocator_);\r\n    }\r\n\r\n    //! Deallocates all memory chunks, excluding the user-supplied buffer.\r\n    void Clear() {\r\n        while (chunkHead_ && chunkHead_ != userBuffer_) {\r\n            ChunkHeader* next = chunkHead_->next;\r\n            baseAllocator_->Free(chunkHead_);\r\n            chunkHead_ = next;\r\n        }\r\n        if (chunkHead_ && chunkHead_ == userBuffer_)\r\n            chunkHead_->size = 0; // Clear user buffer\r\n    }\r\n\r\n    //! Computes the total capacity of allocated memory chunks.\r\n    /*! \\return total capacity in bytes.\r\n    */\r\n    size_t Capacity() const {\r\n        size_t capacity = 0;\r\n        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)\r\n            capacity += c->capacity;\r\n        return capacity;\r\n    }\r\n\r\n    //! Computes the memory blocks allocated.\r\n    /*! \\return total used bytes.\r\n    */\r\n    size_t Size() const {\r\n        size_t size = 0;\r\n        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)\r\n            size += c->size;\r\n        return size;\r\n    }\r\n\r\n    //! Allocates a memory block. (concept Allocator)\r\n    void* Malloc(size_t size) {\r\n        if (!size)\r\n            return NULL;\r\n\r\n        size = RAPIDJSON_ALIGN(size);\r\n        if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)\r\n            if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))\r\n                return NULL;\r\n\r\n        void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;\r\n        chunkHead_->size += size;\r\n        return buffer;\r\n    }\r\n\r\n    //! Resizes a memory block (concept Allocator)\r\n    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {\r\n        if (originalPtr == 0)\r\n            return Malloc(newSize);\r\n\r\n        if (newSize == 0)\r\n            return NULL;\r\n\r\n        originalSize = RAPIDJSON_ALIGN(originalSize);\r\n        newSize = RAPIDJSON_ALIGN(newSize);\r\n\r\n        // Do not shrink if new size is smaller than original\r\n        if (originalSize >= newSize)\r\n            return originalPtr;\r\n\r\n        // Simply expand it if it is the last allocation and there is sufficient space\r\n        if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {\r\n            size_t increment = static_cast<size_t>(newSize - originalSize);\r\n            if (chunkHead_->size + increment <= chunkHead_->capacity) {\r\n                chunkHead_->size += increment;\r\n                return originalPtr;\r\n            }\r\n        }\r\n\r\n        // Realloc process: allocate and copy memory, do not free original buffer.\r\n        if (void* newBuffer = Malloc(newSize)) {\r\n            if (originalSize)\r\n                std::memcpy(newBuffer, originalPtr, originalSize);\r\n            return newBuffer;\r\n        }\r\n        else\r\n            return NULL;\r\n    }\r\n\r\n    //! Frees a memory block (concept Allocator)\r\n    static void Free(void *ptr) { (void)ptr; } // Do nothing\r\n\r\nprivate:\r\n    //! Copy constructor is not permitted.\r\n    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;\r\n    //! Copy assignment operator is not permitted.\r\n    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;\r\n\r\n    //! Creates a new chunk.\r\n    /*! \\param capacity Capacity of the chunk in bytes.\r\n        \\return true if success.\r\n    */\r\n    bool AddChunk(size_t capacity) {\r\n        if (!baseAllocator_)\r\n            ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();\r\n        if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {\r\n            chunk->capacity = capacity;\r\n            chunk->size = 0;\r\n            chunk->next = chunkHead_;\r\n            chunkHead_ =  chunk;\r\n            return true;\r\n        }\r\n        else\r\n            return false;\r\n    }\r\n\r\n    static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.\r\n\r\n    //! Chunk header for perpending to each chunk.\r\n    /*! Chunks are stored as a singly linked list.\r\n    */\r\n    struct ChunkHeader {\r\n        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).\r\n        size_t size;        //!< Current size of allocated memory in bytes.\r\n        ChunkHeader *next;  //!< Next chunk in the linked list.\r\n    };\r\n\r\n    ChunkHeader *chunkHead_;    //!< Head of the chunk linked-list. Only the head chunk serves allocation.\r\n    size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated.\r\n    void *userBuffer_;          //!< User supplied buffer.\r\n    BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks.\r\n    BaseAllocator* ownBaseAllocator_;   //!< base allocator created by this object.\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_ENCODINGS_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/cursorstreamwrapper.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n//\r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed\r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_\r\n#define RAPIDJSON_CURSORSTREAMWRAPPER_H_\r\n\r\n#include \"stream.h\"\r\n\r\n#if defined(__GNUC__)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n\r\n#if defined(_MSC_VER) && _MSC_VER <= 1800\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4702)  // unreachable code\r\nRAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n\r\n//! Cursor stream wrapper for counting line and column number if error exists.\r\n/*!\r\n    \\tparam InputStream     Any stream that implements Stream Concept\r\n*/\r\ntemplate <typename InputStream, typename Encoding = UTF8<> >\r\nclass CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {\r\npublic:\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    CursorStreamWrapper(InputStream& is):\r\n        GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}\r\n\r\n    // counting line and column number\r\n    Ch Take() {\r\n        Ch ch = this->is_.Take();\r\n        if(ch == '\\n') {\r\n            line_ ++;\r\n            col_ = 0;\r\n        } else {\r\n            col_ ++;\r\n        }\r\n        return ch;\r\n    }\r\n\r\n    //! Get the error line number, if error exists.\r\n    size_t GetLine() const { return line_; }\r\n    //! Get the error column number, if error exists.\r\n    size_t GetColumn() const { return col_; }\r\n\r\nprivate:\r\n    size_t line_;   //!< Current Line\r\n    size_t col_;    //!< Current Column\r\n};\r\n\r\n#if defined(_MSC_VER) && _MSC_VER <= 1800\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#if defined(__GNUC__)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/document.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_DOCUMENT_H_\r\n#define RAPIDJSON_DOCUMENT_H_\r\n\r\n/*! \\file document.h */\r\n\r\n#include \"reader.h\"\r\n#include \"internal/meta.h\"\r\n#include \"internal/strfunc.h\"\r\n#include \"memorystream.h\"\r\n#include \"encodedstream.h\"\r\n#include <new>      // placement new\r\n#include <limits>\r\n\r\nRAPIDJSON_DIAG_PUSH\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_OFF(4127) // conditional expression is constant\r\nRAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_OFF(padded)\r\nRAPIDJSON_DIAG_OFF(switch-enum)\r\nRAPIDJSON_DIAG_OFF(c++98-compat)\r\n#endif\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#if __GNUC__ >= 6\r\nRAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions\r\n#endif\r\n#endif // __GNUC__\r\n\r\n#ifndef RAPIDJSON_NOMEMBERITERATORCLASS\r\n#include <iterator> // std::random_access_iterator_tag\r\n#endif\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n#include <utility> // std::move\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n// Forward declaration.\r\ntemplate <typename Encoding, typename Allocator>\r\nclass GenericValue;\r\n\r\ntemplate <typename Encoding, typename Allocator, typename StackAllocator>\r\nclass GenericDocument;\r\n\r\n//! Name-value pair in a JSON object value.\r\n/*!\r\n    This class was internal to GenericValue. It used to be a inner struct.\r\n    But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.\r\n    https://code.google.com/p/rapidjson/issues/detail?id=64\r\n*/\r\ntemplate <typename Encoding, typename Allocator> \r\nstruct GenericMember { \r\n    GenericValue<Encoding, Allocator> name;     //!< name of member (must be a string)\r\n    GenericValue<Encoding, Allocator> value;    //!< value of member.\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericMemberIterator\r\n\r\n#ifndef RAPIDJSON_NOMEMBERITERATORCLASS\r\n\r\n//! (Constant) member iterator for a JSON object value\r\n/*!\r\n    \\tparam Const Is this a constant iterator?\r\n    \\tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)\r\n    \\tparam Allocator   Allocator type for allocating memory of object, array and string.\r\n\r\n    This class implements a Random Access Iterator for GenericMember elements\r\n    of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].\r\n\r\n    \\note This iterator implementation is mainly intended to avoid implicit\r\n        conversions from iterator values to \\c NULL,\r\n        e.g. from GenericValue::FindMember.\r\n\r\n    \\note Define \\c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a\r\n        pointer-based implementation, if your platform doesn't provide\r\n        the C++ <iterator> header.\r\n\r\n    \\see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator\r\n */\r\ntemplate <bool Const, typename Encoding, typename Allocator>\r\nclass GenericMemberIterator {\r\n\r\n    friend class GenericValue<Encoding,Allocator>;\r\n    template <bool, typename, typename> friend class GenericMemberIterator;\r\n\r\n    typedef GenericMember<Encoding,Allocator> PlainType;\r\n    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;\r\n\r\npublic:\r\n    //! Iterator type itself\r\n    typedef GenericMemberIterator Iterator;\r\n    //! Constant iterator type\r\n    typedef GenericMemberIterator<true,Encoding,Allocator>  ConstIterator;\r\n    //! Non-constant iterator type\r\n    typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;\r\n\r\n    /** \\name std::iterator_traits support */\r\n    //@{\r\n    typedef ValueType      value_type;\r\n    typedef ValueType *    pointer;\r\n    typedef ValueType &    reference;\r\n    typedef std::ptrdiff_t difference_type;\r\n    typedef std::random_access_iterator_tag iterator_category;\r\n    //@}\r\n\r\n    //! Pointer to (const) GenericMember\r\n    typedef pointer         Pointer;\r\n    //! Reference to (const) GenericMember\r\n    typedef reference       Reference;\r\n    //! Signed integer type (e.g. \\c ptrdiff_t)\r\n    typedef difference_type DifferenceType;\r\n\r\n    //! Default constructor (singular value)\r\n    /*! Creates an iterator pointing to no element.\r\n        \\note All operations, except for comparisons, are undefined on such values.\r\n     */\r\n    GenericMemberIterator() : ptr_() {}\r\n\r\n    //! Iterator conversions to more const\r\n    /*!\r\n        \\param it (Non-const) iterator to copy from\r\n\r\n        Allows the creation of an iterator from another GenericMemberIterator\r\n        that is \"less const\".  Especially, creating a non-constant iterator\r\n        from a constant iterator are disabled:\r\n        \\li const -> non-const (not ok)\r\n        \\li const -> const (ok)\r\n        \\li non-const -> const (ok)\r\n        \\li non-const -> non-const (ok)\r\n\r\n        \\note If the \\c Const template parameter is already \\c false, this\r\n            constructor effectively defines a regular copy-constructor.\r\n            Otherwise, the copy constructor is implicitly defined.\r\n    */\r\n    GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}\r\n    Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }\r\n\r\n    //! @name stepping\r\n    //@{\r\n    Iterator& operator++(){ ++ptr_; return *this; }\r\n    Iterator& operator--(){ --ptr_; return *this; }\r\n    Iterator  operator++(int){ Iterator old(*this); ++ptr_; return old; }\r\n    Iterator  operator--(int){ Iterator old(*this); --ptr_; return old; }\r\n    //@}\r\n\r\n    //! @name increment/decrement\r\n    //@{\r\n    Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }\r\n    Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }\r\n\r\n    Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }\r\n    Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }\r\n    //@}\r\n\r\n    //! @name relations\r\n    //@{\r\n    bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }\r\n    bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }\r\n    bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }\r\n    bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }\r\n    bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }\r\n    bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }\r\n    //@}\r\n\r\n    //! @name dereference\r\n    //@{\r\n    Reference operator*() const { return *ptr_; }\r\n    Pointer   operator->() const { return ptr_; }\r\n    Reference operator[](DifferenceType n) const { return ptr_[n]; }\r\n    //@}\r\n\r\n    //! Distance\r\n    DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }\r\n\r\nprivate:\r\n    //! Internal constructor from plain pointer\r\n    explicit GenericMemberIterator(Pointer p) : ptr_(p) {}\r\n\r\n    Pointer ptr_; //!< raw pointer\r\n};\r\n\r\n#else // RAPIDJSON_NOMEMBERITERATORCLASS\r\n\r\n// class-based member iterator implementation disabled, use plain pointers\r\n\r\ntemplate <bool Const, typename Encoding, typename Allocator>\r\nstruct GenericMemberIterator;\r\n\r\n//! non-const GenericMemberIterator\r\ntemplate <typename Encoding, typename Allocator>\r\nstruct GenericMemberIterator<false,Encoding,Allocator> {\r\n    //! use plain pointer as iterator type\r\n    typedef GenericMember<Encoding,Allocator>* Iterator;\r\n};\r\n//! const GenericMemberIterator\r\ntemplate <typename Encoding, typename Allocator>\r\nstruct GenericMemberIterator<true,Encoding,Allocator> {\r\n    //! use plain const pointer as iterator type\r\n    typedef const GenericMember<Encoding,Allocator>* Iterator;\r\n};\r\n\r\n#endif // RAPIDJSON_NOMEMBERITERATORCLASS\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericStringRef\r\n\r\n//! Reference to a constant string (not taking a copy)\r\n/*!\r\n    \\tparam CharType character type of the string\r\n\r\n    This helper class is used to automatically infer constant string\r\n    references for string literals, especially from \\c const \\b (!)\r\n    character arrays.\r\n\r\n    The main use is for creating JSON string values without copying the\r\n    source string via an \\ref Allocator.  This requires that the referenced\r\n    string pointers have a sufficient lifetime, which exceeds the lifetime\r\n    of the associated GenericValue.\r\n\r\n    \\b Example\r\n    \\code\r\n    Value v(\"foo\");   // ok, no need to copy & calculate length\r\n    const char foo[] = \"foo\";\r\n    v.SetString(foo); // ok\r\n\r\n    const char* bar = foo;\r\n    // Value x(bar); // not ok, can't rely on bar's lifetime\r\n    Value x(StringRef(bar)); // lifetime explicitly guaranteed by user\r\n    Value y(StringRef(bar, 3));  // ok, explicitly pass length\r\n    \\endcode\r\n\r\n    \\see StringRef, GenericValue::SetString\r\n*/\r\ntemplate<typename CharType>\r\nstruct GenericStringRef {\r\n    typedef CharType Ch; //!< character type of the string\r\n\r\n    //! Create string reference from \\c const character array\r\n#ifndef __clang__ // -Wdocumentation\r\n    /*!\r\n        This constructor implicitly creates a constant string reference from\r\n        a \\c const character array.  It has better performance than\r\n        \\ref StringRef(const CharType*) by inferring the string \\ref length\r\n        from the array length, and also supports strings containing null\r\n        characters.\r\n\r\n        \\tparam N length of the string, automatically inferred\r\n\r\n        \\param str Constant character array, lifetime assumed to be longer\r\n            than the use of the string in e.g. a GenericValue\r\n\r\n        \\post \\ref s == str\r\n\r\n        \\note Constant complexity.\r\n        \\note There is a hidden, private overload to disallow references to\r\n            non-const character arrays to be created via this constructor.\r\n            By this, e.g. function-scope arrays used to be filled via\r\n            \\c snprintf are excluded from consideration.\r\n            In such cases, the referenced string should be \\b copied to the\r\n            GenericValue instead.\r\n     */\r\n#endif\r\n    template<SizeType N>\r\n    GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT\r\n        : s(str), length(N-1) {}\r\n\r\n    //! Explicitly create string reference from \\c const character pointer\r\n#ifndef __clang__ // -Wdocumentation\r\n    /*!\r\n        This constructor can be used to \\b explicitly  create a reference to\r\n        a constant string pointer.\r\n\r\n        \\see StringRef(const CharType*)\r\n\r\n        \\param str Constant character pointer, lifetime assumed to be longer\r\n            than the use of the string in e.g. a GenericValue\r\n\r\n        \\post \\ref s == str\r\n\r\n        \\note There is a hidden, private overload to disallow references to\r\n            non-const character arrays to be created via this constructor.\r\n            By this, e.g. function-scope arrays used to be filled via\r\n            \\c snprintf are excluded from consideration.\r\n            In such cases, the referenced string should be \\b copied to the\r\n            GenericValue instead.\r\n     */\r\n#endif\r\n    explicit GenericStringRef(const CharType* str)\r\n        : s(str), length(NotNullStrLen(str)) {}\r\n\r\n    //! Create constant string reference from pointer and length\r\n#ifndef __clang__ // -Wdocumentation\r\n    /*! \\param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue\r\n        \\param len length of the string, excluding the trailing NULL terminator\r\n\r\n        \\post \\ref s == str && \\ref length == len\r\n        \\note Constant complexity.\r\n     */\r\n#endif\r\n    GenericStringRef(const CharType* str, SizeType len)\r\n        : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }\r\n\r\n    GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}\r\n\r\n    //! implicit conversion to plain CharType pointer\r\n    operator const Ch *() const { return s; }\r\n\r\n    const Ch* const s; //!< plain CharType pointer\r\n    const SizeType length; //!< length of the string (excluding the trailing NULL terminator)\r\n\r\nprivate:\r\n    SizeType NotNullStrLen(const CharType* str) {\r\n        RAPIDJSON_ASSERT(str != 0);\r\n        return internal::StrLen(str);\r\n    }\r\n\r\n    /// Empty string - used when passing in a NULL pointer\r\n    static const Ch emptyString[];\r\n\r\n    //! Disallow construction from non-const array\r\n    template<SizeType N>\r\n    GenericStringRef(CharType (&str)[N]) /* = delete */;\r\n    //! Copy assignment operator not permitted - immutable type\r\n    GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;\r\n};\r\n\r\ntemplate<typename CharType>\r\nconst CharType GenericStringRef<CharType>::emptyString[] = { CharType() };\r\n\r\n//! Mark a character pointer as constant string\r\n/*! Mark a plain character pointer as a \"string literal\".  This function\r\n    can be used to avoid copying a character string to be referenced as a\r\n    value in a JSON GenericValue object, if the string's lifetime is known\r\n    to be valid long enough.\r\n    \\tparam CharType Character type of the string\r\n    \\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue\r\n    \\return GenericStringRef string reference object\r\n    \\relatesalso GenericStringRef\r\n\r\n    \\see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember\r\n*/\r\ntemplate<typename CharType>\r\ninline GenericStringRef<CharType> StringRef(const CharType* str) {\r\n    return GenericStringRef<CharType>(str);\r\n}\r\n\r\n//! Mark a character pointer as constant string\r\n/*! Mark a plain character pointer as a \"string literal\".  This function\r\n    can be used to avoid copying a character string to be referenced as a\r\n    value in a JSON GenericValue object, if the string's lifetime is known\r\n    to be valid long enough.\r\n\r\n    This version has better performance with supplied length, and also\r\n    supports string containing null characters.\r\n\r\n    \\tparam CharType character type of the string\r\n    \\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue\r\n    \\param length The length of source string.\r\n    \\return GenericStringRef string reference object\r\n    \\relatesalso GenericStringRef\r\n*/\r\ntemplate<typename CharType>\r\ninline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {\r\n    return GenericStringRef<CharType>(str, SizeType(length));\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n//! Mark a string object as constant string\r\n/*! Mark a string object (e.g. \\c std::string) as a \"string literal\".\r\n    This function can be used to avoid copying a string to be referenced as a\r\n    value in a JSON GenericValue object, if the string's lifetime is known\r\n    to be valid long enough.\r\n\r\n    \\tparam CharType character type of the string\r\n    \\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue\r\n    \\return GenericStringRef string reference object\r\n    \\relatesalso GenericStringRef\r\n    \\note Requires the definition of the preprocessor symbol \\ref RAPIDJSON_HAS_STDSTRING.\r\n*/\r\ntemplate<typename CharType>\r\ninline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {\r\n    return GenericStringRef<CharType>(str.data(), SizeType(str.size()));\r\n}\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericValue type traits\r\nnamespace internal {\r\n\r\ntemplate <typename T, typename Encoding = void, typename Allocator = void>\r\nstruct IsGenericValueImpl : FalseType {};\r\n\r\n// select candidates according to nested encoding and allocator types\r\ntemplate <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>\r\n    : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};\r\n\r\n// helper to match arbitrary GenericValue instantiations, including derived classes\r\ntemplate <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};\r\n\r\n} // namespace internal\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// TypeHelper\r\n\r\nnamespace internal {\r\n\r\ntemplate <typename ValueType, typename T>\r\nstruct TypeHelper {};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, bool> {\r\n    static bool Is(const ValueType& v) { return v.IsBool(); }\r\n    static bool Get(const ValueType& v) { return v.GetBool(); }\r\n    static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }\r\n    static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, int> {\r\n    static bool Is(const ValueType& v) { return v.IsInt(); }\r\n    static int Get(const ValueType& v) { return v.GetInt(); }\r\n    static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }\r\n    static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, unsigned> {\r\n    static bool Is(const ValueType& v) { return v.IsUint(); }\r\n    static unsigned Get(const ValueType& v) { return v.GetUint(); }\r\n    static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }\r\n    static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }\r\n};\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int));\r\ntemplate<typename ValueType>\r\nstruct TypeHelper<ValueType, long> {\r\n    static bool Is(const ValueType& v) { return v.IsInt(); }\r\n    static long Get(const ValueType& v) { return v.GetInt(); }\r\n    static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); }\r\n    static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); }\r\n};\r\n\r\nRAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned));\r\ntemplate<typename ValueType>\r\nstruct TypeHelper<ValueType, unsigned long> {\r\n    static bool Is(const ValueType& v) { return v.IsUint(); }\r\n    static unsigned long Get(const ValueType& v) { return v.GetUint(); }\r\n    static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); }\r\n    static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); }\r\n};\r\n#endif\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, int64_t> {\r\n    static bool Is(const ValueType& v) { return v.IsInt64(); }\r\n    static int64_t Get(const ValueType& v) { return v.GetInt64(); }\r\n    static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }\r\n    static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, uint64_t> {\r\n    static bool Is(const ValueType& v) { return v.IsUint64(); }\r\n    static uint64_t Get(const ValueType& v) { return v.GetUint64(); }\r\n    static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }\r\n    static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, double> {\r\n    static bool Is(const ValueType& v) { return v.IsDouble(); }\r\n    static double Get(const ValueType& v) { return v.GetDouble(); }\r\n    static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }\r\n    static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, float> {\r\n    static bool Is(const ValueType& v) { return v.IsFloat(); }\r\n    static float Get(const ValueType& v) { return v.GetFloat(); }\r\n    static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }\r\n    static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, const typename ValueType::Ch*> {\r\n    typedef const typename ValueType::Ch* StringType;\r\n    static bool Is(const ValueType& v) { return v.IsString(); }\r\n    static StringType Get(const ValueType& v) { return v.GetString(); }\r\n    static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }\r\n    static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }\r\n};\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {\r\n    typedef std::basic_string<typename ValueType::Ch> StringType;\r\n    static bool Is(const ValueType& v) { return v.IsString(); }\r\n    static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }\r\n    static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }\r\n};\r\n#endif\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, typename ValueType::Array> {\r\n    typedef typename ValueType::Array ArrayType;\r\n    static bool Is(const ValueType& v) { return v.IsArray(); }\r\n    static ArrayType Get(ValueType& v) { return v.GetArray(); }\r\n    static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }\r\n    static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, typename ValueType::ConstArray> {\r\n    typedef typename ValueType::ConstArray ArrayType;\r\n    static bool Is(const ValueType& v) { return v.IsArray(); }\r\n    static ArrayType Get(const ValueType& v) { return v.GetArray(); }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, typename ValueType::Object> {\r\n    typedef typename ValueType::Object ObjectType;\r\n    static bool Is(const ValueType& v) { return v.IsObject(); }\r\n    static ObjectType Get(ValueType& v) { return v.GetObject(); }\r\n    static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }\r\n    static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; }\r\n};\r\n\r\ntemplate<typename ValueType> \r\nstruct TypeHelper<ValueType, typename ValueType::ConstObject> {\r\n    typedef typename ValueType::ConstObject ObjectType;\r\n    static bool Is(const ValueType& v) { return v.IsObject(); }\r\n    static ObjectType Get(const ValueType& v) { return v.GetObject(); }\r\n};\r\n\r\n} // namespace internal\r\n\r\n// Forward declarations\r\ntemplate <bool, typename> class GenericArray;\r\ntemplate <bool, typename> class GenericObject;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericValue\r\n\r\n//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.\r\n/*!\r\n    A JSON value can be one of 7 types. This class is a variant type supporting\r\n    these types.\r\n\r\n    Use the Value if UTF8 and default allocator\r\n\r\n    \\tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)\r\n    \\tparam Allocator   Allocator type for allocating memory of object, array and string.\r\n*/\r\ntemplate <typename Encoding, typename Allocator = MemoryPoolAllocator<> > \r\nclass GenericValue {\r\npublic:\r\n    //! Name-value pair in an object.\r\n    typedef GenericMember<Encoding, Allocator> Member;\r\n    typedef Encoding EncodingType;                  //!< Encoding type from template parameter.\r\n    typedef Allocator AllocatorType;                //!< Allocator type from template parameter.\r\n    typedef typename Encoding::Ch Ch;               //!< Character type derived from Encoding.\r\n    typedef GenericStringRef<Ch> StringRefType;     //!< Reference to a constant string\r\n    typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator;  //!< Member iterator for iterating in object.\r\n    typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator;  //!< Constant member iterator for iterating in object.\r\n    typedef GenericValue* ValueIterator;            //!< Value iterator for iterating in array.\r\n    typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.\r\n    typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of itself.\r\n    typedef GenericArray<false, ValueType> Array;\r\n    typedef GenericArray<true, ValueType> ConstArray;\r\n    typedef GenericObject<false, ValueType> Object;\r\n    typedef GenericObject<true, ValueType> ConstObject;\r\n\r\n    //!@name Constructors and destructor.\r\n    //@{\r\n\r\n    //! Default constructor creates a null value.\r\n    GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    //! Move constructor in C++11\r\n    GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {\r\n        rhs.data_.f.flags = kNullFlag; // give up contents\r\n    }\r\n#endif\r\n\r\nprivate:\r\n    //! Copy constructor is not permitted.\r\n    GenericValue(const GenericValue& rhs);\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    //! Moving from a GenericDocument is not permitted.\r\n    template <typename StackAllocator>\r\n    GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);\r\n\r\n    //! Move assignment from a GenericDocument is not permitted.\r\n    template <typename StackAllocator>\r\n    GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);\r\n#endif\r\n\r\npublic:\r\n\r\n    //! Constructor with JSON value type.\r\n    /*! This creates a Value of specified type with default content.\r\n        \\param type Type of the value.\r\n        \\note Default content for number is zero.\r\n    */\r\n    explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {\r\n        static const uint16_t defaultFlags[7] = {\r\n            kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,\r\n            kNumberAnyFlag\r\n        };\r\n        RAPIDJSON_ASSERT(type >= kNullType && type <= kNumberType);\r\n        data_.f.flags = defaultFlags[type];\r\n\r\n        // Use ShortString to store empty string.\r\n        if (type == kStringType)\r\n            data_.ss.SetLength(0);\r\n    }\r\n\r\n    //! Explicit copy constructor (with allocator)\r\n    /*! Creates a copy of a Value by using the given Allocator\r\n        \\tparam SourceAllocator allocator of \\c rhs\r\n        \\param rhs Value to copy from (read-only)\r\n        \\param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().\r\n        \\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)\r\n        \\see CopyFrom()\r\n    */\r\n    template <typename SourceAllocator>\r\n    GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {\r\n        switch (rhs.GetType()) {\r\n        case kObjectType: {\r\n                SizeType count = rhs.data_.o.size;\r\n                Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member)));\r\n                const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();\r\n                for (SizeType i = 0; i < count; i++) {\r\n                    new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);\r\n                    new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);\r\n                }\r\n                data_.f.flags = kObjectFlag;\r\n                data_.o.size = data_.o.capacity = count;\r\n                SetMembersPointer(lm);\r\n            }\r\n            break;\r\n        case kArrayType: {\r\n                SizeType count = rhs.data_.a.size;\r\n                GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));\r\n                const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer();\r\n                for (SizeType i = 0; i < count; i++)\r\n                    new (&le[i]) GenericValue(re[i], allocator, copyConstStrings);\r\n                data_.f.flags = kArrayFlag;\r\n                data_.a.size = data_.a.capacity = count;\r\n                SetElementsPointer(le);\r\n            }\r\n            break;\r\n        case kStringType:\r\n            if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {\r\n                data_.f.flags = rhs.data_.f.flags;\r\n                data_  = *reinterpret_cast<const Data*>(&rhs.data_);\r\n            }\r\n            else\r\n                SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);\r\n            break;\r\n        default:\r\n            data_.f.flags = rhs.data_.f.flags;\r\n            data_  = *reinterpret_cast<const Data*>(&rhs.data_);\r\n            break;\r\n        }\r\n    }\r\n\r\n    //! Constructor for boolean value.\r\n    /*! \\param b Boolean value\r\n        \\note This constructor is limited to \\em real boolean values and rejects\r\n            implicitly converted types like arbitrary pointers.  Use an explicit cast\r\n            to \\c bool, if you want to construct a boolean JSON value in such cases.\r\n     */\r\n#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen\r\n    template <typename T>\r\n    explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT  // See #472\r\n#else\r\n    explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT\r\n#endif\r\n        : data_() {\r\n            // safe-guard against failing SFINAE\r\n            RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));\r\n            data_.f.flags = b ? kTrueFlag : kFalseFlag;\r\n    }\r\n\r\n    //! Constructor for int value.\r\n    explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {\r\n        data_.n.i64 = i;\r\n        data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;\r\n    }\r\n\r\n    //! Constructor for unsigned value.\r\n    explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {\r\n        data_.n.u64 = u; \r\n        data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);\r\n    }\r\n\r\n    //! Constructor for int64_t value.\r\n    explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {\r\n        data_.n.i64 = i64;\r\n        data_.f.flags = kNumberInt64Flag;\r\n        if (i64 >= 0) {\r\n            data_.f.flags |= kNumberUint64Flag;\r\n            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))\r\n                data_.f.flags |= kUintFlag;\r\n            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))\r\n                data_.f.flags |= kIntFlag;\r\n        }\r\n        else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))\r\n            data_.f.flags |= kIntFlag;\r\n    }\r\n\r\n    //! Constructor for uint64_t value.\r\n    explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {\r\n        data_.n.u64 = u64;\r\n        data_.f.flags = kNumberUint64Flag;\r\n        if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))\r\n            data_.f.flags |= kInt64Flag;\r\n        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))\r\n            data_.f.flags |= kUintFlag;\r\n        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))\r\n            data_.f.flags |= kIntFlag;\r\n    }\r\n\r\n    //! Constructor for double value.\r\n    explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }\r\n\r\n    //! Constructor for float value.\r\n    explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }\r\n\r\n    //! Constructor for constant string (i.e. do not make a copy of string)\r\n    GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }\r\n\r\n    //! Constructor for constant string (i.e. do not make a copy of string)\r\n    explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }\r\n\r\n    //! Constructor for copy-string (i.e. do make a copy of string)\r\n    GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }\r\n\r\n    //! Constructor for copy-string (i.e. do make a copy of string)\r\n    GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Constructor for copy-string from a string object (i.e. do make a copy of string)\r\n    /*! \\note Requires the definition of the preprocessor symbol \\ref RAPIDJSON_HAS_STDSTRING.\r\n     */\r\n    GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }\r\n#endif\r\n\r\n    //! Constructor for Array.\r\n    /*!\r\n        \\param a An array obtained by \\c GetArray().\r\n        \\note \\c Array is always pass-by-value.\r\n        \\note the source array is moved into this value and the sourec array becomes empty.\r\n    */\r\n    GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {\r\n        a.value_.data_ = Data();\r\n        a.value_.data_.f.flags = kArrayFlag;\r\n    }\r\n\r\n    //! Constructor for Object.\r\n    /*!\r\n        \\param o An object obtained by \\c GetObject().\r\n        \\note \\c Object is always pass-by-value.\r\n        \\note the source object is moved into this value and the sourec object becomes empty.\r\n    */\r\n    GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {\r\n        o.value_.data_ = Data();\r\n        o.value_.data_.f.flags = kObjectFlag;\r\n    }\r\n\r\n    //! Destructor.\r\n    /*! Need to destruct elements of array, members of object, or copy-string.\r\n    */\r\n    ~GenericValue() {\r\n        if (Allocator::kNeedFree) { // Shortcut by Allocator's trait\r\n            switch(data_.f.flags) {\r\n            case kArrayFlag:\r\n                {\r\n                    GenericValue* e = GetElementsPointer();\r\n                    for (GenericValue* v = e; v != e + data_.a.size; ++v)\r\n                        v->~GenericValue();\r\n                    Allocator::Free(e);\r\n                }\r\n                break;\r\n\r\n            case kObjectFlag:\r\n                for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)\r\n                    m->~Member();\r\n                Allocator::Free(GetMembersPointer());\r\n                break;\r\n\r\n            case kCopyStringFlag:\r\n                Allocator::Free(const_cast<Ch*>(GetStringPointer()));\r\n                break;\r\n\r\n            default:\r\n                break;  // Do nothing for other types.\r\n            }\r\n        }\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Assignment operators\r\n    //@{\r\n\r\n    //! Assignment with move semantics.\r\n    /*! \\param rhs Source of the assignment. It will become a null value after assignment.\r\n    */\r\n    GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {\r\n        RAPIDJSON_ASSERT(this != &rhs);\r\n        this->~GenericValue();\r\n        RawAssign(rhs);\r\n        return *this;\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    //! Move assignment in C++11\r\n    GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {\r\n        return *this = rhs.Move();\r\n    }\r\n#endif\r\n\r\n    //! Assignment of constant string reference (no copy)\r\n    /*! \\param str Constant string reference to be assigned\r\n        \\note This overload is needed to avoid clashes with the generic primitive type assignment overload below.\r\n        \\see GenericStringRef, operator=(T)\r\n    */\r\n    GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {\r\n        GenericValue s(str);\r\n        return *this = s;\r\n    }\r\n\r\n    //! Assignment with primitive types.\r\n    /*! \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t\r\n        \\param value The value to be assigned.\r\n\r\n        \\note The source type \\c T explicitly disallows all pointer types,\r\n            especially (\\c const) \\ref Ch*.  This helps avoiding implicitly\r\n            referencing character strings with insufficient lifetime, use\r\n            \\ref SetString(const Ch*, Allocator&) (for copying) or\r\n            \\ref StringRef() (to explicitly mark the pointer as constant) instead.\r\n            All other pointer types would implicitly convert to \\c bool,\r\n            use \\ref SetBool() instead.\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))\r\n    operator=(T value) {\r\n        GenericValue v(value);\r\n        return *this = v;\r\n    }\r\n\r\n    //! Deep-copy assignment from Value\r\n    /*! Assigns a \\b copy of the Value to the current Value object\r\n        \\tparam SourceAllocator Allocator type of \\c rhs\r\n        \\param rhs Value to copy from (read-only)\r\n        \\param allocator Allocator to use for copying\r\n        \\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)\r\n     */\r\n    template <typename SourceAllocator>\r\n    GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {\r\n        RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));\r\n        this->~GenericValue();\r\n        new (this) GenericValue(rhs, allocator, copyConstStrings);\r\n        return *this;\r\n    }\r\n\r\n    //! Exchange the contents of this value with those of other.\r\n    /*!\r\n        \\param other Another value.\r\n        \\note Constant complexity.\r\n    */\r\n    GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {\r\n        GenericValue temp;\r\n        temp.RawAssign(*this);\r\n        RawAssign(other);\r\n        other.RawAssign(temp);\r\n        return *this;\r\n    }\r\n\r\n    //! free-standing swap function helper\r\n    /*!\r\n        Helper function to enable support for common swap implementation pattern based on \\c std::swap:\r\n        \\code\r\n        void swap(MyClass& a, MyClass& b) {\r\n            using std::swap;\r\n            swap(a.value, b.value);\r\n            // ...\r\n        }\r\n        \\endcode\r\n        \\see Swap()\r\n     */\r\n    friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }\r\n\r\n    //! Prepare Value for move semantics\r\n    /*! \\return *this */\r\n    GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }\r\n    //@}\r\n\r\n    //!@name Equal-to and not-equal-to operators\r\n    //@{\r\n    //! Equal-to operator\r\n    /*!\r\n        \\note If an object contains duplicated named member, comparing equality with any object is always \\c false.\r\n        \\note Linear time complexity (number of all values in the subtree and total lengths of all strings).\r\n    */\r\n    template <typename SourceAllocator>\r\n    bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {\r\n        typedef GenericValue<Encoding, SourceAllocator> RhsType;\r\n        if (GetType() != rhs.GetType())\r\n            return false;\r\n\r\n        switch (GetType()) {\r\n        case kObjectType: // Warning: O(n^2) inner-loop\r\n            if (data_.o.size != rhs.data_.o.size)\r\n                return false;           \r\n            for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {\r\n                typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);\r\n                if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)\r\n                    return false;\r\n            }\r\n            return true;\r\n            \r\n        case kArrayType:\r\n            if (data_.a.size != rhs.data_.a.size)\r\n                return false;\r\n            for (SizeType i = 0; i < data_.a.size; i++)\r\n                if ((*this)[i] != rhs[i])\r\n                    return false;\r\n            return true;\r\n\r\n        case kStringType:\r\n            return StringEqual(rhs);\r\n\r\n        case kNumberType:\r\n            if (IsDouble() || rhs.IsDouble()) {\r\n                double a = GetDouble();     // May convert from integer to double.\r\n                double b = rhs.GetDouble(); // Ditto\r\n                return a >= b && a <= b;    // Prevent -Wfloat-equal\r\n            }\r\n            else\r\n                return data_.n.u64 == rhs.data_.n.u64;\r\n\r\n        default:\r\n            return true;\r\n        }\r\n    }\r\n\r\n    //! Equal-to operator with const C-string pointer\r\n    bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Equal-to operator with string object\r\n    /*! \\note Requires the definition of the preprocessor symbol \\ref RAPIDJSON_HAS_STDSTRING.\r\n     */\r\n    bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }\r\n#endif\r\n\r\n    //! Equal-to operator with primitive types\r\n    /*! \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t, \\c double, \\c true, \\c false\r\n    */\r\n    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }\r\n\r\n    //! Not-equal-to operator\r\n    /*! \\return !(*this == rhs)\r\n     */\r\n    template <typename SourceAllocator>\r\n    bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }\r\n\r\n    //! Not-equal-to operator with const C-string pointer\r\n    bool operator!=(const Ch* rhs) const { return !(*this == rhs); }\r\n\r\n    //! Not-equal-to operator with arbitrary types\r\n    /*! \\return !(*this == rhs)\r\n     */\r\n    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }\r\n\r\n    //! Equal-to operator with arbitrary types (symmetric version)\r\n    /*! \\return (rhs == lhs)\r\n     */\r\n    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }\r\n\r\n    //! Not-Equal-to operator with arbitrary types (symmetric version)\r\n    /*! \\return !(rhs == lhs)\r\n     */\r\n    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }\r\n    //@}\r\n\r\n    //!@name Type\r\n    //@{\r\n\r\n    Type GetType()  const { return static_cast<Type>(data_.f.flags & kTypeMask); }\r\n    bool IsNull()   const { return data_.f.flags == kNullFlag; }\r\n    bool IsFalse()  const { return data_.f.flags == kFalseFlag; }\r\n    bool IsTrue()   const { return data_.f.flags == kTrueFlag; }\r\n    bool IsBool()   const { return (data_.f.flags & kBoolFlag) != 0; }\r\n    bool IsObject() const { return data_.f.flags == kObjectFlag; }\r\n    bool IsArray()  const { return data_.f.flags == kArrayFlag; }\r\n    bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }\r\n    bool IsInt()    const { return (data_.f.flags & kIntFlag) != 0; }\r\n    bool IsUint()   const { return (data_.f.flags & kUintFlag) != 0; }\r\n    bool IsInt64()  const { return (data_.f.flags & kInt64Flag) != 0; }\r\n    bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }\r\n    bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }\r\n    bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }\r\n\r\n    // Checks whether a number can be losslessly converted to a double.\r\n    bool IsLosslessDouble() const {\r\n        if (!IsNumber()) return false;\r\n        if (IsUint64()) {\r\n            uint64_t u = GetUint64();\r\n            volatile double d = static_cast<double>(u);\r\n            return (d >= 0.0)\r\n                && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)()))\r\n                && (u == static_cast<uint64_t>(d));\r\n        }\r\n        if (IsInt64()) {\r\n            int64_t i = GetInt64();\r\n            volatile double d = static_cast<double>(i);\r\n            return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))\r\n                && (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))\r\n                && (i == static_cast<int64_t>(d));\r\n        }\r\n        return true; // double, int, uint are always lossless\r\n    }\r\n\r\n    // Checks whether a number is a float (possible lossy).\r\n    bool IsFloat() const  {\r\n        if ((data_.f.flags & kDoubleFlag) == 0)\r\n            return false;\r\n        double d = GetDouble();\r\n        return d >= -3.4028234e38 && d <= 3.4028234e38;\r\n    }\r\n    // Checks whether a number can be losslessly converted to a float.\r\n    bool IsLosslessFloat() const {\r\n        if (!IsNumber()) return false;\r\n        double a = GetDouble();\r\n        if (a < static_cast<double>(-(std::numeric_limits<float>::max)())\r\n                || a > static_cast<double>((std::numeric_limits<float>::max)()))\r\n            return false;\r\n        double b = static_cast<double>(static_cast<float>(a));\r\n        return a >= b && a <= b;    // Prevent -Wfloat-equal\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Null\r\n    //@{\r\n\r\n    GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }\r\n\r\n    //@}\r\n\r\n    //!@name Bool\r\n    //@{\r\n\r\n    bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }\r\n    //!< Set boolean value\r\n    /*! \\post IsBool() == true */\r\n    GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }\r\n\r\n    //@}\r\n\r\n    //!@name Object\r\n    //@{\r\n\r\n    //! Set this value as an empty object.\r\n    /*! \\post IsObject() == true */\r\n    GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }\r\n\r\n    //! Get the number of members in the object.\r\n    SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }\r\n\r\n    //! Get the capacity of object.\r\n    SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; }\r\n\r\n    //! Check whether the object is empty.\r\n    bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }\r\n\r\n    //! Get a value from an object associated with the name.\r\n    /*! \\pre IsObject() == true\r\n        \\tparam T Either \\c Ch or \\c const \\c Ch (template used for disambiguation with \\ref operator[](SizeType))\r\n        \\note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.\r\n        Since 0.2, if the name is not correct, it will assert.\r\n        If user is unsure whether a member exists, user should use HasMember() first.\r\n        A better approach is to use FindMember().\r\n        \\note Linear time complexity.\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {\r\n        GenericValue n(StringRef(name));\r\n        return (*this)[n];\r\n    }\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }\r\n\r\n    //! Get a value from an object associated with the name.\r\n    /*! \\pre IsObject() == true\r\n        \\tparam SourceAllocator Allocator of the \\c name value\r\n\r\n        \\note Compared to \\ref operator[](T*), this version is faster because it does not need a StrLen().\r\n        And it can also handle strings with embedded null characters.\r\n\r\n        \\note Linear time complexity.\r\n    */\r\n    template <typename SourceAllocator>\r\n    GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {\r\n        MemberIterator member = FindMember(name);\r\n        if (member != MemberEnd())\r\n            return member->value;\r\n        else {\r\n            RAPIDJSON_ASSERT(false);    // see above note\r\n\r\n            // This will generate -Wexit-time-destructors in clang\r\n            // static GenericValue NullValue;\r\n            // return NullValue;\r\n\r\n            // Use static buffer and placement-new to prevent destruction\r\n            static char buffer[sizeof(GenericValue)];\r\n            return *new (buffer) GenericValue();\r\n        }\r\n    }\r\n    template <typename SourceAllocator>\r\n    const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Get a value from an object associated with name (string object).\r\n    GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }\r\n    const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }\r\n#endif\r\n\r\n    //! Const member iterator\r\n    /*! \\pre IsObject() == true */\r\n    ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }\r\n    //! Const \\em past-the-end member iterator\r\n    /*! \\pre IsObject() == true */\r\n    ConstMemberIterator MemberEnd() const   { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }\r\n    //! Member iterator\r\n    /*! \\pre IsObject() == true */\r\n    MemberIterator MemberBegin()            { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }\r\n    //! \\em Past-the-end member iterator\r\n    /*! \\pre IsObject() == true */\r\n    MemberIterator MemberEnd()              { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }\r\n\r\n    //! Request the object to have enough capacity to store members.\r\n    /*! \\param newCapacity  The capacity that the object at least need to have.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\note Linear time complexity.\r\n    */\r\n    GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {\r\n        RAPIDJSON_ASSERT(IsObject());\r\n        if (newCapacity > data_.o.capacity) {\r\n            SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), data_.o.capacity * sizeof(Member), newCapacity * sizeof(Member))));\r\n            data_.o.capacity = newCapacity;\r\n        }\r\n        return *this;\r\n    }\r\n\r\n    //! Check whether a member exists in the object.\r\n    /*!\r\n        \\param name Member name to be searched.\r\n        \\pre IsObject() == true\r\n        \\return Whether a member with that name exists.\r\n        \\note It is better to use FindMember() directly if you need the obtain the value as well.\r\n        \\note Linear time complexity.\r\n    */\r\n    bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Check whether a member exists in the object with string object.\r\n    /*!\r\n        \\param name Member name to be searched.\r\n        \\pre IsObject() == true\r\n        \\return Whether a member with that name exists.\r\n        \\note It is better to use FindMember() directly if you need the obtain the value as well.\r\n        \\note Linear time complexity.\r\n    */\r\n    bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }\r\n#endif\r\n\r\n    //! Check whether a member exists in the object with GenericValue name.\r\n    /*!\r\n        This version is faster because it does not need a StrLen(). It can also handle string with null character.\r\n        \\param name Member name to be searched.\r\n        \\pre IsObject() == true\r\n        \\return Whether a member with that name exists.\r\n        \\note It is better to use FindMember() directly if you need the obtain the value as well.\r\n        \\note Linear time complexity.\r\n    */\r\n    template <typename SourceAllocator>\r\n    bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }\r\n\r\n    //! Find member by name.\r\n    /*!\r\n        \\param name Member name to be searched.\r\n        \\pre IsObject() == true\r\n        \\return Iterator to member, if it exists.\r\n            Otherwise returns \\ref MemberEnd().\r\n\r\n        \\note Earlier versions of Rapidjson returned a \\c NULL pointer, in case\r\n            the requested member doesn't exist. For consistency with e.g.\r\n            \\c std::map, this has been changed to MemberEnd() now.\r\n        \\note Linear time complexity.\r\n    */\r\n    MemberIterator FindMember(const Ch* name) {\r\n        GenericValue n(StringRef(name));\r\n        return FindMember(n);\r\n    }\r\n\r\n    ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }\r\n\r\n    //! Find member by name.\r\n    /*!\r\n        This version is faster because it does not need a StrLen(). It can also handle string with null character.\r\n        \\param name Member name to be searched.\r\n        \\pre IsObject() == true\r\n        \\return Iterator to member, if it exists.\r\n            Otherwise returns \\ref MemberEnd().\r\n\r\n        \\note Earlier versions of Rapidjson returned a \\c NULL pointer, in case\r\n            the requested member doesn't exist. For consistency with e.g.\r\n            \\c std::map, this has been changed to MemberEnd() now.\r\n        \\note Linear time complexity.\r\n    */\r\n    template <typename SourceAllocator>\r\n    MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {\r\n        RAPIDJSON_ASSERT(IsObject());\r\n        RAPIDJSON_ASSERT(name.IsString());\r\n        MemberIterator member = MemberBegin();\r\n        for ( ; member != MemberEnd(); ++member)\r\n            if (name.StringEqual(member->name))\r\n                break;\r\n        return member;\r\n    }\r\n    template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Find member by string object name.\r\n    /*!\r\n        \\param name Member name to be searched.\r\n        \\pre IsObject() == true\r\n        \\return Iterator to member, if it exists.\r\n            Otherwise returns \\ref MemberEnd().\r\n    */\r\n    MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }\r\n    ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }\r\n#endif\r\n\r\n    //! Add a member (name-value pair) to the object.\r\n    /*! \\param name A string value as name of member.\r\n        \\param value Value of any type.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\note The ownership of \\c name and \\c value will be transferred to this object on success.\r\n        \\pre  IsObject() && name.IsString()\r\n        \\post name.IsNull() && value.IsNull()\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {\r\n        RAPIDJSON_ASSERT(IsObject());\r\n        RAPIDJSON_ASSERT(name.IsString());\r\n\r\n        ObjectData& o = data_.o;\r\n        if (o.size >= o.capacity)\r\n            MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator);\r\n        Member* members = GetMembersPointer();\r\n        members[o.size].name.RawAssign(name);\r\n        members[o.size].value.RawAssign(value);\r\n        o.size++;\r\n        return *this;\r\n    }\r\n\r\n    //! Add a constant string value as member (name-value pair) to the object.\r\n    /*! \\param name A string value as name of member.\r\n        \\param value constant string reference as value of member.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\pre  IsObject()\r\n        \\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {\r\n        GenericValue v(value);\r\n        return AddMember(name, v, allocator);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Add a string object as member (name-value pair) to the object.\r\n    /*! \\param name A string value as name of member.\r\n        \\param value constant string reference as value of member.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\pre  IsObject()\r\n        \\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {\r\n        GenericValue v(value, allocator);\r\n        return AddMember(name, v, allocator);\r\n    }\r\n#endif\r\n\r\n    //! Add any primitive value as member (name-value pair) to the object.\r\n    /*! \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t\r\n        \\param name A string value as name of member.\r\n        \\param value Value of primitive type \\c T as value of member\r\n        \\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\pre  IsObject()\r\n\r\n        \\note The source type \\c T explicitly disallows all pointer types,\r\n            especially (\\c const) \\ref Ch*.  This helps avoiding implicitly\r\n            referencing character strings with insufficient lifetime, use\r\n            \\ref AddMember(StringRefType, GenericValue&, Allocator&) or \\ref\r\n            AddMember(StringRefType, StringRefType, Allocator&).\r\n            All other pointer types would implicitly convert to \\c bool,\r\n            use an explicit cast instead, if needed.\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))\r\n    AddMember(GenericValue& name, T value, Allocator& allocator) {\r\n        GenericValue v(value);\r\n        return AddMember(name, v, allocator);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {\r\n        return AddMember(name, value, allocator);\r\n    }\r\n    GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {\r\n        return AddMember(name, value, allocator);\r\n    }\r\n    GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {\r\n        return AddMember(name, value, allocator);\r\n    }\r\n    GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {\r\n        GenericValue n(name);\r\n        return AddMember(n, value, allocator);\r\n    }\r\n#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n\r\n\r\n    //! Add a member (name-value pair) to the object.\r\n    /*! \\param name A constant string reference as name of member.\r\n        \\param value Value of any type.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\note The ownership of \\c value will be transferred to this object on success.\r\n        \\pre  IsObject()\r\n        \\post value.IsNull()\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {\r\n        GenericValue n(name);\r\n        return AddMember(n, value, allocator);\r\n    }\r\n\r\n    //! Add a constant string value as member (name-value pair) to the object.\r\n    /*! \\param name A constant string reference as name of member.\r\n        \\param value constant string reference as value of member.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\pre  IsObject()\r\n        \\note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {\r\n        GenericValue v(value);\r\n        return AddMember(name, v, allocator);\r\n    }\r\n\r\n    //! Add any primitive value as member (name-value pair) to the object.\r\n    /*! \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t\r\n        \\param name A constant string reference as name of member.\r\n        \\param value Value of primitive type \\c T as value of member\r\n        \\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\pre  IsObject()\r\n\r\n        \\note The source type \\c T explicitly disallows all pointer types,\r\n            especially (\\c const) \\ref Ch*.  This helps avoiding implicitly\r\n            referencing character strings with insufficient lifetime, use\r\n            \\ref AddMember(StringRefType, GenericValue&, Allocator&) or \\ref\r\n            AddMember(StringRefType, StringRefType, Allocator&).\r\n            All other pointer types would implicitly convert to \\c bool,\r\n            use an explicit cast instead, if needed.\r\n        \\note Amortized Constant time complexity.\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))\r\n    AddMember(StringRefType name, T value, Allocator& allocator) {\r\n        GenericValue n(name);\r\n        return AddMember(n, value, allocator);\r\n    }\r\n\r\n    //! Remove all members in the object.\r\n    /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.\r\n        \\note Linear time complexity.\r\n    */\r\n    void RemoveAllMembers() {\r\n        RAPIDJSON_ASSERT(IsObject()); \r\n        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)\r\n            m->~Member();\r\n        data_.o.size = 0;\r\n    }\r\n\r\n    //! Remove a member in object by its name.\r\n    /*! \\param name Name of member to be removed.\r\n        \\return Whether the member existed.\r\n        \\note This function may reorder the object members. Use \\ref\r\n            EraseMember(ConstMemberIterator) if you need to preserve the\r\n            relative order of the remaining members.\r\n        \\note Linear time complexity.\r\n    */\r\n    bool RemoveMember(const Ch* name) {\r\n        GenericValue n(StringRef(name));\r\n        return RemoveMember(n);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }\r\n#endif\r\n\r\n    template <typename SourceAllocator>\r\n    bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {\r\n        MemberIterator m = FindMember(name);\r\n        if (m != MemberEnd()) {\r\n            RemoveMember(m);\r\n            return true;\r\n        }\r\n        else\r\n            return false;\r\n    }\r\n\r\n    //! Remove a member in object by iterator.\r\n    /*! \\param m member iterator (obtained by FindMember() or MemberBegin()).\r\n        \\return the new iterator after removal.\r\n        \\note This function may reorder the object members. Use \\ref\r\n            EraseMember(ConstMemberIterator) if you need to preserve the\r\n            relative order of the remaining members.\r\n        \\note Constant time complexity.\r\n    */\r\n    MemberIterator RemoveMember(MemberIterator m) {\r\n        RAPIDJSON_ASSERT(IsObject());\r\n        RAPIDJSON_ASSERT(data_.o.size > 0);\r\n        RAPIDJSON_ASSERT(GetMembersPointer() != 0);\r\n        RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());\r\n\r\n        MemberIterator last(GetMembersPointer() + (data_.o.size - 1));\r\n        if (data_.o.size > 1 && m != last)\r\n            *m = *last; // Move the last one to this place\r\n        else\r\n            m->~Member(); // Only one left, just destroy\r\n        --data_.o.size;\r\n        return m;\r\n    }\r\n\r\n    //! Remove a member from an object by iterator.\r\n    /*! \\param pos iterator to the member to remove\r\n        \\pre IsObject() == true && \\ref MemberBegin() <= \\c pos < \\ref MemberEnd()\r\n        \\return Iterator following the removed element.\r\n            If the iterator \\c pos refers to the last element, the \\ref MemberEnd() iterator is returned.\r\n        \\note This function preserves the relative order of the remaining object\r\n            members. If you do not need this, use the more efficient \\ref RemoveMember(MemberIterator).\r\n        \\note Linear time complexity.\r\n    */\r\n    MemberIterator EraseMember(ConstMemberIterator pos) {\r\n        return EraseMember(pos, pos +1);\r\n    }\r\n\r\n    //! Remove members in the range [first, last) from an object.\r\n    /*! \\param first iterator to the first member to remove\r\n        \\param last  iterator following the last member to remove\r\n        \\pre IsObject() == true && \\ref MemberBegin() <= \\c first <= \\c last <= \\ref MemberEnd()\r\n        \\return Iterator following the last removed element.\r\n        \\note This function preserves the relative order of the remaining object\r\n            members.\r\n        \\note Linear time complexity.\r\n    */\r\n    MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {\r\n        RAPIDJSON_ASSERT(IsObject());\r\n        RAPIDJSON_ASSERT(data_.o.size > 0);\r\n        RAPIDJSON_ASSERT(GetMembersPointer() != 0);\r\n        RAPIDJSON_ASSERT(first >= MemberBegin());\r\n        RAPIDJSON_ASSERT(first <= last);\r\n        RAPIDJSON_ASSERT(last <= MemberEnd());\r\n\r\n        MemberIterator pos = MemberBegin() + (first - MemberBegin());\r\n        for (MemberIterator itr = pos; itr != last; ++itr)\r\n            itr->~Member();\r\n        std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));\r\n        data_.o.size -= static_cast<SizeType>(last - first);\r\n        return pos;\r\n    }\r\n\r\n    //! Erase a member in object by its name.\r\n    /*! \\param name Name of member to be removed.\r\n        \\return Whether the member existed.\r\n        \\note Linear time complexity.\r\n    */\r\n    bool EraseMember(const Ch* name) {\r\n        GenericValue n(StringRef(name));\r\n        return EraseMember(n);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }\r\n#endif\r\n\r\n    template <typename SourceAllocator>\r\n    bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {\r\n        MemberIterator m = FindMember(name);\r\n        if (m != MemberEnd()) {\r\n            EraseMember(m);\r\n            return true;\r\n        }\r\n        else\r\n            return false;\r\n    }\r\n\r\n    Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }\r\n    ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }\r\n\r\n    //@}\r\n\r\n    //!@name Array\r\n    //@{\r\n\r\n    //! Set this value as an empty array.\r\n    /*! \\post IsArray == true */\r\n    GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }\r\n\r\n    //! Get the number of elements in array.\r\n    SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }\r\n\r\n    //! Get the capacity of array.\r\n    SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }\r\n\r\n    //! Check whether the array is empty.\r\n    bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }\r\n\r\n    //! Remove all elements in the array.\r\n    /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.\r\n        \\note Linear time complexity.\r\n    */\r\n    void Clear() {\r\n        RAPIDJSON_ASSERT(IsArray()); \r\n        GenericValue* e = GetElementsPointer();\r\n        for (GenericValue* v = e; v != e + data_.a.size; ++v)\r\n            v->~GenericValue();\r\n        data_.a.size = 0;\r\n    }\r\n\r\n    //! Get an element from array by index.\r\n    /*! \\pre IsArray() == true\r\n        \\param index Zero-based index of element.\r\n        \\see operator[](T*)\r\n    */\r\n    GenericValue& operator[](SizeType index) {\r\n        RAPIDJSON_ASSERT(IsArray());\r\n        RAPIDJSON_ASSERT(index < data_.a.size);\r\n        return GetElementsPointer()[index];\r\n    }\r\n    const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }\r\n\r\n    //! Element iterator\r\n    /*! \\pre IsArray() == true */\r\n    ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }\r\n    //! \\em Past-the-end element iterator\r\n    /*! \\pre IsArray() == true */\r\n    ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }\r\n    //! Constant element iterator\r\n    /*! \\pre IsArray() == true */\r\n    ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }\r\n    //! Constant \\em past-the-end element iterator\r\n    /*! \\pre IsArray() == true */\r\n    ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }\r\n\r\n    //! Request the array to have enough capacity to store elements.\r\n    /*! \\param newCapacity  The capacity that the array at least need to have.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\note Linear time complexity.\r\n    */\r\n    GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {\r\n        RAPIDJSON_ASSERT(IsArray());\r\n        if (newCapacity > data_.a.capacity) {\r\n            SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));\r\n            data_.a.capacity = newCapacity;\r\n        }\r\n        return *this;\r\n    }\r\n\r\n    //! Append a GenericValue at the end of the array.\r\n    /*! \\param value        Value to be appended.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\pre IsArray() == true\r\n        \\post value.IsNull() == true\r\n        \\return The value itself for fluent API.\r\n        \\note The ownership of \\c value will be transferred to this array on success.\r\n        \\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.\r\n        \\note Amortized constant time complexity.\r\n    */\r\n    GenericValue& PushBack(GenericValue& value, Allocator& allocator) {\r\n        RAPIDJSON_ASSERT(IsArray());\r\n        if (data_.a.size >= data_.a.capacity)\r\n            Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);\r\n        GetElementsPointer()[data_.a.size++].RawAssign(value);\r\n        return *this;\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {\r\n        return PushBack(value, allocator);\r\n    }\r\n#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n\r\n    //! Append a constant string reference at the end of the array.\r\n    /*! \\param value        Constant string reference to be appended.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().\r\n        \\pre IsArray() == true\r\n        \\return The value itself for fluent API.\r\n        \\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.\r\n        \\note Amortized constant time complexity.\r\n        \\see GenericStringRef\r\n    */\r\n    GenericValue& PushBack(StringRefType value, Allocator& allocator) {\r\n        return (*this).template PushBack<StringRefType>(value, allocator);\r\n    }\r\n\r\n    //! Append a primitive value at the end of the array.\r\n    /*! \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t\r\n        \\param value Value of primitive type T to be appended.\r\n        \\param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().\r\n        \\pre IsArray() == true\r\n        \\return The value itself for fluent API.\r\n        \\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.\r\n\r\n        \\note The source type \\c T explicitly disallows all pointer types,\r\n            especially (\\c const) \\ref Ch*.  This helps avoiding implicitly\r\n            referencing character strings with insufficient lifetime, use\r\n            \\ref PushBack(GenericValue&, Allocator&) or \\ref\r\n            PushBack(StringRefType, Allocator&).\r\n            All other pointer types would implicitly convert to \\c bool,\r\n            use an explicit cast instead, if needed.\r\n        \\note Amortized constant time complexity.\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))\r\n    PushBack(T value, Allocator& allocator) {\r\n        GenericValue v(value);\r\n        return PushBack(v, allocator);\r\n    }\r\n\r\n    //! Remove the last element in the array.\r\n    /*!\r\n        \\note Constant time complexity.\r\n    */\r\n    GenericValue& PopBack() {\r\n        RAPIDJSON_ASSERT(IsArray());\r\n        RAPIDJSON_ASSERT(!Empty());\r\n        GetElementsPointer()[--data_.a.size].~GenericValue();\r\n        return *this;\r\n    }\r\n\r\n    //! Remove an element of array by iterator.\r\n    /*!\r\n        \\param pos iterator to the element to remove\r\n        \\pre IsArray() == true && \\ref Begin() <= \\c pos < \\ref End()\r\n        \\return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.\r\n        \\note Linear time complexity.\r\n    */\r\n    ValueIterator Erase(ConstValueIterator pos) {\r\n        return Erase(pos, pos + 1);\r\n    }\r\n\r\n    //! Remove elements in the range [first, last) of the array.\r\n    /*!\r\n        \\param first iterator to the first element to remove\r\n        \\param last  iterator following the last element to remove\r\n        \\pre IsArray() == true && \\ref Begin() <= \\c first <= \\c last <= \\ref End()\r\n        \\return Iterator following the last removed element.\r\n        \\note Linear time complexity.\r\n    */\r\n    ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {\r\n        RAPIDJSON_ASSERT(IsArray());\r\n        RAPIDJSON_ASSERT(data_.a.size > 0);\r\n        RAPIDJSON_ASSERT(GetElementsPointer() != 0);\r\n        RAPIDJSON_ASSERT(first >= Begin());\r\n        RAPIDJSON_ASSERT(first <= last);\r\n        RAPIDJSON_ASSERT(last <= End());\r\n        ValueIterator pos = Begin() + (first - Begin());\r\n        for (ValueIterator itr = pos; itr != last; ++itr)\r\n            itr->~GenericValue();       \r\n        std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));\r\n        data_.a.size -= static_cast<SizeType>(last - first);\r\n        return pos;\r\n    }\r\n\r\n    Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }\r\n    ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }\r\n\r\n    //@}\r\n\r\n    //!@name Number\r\n    //@{\r\n\r\n    int GetInt() const          { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag);   return data_.n.i.i;   }\r\n    unsigned GetUint() const    { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag);  return data_.n.u.u;   }\r\n    int64_t GetInt64() const    { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }\r\n    uint64_t GetUint64() const  { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }\r\n\r\n    //! Get the value as double type.\r\n    /*! \\note If the value is 64-bit integer type, it may lose precision. Use \\c IsLosslessDouble() to check whether the converison is lossless.\r\n    */\r\n    double GetDouble() const {\r\n        RAPIDJSON_ASSERT(IsNumber());\r\n        if ((data_.f.flags & kDoubleFlag) != 0)                return data_.n.d;   // exact type, no conversion.\r\n        if ((data_.f.flags & kIntFlag) != 0)                   return data_.n.i.i; // int -> double\r\n        if ((data_.f.flags & kUintFlag) != 0)                  return data_.n.u.u; // unsigned -> double\r\n        if ((data_.f.flags & kInt64Flag) != 0)                 return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)\r\n        RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0);  return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)\r\n    }\r\n\r\n    //! Get the value as float type.\r\n    /*! \\note If the value is 64-bit integer type, it may lose precision. Use \\c IsLosslessFloat() to check whether the converison is lossless.\r\n    */\r\n    float GetFloat() const {\r\n        return static_cast<float>(GetDouble());\r\n    }\r\n\r\n    GenericValue& SetInt(int i)             { this->~GenericValue(); new (this) GenericValue(i);    return *this; }\r\n    GenericValue& SetUint(unsigned u)       { this->~GenericValue(); new (this) GenericValue(u);    return *this; }\r\n    GenericValue& SetInt64(int64_t i64)     { this->~GenericValue(); new (this) GenericValue(i64);  return *this; }\r\n    GenericValue& SetUint64(uint64_t u64)   { this->~GenericValue(); new (this) GenericValue(u64);  return *this; }\r\n    GenericValue& SetDouble(double d)       { this->~GenericValue(); new (this) GenericValue(d);    return *this; }\r\n    GenericValue& SetFloat(float f)         { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }\r\n\r\n    //@}\r\n\r\n    //!@name String\r\n    //@{\r\n\r\n    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }\r\n\r\n    //! Get the length of string.\r\n    /*! Since rapidjson permits \"\\\\u0000\" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().\r\n    */\r\n    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }\r\n\r\n    //! Set this value as a string without copying source string.\r\n    /*! This version has better performance with supplied length, and also support string containing null character.\r\n        \\param s source string pointer. \r\n        \\param length The length of source string, excluding the trailing null terminator.\r\n        \\return The value itself for fluent API.\r\n        \\post IsString() == true && GetString() == s && GetStringLength() == length\r\n        \\see SetString(StringRefType)\r\n    */\r\n    GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }\r\n\r\n    //! Set this value as a string without copying source string.\r\n    /*! \\param s source string reference\r\n        \\return The value itself for fluent API.\r\n        \\post IsString() == true && GetString() == s && GetStringLength() == s.length\r\n    */\r\n    GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }\r\n\r\n    //! Set this value as a string by copying from source string.\r\n    /*! This version has better performance with supplied length, and also support string containing null character.\r\n        \\param s source string. \r\n        \\param length The length of source string, excluding the trailing null terminator.\r\n        \\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length\r\n    */\r\n    GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); }\r\n\r\n    //! Set this value as a string by copying from source string.\r\n    /*! \\param s source string. \r\n        \\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length\r\n    */\r\n    GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); }\r\n\r\n    //! Set this value as a string by copying from source string.\r\n    /*! \\param s source string reference\r\n        \\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length\r\n    */\r\n    GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Set this value as a string by copying from source string.\r\n    /*! \\param s source string.\r\n        \\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().\r\n        \\return The value itself for fluent API.\r\n        \\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()\r\n        \\note Requires the definition of the preprocessor symbol \\ref RAPIDJSON_HAS_STDSTRING.\r\n    */\r\n    GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); }\r\n#endif\r\n\r\n    //@}\r\n\r\n    //!@name Array\r\n    //@{\r\n\r\n    //! Templated version for checking whether this value is type T.\r\n    /*!\r\n        \\tparam T Either \\c bool, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t, \\c double, \\c float, \\c const \\c char*, \\c std::basic_string<Ch>\r\n    */\r\n    template <typename T>\r\n    bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }\r\n\r\n    template <typename T>\r\n    T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }\r\n\r\n    template <typename T>\r\n    T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }\r\n\r\n    template<typename T>\r\n    ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }\r\n\r\n    template<typename T>\r\n    ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }\r\n\r\n    //@}\r\n\r\n    //! Generate events of this value to a Handler.\r\n    /*! This function adopts the GoF visitor pattern.\r\n        Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.\r\n        It can also be used to deep clone this value via GenericDocument, which is also a Handler.\r\n        \\tparam Handler type of handler.\r\n        \\param handler An object implementing concept Handler.\r\n    */\r\n    template <typename Handler>\r\n    bool Accept(Handler& handler) const {\r\n        switch(GetType()) {\r\n        case kNullType:     return handler.Null();\r\n        case kFalseType:    return handler.Bool(false);\r\n        case kTrueType:     return handler.Bool(true);\r\n\r\n        case kObjectType:\r\n            if (RAPIDJSON_UNLIKELY(!handler.StartObject()))\r\n                return false;\r\n            for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {\r\n                RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.\r\n                if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))\r\n                    return false;\r\n                if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))\r\n                    return false;\r\n            }\r\n            return handler.EndObject(data_.o.size);\r\n\r\n        case kArrayType:\r\n            if (RAPIDJSON_UNLIKELY(!handler.StartArray()))\r\n                return false;\r\n            for (const GenericValue* v = Begin(); v != End(); ++v)\r\n                if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))\r\n                    return false;\r\n            return handler.EndArray(data_.a.size);\r\n    \r\n        case kStringType:\r\n            return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);\r\n    \r\n        default:\r\n            RAPIDJSON_ASSERT(GetType() == kNumberType);\r\n            if (IsDouble())         return handler.Double(data_.n.d);\r\n            else if (IsInt())       return handler.Int(data_.n.i.i);\r\n            else if (IsUint())      return handler.Uint(data_.n.u.u);\r\n            else if (IsInt64())     return handler.Int64(data_.n.i64);\r\n            else                    return handler.Uint64(data_.n.u64);\r\n        }\r\n    }\r\n\r\nprivate:\r\n    template <typename, typename> friend class GenericValue;\r\n    template <typename, typename, typename> friend class GenericDocument;\r\n\r\n    enum {\r\n        kBoolFlag       = 0x0008,\r\n        kNumberFlag     = 0x0010,\r\n        kIntFlag        = 0x0020,\r\n        kUintFlag       = 0x0040,\r\n        kInt64Flag      = 0x0080,\r\n        kUint64Flag     = 0x0100,\r\n        kDoubleFlag     = 0x0200,\r\n        kStringFlag     = 0x0400,\r\n        kCopyFlag       = 0x0800,\r\n        kInlineStrFlag  = 0x1000,\r\n\r\n        // Initial flags of different types.\r\n        kNullFlag = kNullType,\r\n        kTrueFlag = kTrueType | kBoolFlag,\r\n        kFalseFlag = kFalseType | kBoolFlag,\r\n        kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,\r\n        kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,\r\n        kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,\r\n        kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,\r\n        kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,\r\n        kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,\r\n        kConstStringFlag = kStringType | kStringFlag,\r\n        kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,\r\n        kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,\r\n        kObjectFlag = kObjectType,\r\n        kArrayFlag = kArrayType,\r\n\r\n        kTypeMask = 0x07\r\n    };\r\n\r\n    static const SizeType kDefaultArrayCapacity = 16;\r\n    static const SizeType kDefaultObjectCapacity = 16;\r\n\r\n    struct Flag {\r\n#if RAPIDJSON_48BITPOINTER_OPTIMIZATION\r\n        char payload[sizeof(SizeType) * 2 + 6];     // 2 x SizeType + lower 48-bit pointer\r\n#elif RAPIDJSON_64BIT\r\n        char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes\r\n#else\r\n        char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes\r\n#endif\r\n        uint16_t flags;\r\n    };\r\n\r\n    struct String {\r\n        SizeType length;\r\n        SizeType hashcode;  //!< reserved\r\n        const Ch* str;\r\n    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode\r\n\r\n    // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars\r\n    // (excluding the terminating zero) and store a value to determine the length of the contained\r\n    // string in the last character str[LenPos] by storing \"MaxSize - length\" there. If the string\r\n    // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as\r\n    // the string terminator as well. For getting the string length back from that value just use\r\n    // \"MaxSize - str[LenPos]\".\r\n    // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,\r\n    // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).\r\n    struct ShortString {\r\n        enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };\r\n        Ch str[MaxChars];\r\n\r\n        inline static bool Usable(SizeType len) { return                       (MaxSize >= len); }\r\n        inline void     SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize -  len); }\r\n        inline SizeType GetLength() const       { return  static_cast<SizeType>(MaxSize -  str[LenPos]); }\r\n    };  // at most as many bytes as \"String\" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode\r\n\r\n    // By using proper binary layout, retrieval of different integer types do not need conversions.\r\n    union Number {\r\n#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN\r\n        struct I {\r\n            int i;\r\n            char padding[4];\r\n        }i;\r\n        struct U {\r\n            unsigned u;\r\n            char padding2[4];\r\n        }u;\r\n#else\r\n        struct I {\r\n            char padding[4];\r\n            int i;\r\n        }i;\r\n        struct U {\r\n            char padding2[4];\r\n            unsigned u;\r\n        }u;\r\n#endif\r\n        int64_t i64;\r\n        uint64_t u64;\r\n        double d;\r\n    };  // 8 bytes\r\n\r\n    struct ObjectData {\r\n        SizeType size;\r\n        SizeType capacity;\r\n        Member* members;\r\n    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode\r\n\r\n    struct ArrayData {\r\n        SizeType size;\r\n        SizeType capacity;\r\n        GenericValue* elements;\r\n    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode\r\n\r\n    union Data {\r\n        String s;\r\n        ShortString ss;\r\n        Number n;\r\n        ObjectData o;\r\n        ArrayData a;\r\n        Flag f;\r\n    };  // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION\r\n\r\n    RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }\r\n    RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }\r\n    RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }\r\n    RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }\r\n    RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }\r\n    RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }\r\n\r\n    // Initialize this value as array with initial data, without calling destructor.\r\n    void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {\r\n        data_.f.flags = kArrayFlag;\r\n        if (count) {\r\n            GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));\r\n            SetElementsPointer(e);\r\nRAPIDJSON_DIAG_PUSH\r\n#if defined(__GNUC__) && __GNUC__ >= 8\r\nRAPIDJSON_DIAG_OFF(class-memaccess) // ignore complains from gcc that no trivial copy constructor exists.\r\n#endif\r\n            std::memcpy(e, values, count * sizeof(GenericValue));\r\nRAPIDJSON_DIAG_POP\r\n        }\r\n        else\r\n            SetElementsPointer(0);\r\n        data_.a.size = data_.a.capacity = count;\r\n    }\r\n\r\n    //! Initialize this value as object with initial data, without calling destructor.\r\n    void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {\r\n        data_.f.flags = kObjectFlag;\r\n        if (count) {\r\n            Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));\r\n            SetMembersPointer(m);\r\nRAPIDJSON_DIAG_PUSH\r\n#if defined(__GNUC__) && __GNUC__ >= 8\r\nRAPIDJSON_DIAG_OFF(class-memaccess) // ignore complains from gcc that no trivial copy constructor exists.\r\n#endif\r\n            std::memcpy(m, members, count * sizeof(Member));\r\nRAPIDJSON_DIAG_POP\r\n        }\r\n        else\r\n            SetMembersPointer(0);\r\n        data_.o.size = data_.o.capacity = count;\r\n    }\r\n\r\n    //! Initialize this value as constant string, without calling destructor.\r\n    void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {\r\n        data_.f.flags = kConstStringFlag;\r\n        SetStringPointer(s);\r\n        data_.s.length = s.length;\r\n    }\r\n\r\n    //! Initialize this value as copy string with initial data, without calling destructor.\r\n    void SetStringRaw(StringRefType s, Allocator& allocator) {\r\n        Ch* str = 0;\r\n        if (ShortString::Usable(s.length)) {\r\n            data_.f.flags = kShortStringFlag;\r\n            data_.ss.SetLength(s.length);\r\n            str = data_.ss.str;\r\n        } else {\r\n            data_.f.flags = kCopyStringFlag;\r\n            data_.s.length = s.length;\r\n            str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));\r\n            SetStringPointer(str);\r\n        }\r\n        std::memcpy(str, s, s.length * sizeof(Ch));\r\n        str[s.length] = '\\0';\r\n    }\r\n\r\n    //! Assignment without calling destructor\r\n    void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {\r\n        data_ = rhs.data_;\r\n        // data_.f.flags = rhs.data_.f.flags;\r\n        rhs.data_.f.flags = kNullFlag;\r\n    }\r\n\r\n    template <typename SourceAllocator>\r\n    bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {\r\n        RAPIDJSON_ASSERT(IsString());\r\n        RAPIDJSON_ASSERT(rhs.IsString());\r\n\r\n        const SizeType len1 = GetStringLength();\r\n        const SizeType len2 = rhs.GetStringLength();\r\n        if(len1 != len2) { return false; }\r\n\r\n        const Ch* const str1 = GetString();\r\n        const Ch* const str2 = rhs.GetString();\r\n        if(str1 == str2) { return true; } // fast path for constant string\r\n\r\n        return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);\r\n    }\r\n\r\n    Data data_;\r\n};\r\n\r\n//! GenericValue with UTF8 encoding\r\ntypedef GenericValue<UTF8<> > Value;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericDocument \r\n\r\n//! A document for parsing JSON text as DOM.\r\n/*!\r\n    \\note implements Handler concept\r\n    \\tparam Encoding Encoding for both parsing and string storage.\r\n    \\tparam Allocator Allocator for allocating memory for the DOM\r\n    \\tparam StackAllocator Allocator for allocating memory for stack during parsing.\r\n    \\warning Although GenericDocument inherits from GenericValue, the API does \\b not provide any virtual functions, especially no virtual destructor.  To avoid memory leaks, do not \\c delete a GenericDocument object via a pointer to a GenericValue.\r\n*/\r\ntemplate <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>\r\nclass GenericDocument : public GenericValue<Encoding, Allocator> {\r\npublic:\r\n    typedef typename Encoding::Ch Ch;                       //!< Character type derived from Encoding.\r\n    typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of the document.\r\n    typedef Allocator AllocatorType;                        //!< Allocator type from template parameter.\r\n\r\n    //! Constructor\r\n    /*! Creates an empty document of specified type.\r\n        \\param type             Mandatory type of object to create.\r\n        \\param allocator        Optional allocator for allocating memory.\r\n        \\param stackCapacity    Optional initial capacity of stack in bytes.\r\n        \\param stackAllocator   Optional allocator for allocating memory for stack.\r\n    */\r\n    explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :\r\n        GenericValue<Encoding, Allocator>(type),  allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()\r\n    {\r\n        if (!allocator_)\r\n            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n    }\r\n\r\n    //! Constructor\r\n    /*! Creates an empty document which type is Null. \r\n        \\param allocator        Optional allocator for allocating memory.\r\n        \\param stackCapacity    Optional initial capacity of stack in bytes.\r\n        \\param stackAllocator   Optional allocator for allocating memory for stack.\r\n    */\r\n    GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : \r\n        allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()\r\n    {\r\n        if (!allocator_)\r\n            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    //! Move constructor in C++11\r\n    GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT\r\n        : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document\r\n          allocator_(rhs.allocator_),\r\n          ownAllocator_(rhs.ownAllocator_),\r\n          stack_(std::move(rhs.stack_)),\r\n          parseResult_(rhs.parseResult_)\r\n    {\r\n        rhs.allocator_ = 0;\r\n        rhs.ownAllocator_ = 0;\r\n        rhs.parseResult_ = ParseResult();\r\n    }\r\n#endif\r\n\r\n    ~GenericDocument() {\r\n        Destroy();\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    //! Move assignment in C++11\r\n    GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT\r\n    {\r\n        // The cast to ValueType is necessary here, because otherwise it would\r\n        // attempt to call GenericValue's templated assignment operator.\r\n        ValueType::operator=(std::forward<ValueType>(rhs));\r\n\r\n        // Calling the destructor here would prematurely call stack_'s destructor\r\n        Destroy();\r\n\r\n        allocator_ = rhs.allocator_;\r\n        ownAllocator_ = rhs.ownAllocator_;\r\n        stack_ = std::move(rhs.stack_);\r\n        parseResult_ = rhs.parseResult_;\r\n\r\n        rhs.allocator_ = 0;\r\n        rhs.ownAllocator_ = 0;\r\n        rhs.parseResult_ = ParseResult();\r\n\r\n        return *this;\r\n    }\r\n#endif\r\n\r\n    //! Exchange the contents of this document with those of another.\r\n    /*!\r\n        \\param rhs Another document.\r\n        \\note Constant complexity.\r\n        \\see GenericValue::Swap\r\n    */\r\n    GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {\r\n        ValueType::Swap(rhs);\r\n        stack_.Swap(rhs.stack_);\r\n        internal::Swap(allocator_, rhs.allocator_);\r\n        internal::Swap(ownAllocator_, rhs.ownAllocator_);\r\n        internal::Swap(parseResult_, rhs.parseResult_);\r\n        return *this;\r\n    }\r\n\r\n    // Allow Swap with ValueType.\r\n    // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names.\r\n    using ValueType::Swap;\r\n\r\n    //! free-standing swap function helper\r\n    /*!\r\n        Helper function to enable support for common swap implementation pattern based on \\c std::swap:\r\n        \\code\r\n        void swap(MyClass& a, MyClass& b) {\r\n            using std::swap;\r\n            swap(a.doc, b.doc);\r\n            // ...\r\n        }\r\n        \\endcode\r\n        \\see Swap()\r\n     */\r\n    friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }\r\n\r\n    //! Populate this document by a generator which produces SAX events.\r\n    /*! \\tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.\r\n        \\param g Generator functor which sends SAX events to the parameter.\r\n        \\return The document itself for fluent API.\r\n    */\r\n    template <typename Generator>\r\n    GenericDocument& Populate(Generator& g) {\r\n        ClearStackOnExit scope(*this);\r\n        if (g(*this)) {\r\n            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object\r\n            ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document\r\n        }\r\n        return *this;\r\n    }\r\n\r\n    //!@name Parse from stream\r\n    //!@{\r\n\r\n    //! Parse JSON text from an input stream (with Encoding conversion)\r\n    /*! \\tparam parseFlags Combination of \\ref ParseFlag.\r\n        \\tparam SourceEncoding Encoding of input stream\r\n        \\tparam InputStream Type of input stream, implementing Stream concept\r\n        \\param is Input stream to be parsed.\r\n        \\return The document itself for fluent API.\r\n    */\r\n    template <unsigned parseFlags, typename SourceEncoding, typename InputStream>\r\n    GenericDocument& ParseStream(InputStream& is) {\r\n        GenericReader<SourceEncoding, Encoding, StackAllocator> reader(\r\n            stack_.HasAllocator() ? &stack_.GetAllocator() : 0);\r\n        ClearStackOnExit scope(*this);\r\n        parseResult_ = reader.template Parse<parseFlags>(is, *this);\r\n        if (parseResult_) {\r\n            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object\r\n            ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document\r\n        }\r\n        return *this;\r\n    }\r\n\r\n    //! Parse JSON text from an input stream\r\n    /*! \\tparam parseFlags Combination of \\ref ParseFlag.\r\n        \\tparam InputStream Type of input stream, implementing Stream concept\r\n        \\param is Input stream to be parsed.\r\n        \\return The document itself for fluent API.\r\n    */\r\n    template <unsigned parseFlags, typename InputStream>\r\n    GenericDocument& ParseStream(InputStream& is) {\r\n        return ParseStream<parseFlags, Encoding, InputStream>(is);\r\n    }\r\n\r\n    //! Parse JSON text from an input stream (with \\ref kParseDefaultFlags)\r\n    /*! \\tparam InputStream Type of input stream, implementing Stream concept\r\n        \\param is Input stream to be parsed.\r\n        \\return The document itself for fluent API.\r\n    */\r\n    template <typename InputStream>\r\n    GenericDocument& ParseStream(InputStream& is) {\r\n        return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);\r\n    }\r\n    //!@}\r\n\r\n    //!@name Parse in-place from mutable string\r\n    //!@{\r\n\r\n    //! Parse JSON text from a mutable string\r\n    /*! \\tparam parseFlags Combination of \\ref ParseFlag.\r\n        \\param str Mutable zero-terminated string to be parsed.\r\n        \\return The document itself for fluent API.\r\n    */\r\n    template <unsigned parseFlags>\r\n    GenericDocument& ParseInsitu(Ch* str) {\r\n        GenericInsituStringStream<Encoding> s(str);\r\n        return ParseStream<parseFlags | kParseInsituFlag>(s);\r\n    }\r\n\r\n    //! Parse JSON text from a mutable string (with \\ref kParseDefaultFlags)\r\n    /*! \\param str Mutable zero-terminated string to be parsed.\r\n        \\return The document itself for fluent API.\r\n    */\r\n    GenericDocument& ParseInsitu(Ch* str) {\r\n        return ParseInsitu<kParseDefaultFlags>(str);\r\n    }\r\n    //!@}\r\n\r\n    //!@name Parse from read-only string\r\n    //!@{\r\n\r\n    //! Parse JSON text from a read-only string (with Encoding conversion)\r\n    /*! \\tparam parseFlags Combination of \\ref ParseFlag (must not contain \\ref kParseInsituFlag).\r\n        \\tparam SourceEncoding Transcoding from input Encoding\r\n        \\param str Read-only zero-terminated string to be parsed.\r\n    */\r\n    template <unsigned parseFlags, typename SourceEncoding>\r\n    GenericDocument& Parse(const typename SourceEncoding::Ch* str) {\r\n        RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));\r\n        GenericStringStream<SourceEncoding> s(str);\r\n        return ParseStream<parseFlags, SourceEncoding>(s);\r\n    }\r\n\r\n    //! Parse JSON text from a read-only string\r\n    /*! \\tparam parseFlags Combination of \\ref ParseFlag (must not contain \\ref kParseInsituFlag).\r\n        \\param str Read-only zero-terminated string to be parsed.\r\n    */\r\n    template <unsigned parseFlags>\r\n    GenericDocument& Parse(const Ch* str) {\r\n        return Parse<parseFlags, Encoding>(str);\r\n    }\r\n\r\n    //! Parse JSON text from a read-only string (with \\ref kParseDefaultFlags)\r\n    /*! \\param str Read-only zero-terminated string to be parsed.\r\n    */\r\n    GenericDocument& Parse(const Ch* str) {\r\n        return Parse<kParseDefaultFlags>(str);\r\n    }\r\n\r\n    template <unsigned parseFlags, typename SourceEncoding>\r\n    GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {\r\n        RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));\r\n        MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));\r\n        EncodedInputStream<SourceEncoding, MemoryStream> is(ms);\r\n        ParseStream<parseFlags, SourceEncoding>(is);\r\n        return *this;\r\n    }\r\n\r\n    template <unsigned parseFlags>\r\n    GenericDocument& Parse(const Ch* str, size_t length) {\r\n        return Parse<parseFlags, Encoding>(str, length);\r\n    }\r\n    \r\n    GenericDocument& Parse(const Ch* str, size_t length) {\r\n        return Parse<kParseDefaultFlags>(str, length);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    template <unsigned parseFlags, typename SourceEncoding>\r\n    GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {\r\n        // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)\r\n        return Parse<parseFlags, SourceEncoding>(str.c_str());\r\n    }\r\n\r\n    template <unsigned parseFlags>\r\n    GenericDocument& Parse(const std::basic_string<Ch>& str) {\r\n        return Parse<parseFlags, Encoding>(str.c_str());\r\n    }\r\n\r\n    GenericDocument& Parse(const std::basic_string<Ch>& str) {\r\n        return Parse<kParseDefaultFlags>(str);\r\n    }\r\n#endif // RAPIDJSON_HAS_STDSTRING    \r\n\r\n    //!@}\r\n\r\n    //!@name Handling parse errors\r\n    //!@{\r\n\r\n    //! Whether a parse error has occurred in the last parsing.\r\n    bool HasParseError() const { return parseResult_.IsError(); }\r\n\r\n    //! Get the \\ref ParseErrorCode of last parsing.\r\n    ParseErrorCode GetParseError() const { return parseResult_.Code(); }\r\n\r\n    //! Get the position of last parsing error in input, 0 otherwise.\r\n    size_t GetErrorOffset() const { return parseResult_.Offset(); }\r\n\r\n    //! Implicit conversion to get the last parse result\r\n#ifndef __clang // -Wdocumentation\r\n    /*! \\return \\ref ParseResult of the last parse operation\r\n\r\n        \\code\r\n          Document doc;\r\n          ParseResult ok = doc.Parse(json);\r\n          if (!ok)\r\n            printf( \"JSON parse error: %s (%u)\\n\", GetParseError_En(ok.Code()), ok.Offset());\r\n        \\endcode\r\n     */\r\n#endif\r\n    operator ParseResult() const { return parseResult_; }\r\n    //!@}\r\n\r\n    //! Get the allocator of this document.\r\n    Allocator& GetAllocator() {\r\n        RAPIDJSON_ASSERT(allocator_);\r\n        return *allocator_;\r\n    }\r\n\r\n    //! Get the capacity of stack in bytes.\r\n    size_t GetStackCapacity() const { return stack_.GetCapacity(); }\r\n\r\nprivate:\r\n    // clear stack on any exit from ParseStream, e.g. due to exception\r\n    struct ClearStackOnExit {\r\n        explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}\r\n        ~ClearStackOnExit() { d_.ClearStack(); }\r\n    private:\r\n        ClearStackOnExit(const ClearStackOnExit&);\r\n        ClearStackOnExit& operator=(const ClearStackOnExit&);\r\n        GenericDocument& d_;\r\n    };\r\n\r\n    // callers of the following private Handler functions\r\n    // template <typename,typename,typename> friend class GenericReader; // for parsing\r\n    template <typename, typename> friend class GenericValue; // for deep copying\r\n\r\npublic:\r\n    // Implementation of Handler\r\n    bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }\r\n    bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }\r\n    bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }\r\n    bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }\r\n    bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }\r\n    bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }\r\n    bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }\r\n\r\n    bool RawNumber(const Ch* str, SizeType length, bool copy) { \r\n        if (copy) \r\n            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());\r\n        else\r\n            new (stack_.template Push<ValueType>()) ValueType(str, length);\r\n        return true;\r\n    }\r\n\r\n    bool String(const Ch* str, SizeType length, bool copy) { \r\n        if (copy) \r\n            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());\r\n        else\r\n            new (stack_.template Push<ValueType>()) ValueType(str, length);\r\n        return true;\r\n    }\r\n\r\n    bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }\r\n    \r\n    bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }\r\n\r\n    bool EndObject(SizeType memberCount) {\r\n        typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);\r\n        stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());\r\n        return true;\r\n    }\r\n\r\n    bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }\r\n    \r\n    bool EndArray(SizeType elementCount) {\r\n        ValueType* elements = stack_.template Pop<ValueType>(elementCount);\r\n        stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());\r\n        return true;\r\n    }\r\n\r\nprivate:\r\n    //! Prohibit copying\r\n    GenericDocument(const GenericDocument&);\r\n    //! Prohibit assignment\r\n    GenericDocument& operator=(const GenericDocument&);\r\n\r\n    void ClearStack() {\r\n        if (Allocator::kNeedFree)\r\n            while (stack_.GetSize() > 0)    // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)\r\n                (stack_.template Pop<ValueType>(1))->~ValueType();\r\n        else\r\n            stack_.Clear();\r\n        stack_.ShrinkToFit();\r\n    }\r\n\r\n    void Destroy() {\r\n        RAPIDJSON_DELETE(ownAllocator_);\r\n    }\r\n\r\n    static const size_t kDefaultStackCapacity = 1024;\r\n    Allocator* allocator_;\r\n    Allocator* ownAllocator_;\r\n    internal::Stack<StackAllocator> stack_;\r\n    ParseResult parseResult_;\r\n};\r\n\r\n//! GenericDocument with UTF8 encoding\r\ntypedef GenericDocument<UTF8<> > Document;\r\n\r\n//! Helper class for accessing Value of array type.\r\n/*!\r\n    Instance of this helper class is obtained by \\c GenericValue::GetArray().\r\n    In addition to all APIs for array type, it provides range-based for loop if \\c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.\r\n*/\r\ntemplate <bool Const, typename ValueT>\r\nclass GenericArray {\r\npublic:\r\n    typedef GenericArray<true, ValueT> ConstArray;\r\n    typedef GenericArray<false, ValueT> Array;\r\n    typedef ValueT PlainType;\r\n    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;\r\n    typedef ValueType* ValueIterator;  // This may be const or non-const iterator\r\n    typedef const ValueT* ConstValueIterator;\r\n    typedef typename ValueType::AllocatorType AllocatorType;\r\n    typedef typename ValueType::StringRefType StringRefType;\r\n\r\n    template <typename, typename>\r\n    friend class GenericValue;\r\n\r\n    GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}\r\n    GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }\r\n    ~GenericArray() {}\r\n\r\n    SizeType Size() const { return value_.Size(); }\r\n    SizeType Capacity() const { return value_.Capacity(); }\r\n    bool Empty() const { return value_.Empty(); }\r\n    void Clear() const { value_.Clear(); }\r\n    ValueType& operator[](SizeType index) const {  return value_[index]; }\r\n    ValueIterator Begin() const { return value_.Begin(); }\r\n    ValueIterator End() const { return value_.End(); }\r\n    GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }\r\n    GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }\r\n#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }\r\n    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }\r\n    GenericArray PopBack() const { value_.PopBack(); return *this; }\r\n    ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }\r\n    ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RANGE_FOR\r\n    ValueIterator begin() const { return value_.Begin(); }\r\n    ValueIterator end() const { return value_.End(); }\r\n#endif\r\n\r\nprivate:\r\n    GenericArray();\r\n    GenericArray(ValueType& value) : value_(value) {}\r\n    ValueType& value_;\r\n};\r\n\r\n//! Helper class for accessing Value of object type.\r\n/*!\r\n    Instance of this helper class is obtained by \\c GenericValue::GetObject().\r\n    In addition to all APIs for array type, it provides range-based for loop if \\c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.\r\n*/\r\ntemplate <bool Const, typename ValueT>\r\nclass GenericObject {\r\npublic:\r\n    typedef GenericObject<true, ValueT> ConstObject;\r\n    typedef GenericObject<false, ValueT> Object;\r\n    typedef ValueT PlainType;\r\n    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;\r\n    typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator;  // This may be const or non-const iterator\r\n    typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;\r\n    typedef typename ValueType::AllocatorType AllocatorType;\r\n    typedef typename ValueType::StringRefType StringRefType;\r\n    typedef typename ValueType::EncodingType EncodingType;\r\n    typedef typename ValueType::Ch Ch;\r\n\r\n    template <typename, typename>\r\n    friend class GenericValue;\r\n\r\n    GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}\r\n    GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }\r\n    ~GenericObject() {}\r\n\r\n    SizeType MemberCount() const { return value_.MemberCount(); }\r\n    SizeType MemberCapacity() const { return value_.MemberCapacity(); }\r\n    bool ObjectEmpty() const { return value_.ObjectEmpty(); }\r\n    template <typename T> ValueType& operator[](T* name) const { return value_[name]; }\r\n    template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }\r\n#endif\r\n    MemberIterator MemberBegin() const { return value_.MemberBegin(); }\r\n    MemberIterator MemberEnd() const { return value_.MemberEnd(); }\r\n    GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; }\r\n    bool HasMember(const Ch* name) const { return value_.HasMember(name); }\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }\r\n#endif\r\n    template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }\r\n    MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }\r\n    template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }\r\n#endif\r\n    GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n#endif\r\n    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }\r\n    void RemoveAllMembers() { value_.RemoveAllMembers(); }\r\n    bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }\r\n#endif\r\n    template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }\r\n    MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }\r\n    MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }\r\n    MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }\r\n    bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }\r\n#endif\r\n    template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RANGE_FOR\r\n    MemberIterator begin() const { return value_.MemberBegin(); }\r\n    MemberIterator end() const { return value_.MemberEnd(); }\r\n#endif\r\n\r\nprivate:\r\n    GenericObject();\r\n    GenericObject(ValueType& value) : value_(value) {}\r\n    ValueType& value_;\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\nRAPIDJSON_DIAG_POP\r\n\r\n#endif // RAPIDJSON_DOCUMENT_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/encodedstream.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ENCODEDSTREAM_H_\r\n#define RAPIDJSON_ENCODEDSTREAM_H_\r\n\r\n#include \"stream.h\"\r\n#include \"memorystream.h\"\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Input byte stream wrapper with a statically bound encoding.\r\n/*!\r\n    \\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.\r\n    \\tparam InputByteStream Type of input byte stream. For example, FileReadStream.\r\n*/\r\ntemplate <typename Encoding, typename InputByteStream>\r\nclass EncodedInputStream {\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\npublic:\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    EncodedInputStream(InputByteStream& is) : is_(is) { \r\n        current_ = Encoding::TakeBOM(is_);\r\n    }\r\n\r\n    Ch Peek() const { return current_; }\r\n    Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }\r\n    size_t Tell() const { return is_.Tell(); }\r\n\r\n    // Not implemented\r\n    void Put(Ch) { RAPIDJSON_ASSERT(false); }\r\n    void Flush() { RAPIDJSON_ASSERT(false); } \r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\nprivate:\r\n    EncodedInputStream(const EncodedInputStream&);\r\n    EncodedInputStream& operator=(const EncodedInputStream&);\r\n\r\n    InputByteStream& is_;\r\n    Ch current_;\r\n};\r\n\r\n//! Specialized for UTF8 MemoryStream.\r\ntemplate <>\r\nclass EncodedInputStream<UTF8<>, MemoryStream> {\r\npublic:\r\n    typedef UTF8<>::Ch Ch;\r\n\r\n    EncodedInputStream(MemoryStream& is) : is_(is) {\r\n        if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();\r\n        if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();\r\n        if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();\r\n    }\r\n    Ch Peek() const { return is_.Peek(); }\r\n    Ch Take() { return is_.Take(); }\r\n    size_t Tell() const { return is_.Tell(); }\r\n\r\n    // Not implemented\r\n    void Put(Ch) {}\r\n    void Flush() {} \r\n    Ch* PutBegin() { return 0; }\r\n    size_t PutEnd(Ch*) { return 0; }\r\n\r\n    MemoryStream& is_;\r\n\r\nprivate:\r\n    EncodedInputStream(const EncodedInputStream&);\r\n    EncodedInputStream& operator=(const EncodedInputStream&);\r\n};\r\n\r\n//! Output byte stream wrapper with statically bound encoding.\r\n/*!\r\n    \\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.\r\n    \\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.\r\n*/\r\ntemplate <typename Encoding, typename OutputByteStream>\r\nclass EncodedOutputStream {\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\npublic:\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { \r\n        if (putBOM)\r\n            Encoding::PutBOM(os_);\r\n    }\r\n\r\n    void Put(Ch c) { Encoding::Put(os_, c);  }\r\n    void Flush() { os_.Flush(); }\r\n\r\n    // Not implemented\r\n    Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}\r\n    Ch Take() { RAPIDJSON_ASSERT(false); return 0;}\r\n    size_t Tell() const { RAPIDJSON_ASSERT(false);  return 0; }\r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\nprivate:\r\n    EncodedOutputStream(const EncodedOutputStream&);\r\n    EncodedOutputStream& operator=(const EncodedOutputStream&);\r\n\r\n    OutputByteStream& os_;\r\n};\r\n\r\n#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x\r\n\r\n//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.\r\n/*!\r\n    \\tparam CharType Type of character for reading.\r\n    \\tparam InputByteStream type of input byte stream to be wrapped.\r\n*/\r\ntemplate <typename CharType, typename InputByteStream>\r\nclass AutoUTFInputStream {\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\npublic:\r\n    typedef CharType Ch;\r\n\r\n    //! Constructor.\r\n    /*!\r\n        \\param is input stream to be wrapped.\r\n        \\param type UTF encoding type if it is not detected from the stream.\r\n    */\r\n    AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {\r\n        RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);        \r\n        DetectType();\r\n        static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };\r\n        takeFunc_ = f[type_];\r\n        current_ = takeFunc_(*is_);\r\n    }\r\n\r\n    UTFType GetType() const { return type_; }\r\n    bool HasBOM() const { return hasBOM_; }\r\n\r\n    Ch Peek() const { return current_; }\r\n    Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }\r\n    size_t Tell() const { return is_->Tell(); }\r\n\r\n    // Not implemented\r\n    void Put(Ch) { RAPIDJSON_ASSERT(false); }\r\n    void Flush() { RAPIDJSON_ASSERT(false); } \r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\nprivate:\r\n    AutoUTFInputStream(const AutoUTFInputStream&);\r\n    AutoUTFInputStream& operator=(const AutoUTFInputStream&);\r\n\r\n    // Detect encoding type with BOM or RFC 4627\r\n    void DetectType() {\r\n        // BOM (Byte Order Mark):\r\n        // 00 00 FE FF  UTF-32BE\r\n        // FF FE 00 00  UTF-32LE\r\n        // FE FF        UTF-16BE\r\n        // FF FE        UTF-16LE\r\n        // EF BB BF     UTF-8\r\n\r\n        const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());\r\n        if (!c)\r\n            return;\r\n\r\n        unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));\r\n        hasBOM_ = false;\r\n        if (bom == 0xFFFE0000)                  { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }\r\n        else if (bom == 0x0000FEFF)             { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }\r\n        else if ((bom & 0xFFFF) == 0xFFFE)      { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take();                           }\r\n        else if ((bom & 0xFFFF) == 0xFEFF)      { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take();                           }\r\n        else if ((bom & 0xFFFFFF) == 0xBFBBEF)  { type_ = kUTF8;    hasBOM_ = true; is_->Take(); is_->Take(); is_->Take();              }\r\n\r\n        // RFC 4627: Section 3\r\n        // \"Since the first two characters of a JSON text will always be ASCII\r\n        // characters [RFC0020], it is possible to determine whether an octet\r\n        // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking\r\n        // at the pattern of nulls in the first four octets.\"\r\n        // 00 00 00 xx  UTF-32BE\r\n        // 00 xx 00 xx  UTF-16BE\r\n        // xx 00 00 00  UTF-32LE\r\n        // xx 00 xx 00  UTF-16LE\r\n        // xx xx xx xx  UTF-8\r\n\r\n        if (!hasBOM_) {\r\n            int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);\r\n            switch (pattern) {\r\n            case 0x08: type_ = kUTF32BE; break;\r\n            case 0x0A: type_ = kUTF16BE; break;\r\n            case 0x01: type_ = kUTF32LE; break;\r\n            case 0x05: type_ = kUTF16LE; break;\r\n            case 0x0F: type_ = kUTF8;    break;\r\n            default: break; // Use type defined by user.\r\n            }\r\n        }\r\n\r\n        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.\r\n        if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);\r\n        if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);\r\n    }\r\n\r\n    typedef Ch (*TakeFunc)(InputByteStream& is);\r\n    InputByteStream* is_;\r\n    UTFType type_;\r\n    Ch current_;\r\n    TakeFunc takeFunc_;\r\n    bool hasBOM_;\r\n};\r\n\r\n//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.\r\n/*!\r\n    \\tparam CharType Type of character for writing.\r\n    \\tparam OutputByteStream type of output byte stream to be wrapped.\r\n*/\r\ntemplate <typename CharType, typename OutputByteStream>\r\nclass AutoUTFOutputStream {\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\npublic:\r\n    typedef CharType Ch;\r\n\r\n    //! Constructor.\r\n    /*!\r\n        \\param os output stream to be wrapped.\r\n        \\param type UTF encoding type.\r\n        \\param putBOM Whether to write BOM at the beginning of the stream.\r\n    */\r\n    AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {\r\n        RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);\r\n\r\n        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.\r\n        if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);\r\n        if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);\r\n\r\n        static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };\r\n        putFunc_ = f[type_];\r\n\r\n        if (putBOM)\r\n            PutBOM();\r\n    }\r\n\r\n    UTFType GetType() const { return type_; }\r\n\r\n    void Put(Ch c) { putFunc_(*os_, c); }\r\n    void Flush() { os_->Flush(); } \r\n\r\n    // Not implemented\r\n    Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}\r\n    Ch Take() { RAPIDJSON_ASSERT(false); return 0;}\r\n    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }\r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\nprivate:\r\n    AutoUTFOutputStream(const AutoUTFOutputStream&);\r\n    AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);\r\n\r\n    void PutBOM() { \r\n        typedef void (*PutBOMFunc)(OutputByteStream&);\r\n        static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };\r\n        f[type_](*os_);\r\n    }\r\n\r\n    typedef void (*PutFunc)(OutputByteStream&, Ch);\r\n\r\n    OutputByteStream* os_;\r\n    UTFType type_;\r\n    PutFunc putFunc_;\r\n};\r\n\r\n#undef RAPIDJSON_ENCODINGS_FUNC\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_FILESTREAM_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/encodings.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ENCODINGS_H_\r\n#define RAPIDJSON_ENCODINGS_H_\r\n\r\n#include \"rapidjson.h\"\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data\r\nRAPIDJSON_DIAG_OFF(4702)  // unreachable code\r\n#elif defined(__GNUC__)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\nRAPIDJSON_DIAG_OFF(overflow)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Encoding\r\n\r\n/*! \\class rapidjson::Encoding\r\n    \\brief Concept for encoding of Unicode characters.\r\n\r\n\\code\r\nconcept Encoding {\r\n    typename Ch;    //! Type of character. A \"character\" is actually a code unit in unicode's definition.\r\n\r\n    enum { supportUnicode = 1 }; // or 0 if not supporting unicode\r\n\r\n    //! \\brief Encode a Unicode codepoint to an output stream.\r\n    //! \\param os Output stream.\r\n    //! \\param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.\r\n    template<typename OutputStream>\r\n    static void Encode(OutputStream& os, unsigned codepoint);\r\n\r\n    //! \\brief Decode a Unicode codepoint from an input stream.\r\n    //! \\param is Input stream.\r\n    //! \\param codepoint Output of the unicode codepoint.\r\n    //! \\return true if a valid codepoint can be decoded from the stream.\r\n    template <typename InputStream>\r\n    static bool Decode(InputStream& is, unsigned* codepoint);\r\n\r\n    //! \\brief Validate one Unicode codepoint from an encoded stream.\r\n    //! \\param is Input stream to obtain codepoint.\r\n    //! \\param os Output for copying one codepoint.\r\n    //! \\return true if it is valid.\r\n    //! \\note This function just validating and copying the codepoint without actually decode it.\r\n    template <typename InputStream, typename OutputStream>\r\n    static bool Validate(InputStream& is, OutputStream& os);\r\n\r\n    // The following functions are deal with byte streams.\r\n\r\n    //! Take a character from input byte stream, skip BOM if exist.\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is);\r\n\r\n    //! Take a character from input byte stream.\r\n    template <typename InputByteStream>\r\n    static Ch Take(InputByteStream& is);\r\n\r\n    //! Put BOM to output byte stream.\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os);\r\n\r\n    //! Put a character to output byte stream.\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, Ch c);\r\n};\r\n\\endcode\r\n*/\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// UTF8\r\n\r\n//! UTF-8 encoding.\r\n/*! http://en.wikipedia.org/wiki/UTF-8\r\n    http://tools.ietf.org/html/rfc3629\r\n    \\tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.\r\n    \\note implements Encoding concept\r\n*/\r\ntemplate<typename CharType = char>\r\nstruct UTF8 {\r\n    typedef CharType Ch;\r\n\r\n    enum { supportUnicode = 1 };\r\n\r\n    template<typename OutputStream>\r\n    static void Encode(OutputStream& os, unsigned codepoint) {\r\n        if (codepoint <= 0x7F) \r\n            os.Put(static_cast<Ch>(codepoint & 0xFF));\r\n        else if (codepoint <= 0x7FF) {\r\n            os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));\r\n            os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));\r\n        }\r\n        else if (codepoint <= 0xFFFF) {\r\n            os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));\r\n            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));\r\n            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));\r\n        }\r\n        else {\r\n            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);\r\n            os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));\r\n            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));\r\n            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));\r\n            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));\r\n        }\r\n    }\r\n\r\n    template<typename OutputStream>\r\n    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {\r\n        if (codepoint <= 0x7F) \r\n            PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));\r\n        else if (codepoint <= 0x7FF) {\r\n            PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));\r\n            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));\r\n        }\r\n        else if (codepoint <= 0xFFFF) {\r\n            PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));\r\n            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));\r\n            PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));\r\n        }\r\n        else {\r\n            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);\r\n            PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));\r\n            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));\r\n            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));\r\n            PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));\r\n        }\r\n    }\r\n\r\n    template <typename InputStream>\r\n    static bool Decode(InputStream& is, unsigned* codepoint) {\r\n#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)\r\n#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)\r\n#define TAIL() COPY(); TRANS(0x70)\r\n        typename InputStream::Ch c = is.Take();\r\n        if (!(c & 0x80)) {\r\n            *codepoint = static_cast<unsigned char>(c);\r\n            return true;\r\n        }\r\n\r\n        unsigned char type = GetRange(static_cast<unsigned char>(c));\r\n        if (type >= 32) {\r\n            *codepoint = 0;\r\n        } else {\r\n            *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);\r\n        }\r\n        bool result = true;\r\n        switch (type) {\r\n        case 2: TAIL(); return result;\r\n        case 3: TAIL(); TAIL(); return result;\r\n        case 4: COPY(); TRANS(0x50); TAIL(); return result;\r\n        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;\r\n        case 6: TAIL(); TAIL(); TAIL(); return result;\r\n        case 10: COPY(); TRANS(0x20); TAIL(); return result;\r\n        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;\r\n        default: return false;\r\n        }\r\n#undef COPY\r\n#undef TRANS\r\n#undef TAIL\r\n    }\r\n\r\n    template <typename InputStream, typename OutputStream>\r\n    static bool Validate(InputStream& is, OutputStream& os) {\r\n#define COPY() os.Put(c = is.Take())\r\n#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)\r\n#define TAIL() COPY(); TRANS(0x70)\r\n        Ch c;\r\n        COPY();\r\n        if (!(c & 0x80))\r\n            return true;\r\n\r\n        bool result = true;\r\n        switch (GetRange(static_cast<unsigned char>(c))) {\r\n        case 2: TAIL(); return result;\r\n        case 3: TAIL(); TAIL(); return result;\r\n        case 4: COPY(); TRANS(0x50); TAIL(); return result;\r\n        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;\r\n        case 6: TAIL(); TAIL(); TAIL(); return result;\r\n        case 10: COPY(); TRANS(0x20); TAIL(); return result;\r\n        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;\r\n        default: return false;\r\n        }\r\n#undef COPY\r\n#undef TRANS\r\n#undef TAIL\r\n    }\r\n\r\n    static unsigned char GetRange(unsigned char c) {\r\n        // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/\r\n        // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.\r\n        static const unsigned char type[] = {\r\n            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\r\n            0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,\r\n            0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,\r\n            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,\r\n            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,\r\n            8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\r\n            10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,\r\n        };\r\n        return type[c];\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        typename InputByteStream::Ch c = Take(is);\r\n        if (static_cast<unsigned char>(c) != 0xEFu) return c;\r\n        c = is.Take();\r\n        if (static_cast<unsigned char>(c) != 0xBBu) return c;\r\n        c = is.Take();\r\n        if (static_cast<unsigned char>(c) != 0xBFu) return c;\r\n        c = is.Take();\r\n        return c;\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static Ch Take(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        return static_cast<Ch>(is.Take());\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, Ch c) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(c));\r\n    }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// UTF16\r\n\r\n//! UTF-16 encoding.\r\n/*! http://en.wikipedia.org/wiki/UTF-16\r\n    http://tools.ietf.org/html/rfc2781\r\n    \\tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.\r\n    \\note implements Encoding concept\r\n\r\n    \\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.\r\n    For streaming, use UTF16LE and UTF16BE, which handle endianness.\r\n*/\r\ntemplate<typename CharType = wchar_t>\r\nstruct UTF16 {\r\n    typedef CharType Ch;\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);\r\n\r\n    enum { supportUnicode = 1 };\r\n\r\n    template<typename OutputStream>\r\n    static void Encode(OutputStream& os, unsigned codepoint) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);\r\n        if (codepoint <= 0xFFFF) {\r\n            RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair \r\n            os.Put(static_cast<typename OutputStream::Ch>(codepoint));\r\n        }\r\n        else {\r\n            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);\r\n            unsigned v = codepoint - 0x10000;\r\n            os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));\r\n            os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));\r\n        }\r\n    }\r\n\r\n\r\n    template<typename OutputStream>\r\n    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);\r\n        if (codepoint <= 0xFFFF) {\r\n            RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair \r\n            PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));\r\n        }\r\n        else {\r\n            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);\r\n            unsigned v = codepoint - 0x10000;\r\n            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));\r\n            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));\r\n        }\r\n    }\r\n\r\n    template <typename InputStream>\r\n    static bool Decode(InputStream& is, unsigned* codepoint) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);\r\n        typename InputStream::Ch c = is.Take();\r\n        if (c < 0xD800 || c > 0xDFFF) {\r\n            *codepoint = static_cast<unsigned>(c);\r\n            return true;\r\n        }\r\n        else if (c <= 0xDBFF) {\r\n            *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;\r\n            c = is.Take();\r\n            *codepoint |= (static_cast<unsigned>(c) & 0x3FF);\r\n            *codepoint += 0x10000;\r\n            return c >= 0xDC00 && c <= 0xDFFF;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    template <typename InputStream, typename OutputStream>\r\n    static bool Validate(InputStream& is, OutputStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);\r\n        typename InputStream::Ch c;\r\n        os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));\r\n        if (c < 0xD800 || c > 0xDFFF)\r\n            return true;\r\n        else if (c <= 0xDBFF) {\r\n            os.Put(c = is.Take());\r\n            return c >= 0xDC00 && c <= 0xDFFF;\r\n        }\r\n        return false;\r\n    }\r\n};\r\n\r\n//! UTF-16 little endian encoding.\r\ntemplate<typename CharType = wchar_t>\r\nstruct UTF16LE : UTF16<CharType> {\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        CharType c = Take(is);\r\n        return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static CharType Take(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        unsigned c = static_cast<uint8_t>(is.Take());\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;\r\n        return static_cast<CharType>(c);\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, CharType c) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));\r\n    }\r\n};\r\n\r\n//! UTF-16 big endian encoding.\r\ntemplate<typename CharType = wchar_t>\r\nstruct UTF16BE : UTF16<CharType> {\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        CharType c = Take(is);\r\n        return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static CharType Take(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));\r\n        return static_cast<CharType>(c);\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, CharType c) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));\r\n    }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// UTF32\r\n\r\n//! UTF-32 encoding. \r\n/*! http://en.wikipedia.org/wiki/UTF-32\r\n    \\tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.\r\n    \\note implements Encoding concept\r\n\r\n    \\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.\r\n    For streaming, use UTF32LE and UTF32BE, which handle endianness.\r\n*/\r\ntemplate<typename CharType = unsigned>\r\nstruct UTF32 {\r\n    typedef CharType Ch;\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);\r\n\r\n    enum { supportUnicode = 1 };\r\n\r\n    template<typename OutputStream>\r\n    static void Encode(OutputStream& os, unsigned codepoint) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);\r\n        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);\r\n        os.Put(codepoint);\r\n    }\r\n\r\n    template<typename OutputStream>\r\n    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);\r\n        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);\r\n        PutUnsafe(os, codepoint);\r\n    }\r\n\r\n    template <typename InputStream>\r\n    static bool Decode(InputStream& is, unsigned* codepoint) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);\r\n        Ch c = is.Take();\r\n        *codepoint = c;\r\n        return c <= 0x10FFFF;\r\n    }\r\n\r\n    template <typename InputStream, typename OutputStream>\r\n    static bool Validate(InputStream& is, OutputStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);\r\n        Ch c;\r\n        os.Put(c = is.Take());\r\n        return c <= 0x10FFFF;\r\n    }\r\n};\r\n\r\n//! UTF-32 little endian enocoding.\r\ntemplate<typename CharType = unsigned>\r\nstruct UTF32LE : UTF32<CharType> {\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        CharType c = Take(is);\r\n        return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static CharType Take(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        unsigned c = static_cast<uint8_t>(is.Take());\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;\r\n        return static_cast<CharType>(c);\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, CharType c) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));\r\n    }\r\n};\r\n\r\n//! UTF-32 big endian encoding.\r\ntemplate<typename CharType = unsigned>\r\nstruct UTF32BE : UTF32<CharType> {\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        CharType c = Take(is);\r\n        return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; \r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static CharType Take(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;\r\n        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));\r\n        return static_cast<CharType>(c);\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, CharType c) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));\r\n    }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// ASCII\r\n\r\n//! ASCII encoding.\r\n/*! http://en.wikipedia.org/wiki/ASCII\r\n    \\tparam CharType Code unit for storing 7-bit ASCII data. Default is char.\r\n    \\note implements Encoding concept\r\n*/\r\ntemplate<typename CharType = char>\r\nstruct ASCII {\r\n    typedef CharType Ch;\r\n\r\n    enum { supportUnicode = 0 };\r\n\r\n    template<typename OutputStream>\r\n    static void Encode(OutputStream& os, unsigned codepoint) {\r\n        RAPIDJSON_ASSERT(codepoint <= 0x7F);\r\n        os.Put(static_cast<Ch>(codepoint & 0xFF));\r\n    }\r\n\r\n    template<typename OutputStream>\r\n    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {\r\n        RAPIDJSON_ASSERT(codepoint <= 0x7F);\r\n        PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));\r\n    }\r\n\r\n    template <typename InputStream>\r\n    static bool Decode(InputStream& is, unsigned* codepoint) {\r\n        uint8_t c = static_cast<uint8_t>(is.Take());\r\n        *codepoint = c;\r\n        return c <= 0X7F;\r\n    }\r\n\r\n    template <typename InputStream, typename OutputStream>\r\n    static bool Validate(InputStream& is, OutputStream& os) {\r\n        uint8_t c = static_cast<uint8_t>(is.Take());\r\n        os.Put(static_cast<typename OutputStream::Ch>(c));\r\n        return c <= 0x7F;\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static CharType TakeBOM(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        uint8_t c = static_cast<uint8_t>(Take(is));\r\n        return static_cast<Ch>(c);\r\n    }\r\n\r\n    template <typename InputByteStream>\r\n    static Ch Take(InputByteStream& is) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);\r\n        return static_cast<Ch>(is.Take());\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void PutBOM(OutputByteStream& os) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        (void)os;\r\n    }\r\n\r\n    template <typename OutputByteStream>\r\n    static void Put(OutputByteStream& os, Ch c) {\r\n        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);\r\n        os.Put(static_cast<typename OutputByteStream::Ch>(c));\r\n    }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// AutoUTF\r\n\r\n//! Runtime-specified UTF encoding type of a stream.\r\nenum UTFType {\r\n    kUTF8 = 0,      //!< UTF-8.\r\n    kUTF16LE = 1,   //!< UTF-16 little endian.\r\n    kUTF16BE = 2,   //!< UTF-16 big endian.\r\n    kUTF32LE = 3,   //!< UTF-32 little endian.\r\n    kUTF32BE = 4    //!< UTF-32 big endian.\r\n};\r\n\r\n//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.\r\n/*! \\note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().\r\n*/\r\ntemplate<typename CharType>\r\nstruct AutoUTF {\r\n    typedef CharType Ch;\r\n\r\n    enum { supportUnicode = 1 };\r\n\r\n#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x\r\n\r\n    template<typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {\r\n        typedef void (*EncodeFunc)(OutputStream&, unsigned);\r\n        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };\r\n        (*f[os.GetType()])(os, codepoint);\r\n    }\r\n\r\n    template<typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {\r\n        typedef void (*EncodeFunc)(OutputStream&, unsigned);\r\n        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };\r\n        (*f[os.GetType()])(os, codepoint);\r\n    }\r\n\r\n    template <typename InputStream>\r\n    static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {\r\n        typedef bool (*DecodeFunc)(InputStream&, unsigned*);\r\n        static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };\r\n        return (*f[is.GetType()])(is, codepoint);\r\n    }\r\n\r\n    template <typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {\r\n        typedef bool (*ValidateFunc)(InputStream&, OutputStream&);\r\n        static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };\r\n        return (*f[is.GetType()])(is, os);\r\n    }\r\n\r\n#undef RAPIDJSON_ENCODINGS_FUNC\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Transcoder\r\n\r\n//! Encoding conversion.\r\ntemplate<typename SourceEncoding, typename TargetEncoding>\r\nstruct Transcoder {\r\n    //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.\r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {\r\n        unsigned codepoint;\r\n        if (!SourceEncoding::Decode(is, &codepoint))\r\n            return false;\r\n        TargetEncoding::Encode(os, codepoint);\r\n        return true;\r\n    }\r\n\r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {\r\n        unsigned codepoint;\r\n        if (!SourceEncoding::Decode(is, &codepoint))\r\n            return false;\r\n        TargetEncoding::EncodeUnsafe(os, codepoint);\r\n        return true;\r\n    }\r\n\r\n    //! Validate one Unicode codepoint from an encoded stream.\r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {\r\n        return Transcode(is, os);   // Since source/target encoding is different, must transcode.\r\n    }\r\n};\r\n\r\n// Forward declaration.\r\ntemplate<typename Stream>\r\ninline void PutUnsafe(Stream& stream, typename Stream::Ch c);\r\n\r\n//! Specialization of Transcoder with same source and target encoding.\r\ntemplate<typename Encoding>\r\nstruct Transcoder<Encoding, Encoding> {\r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {\r\n        os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class.\r\n        return true;\r\n    }\r\n    \r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {\r\n        PutUnsafe(os, is.Take());  // Just copy one code unit. This semantic is different from primary template class.\r\n        return true;\r\n    }\r\n    \r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {\r\n        return Encoding::Validate(is, os);  // source/target encoding are the same\r\n    }\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#if defined(__GNUC__) || defined(_MSC_VER)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_ENCODINGS_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/error/en.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ERROR_EN_H_\r\n#define RAPIDJSON_ERROR_EN_H_\r\n\r\n#include \"error.h\"\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(switch-enum)\r\nRAPIDJSON_DIAG_OFF(covered-switch-default)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Maps error code of parsing into error message.\r\n/*!\r\n    \\ingroup RAPIDJSON_ERRORS\r\n    \\param parseErrorCode Error code obtained in parsing.\r\n    \\return the error message.\r\n    \\note User can make a copy of this function for localization.\r\n        Using switch-case is safer for future modification of error codes.\r\n*/\r\ninline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {\r\n    switch (parseErrorCode) {\r\n        case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING(\"No error.\");\r\n\r\n        case kParseErrorDocumentEmpty:                  return RAPIDJSON_ERROR_STRING(\"The document is empty.\");\r\n        case kParseErrorDocumentRootNotSingular:        return RAPIDJSON_ERROR_STRING(\"The document root must not be followed by other values.\");\r\n    \r\n        case kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING(\"Invalid value.\");\r\n    \r\n        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING(\"Missing a name for object member.\");\r\n        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING(\"Missing a colon after a name of object member.\");\r\n        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING(\"Missing a comma or '}' after an object member.\");\r\n    \r\n        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING(\"Missing a comma or ']' after an array element.\");\r\n\r\n        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING(\"Incorrect hex digit after \\\\u escape in string.\");\r\n        case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING(\"The surrogate pair in string is invalid.\");\r\n        case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING(\"Invalid escape character in string.\");\r\n        case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING(\"Missing a closing quotation mark in string.\");\r\n        case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING(\"Invalid encoding in string.\");\r\n\r\n        case kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING(\"Number too big to be stored in double.\");\r\n        case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING(\"Miss fraction part in number.\");\r\n        case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING(\"Miss exponent in number.\");\r\n\r\n        case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING(\"Terminate parsing due to Handler error.\");\r\n        case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING(\"Unspecific syntax error.\");\r\n\r\n        default:                                        return RAPIDJSON_ERROR_STRING(\"Unknown error.\");\r\n    }\r\n}\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_ERROR_EN_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/error/error.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ERROR_ERROR_H_\r\n#define RAPIDJSON_ERROR_ERROR_H_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\n#endif\r\n\r\n/*! \\file error.h */\r\n\r\n/*! \\defgroup RAPIDJSON_ERRORS RapidJSON error handling */\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_ERROR_CHARTYPE\r\n\r\n//! Character type of error messages.\r\n/*! \\ingroup RAPIDJSON_ERRORS\r\n    The default character type is \\c char.\r\n    On Windows, user can define this macro as \\c TCHAR for supporting both\r\n    unicode/non-unicode settings.\r\n*/\r\n#ifndef RAPIDJSON_ERROR_CHARTYPE\r\n#define RAPIDJSON_ERROR_CHARTYPE char\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_ERROR_STRING\r\n\r\n//! Macro for converting string literial to \\ref RAPIDJSON_ERROR_CHARTYPE[].\r\n/*! \\ingroup RAPIDJSON_ERRORS\r\n    By default this conversion macro does nothing.\r\n    On Windows, user can define this macro as \\c _T(x) for supporting both\r\n    unicode/non-unicode settings.\r\n*/\r\n#ifndef RAPIDJSON_ERROR_STRING\r\n#define RAPIDJSON_ERROR_STRING(x) x\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// ParseErrorCode\r\n\r\n//! Error code of parsing.\r\n/*! \\ingroup RAPIDJSON_ERRORS\r\n    \\see GenericReader::Parse, GenericReader::GetParseErrorCode\r\n*/\r\nenum ParseErrorCode {\r\n    kParseErrorNone = 0,                        //!< No error.\r\n\r\n    kParseErrorDocumentEmpty,                   //!< The document is empty.\r\n    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.\r\n\r\n    kParseErrorValueInvalid,                    //!< Invalid value.\r\n\r\n    kParseErrorObjectMissName,                  //!< Missing a name for object member.\r\n    kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member.\r\n    kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member.\r\n\r\n    kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element.\r\n\r\n    kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\\\u escape in string.\r\n    kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid.\r\n    kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string.\r\n    kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string.\r\n    kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string.\r\n\r\n    kParseErrorNumberTooBig,                    //!< Number too big to be stored in double.\r\n    kParseErrorNumberMissFraction,              //!< Miss fraction part in number.\r\n    kParseErrorNumberMissExponent,              //!< Miss exponent in number.\r\n\r\n    kParseErrorTermination,                     //!< Parsing was terminated.\r\n    kParseErrorUnspecificSyntaxError            //!< Unspecific syntax error.\r\n};\r\n\r\n//! Result of parsing (wraps ParseErrorCode)\r\n/*!\r\n    \\ingroup RAPIDJSON_ERRORS\r\n    \\code\r\n        Document doc;\r\n        ParseResult ok = doc.Parse(\"[42]\");\r\n        if (!ok) {\r\n            fprintf(stderr, \"JSON parse error: %s (%u)\",\r\n                    GetParseError_En(ok.Code()), ok.Offset());\r\n            exit(EXIT_FAILURE);\r\n        }\r\n    \\endcode\r\n    \\see GenericReader::Parse, GenericDocument::Parse\r\n*/\r\nstruct ParseResult {\r\n    //!! Unspecified boolean type\r\n    typedef bool (ParseResult::*BooleanType)() const;\r\npublic:\r\n    //! Default constructor, no error.\r\n    ParseResult() : code_(kParseErrorNone), offset_(0) {}\r\n    //! Constructor to set an error.\r\n    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}\r\n\r\n    //! Get the error code.\r\n    ParseErrorCode Code() const { return code_; }\r\n    //! Get the error offset, if \\ref IsError(), 0 otherwise.\r\n    size_t Offset() const { return offset_; }\r\n\r\n    //! Explicit conversion to \\c bool, returns \\c true, iff !\\ref IsError().\r\n    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }\r\n    //! Whether the result is an error.\r\n    bool IsError() const { return code_ != kParseErrorNone; }\r\n\r\n    bool operator==(const ParseResult& that) const { return code_ == that.code_; }\r\n    bool operator==(ParseErrorCode code) const { return code_ == code; }\r\n    friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }\r\n\r\n    bool operator!=(const ParseResult& that) const { return !(*this == that); }\r\n    bool operator!=(ParseErrorCode code) const { return !(*this == code); }\r\n    friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }\r\n\r\n    //! Reset error code.\r\n    void Clear() { Set(kParseErrorNone); }\r\n    //! Update error code and offset.\r\n    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }\r\n\r\nprivate:\r\n    ParseErrorCode code_;\r\n    size_t offset_;\r\n};\r\n\r\n//! Function pointer type of GetParseError().\r\n/*! \\ingroup RAPIDJSON_ERRORS\r\n\r\n    This is the prototype for \\c GetParseError_X(), where \\c X is a locale.\r\n    User can dynamically change locale in runtime, e.g.:\r\n\\code\r\n    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever\r\n    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());\r\n\\endcode\r\n*/\r\ntypedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_ERROR_ERROR_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/filereadstream.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_FILEREADSTREAM_H_\r\n#define RAPIDJSON_FILEREADSTREAM_H_\r\n\r\n#include \"stream.h\"\r\n#include <cstdio>\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\nRAPIDJSON_DIAG_OFF(unreachable-code)\r\nRAPIDJSON_DIAG_OFF(missing-noreturn)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! File byte stream for input using fread().\r\n/*!\r\n    \\note implements Stream concept\r\n*/\r\nclass FileReadStream {\r\npublic:\r\n    typedef char Ch;    //!< Character type (byte).\r\n\r\n    //! Constructor.\r\n    /*!\r\n        \\param fp File pointer opened for read.\r\n        \\param buffer user-supplied buffer.\r\n        \\param bufferSize size of buffer in bytes. Must >=4 bytes.\r\n    */\r\n    FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { \r\n        RAPIDJSON_ASSERT(fp_ != 0);\r\n        RAPIDJSON_ASSERT(bufferSize >= 4);\r\n        Read();\r\n    }\r\n\r\n    Ch Peek() const { return *current_; }\r\n    Ch Take() { Ch c = *current_; Read(); return c; }\r\n    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }\r\n\r\n    // Not implemented\r\n    void Put(Ch) { RAPIDJSON_ASSERT(false); }\r\n    void Flush() { RAPIDJSON_ASSERT(false); } \r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\n    // For encoding detection only.\r\n    const Ch* Peek4() const {\r\n        return (current_ + 4 <= bufferLast_) ? current_ : 0;\r\n    }\r\n\r\nprivate:\r\n    void Read() {\r\n        if (current_ < bufferLast_)\r\n            ++current_;\r\n        else if (!eof_) {\r\n            count_ += readCount_;\r\n            readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);\r\n            bufferLast_ = buffer_ + readCount_ - 1;\r\n            current_ = buffer_;\r\n\r\n            if (readCount_ < bufferSize_) {\r\n                buffer_[readCount_] = '\\0';\r\n                ++bufferLast_;\r\n                eof_ = true;\r\n            }\r\n        }\r\n    }\r\n\r\n    std::FILE* fp_;\r\n    Ch *buffer_;\r\n    size_t bufferSize_;\r\n    Ch *bufferLast_;\r\n    Ch *current_;\r\n    size_t readCount_;\r\n    size_t count_;  //!< Number of characters read\r\n    bool eof_;\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_FILESTREAM_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/filewritestream.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_FILEWRITESTREAM_H_\r\n#define RAPIDJSON_FILEWRITESTREAM_H_\r\n\r\n#include \"stream.h\"\r\n#include <cstdio>\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(unreachable-code)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Wrapper of C file stream for output using fwrite().\r\n/*!\r\n    \\note implements Stream concept\r\n*/\r\nclass FileWriteStream {\r\npublic:\r\n    typedef char Ch;    //!< Character type. Only support char.\r\n\r\n    FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { \r\n        RAPIDJSON_ASSERT(fp_ != 0);\r\n    }\r\n\r\n    void Put(char c) { \r\n        if (current_ >= bufferEnd_)\r\n            Flush();\r\n\r\n        *current_++ = c;\r\n    }\r\n\r\n    void PutN(char c, size_t n) {\r\n        size_t avail = static_cast<size_t>(bufferEnd_ - current_);\r\n        while (n > avail) {\r\n            std::memset(current_, c, avail);\r\n            current_ += avail;\r\n            Flush();\r\n            n -= avail;\r\n            avail = static_cast<size_t>(bufferEnd_ - current_);\r\n        }\r\n\r\n        if (n > 0) {\r\n            std::memset(current_, c, n);\r\n            current_ += n;\r\n        }\r\n    }\r\n\r\n    void Flush() {\r\n        if (current_ != buffer_) {\r\n            size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);\r\n            if (result < static_cast<size_t>(current_ - buffer_)) {\r\n                // failure deliberately ignored at this time\r\n                // added to avoid warn_unused_result build errors\r\n            }\r\n            current_ = buffer_;\r\n        }\r\n    }\r\n\r\n    // Not implemented\r\n    char Peek() const { RAPIDJSON_ASSERT(false); return 0; }\r\n    char Take() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }\r\n    char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\nprivate:\r\n    // Prohibit copy constructor & assignment operator.\r\n    FileWriteStream(const FileWriteStream&);\r\n    FileWriteStream& operator=(const FileWriteStream&);\r\n\r\n    std::FILE* fp_;\r\n    char *buffer_;\r\n    char *bufferEnd_;\r\n    char *current_;\r\n};\r\n\r\n//! Implement specialized version of PutN() with memset() for better performance.\r\ntemplate<>\r\ninline void PutN(FileWriteStream& stream, char c, size_t n) {\r\n    stream.PutN(c, n);\r\n}\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_FILESTREAM_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/fwd.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_FWD_H_\r\n#define RAPIDJSON_FWD_H_\r\n\r\n#include \"rapidjson.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n// encodings.h\r\n\r\ntemplate<typename CharType> struct UTF8;\r\ntemplate<typename CharType> struct UTF16;\r\ntemplate<typename CharType> struct UTF16BE;\r\ntemplate<typename CharType> struct UTF16LE;\r\ntemplate<typename CharType> struct UTF32;\r\ntemplate<typename CharType> struct UTF32BE;\r\ntemplate<typename CharType> struct UTF32LE;\r\ntemplate<typename CharType> struct ASCII;\r\ntemplate<typename CharType> struct AutoUTF;\r\n\r\ntemplate<typename SourceEncoding, typename TargetEncoding>\r\nstruct Transcoder;\r\n\r\n// allocators.h\r\n\r\nclass CrtAllocator;\r\n\r\ntemplate <typename BaseAllocator>\r\nclass MemoryPoolAllocator;\r\n\r\n// stream.h\r\n\r\ntemplate <typename Encoding>\r\nstruct GenericStringStream;\r\n\r\ntypedef GenericStringStream<UTF8<char> > StringStream;\r\n\r\ntemplate <typename Encoding>\r\nstruct GenericInsituStringStream;\r\n\r\ntypedef GenericInsituStringStream<UTF8<char> > InsituStringStream;\r\n\r\n// stringbuffer.h\r\n\r\ntemplate <typename Encoding, typename Allocator>\r\nclass GenericStringBuffer;\r\n\r\ntypedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;\r\n\r\n// filereadstream.h\r\n\r\nclass FileReadStream;\r\n\r\n// filewritestream.h\r\n\r\nclass FileWriteStream;\r\n\r\n// memorybuffer.h\r\n\r\ntemplate <typename Allocator>\r\nstruct GenericMemoryBuffer;\r\n\r\ntypedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;\r\n\r\n// memorystream.h\r\n\r\nstruct MemoryStream;\r\n\r\n// reader.h\r\n\r\ntemplate<typename Encoding, typename Derived>\r\nstruct BaseReaderHandler;\r\n\r\ntemplate <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>\r\nclass GenericReader;\r\n\r\ntypedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;\r\n\r\n// writer.h\r\n\r\ntemplate<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>\r\nclass Writer;\r\n\r\n// prettywriter.h\r\n\r\ntemplate<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>\r\nclass PrettyWriter;\r\n\r\n// document.h\r\n\r\ntemplate <typename Encoding, typename Allocator> \r\nstruct GenericMember;\r\n\r\ntemplate <bool Const, typename Encoding, typename Allocator>\r\nclass GenericMemberIterator;\r\n\r\ntemplate<typename CharType>\r\nstruct GenericStringRef;\r\n\r\ntemplate <typename Encoding, typename Allocator> \r\nclass GenericValue;\r\n\r\ntypedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;\r\n\r\ntemplate <typename Encoding, typename Allocator, typename StackAllocator>\r\nclass GenericDocument;\r\n\r\ntypedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;\r\n\r\n// pointer.h\r\n\r\ntemplate <typename ValueType, typename Allocator>\r\nclass GenericPointer;\r\n\r\ntypedef GenericPointer<Value, CrtAllocator> Pointer;\r\n\r\n// schema.h\r\n\r\ntemplate <typename SchemaDocumentType>\r\nclass IGenericRemoteSchemaDocumentProvider;\r\n\r\ntemplate <typename ValueT, typename Allocator>\r\nclass GenericSchemaDocument;\r\n\r\ntypedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;\r\ntypedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;\r\n\r\ntemplate <\r\n    typename SchemaDocumentType,\r\n    typename OutputHandler,\r\n    typename StateAllocator>\r\nclass GenericSchemaValidator;\r\n\r\ntypedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_RAPIDJSONFWD_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/biginteger.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_BIGINTEGER_H_\r\n#define RAPIDJSON_BIGINTEGER_H_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\n#if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64)\r\n#include <intrin.h> // for _umul128\r\n#pragma intrinsic(_umul128)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\nclass BigInteger {\r\npublic:\r\n    typedef uint64_t Type;\r\n\r\n    BigInteger(const BigInteger& rhs) : count_(rhs.count_) {\r\n        std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));\r\n    }\r\n\r\n    explicit BigInteger(uint64_t u) : count_(1) {\r\n        digits_[0] = u;\r\n    }\r\n\r\n    BigInteger(const char* decimals, size_t length) : count_(1) {\r\n        RAPIDJSON_ASSERT(length > 0);\r\n        digits_[0] = 0;\r\n        size_t i = 0;\r\n        const size_t kMaxDigitPerIteration = 19;  // 2^64 = 18446744073709551616 > 10^19\r\n        while (length >= kMaxDigitPerIteration) {\r\n            AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);\r\n            length -= kMaxDigitPerIteration;\r\n            i += kMaxDigitPerIteration;\r\n        }\r\n\r\n        if (length > 0)\r\n            AppendDecimal64(decimals + i, decimals + i + length);\r\n    }\r\n    \r\n    BigInteger& operator=(const BigInteger &rhs)\r\n    {\r\n        if (this != &rhs) {\r\n            count_ = rhs.count_;\r\n            std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));\r\n        }\r\n        return *this;\r\n    }\r\n    \r\n    BigInteger& operator=(uint64_t u) {\r\n        digits_[0] = u;            \r\n        count_ = 1;\r\n        return *this;\r\n    }\r\n\r\n    BigInteger& operator+=(uint64_t u) {\r\n        Type backup = digits_[0];\r\n        digits_[0] += u;\r\n        for (size_t i = 0; i < count_ - 1; i++) {\r\n            if (digits_[i] >= backup)\r\n                return *this; // no carry\r\n            backup = digits_[i + 1];\r\n            digits_[i + 1] += 1;\r\n        }\r\n\r\n        // Last carry\r\n        if (digits_[count_ - 1] < backup)\r\n            PushBack(1);\r\n\r\n        return *this;\r\n    }\r\n\r\n    BigInteger& operator*=(uint64_t u) {\r\n        if (u == 0) return *this = 0;\r\n        if (u == 1) return *this;\r\n        if (*this == 1) return *this = u;\r\n\r\n        uint64_t k = 0;\r\n        for (size_t i = 0; i < count_; i++) {\r\n            uint64_t hi;\r\n            digits_[i] = MulAdd64(digits_[i], u, k, &hi);\r\n            k = hi;\r\n        }\r\n        \r\n        if (k > 0)\r\n            PushBack(k);\r\n\r\n        return *this;\r\n    }\r\n\r\n    BigInteger& operator*=(uint32_t u) {\r\n        if (u == 0) return *this = 0;\r\n        if (u == 1) return *this;\r\n        if (*this == 1) return *this = u;\r\n\r\n        uint64_t k = 0;\r\n        for (size_t i = 0; i < count_; i++) {\r\n            const uint64_t c = digits_[i] >> 32;\r\n            const uint64_t d = digits_[i] & 0xFFFFFFFF;\r\n            const uint64_t uc = u * c;\r\n            const uint64_t ud = u * d;\r\n            const uint64_t p0 = ud + k;\r\n            const uint64_t p1 = uc + (p0 >> 32);\r\n            digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);\r\n            k = p1 >> 32;\r\n        }\r\n        \r\n        if (k > 0)\r\n            PushBack(k);\r\n\r\n        return *this;\r\n    }\r\n\r\n    BigInteger& operator<<=(size_t shift) {\r\n        if (IsZero() || shift == 0) return *this;\r\n\r\n        size_t offset = shift / kTypeBit;\r\n        size_t interShift = shift % kTypeBit;\r\n        RAPIDJSON_ASSERT(count_ + offset <= kCapacity);\r\n\r\n        if (interShift == 0) {\r\n            std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));\r\n            count_ += offset;\r\n        }\r\n        else {\r\n            digits_[count_] = 0;\r\n            for (size_t i = count_; i > 0; i--)\r\n                digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));\r\n            digits_[offset] = digits_[0] << interShift;\r\n            count_ += offset;\r\n            if (digits_[count_])\r\n                count_++;\r\n        }\r\n\r\n        std::memset(digits_, 0, offset * sizeof(Type));\r\n\r\n        return *this;\r\n    }\r\n\r\n    bool operator==(const BigInteger& rhs) const {\r\n        return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;\r\n    }\r\n\r\n    bool operator==(const Type rhs) const {\r\n        return count_ == 1 && digits_[0] == rhs;\r\n    }\r\n\r\n    BigInteger& MultiplyPow5(unsigned exp) {\r\n        static const uint32_t kPow5[12] = {\r\n            5,\r\n            5 * 5,\r\n            5 * 5 * 5,\r\n            5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,\r\n            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5\r\n        };\r\n        if (exp == 0) return *this;\r\n        for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27\r\n        for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13\r\n        if (exp > 0)                 *this *= kPow5[exp - 1];\r\n        return *this;\r\n    }\r\n\r\n    // Compute absolute difference of this and rhs.\r\n    // Assume this != rhs\r\n    bool Difference(const BigInteger& rhs, BigInteger* out) const {\r\n        int cmp = Compare(rhs);\r\n        RAPIDJSON_ASSERT(cmp != 0);\r\n        const BigInteger *a, *b;  // Makes a > b\r\n        bool ret;\r\n        if (cmp < 0) { a = &rhs; b = this; ret = true; }\r\n        else         { a = this; b = &rhs; ret = false; }\r\n\r\n        Type borrow = 0;\r\n        for (size_t i = 0; i < a->count_; i++) {\r\n            Type d = a->digits_[i] - borrow;\r\n            if (i < b->count_)\r\n                d -= b->digits_[i];\r\n            borrow = (d > a->digits_[i]) ? 1 : 0;\r\n            out->digits_[i] = d;\r\n            if (d != 0)\r\n                out->count_ = i + 1;\r\n        }\r\n\r\n        return ret;\r\n    }\r\n\r\n    int Compare(const BigInteger& rhs) const {\r\n        if (count_ != rhs.count_)\r\n            return count_ < rhs.count_ ? -1 : 1;\r\n\r\n        for (size_t i = count_; i-- > 0;)\r\n            if (digits_[i] != rhs.digits_[i])\r\n                return digits_[i] < rhs.digits_[i] ? -1 : 1;\r\n\r\n        return 0;\r\n    }\r\n\r\n    size_t GetCount() const { return count_; }\r\n    Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }\r\n    bool IsZero() const { return count_ == 1 && digits_[0] == 0; }\r\n\r\nprivate:\r\n    void AppendDecimal64(const char* begin, const char* end) {\r\n        uint64_t u = ParseUint64(begin, end);\r\n        if (IsZero())\r\n            *this = u;\r\n        else {\r\n            unsigned exp = static_cast<unsigned>(end - begin);\r\n            (MultiplyPow5(exp) <<= exp) += u;   // *this = *this * 10^exp + u\r\n        }\r\n    }\r\n\r\n    void PushBack(Type digit) {\r\n        RAPIDJSON_ASSERT(count_ < kCapacity);\r\n        digits_[count_++] = digit;\r\n    }\r\n\r\n    static uint64_t ParseUint64(const char* begin, const char* end) {\r\n        uint64_t r = 0;\r\n        for (const char* p = begin; p != end; ++p) {\r\n            RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');\r\n            r = r * 10u + static_cast<unsigned>(*p - '0');\r\n        }\r\n        return r;\r\n    }\r\n\r\n    // Assume a * b + k < 2^128\r\n    static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {\r\n#if defined(_MSC_VER) && defined(_M_AMD64)\r\n        uint64_t low = _umul128(a, b, outHigh) + k;\r\n        if (low < k)\r\n            (*outHigh)++;\r\n        return low;\r\n#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)\r\n        __extension__ typedef unsigned __int128 uint128;\r\n        uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);\r\n        p += k;\r\n        *outHigh = static_cast<uint64_t>(p >> 64);\r\n        return static_cast<uint64_t>(p);\r\n#else\r\n        const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;\r\n        uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;\r\n        x1 += (x0 >> 32); // can't give carry\r\n        x1 += x2;\r\n        if (x1 < x2)\r\n            x3 += (static_cast<uint64_t>(1) << 32);\r\n        uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);\r\n        uint64_t hi = x3 + (x1 >> 32);\r\n\r\n        lo += k;\r\n        if (lo < k)\r\n            hi++;\r\n        *outHigh = hi;\r\n        return lo;\r\n#endif\r\n    }\r\n\r\n    static const size_t kBitCount = 3328;  // 64bit * 54 > 10^1000\r\n    static const size_t kCapacity = kBitCount / sizeof(Type);\r\n    static const size_t kTypeBit = sizeof(Type) * 8;\r\n\r\n    Type digits_[kCapacity];\r\n    size_t count_;\r\n};\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_BIGINTEGER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/diyfp.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n// This is a C++ header-only implementation of Grisu2 algorithm from the publication:\r\n// Loitsch, Florian. \"Printing floating-point numbers quickly and accurately with\r\n// integers.\" ACM Sigplan Notices 45.6 (2010): 233-243.\r\n\r\n#ifndef RAPIDJSON_DIYFP_H_\r\n#define RAPIDJSON_DIYFP_H_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\n#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)\r\n#include <intrin.h>\r\n#pragma intrinsic(_BitScanReverse64)\r\n#pragma intrinsic(_umul128)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\n#endif\r\n\r\nstruct DiyFp {\r\n    DiyFp() : f(), e() {}\r\n\r\n    DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}\r\n\r\n    explicit DiyFp(double d) {\r\n        union {\r\n            double d;\r\n            uint64_t u64;\r\n        } u = { d };\r\n\r\n        int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);\r\n        uint64_t significand = (u.u64 & kDpSignificandMask);\r\n        if (biased_e != 0) {\r\n            f = significand + kDpHiddenBit;\r\n            e = biased_e - kDpExponentBias;\r\n        } \r\n        else {\r\n            f = significand;\r\n            e = kDpMinExponent + 1;\r\n        }\r\n    }\r\n\r\n    DiyFp operator-(const DiyFp& rhs) const {\r\n        return DiyFp(f - rhs.f, e);\r\n    }\r\n\r\n    DiyFp operator*(const DiyFp& rhs) const {\r\n#if defined(_MSC_VER) && defined(_M_AMD64)\r\n        uint64_t h;\r\n        uint64_t l = _umul128(f, rhs.f, &h);\r\n        if (l & (uint64_t(1) << 63)) // rounding\r\n            h++;\r\n        return DiyFp(h, e + rhs.e + 64);\r\n#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)\r\n        __extension__ typedef unsigned __int128 uint128;\r\n        uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);\r\n        uint64_t h = static_cast<uint64_t>(p >> 64);\r\n        uint64_t l = static_cast<uint64_t>(p);\r\n        if (l & (uint64_t(1) << 63)) // rounding\r\n            h++;\r\n        return DiyFp(h, e + rhs.e + 64);\r\n#else\r\n        const uint64_t M32 = 0xFFFFFFFF;\r\n        const uint64_t a = f >> 32;\r\n        const uint64_t b = f & M32;\r\n        const uint64_t c = rhs.f >> 32;\r\n        const uint64_t d = rhs.f & M32;\r\n        const uint64_t ac = a * c;\r\n        const uint64_t bc = b * c;\r\n        const uint64_t ad = a * d;\r\n        const uint64_t bd = b * d;\r\n        uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);\r\n        tmp += 1U << 31;  /// mult_round\r\n        return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);\r\n#endif\r\n    }\r\n\r\n    DiyFp Normalize() const {\r\n#if defined(_MSC_VER) && defined(_M_AMD64)\r\n        unsigned long index;\r\n        _BitScanReverse64(&index, f);\r\n        return DiyFp(f << (63 - index), e - (63 - index));\r\n#elif defined(__GNUC__) && __GNUC__ >= 4\r\n        int s = __builtin_clzll(f);\r\n        return DiyFp(f << s, e - s);\r\n#else\r\n        DiyFp res = *this;\r\n        while (!(res.f & (static_cast<uint64_t>(1) << 63))) {\r\n            res.f <<= 1;\r\n            res.e--;\r\n        }\r\n        return res;\r\n#endif\r\n    }\r\n\r\n    DiyFp NormalizeBoundary() const {\r\n        DiyFp res = *this;\r\n        while (!(res.f & (kDpHiddenBit << 1))) {\r\n            res.f <<= 1;\r\n            res.e--;\r\n        }\r\n        res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);\r\n        res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);\r\n        return res;\r\n    }\r\n\r\n    void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {\r\n        DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();\r\n        DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);\r\n        mi.f <<= mi.e - pl.e;\r\n        mi.e = pl.e;\r\n        *plus = pl;\r\n        *minus = mi;\r\n    }\r\n\r\n    double ToDouble() const {\r\n        union {\r\n            double d;\r\n            uint64_t u64;\r\n        }u;\r\n        const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : \r\n            static_cast<uint64_t>(e + kDpExponentBias);\r\n        u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);\r\n        return u.d;\r\n    }\r\n\r\n    static const int kDiySignificandSize = 64;\r\n    static const int kDpSignificandSize = 52;\r\n    static const int kDpExponentBias = 0x3FF + kDpSignificandSize;\r\n    static const int kDpMaxExponent = 0x7FF - kDpExponentBias;\r\n    static const int kDpMinExponent = -kDpExponentBias;\r\n    static const int kDpDenormalExponent = -kDpExponentBias + 1;\r\n    static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);\r\n    static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);\r\n    static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);\r\n\r\n    uint64_t f;\r\n    int e;\r\n};\r\n\r\ninline DiyFp GetCachedPowerByIndex(size_t index) {\r\n    // 10^-348, 10^-340, ..., 10^340\r\n    static const uint64_t kCachedPowers_F[] = {\r\n        RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),\r\n        RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),\r\n        RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),\r\n        RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),\r\n        RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),\r\n        RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),\r\n        RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),\r\n        RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),\r\n        RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),\r\n        RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),\r\n        RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),\r\n        RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),\r\n        RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),\r\n        RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),\r\n        RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),\r\n        RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),\r\n        RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),\r\n        RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),\r\n        RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),\r\n        RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),\r\n        RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),\r\n        RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),\r\n        RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),\r\n        RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),\r\n        RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),\r\n        RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),\r\n        RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),\r\n        RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),\r\n        RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),\r\n        RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),\r\n        RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),\r\n        RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),\r\n        RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),\r\n        RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),\r\n        RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),\r\n        RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),\r\n        RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),\r\n        RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),\r\n        RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),\r\n        RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),\r\n        RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),\r\n        RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),\r\n        RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),\r\n        RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)\r\n    };\r\n    static const int16_t kCachedPowers_E[] = {\r\n        -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,\r\n        -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,\r\n        -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,\r\n        -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183,\r\n        -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83,\r\n        109,   136,   162,   189,   216,   242,   269,   295,   322,   348,\r\n        375,   402,   428,   455,   481,   508,   534,   561,   588,   614,\r\n        641,   667,   694,   720,   747,   774,   800,   827,   853,   880,\r\n        907,   933,   960,   986,  1013,  1039,  1066\r\n    };\r\n    return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);\r\n}\r\n    \r\ninline DiyFp GetCachedPower(int e, int* K) {\r\n\r\n    //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;\r\n    double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive\r\n    int k = static_cast<int>(dk);\r\n    if (dk - k > 0.0)\r\n        k++;\r\n\r\n    unsigned index = static_cast<unsigned>((k >> 3) + 1);\r\n    *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table\r\n\r\n    return GetCachedPowerByIndex(index);\r\n}\r\n\r\ninline DiyFp GetCachedPower10(int exp, int *outExp) {\r\n     unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;\r\n     *outExp = -348 + static_cast<int>(index) * 8;\r\n     return GetCachedPowerByIndex(index);\r\n }\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\nRAPIDJSON_DIAG_OFF(padded)\r\n#endif\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_DIYFP_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/dtoa.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n// This is a C++ header-only implementation of Grisu2 algorithm from the publication:\r\n// Loitsch, Florian. \"Printing floating-point numbers quickly and accurately with\r\n// integers.\" ACM Sigplan Notices 45.6 (2010): 233-243.\r\n\r\n#ifndef RAPIDJSON_DTOA_\r\n#define RAPIDJSON_DTOA_\r\n\r\n#include \"itoa.h\" // GetDigitsLut()\r\n#include \"diyfp.h\"\r\n#include \"ieee754.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\nRAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124\r\n#endif\r\n\r\ninline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {\r\n    while (rest < wp_w && delta - rest >= ten_kappa &&\r\n           (rest + ten_kappa < wp_w ||  /// closer\r\n            wp_w - rest > rest + ten_kappa - wp_w)) {\r\n        buffer[len - 1]--;\r\n        rest += ten_kappa;\r\n    }\r\n}\r\n\r\ninline int CountDecimalDigit32(uint32_t n) {\r\n    // Simple pure C++ implementation was faster than __builtin_clz version in this situation.\r\n    if (n < 10) return 1;\r\n    if (n < 100) return 2;\r\n    if (n < 1000) return 3;\r\n    if (n < 10000) return 4;\r\n    if (n < 100000) return 5;\r\n    if (n < 1000000) return 6;\r\n    if (n < 10000000) return 7;\r\n    if (n < 100000000) return 8;\r\n    // Will not reach 10 digits in DigitGen()\r\n    //if (n < 1000000000) return 9;\r\n    //return 10;\r\n    return 9;\r\n}\r\n\r\ninline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {\r\n    static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };\r\n    const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);\r\n    const DiyFp wp_w = Mp - W;\r\n    uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);\r\n    uint64_t p2 = Mp.f & (one.f - 1);\r\n    int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]\r\n    *len = 0;\r\n\r\n    while (kappa > 0) {\r\n        uint32_t d = 0;\r\n        switch (kappa) {\r\n            case  9: d = p1 /  100000000; p1 %=  100000000; break;\r\n            case  8: d = p1 /   10000000; p1 %=   10000000; break;\r\n            case  7: d = p1 /    1000000; p1 %=    1000000; break;\r\n            case  6: d = p1 /     100000; p1 %=     100000; break;\r\n            case  5: d = p1 /      10000; p1 %=      10000; break;\r\n            case  4: d = p1 /       1000; p1 %=       1000; break;\r\n            case  3: d = p1 /        100; p1 %=        100; break;\r\n            case  2: d = p1 /         10; p1 %=         10; break;\r\n            case  1: d = p1;              p1 =           0; break;\r\n            default:;\r\n        }\r\n        if (d || *len)\r\n            buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));\r\n        kappa--;\r\n        uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;\r\n        if (tmp <= delta) {\r\n            *K += kappa;\r\n            GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);\r\n            return;\r\n        }\r\n    }\r\n\r\n    // kappa = 0\r\n    for (;;) {\r\n        p2 *= 10;\r\n        delta *= 10;\r\n        char d = static_cast<char>(p2 >> -one.e);\r\n        if (d || *len)\r\n            buffer[(*len)++] = static_cast<char>('0' + d);\r\n        p2 &= one.f - 1;\r\n        kappa--;\r\n        if (p2 < delta) {\r\n            *K += kappa;\r\n            int index = -kappa;\r\n            GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0));\r\n            return;\r\n        }\r\n    }\r\n}\r\n\r\ninline void Grisu2(double value, char* buffer, int* length, int* K) {\r\n    const DiyFp v(value);\r\n    DiyFp w_m, w_p;\r\n    v.NormalizedBoundaries(&w_m, &w_p);\r\n\r\n    const DiyFp c_mk = GetCachedPower(w_p.e, K);\r\n    const DiyFp W = v.Normalize() * c_mk;\r\n    DiyFp Wp = w_p * c_mk;\r\n    DiyFp Wm = w_m * c_mk;\r\n    Wm.f++;\r\n    Wp.f--;\r\n    DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);\r\n}\r\n\r\ninline char* WriteExponent(int K, char* buffer) {\r\n    if (K < 0) {\r\n        *buffer++ = '-';\r\n        K = -K;\r\n    }\r\n\r\n    if (K >= 100) {\r\n        *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));\r\n        K %= 100;\r\n        const char* d = GetDigitsLut() + K * 2;\r\n        *buffer++ = d[0];\r\n        *buffer++ = d[1];\r\n    }\r\n    else if (K >= 10) {\r\n        const char* d = GetDigitsLut() + K * 2;\r\n        *buffer++ = d[0];\r\n        *buffer++ = d[1];\r\n    }\r\n    else\r\n        *buffer++ = static_cast<char>('0' + static_cast<char>(K));\r\n\r\n    return buffer;\r\n}\r\n\r\ninline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {\r\n    const int kk = length + k;  // 10^(kk-1) <= v < 10^kk\r\n\r\n    if (0 <= k && kk <= 21) {\r\n        // 1234e7 -> 12340000000\r\n        for (int i = length; i < kk; i++)\r\n            buffer[i] = '0';\r\n        buffer[kk] = '.';\r\n        buffer[kk + 1] = '0';\r\n        return &buffer[kk + 2];\r\n    }\r\n    else if (0 < kk && kk <= 21) {\r\n        // 1234e-2 -> 12.34\r\n        std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));\r\n        buffer[kk] = '.';\r\n        if (0 > k + maxDecimalPlaces) {\r\n            // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1\r\n            // Remove extra trailing zeros (at least one) after truncation.\r\n            for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)\r\n                if (buffer[i] != '0')\r\n                    return &buffer[i + 1];\r\n            return &buffer[kk + 2]; // Reserve one zero\r\n        }\r\n        else\r\n            return &buffer[length + 1];\r\n    }\r\n    else if (-6 < kk && kk <= 0) {\r\n        // 1234e-6 -> 0.001234\r\n        const int offset = 2 - kk;\r\n        std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));\r\n        buffer[0] = '0';\r\n        buffer[1] = '.';\r\n        for (int i = 2; i < offset; i++)\r\n            buffer[i] = '0';\r\n        if (length - kk > maxDecimalPlaces) {\r\n            // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1\r\n            // Remove extra trailing zeros (at least one) after truncation.\r\n            for (int i = maxDecimalPlaces + 1; i > 2; i--)\r\n                if (buffer[i] != '0')\r\n                    return &buffer[i + 1];\r\n            return &buffer[3]; // Reserve one zero\r\n        }\r\n        else\r\n            return &buffer[length + offset];\r\n    }\r\n    else if (kk < -maxDecimalPlaces) {\r\n        // Truncate to zero\r\n        buffer[0] = '0';\r\n        buffer[1] = '.';\r\n        buffer[2] = '0';\r\n        return &buffer[3];\r\n    }\r\n    else if (length == 1) {\r\n        // 1e30\r\n        buffer[1] = 'e';\r\n        return WriteExponent(kk - 1, &buffer[2]);\r\n    }\r\n    else {\r\n        // 1234e30 -> 1.234e33\r\n        std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));\r\n        buffer[1] = '.';\r\n        buffer[length + 1] = 'e';\r\n        return WriteExponent(kk - 1, &buffer[0 + length + 2]);\r\n    }\r\n}\r\n\r\ninline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {\r\n    RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);\r\n    Double d(value);\r\n    if (d.IsZero()) {\r\n        if (d.Sign())\r\n            *buffer++ = '-';     // -0.0, Issue #289\r\n        buffer[0] = '0';\r\n        buffer[1] = '.';\r\n        buffer[2] = '0';\r\n        return &buffer[3];\r\n    }\r\n    else {\r\n        if (value < 0) {\r\n            *buffer++ = '-';\r\n            value = -value;\r\n        }\r\n        int length, K;\r\n        Grisu2(value, buffer, &length, &K);\r\n        return Prettify(buffer, length, K, maxDecimalPlaces);\r\n    }\r\n}\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_DTOA_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/ieee754.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_IEEE754_\r\n#define RAPIDJSON_IEEE754_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\nclass Double {\r\npublic:\r\n    Double() {}\r\n    Double(double d) : d_(d) {}\r\n    Double(uint64_t u) : u_(u) {}\r\n\r\n    double Value() const { return d_; }\r\n    uint64_t Uint64Value() const { return u_; }\r\n\r\n    double NextPositiveDouble() const {\r\n        RAPIDJSON_ASSERT(!Sign());\r\n        return Double(u_ + 1).Value();\r\n    }\r\n\r\n    bool Sign() const { return (u_ & kSignMask) != 0; }\r\n    uint64_t Significand() const { return u_ & kSignificandMask; }\r\n    int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }\r\n\r\n    bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }\r\n    bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }\r\n    bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }\r\n    bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }\r\n    bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }\r\n\r\n    uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }\r\n    int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }\r\n    uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }\r\n\r\n    static int EffectiveSignificandSize(int order) {\r\n        if (order >= -1021)\r\n            return 53;\r\n        else if (order <= -1074)\r\n            return 0;\r\n        else\r\n            return order + 1074;\r\n    }\r\n\r\nprivate:\r\n    static const int kSignificandSize = 52;\r\n    static const int kExponentBias = 0x3FF;\r\n    static const int kDenormalExponent = 1 - kExponentBias;\r\n    static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);\r\n    static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);\r\n    static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);\r\n    static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);\r\n\r\n    union {\r\n        double d_;\r\n        uint64_t u_;\r\n    };\r\n};\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_IEEE754_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/itoa.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n//\r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed\r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ITOA_\r\n#define RAPIDJSON_ITOA_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\ninline const char* GetDigitsLut() {\r\n    static const char cDigitsLut[200] = {\r\n        '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',\r\n        '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',\r\n        '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',\r\n        '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',\r\n        '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',\r\n        '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',\r\n        '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',\r\n        '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',\r\n        '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',\r\n        '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'\r\n    };\r\n    return cDigitsLut;\r\n}\r\n\r\ninline char* u32toa(uint32_t value, char* buffer) {\r\n    RAPIDJSON_ASSERT(buffer != 0);\r\n\r\n    const char* cDigitsLut = GetDigitsLut();\r\n\r\n    if (value < 10000) {\r\n        const uint32_t d1 = (value / 100) << 1;\r\n        const uint32_t d2 = (value % 100) << 1;\r\n\r\n        if (value >= 1000)\r\n            *buffer++ = cDigitsLut[d1];\r\n        if (value >= 100)\r\n            *buffer++ = cDigitsLut[d1 + 1];\r\n        if (value >= 10)\r\n            *buffer++ = cDigitsLut[d2];\r\n        *buffer++ = cDigitsLut[d2 + 1];\r\n    }\r\n    else if (value < 100000000) {\r\n        // value = bbbbcccc\r\n        const uint32_t b = value / 10000;\r\n        const uint32_t c = value % 10000;\r\n\r\n        const uint32_t d1 = (b / 100) << 1;\r\n        const uint32_t d2 = (b % 100) << 1;\r\n\r\n        const uint32_t d3 = (c / 100) << 1;\r\n        const uint32_t d4 = (c % 100) << 1;\r\n\r\n        if (value >= 10000000)\r\n            *buffer++ = cDigitsLut[d1];\r\n        if (value >= 1000000)\r\n            *buffer++ = cDigitsLut[d1 + 1];\r\n        if (value >= 100000)\r\n            *buffer++ = cDigitsLut[d2];\r\n        *buffer++ = cDigitsLut[d2 + 1];\r\n\r\n        *buffer++ = cDigitsLut[d3];\r\n        *buffer++ = cDigitsLut[d3 + 1];\r\n        *buffer++ = cDigitsLut[d4];\r\n        *buffer++ = cDigitsLut[d4 + 1];\r\n    }\r\n    else {\r\n        // value = aabbbbcccc in decimal\r\n\r\n        const uint32_t a = value / 100000000; // 1 to 42\r\n        value %= 100000000;\r\n\r\n        if (a >= 10) {\r\n            const unsigned i = a << 1;\r\n            *buffer++ = cDigitsLut[i];\r\n            *buffer++ = cDigitsLut[i + 1];\r\n        }\r\n        else\r\n            *buffer++ = static_cast<char>('0' + static_cast<char>(a));\r\n\r\n        const uint32_t b = value / 10000; // 0 to 9999\r\n        const uint32_t c = value % 10000; // 0 to 9999\r\n\r\n        const uint32_t d1 = (b / 100) << 1;\r\n        const uint32_t d2 = (b % 100) << 1;\r\n\r\n        const uint32_t d3 = (c / 100) << 1;\r\n        const uint32_t d4 = (c % 100) << 1;\r\n\r\n        *buffer++ = cDigitsLut[d1];\r\n        *buffer++ = cDigitsLut[d1 + 1];\r\n        *buffer++ = cDigitsLut[d2];\r\n        *buffer++ = cDigitsLut[d2 + 1];\r\n        *buffer++ = cDigitsLut[d3];\r\n        *buffer++ = cDigitsLut[d3 + 1];\r\n        *buffer++ = cDigitsLut[d4];\r\n        *buffer++ = cDigitsLut[d4 + 1];\r\n    }\r\n    return buffer;\r\n}\r\n\r\ninline char* i32toa(int32_t value, char* buffer) {\r\n    RAPIDJSON_ASSERT(buffer != 0);\r\n    uint32_t u = static_cast<uint32_t>(value);\r\n    if (value < 0) {\r\n        *buffer++ = '-';\r\n        u = ~u + 1;\r\n    }\r\n\r\n    return u32toa(u, buffer);\r\n}\r\n\r\ninline char* u64toa(uint64_t value, char* buffer) {\r\n    RAPIDJSON_ASSERT(buffer != 0);\r\n    const char* cDigitsLut = GetDigitsLut();\r\n    const uint64_t  kTen8 = 100000000;\r\n    const uint64_t  kTen9 = kTen8 * 10;\r\n    const uint64_t kTen10 = kTen8 * 100;\r\n    const uint64_t kTen11 = kTen8 * 1000;\r\n    const uint64_t kTen12 = kTen8 * 10000;\r\n    const uint64_t kTen13 = kTen8 * 100000;\r\n    const uint64_t kTen14 = kTen8 * 1000000;\r\n    const uint64_t kTen15 = kTen8 * 10000000;\r\n    const uint64_t kTen16 = kTen8 * kTen8;\r\n\r\n    if (value < kTen8) {\r\n        uint32_t v = static_cast<uint32_t>(value);\r\n        if (v < 10000) {\r\n            const uint32_t d1 = (v / 100) << 1;\r\n            const uint32_t d2 = (v % 100) << 1;\r\n\r\n            if (v >= 1000)\r\n                *buffer++ = cDigitsLut[d1];\r\n            if (v >= 100)\r\n                *buffer++ = cDigitsLut[d1 + 1];\r\n            if (v >= 10)\r\n                *buffer++ = cDigitsLut[d2];\r\n            *buffer++ = cDigitsLut[d2 + 1];\r\n        }\r\n        else {\r\n            // value = bbbbcccc\r\n            const uint32_t b = v / 10000;\r\n            const uint32_t c = v % 10000;\r\n\r\n            const uint32_t d1 = (b / 100) << 1;\r\n            const uint32_t d2 = (b % 100) << 1;\r\n\r\n            const uint32_t d3 = (c / 100) << 1;\r\n            const uint32_t d4 = (c % 100) << 1;\r\n\r\n            if (value >= 10000000)\r\n                *buffer++ = cDigitsLut[d1];\r\n            if (value >= 1000000)\r\n                *buffer++ = cDigitsLut[d1 + 1];\r\n            if (value >= 100000)\r\n                *buffer++ = cDigitsLut[d2];\r\n            *buffer++ = cDigitsLut[d2 + 1];\r\n\r\n            *buffer++ = cDigitsLut[d3];\r\n            *buffer++ = cDigitsLut[d3 + 1];\r\n            *buffer++ = cDigitsLut[d4];\r\n            *buffer++ = cDigitsLut[d4 + 1];\r\n        }\r\n    }\r\n    else if (value < kTen16) {\r\n        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);\r\n        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);\r\n\r\n        const uint32_t b0 = v0 / 10000;\r\n        const uint32_t c0 = v0 % 10000;\r\n\r\n        const uint32_t d1 = (b0 / 100) << 1;\r\n        const uint32_t d2 = (b0 % 100) << 1;\r\n\r\n        const uint32_t d3 = (c0 / 100) << 1;\r\n        const uint32_t d4 = (c0 % 100) << 1;\r\n\r\n        const uint32_t b1 = v1 / 10000;\r\n        const uint32_t c1 = v1 % 10000;\r\n\r\n        const uint32_t d5 = (b1 / 100) << 1;\r\n        const uint32_t d6 = (b1 % 100) << 1;\r\n\r\n        const uint32_t d7 = (c1 / 100) << 1;\r\n        const uint32_t d8 = (c1 % 100) << 1;\r\n\r\n        if (value >= kTen15)\r\n            *buffer++ = cDigitsLut[d1];\r\n        if (value >= kTen14)\r\n            *buffer++ = cDigitsLut[d1 + 1];\r\n        if (value >= kTen13)\r\n            *buffer++ = cDigitsLut[d2];\r\n        if (value >= kTen12)\r\n            *buffer++ = cDigitsLut[d2 + 1];\r\n        if (value >= kTen11)\r\n            *buffer++ = cDigitsLut[d3];\r\n        if (value >= kTen10)\r\n            *buffer++ = cDigitsLut[d3 + 1];\r\n        if (value >= kTen9)\r\n            *buffer++ = cDigitsLut[d4];\r\n        if (value >= kTen8)\r\n            *buffer++ = cDigitsLut[d4 + 1];\r\n\r\n        *buffer++ = cDigitsLut[d5];\r\n        *buffer++ = cDigitsLut[d5 + 1];\r\n        *buffer++ = cDigitsLut[d6];\r\n        *buffer++ = cDigitsLut[d6 + 1];\r\n        *buffer++ = cDigitsLut[d7];\r\n        *buffer++ = cDigitsLut[d7 + 1];\r\n        *buffer++ = cDigitsLut[d8];\r\n        *buffer++ = cDigitsLut[d8 + 1];\r\n    }\r\n    else {\r\n        const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844\r\n        value %= kTen16;\r\n\r\n        if (a < 10)\r\n            *buffer++ = static_cast<char>('0' + static_cast<char>(a));\r\n        else if (a < 100) {\r\n            const uint32_t i = a << 1;\r\n            *buffer++ = cDigitsLut[i];\r\n            *buffer++ = cDigitsLut[i + 1];\r\n        }\r\n        else if (a < 1000) {\r\n            *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));\r\n\r\n            const uint32_t i = (a % 100) << 1;\r\n            *buffer++ = cDigitsLut[i];\r\n            *buffer++ = cDigitsLut[i + 1];\r\n        }\r\n        else {\r\n            const uint32_t i = (a / 100) << 1;\r\n            const uint32_t j = (a % 100) << 1;\r\n            *buffer++ = cDigitsLut[i];\r\n            *buffer++ = cDigitsLut[i + 1];\r\n            *buffer++ = cDigitsLut[j];\r\n            *buffer++ = cDigitsLut[j + 1];\r\n        }\r\n\r\n        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);\r\n        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);\r\n\r\n        const uint32_t b0 = v0 / 10000;\r\n        const uint32_t c0 = v0 % 10000;\r\n\r\n        const uint32_t d1 = (b0 / 100) << 1;\r\n        const uint32_t d2 = (b0 % 100) << 1;\r\n\r\n        const uint32_t d3 = (c0 / 100) << 1;\r\n        const uint32_t d4 = (c0 % 100) << 1;\r\n\r\n        const uint32_t b1 = v1 / 10000;\r\n        const uint32_t c1 = v1 % 10000;\r\n\r\n        const uint32_t d5 = (b1 / 100) << 1;\r\n        const uint32_t d6 = (b1 % 100) << 1;\r\n\r\n        const uint32_t d7 = (c1 / 100) << 1;\r\n        const uint32_t d8 = (c1 % 100) << 1;\r\n\r\n        *buffer++ = cDigitsLut[d1];\r\n        *buffer++ = cDigitsLut[d1 + 1];\r\n        *buffer++ = cDigitsLut[d2];\r\n        *buffer++ = cDigitsLut[d2 + 1];\r\n        *buffer++ = cDigitsLut[d3];\r\n        *buffer++ = cDigitsLut[d3 + 1];\r\n        *buffer++ = cDigitsLut[d4];\r\n        *buffer++ = cDigitsLut[d4 + 1];\r\n        *buffer++ = cDigitsLut[d5];\r\n        *buffer++ = cDigitsLut[d5 + 1];\r\n        *buffer++ = cDigitsLut[d6];\r\n        *buffer++ = cDigitsLut[d6 + 1];\r\n        *buffer++ = cDigitsLut[d7];\r\n        *buffer++ = cDigitsLut[d7 + 1];\r\n        *buffer++ = cDigitsLut[d8];\r\n        *buffer++ = cDigitsLut[d8 + 1];\r\n    }\r\n\r\n    return buffer;\r\n}\r\n\r\ninline char* i64toa(int64_t value, char* buffer) {\r\n    RAPIDJSON_ASSERT(buffer != 0);\r\n    uint64_t u = static_cast<uint64_t>(value);\r\n    if (value < 0) {\r\n        *buffer++ = '-';\r\n        u = ~u + 1;\r\n    }\r\n\r\n    return u64toa(u, buffer);\r\n}\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_ITOA_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/meta.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_INTERNAL_META_H_\r\n#define RAPIDJSON_INTERNAL_META_H_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n#if defined(_MSC_VER)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(6334)\r\n#endif\r\n\r\n#if RAPIDJSON_HAS_CXX11_TYPETRAITS\r\n#include <type_traits>\r\n#endif\r\n\r\n//@cond RAPIDJSON_INTERNAL\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching\r\ntemplate <typename T> struct Void { typedef void Type; };\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// BoolType, TrueType, FalseType\r\n//\r\ntemplate <bool Cond> struct BoolType {\r\n    static const bool Value = Cond;\r\n    typedef BoolType Type;\r\n};\r\ntypedef BoolType<true> TrueType;\r\ntypedef BoolType<false> FalseType;\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr\r\n//\r\n\r\ntemplate <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };\r\ntemplate <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };\r\ntemplate <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};\r\ntemplate <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};\r\n\r\ntemplate <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};\r\ntemplate <> struct AndExprCond<true, true> : TrueType {};\r\ntemplate <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};\r\ntemplate <> struct OrExprCond<false, false> : FalseType {};\r\n\r\ntemplate <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};\r\ntemplate <typename C> struct NotExpr  : SelectIf<C,FalseType,TrueType>::Type {};\r\ntemplate <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};\r\ntemplate <typename C1, typename C2> struct OrExpr  : OrExprCond<C1::Value, C2::Value>::Type {};\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// AddConst, MaybeAddConst, RemoveConst\r\ntemplate <typename T> struct AddConst { typedef const T Type; };\r\ntemplate <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};\r\ntemplate <typename T> struct RemoveConst { typedef T Type; };\r\ntemplate <typename T> struct RemoveConst<const T> { typedef T Type; };\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// IsSame, IsConst, IsMoreConst, IsPointer\r\n//\r\ntemplate <typename T, typename U> struct IsSame : FalseType {};\r\ntemplate <typename T> struct IsSame<T, T> : TrueType {};\r\n\r\ntemplate <typename T> struct IsConst : FalseType {};\r\ntemplate <typename T> struct IsConst<const T> : TrueType {};\r\n\r\ntemplate <typename CT, typename T>\r\nstruct IsMoreConst\r\n    : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,\r\n              BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};\r\n\r\ntemplate <typename T> struct IsPointer : FalseType {};\r\ntemplate <typename T> struct IsPointer<T*> : TrueType {};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// IsBaseOf\r\n//\r\n#if RAPIDJSON_HAS_CXX11_TYPETRAITS\r\n\r\ntemplate <typename B, typename D> struct IsBaseOf\r\n    : BoolType< ::std::is_base_of<B,D>::value> {};\r\n\r\n#else // simplified version adopted from Boost\r\n\r\ntemplate<typename B, typename D> struct IsBaseOfImpl {\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);\r\n    RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);\r\n\r\n    typedef char (&Yes)[1];\r\n    typedef char (&No) [2];\r\n\r\n    template <typename T>\r\n    static Yes Check(const D*, T);\r\n    static No  Check(const B*, int);\r\n\r\n    struct Host {\r\n        operator const B*() const;\r\n        operator const D*();\r\n    };\r\n\r\n    enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };\r\n};\r\n\r\ntemplate <typename B, typename D> struct IsBaseOf\r\n    : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};\r\n\r\n#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS\r\n\r\n\r\n//////////////////////////////////////////////////////////////////////////\r\n// EnableIf / DisableIf\r\n//\r\ntemplate <bool Condition, typename T = void> struct EnableIfCond  { typedef T Type; };\r\ntemplate <typename T> struct EnableIfCond<false, T> { /* empty */ };\r\n\r\ntemplate <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };\r\ntemplate <typename T> struct DisableIfCond<true, T> { /* empty */ };\r\n\r\ntemplate <typename Condition, typename T = void>\r\nstruct EnableIf : EnableIfCond<Condition::Value, T> {};\r\n\r\ntemplate <typename Condition, typename T = void>\r\nstruct DisableIf : DisableIfCond<Condition::Value, T> {};\r\n\r\n// SFINAE helpers\r\nstruct SfinaeTag {};\r\ntemplate <typename T> struct RemoveSfinaeTag;\r\ntemplate <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };\r\n\r\n#define RAPIDJSON_REMOVEFPTR_(type) \\\r\n    typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \\\r\n        < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type\r\n\r\n#define RAPIDJSON_ENABLEIF(cond) \\\r\n    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \\\r\n        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL\r\n\r\n#define RAPIDJSON_DISABLEIF(cond) \\\r\n    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \\\r\n        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL\r\n\r\n#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \\\r\n    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \\\r\n        <RAPIDJSON_REMOVEFPTR_(cond), \\\r\n         RAPIDJSON_REMOVEFPTR_(returntype)>::Type\r\n\r\n#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \\\r\n    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \\\r\n        <RAPIDJSON_REMOVEFPTR_(cond), \\\r\n         RAPIDJSON_REMOVEFPTR_(returntype)>::Type\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n//@endcond\r\n\r\n#if defined(__GNUC__) || defined(_MSC_VER)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_INTERNAL_META_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/pow10.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_POW10_\r\n#define RAPIDJSON_POW10_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n//! Computes integer powers of 10 in double (10.0^n).\r\n/*! This function uses lookup table for fast and accurate results.\r\n    \\param n non-negative exponent. Must <= 308.\r\n    \\return 10.0^n\r\n*/\r\ninline double Pow10(int n) {\r\n    static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes\r\n        1e+0,  \r\n        1e+1,  1e+2,  1e+3,  1e+4,  1e+5,  1e+6,  1e+7,  1e+8,  1e+9,  1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, \r\n        1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,\r\n        1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,\r\n        1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,\r\n        1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,\r\n        1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,\r\n        1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,\r\n        1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,\r\n        1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,\r\n        1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,\r\n        1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,\r\n        1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,\r\n        1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,\r\n        1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,\r\n        1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,\r\n        1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308\r\n    };\r\n    RAPIDJSON_ASSERT(n >= 0 && n <= 308);\r\n    return e[n];\r\n}\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_POW10_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/regex.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_INTERNAL_REGEX_H_\r\n#define RAPIDJSON_INTERNAL_REGEX_H_\r\n\r\n#include \"../allocators.h\"\r\n#include \"../stream.h\"\r\n#include \"stack.h\"\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\nRAPIDJSON_DIAG_OFF(switch-enum)\r\nRAPIDJSON_DIAG_OFF(implicit-fallthrough)\r\n#endif\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#if __GNUC__ >= 7\r\nRAPIDJSON_DIAG_OFF(implicit-fallthrough)\r\n#endif\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated\r\n#endif\r\n\r\n#ifndef RAPIDJSON_REGEX_VERBOSE\r\n#define RAPIDJSON_REGEX_VERBOSE 0\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// DecodedStream\r\n\r\ntemplate <typename SourceStream, typename Encoding>\r\nclass DecodedStream {\r\npublic:\r\n    DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }\r\n    unsigned Peek() { return codepoint_; }\r\n    unsigned Take() {\r\n        unsigned c = codepoint_;\r\n        if (c) // No further decoding when '\\0'\r\n            Decode();\r\n        return c;\r\n    }\r\n\r\nprivate:\r\n    void Decode() {\r\n        if (!Encoding::Decode(ss_, &codepoint_))\r\n            codepoint_ = 0;\r\n    }\r\n\r\n    SourceStream& ss_;\r\n    unsigned codepoint_;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericRegex\r\n\r\nstatic const SizeType kRegexInvalidState = ~SizeType(0);  //!< Represents an invalid index in GenericRegex::State::out, out1\r\nstatic const SizeType kRegexInvalidRange = ~SizeType(0);\r\n\r\ntemplate <typename Encoding, typename Allocator>\r\nclass GenericRegexSearch;\r\n\r\n//! Regular expression engine with subset of ECMAscript grammar.\r\n/*!\r\n    Supported regular expression syntax:\r\n    - \\c ab     Concatenation\r\n    - \\c a|b    Alternation\r\n    - \\c a?     Zero or one\r\n    - \\c a*     Zero or more\r\n    - \\c a+     One or more\r\n    - \\c a{3}   Exactly 3 times\r\n    - \\c a{3,}  At least 3 times\r\n    - \\c a{3,5} 3 to 5 times\r\n    - \\c (ab)   Grouping\r\n    - \\c ^a     At the beginning\r\n    - \\c a$     At the end\r\n    - \\c .      Any character\r\n    - \\c [abc]  Character classes\r\n    - \\c [a-c]  Character class range\r\n    - \\c [a-z0-9_] Character class combination\r\n    - \\c [^abc] Negated character classes\r\n    - \\c [^a-c] Negated character class range\r\n    - \\c [\\b]   Backspace (U+0008)\r\n    - \\c \\\\| \\\\\\\\ ...  Escape characters\r\n    - \\c \\\\f Form feed (U+000C)\r\n    - \\c \\\\n Line feed (U+000A)\r\n    - \\c \\\\r Carriage return (U+000D)\r\n    - \\c \\\\t Tab (U+0009)\r\n    - \\c \\\\v Vertical tab (U+000B)\r\n\r\n    \\note This is a Thompson NFA engine, implemented with reference to \r\n        Cox, Russ. \"Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).\", \r\n        https://swtch.com/~rsc/regexp/regexp1.html \r\n*/\r\ntemplate <typename Encoding, typename Allocator = CrtAllocator>\r\nclass GenericRegex {\r\npublic:\r\n    typedef Encoding EncodingType;\r\n    typedef typename Encoding::Ch Ch;\r\n    template <typename, typename> friend class GenericRegexSearch;\r\n\r\n    GenericRegex(const Ch* source, Allocator* allocator = 0) : \r\n        states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), \r\n        anchorBegin_(), anchorEnd_()\r\n    {\r\n        GenericStringStream<Encoding> ss(source);\r\n        DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);\r\n        Parse(ds);\r\n    }\r\n\r\n    ~GenericRegex() {}\r\n\r\n    bool IsValid() const {\r\n        return root_ != kRegexInvalidState;\r\n    }\r\n\r\nprivate:\r\n    enum Operator {\r\n        kZeroOrOne,\r\n        kZeroOrMore,\r\n        kOneOrMore,\r\n        kConcatenation,\r\n        kAlternation,\r\n        kLeftParenthesis\r\n    };\r\n\r\n    static const unsigned kAnyCharacterClass = 0xFFFFFFFF;   //!< For '.'\r\n    static const unsigned kRangeCharacterClass = 0xFFFFFFFE;\r\n    static const unsigned kRangeNegationFlag = 0x80000000;\r\n\r\n    struct Range {\r\n        unsigned start; // \r\n        unsigned end;\r\n        SizeType next;\r\n    };\r\n\r\n    struct State {\r\n        SizeType out;     //!< Equals to kInvalid for matching state\r\n        SizeType out1;    //!< Equals to non-kInvalid for split\r\n        SizeType rangeStart;\r\n        unsigned codepoint;\r\n    };\r\n\r\n    struct Frag {\r\n        Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}\r\n        SizeType start;\r\n        SizeType out; //!< link-list of all output states\r\n        SizeType minIndex;\r\n    };\r\n\r\n    State& GetState(SizeType index) {\r\n        RAPIDJSON_ASSERT(index < stateCount_);\r\n        return states_.template Bottom<State>()[index];\r\n    }\r\n\r\n    const State& GetState(SizeType index) const {\r\n        RAPIDJSON_ASSERT(index < stateCount_);\r\n        return states_.template Bottom<State>()[index];\r\n    }\r\n\r\n    Range& GetRange(SizeType index) {\r\n        RAPIDJSON_ASSERT(index < rangeCount_);\r\n        return ranges_.template Bottom<Range>()[index];\r\n    }\r\n\r\n    const Range& GetRange(SizeType index) const {\r\n        RAPIDJSON_ASSERT(index < rangeCount_);\r\n        return ranges_.template Bottom<Range>()[index];\r\n    }\r\n\r\n    template <typename InputStream>\r\n    void Parse(DecodedStream<InputStream, Encoding>& ds) {\r\n        Allocator allocator;\r\n        Stack<Allocator> operandStack(&allocator, 256);     // Frag\r\n        Stack<Allocator> operatorStack(&allocator, 256);    // Operator\r\n        Stack<Allocator> atomCountStack(&allocator, 256);   // unsigned (Atom per parenthesis)\r\n\r\n        *atomCountStack.template Push<unsigned>() = 0;\r\n\r\n        unsigned codepoint;\r\n        while (ds.Peek() != 0) {\r\n            switch (codepoint = ds.Take()) {\r\n                case '^':\r\n                    anchorBegin_ = true;\r\n                    break;\r\n\r\n                case '$':\r\n                    anchorEnd_ = true;\r\n                    break;\r\n\r\n                case '|':\r\n                    while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)\r\n                        if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))\r\n                            return;\r\n                    *operatorStack.template Push<Operator>() = kAlternation;\r\n                    *atomCountStack.template Top<unsigned>() = 0;\r\n                    break;\r\n\r\n                case '(':\r\n                    *operatorStack.template Push<Operator>() = kLeftParenthesis;\r\n                    *atomCountStack.template Push<unsigned>() = 0;\r\n                    break;\r\n\r\n                case ')':\r\n                    while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)\r\n                        if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))\r\n                            return;\r\n                    if (operatorStack.Empty())\r\n                        return;\r\n                    operatorStack.template Pop<Operator>(1);\r\n                    atomCountStack.template Pop<unsigned>(1);\r\n                    ImplicitConcatenation(atomCountStack, operatorStack);\r\n                    break;\r\n\r\n                case '?':\r\n                    if (!Eval(operandStack, kZeroOrOne))\r\n                        return;\r\n                    break;\r\n\r\n                case '*':\r\n                    if (!Eval(operandStack, kZeroOrMore))\r\n                        return;\r\n                    break;\r\n\r\n                case '+':\r\n                    if (!Eval(operandStack, kOneOrMore))\r\n                        return;\r\n                    break;\r\n\r\n                case '{':\r\n                    {\r\n                        unsigned n, m;\r\n                        if (!ParseUnsigned(ds, &n))\r\n                            return;\r\n\r\n                        if (ds.Peek() == ',') {\r\n                            ds.Take();\r\n                            if (ds.Peek() == '}')\r\n                                m = kInfinityQuantifier;\r\n                            else if (!ParseUnsigned(ds, &m) || m < n)\r\n                                return;\r\n                        }\r\n                        else\r\n                            m = n;\r\n\r\n                        if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')\r\n                            return;\r\n                        ds.Take();\r\n                    }\r\n                    break;\r\n\r\n                case '.':\r\n                    PushOperand(operandStack, kAnyCharacterClass);\r\n                    ImplicitConcatenation(atomCountStack, operatorStack);\r\n                    break;\r\n\r\n                case '[':\r\n                    {\r\n                        SizeType range;\r\n                        if (!ParseRange(ds, &range))\r\n                            return;\r\n                        SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);\r\n                        GetState(s).rangeStart = range;\r\n                        *operandStack.template Push<Frag>() = Frag(s, s, s);\r\n                    }\r\n                    ImplicitConcatenation(atomCountStack, operatorStack);\r\n                    break;\r\n\r\n                case '\\\\': // Escape character\r\n                    if (!CharacterEscape(ds, &codepoint))\r\n                        return; // Unsupported escape character\r\n                    // fall through to default\r\n\r\n                default: // Pattern character\r\n                    PushOperand(operandStack, codepoint);\r\n                    ImplicitConcatenation(atomCountStack, operatorStack);\r\n            }\r\n        }\r\n\r\n        while (!operatorStack.Empty())\r\n            if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))\r\n                return;\r\n\r\n        // Link the operand to matching state.\r\n        if (operandStack.GetSize() == sizeof(Frag)) {\r\n            Frag* e = operandStack.template Pop<Frag>(1);\r\n            Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));\r\n            root_ = e->start;\r\n\r\n#if RAPIDJSON_REGEX_VERBOSE\r\n            printf(\"root: %d\\n\", root_);\r\n            for (SizeType i = 0; i < stateCount_ ; i++) {\r\n                State& s = GetState(i);\r\n                printf(\"[%2d] out: %2d out1: %2d c: '%c'\\n\", i, s.out, s.out1, (char)s.codepoint);\r\n            }\r\n            printf(\"\\n\");\r\n#endif\r\n        }\r\n    }\r\n\r\n    SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {\r\n        State* s = states_.template Push<State>();\r\n        s->out = out;\r\n        s->out1 = out1;\r\n        s->codepoint = codepoint;\r\n        s->rangeStart = kRegexInvalidRange;\r\n        return stateCount_++;\r\n    }\r\n\r\n    void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {\r\n        SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);\r\n        *operandStack.template Push<Frag>() = Frag(s, s, s);\r\n    }\r\n\r\n    void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {\r\n        if (*atomCountStack.template Top<unsigned>())\r\n            *operatorStack.template Push<Operator>() = kConcatenation;\r\n        (*atomCountStack.template Top<unsigned>())++;\r\n    }\r\n\r\n    SizeType Append(SizeType l1, SizeType l2) {\r\n        SizeType old = l1;\r\n        while (GetState(l1).out != kRegexInvalidState)\r\n            l1 = GetState(l1).out;\r\n        GetState(l1).out = l2;\r\n        return old;\r\n    }\r\n\r\n    void Patch(SizeType l, SizeType s) {\r\n        for (SizeType next; l != kRegexInvalidState; l = next) {\r\n            next = GetState(l).out;\r\n            GetState(l).out = s;\r\n        }\r\n    }\r\n\r\n    bool Eval(Stack<Allocator>& operandStack, Operator op) {\r\n        switch (op) {\r\n            case kConcatenation:\r\n                RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);\r\n                {\r\n                    Frag e2 = *operandStack.template Pop<Frag>(1);\r\n                    Frag e1 = *operandStack.template Pop<Frag>(1);\r\n                    Patch(e1.out, e2.start);\r\n                    *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));\r\n                }\r\n                return true;\r\n\r\n            case kAlternation:\r\n                if (operandStack.GetSize() >= sizeof(Frag) * 2) {\r\n                    Frag e2 = *operandStack.template Pop<Frag>(1);\r\n                    Frag e1 = *operandStack.template Pop<Frag>(1);\r\n                    SizeType s = NewState(e1.start, e2.start, 0);\r\n                    *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));\r\n                    return true;\r\n                }\r\n                return false;\r\n\r\n            case kZeroOrOne:\r\n                if (operandStack.GetSize() >= sizeof(Frag)) {\r\n                    Frag e = *operandStack.template Pop<Frag>(1);\r\n                    SizeType s = NewState(kRegexInvalidState, e.start, 0);\r\n                    *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);\r\n                    return true;\r\n                }\r\n                return false;\r\n\r\n            case kZeroOrMore:\r\n                if (operandStack.GetSize() >= sizeof(Frag)) {\r\n                    Frag e = *operandStack.template Pop<Frag>(1);\r\n                    SizeType s = NewState(kRegexInvalidState, e.start, 0);\r\n                    Patch(e.out, s);\r\n                    *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);\r\n                    return true;\r\n                }\r\n                return false;\r\n\r\n            default: \r\n                RAPIDJSON_ASSERT(op == kOneOrMore);\r\n                if (operandStack.GetSize() >= sizeof(Frag)) {\r\n                    Frag e = *operandStack.template Pop<Frag>(1);\r\n                    SizeType s = NewState(kRegexInvalidState, e.start, 0);\r\n                    Patch(e.out, s);\r\n                    *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);\r\n                    return true;\r\n                }\r\n                return false;\r\n        }\r\n    }\r\n\r\n    bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {\r\n        RAPIDJSON_ASSERT(n <= m);\r\n        RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));\r\n\r\n        if (n == 0) {\r\n            if (m == 0)                             // a{0} not support\r\n                return false;\r\n            else if (m == kInfinityQuantifier)\r\n                Eval(operandStack, kZeroOrMore);    // a{0,} -> a*\r\n            else {\r\n                Eval(operandStack, kZeroOrOne);         // a{0,5} -> a?\r\n                for (unsigned i = 0; i < m - 1; i++)\r\n                    CloneTopOperand(operandStack);      // a{0,5} -> a? a? a? a? a?\r\n                for (unsigned i = 0; i < m - 1; i++)\r\n                    Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?\r\n            }\r\n            return true;\r\n        }\r\n\r\n        for (unsigned i = 0; i < n - 1; i++)        // a{3} -> a a a\r\n            CloneTopOperand(operandStack);\r\n\r\n        if (m == kInfinityQuantifier)\r\n            Eval(operandStack, kOneOrMore);         // a{3,} -> a a a+\r\n        else if (m > n) {\r\n            CloneTopOperand(operandStack);          // a{3,5} -> a a a a\r\n            Eval(operandStack, kZeroOrOne);         // a{3,5} -> a a a a?\r\n            for (unsigned i = n; i < m - 1; i++)\r\n                CloneTopOperand(operandStack);      // a{3,5} -> a a a a? a?\r\n            for (unsigned i = n; i < m; i++)\r\n                Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?\r\n        }\r\n\r\n        for (unsigned i = 0; i < n - 1; i++)\r\n            Eval(operandStack, kConcatenation);     // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?\r\n\r\n        return true;\r\n    }\r\n\r\n    static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }\r\n\r\n    void CloneTopOperand(Stack<Allocator>& operandStack) {\r\n        const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation\r\n        SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)\r\n        State* s = states_.template Push<State>(count);\r\n        memcpy(s, &GetState(src.minIndex), count * sizeof(State));\r\n        for (SizeType j = 0; j < count; j++) {\r\n            if (s[j].out != kRegexInvalidState)\r\n                s[j].out += count;\r\n            if (s[j].out1 != kRegexInvalidState)\r\n                s[j].out1 += count;\r\n        }\r\n        *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);\r\n        stateCount_ += count;\r\n    }\r\n\r\n    template <typename InputStream>\r\n    bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {\r\n        unsigned r = 0;\r\n        if (ds.Peek() < '0' || ds.Peek() > '9')\r\n            return false;\r\n        while (ds.Peek() >= '0' && ds.Peek() <= '9') {\r\n            if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295\r\n                return false; // overflow\r\n            r = r * 10 + (ds.Take() - '0');\r\n        }\r\n        *u = r;\r\n        return true;\r\n    }\r\n\r\n    template <typename InputStream>\r\n    bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {\r\n        bool isBegin = true;\r\n        bool negate = false;\r\n        int step = 0;\r\n        SizeType start = kRegexInvalidRange;\r\n        SizeType current = kRegexInvalidRange;\r\n        unsigned codepoint;\r\n        while ((codepoint = ds.Take()) != 0) {\r\n            if (isBegin) {\r\n                isBegin = false;\r\n                if (codepoint == '^') {\r\n                    negate = true;\r\n                    continue;\r\n                }\r\n            }\r\n\r\n            switch (codepoint) {\r\n            case ']':\r\n                if (start == kRegexInvalidRange)\r\n                    return false;   // Error: nothing inside []\r\n                if (step == 2) { // Add trailing '-'\r\n                    SizeType r = NewRange('-');\r\n                    RAPIDJSON_ASSERT(current != kRegexInvalidRange);\r\n                    GetRange(current).next = r;\r\n                }\r\n                if (negate)\r\n                    GetRange(start).start |= kRangeNegationFlag;\r\n                *range = start;\r\n                return true;\r\n\r\n            case '\\\\':\r\n                if (ds.Peek() == 'b') {\r\n                    ds.Take();\r\n                    codepoint = 0x0008; // Escape backspace character\r\n                }\r\n                else if (!CharacterEscape(ds, &codepoint))\r\n                    return false;\r\n                // fall through to default\r\n\r\n            default:\r\n                switch (step) {\r\n                case 1:\r\n                    if (codepoint == '-') {\r\n                        step++;\r\n                        break;\r\n                    }\r\n                    // fall through to step 0 for other characters\r\n\r\n                case 0:\r\n                    {\r\n                        SizeType r = NewRange(codepoint);\r\n                        if (current != kRegexInvalidRange)\r\n                            GetRange(current).next = r;\r\n                        if (start == kRegexInvalidRange)\r\n                            start = r;\r\n                        current = r;\r\n                    }\r\n                    step = 1;\r\n                    break;\r\n\r\n                default:\r\n                    RAPIDJSON_ASSERT(step == 2);\r\n                    GetRange(current).end = codepoint;\r\n                    step = 0;\r\n                }\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n    \r\n    SizeType NewRange(unsigned codepoint) {\r\n        Range* r = ranges_.template Push<Range>();\r\n        r->start = r->end = codepoint;\r\n        r->next = kRegexInvalidRange;\r\n        return rangeCount_++;\r\n    }\r\n\r\n    template <typename InputStream>\r\n    bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {\r\n        unsigned codepoint;\r\n        switch (codepoint = ds.Take()) {\r\n            case '^':\r\n            case '$':\r\n            case '|':\r\n            case '(':\r\n            case ')':\r\n            case '?':\r\n            case '*':\r\n            case '+':\r\n            case '.':\r\n            case '[':\r\n            case ']':\r\n            case '{':\r\n            case '}':\r\n            case '\\\\':\r\n                *escapedCodepoint = codepoint; return true;\r\n            case 'f': *escapedCodepoint = 0x000C; return true;\r\n            case 'n': *escapedCodepoint = 0x000A; return true;\r\n            case 'r': *escapedCodepoint = 0x000D; return true;\r\n            case 't': *escapedCodepoint = 0x0009; return true;\r\n            case 'v': *escapedCodepoint = 0x000B; return true;\r\n            default:\r\n                return false; // Unsupported escape character\r\n        }\r\n    }\r\n\r\n    Stack<Allocator> states_;\r\n    Stack<Allocator> ranges_;\r\n    SizeType root_;\r\n    SizeType stateCount_;\r\n    SizeType rangeCount_;\r\n\r\n    static const unsigned kInfinityQuantifier = ~0u;\r\n\r\n    // For SearchWithAnchoring()\r\n    bool anchorBegin_;\r\n    bool anchorEnd_;\r\n};\r\n\r\ntemplate <typename RegexType, typename Allocator = CrtAllocator>\r\nclass GenericRegexSearch {\r\npublic:\r\n    typedef typename RegexType::EncodingType Encoding;\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : \r\n        regex_(regex), allocator_(allocator), ownAllocator_(0),\r\n        state0_(allocator, 0), state1_(allocator, 0), stateSet_()\r\n    {\r\n        RAPIDJSON_ASSERT(regex_.IsValid());\r\n        if (!allocator_)\r\n            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n        stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));\r\n        state0_.template Reserve<SizeType>(regex_.stateCount_);\r\n        state1_.template Reserve<SizeType>(regex_.stateCount_);\r\n    }\r\n\r\n    ~GenericRegexSearch() {\r\n        Allocator::Free(stateSet_);\r\n        RAPIDJSON_DELETE(ownAllocator_);\r\n    }\r\n\r\n    template <typename InputStream>\r\n    bool Match(InputStream& is) {\r\n        return SearchWithAnchoring(is, true, true);\r\n    }\r\n\r\n    bool Match(const Ch* s) {\r\n        GenericStringStream<Encoding> is(s);\r\n        return Match(is);\r\n    }\r\n\r\n    template <typename InputStream>\r\n    bool Search(InputStream& is) {\r\n        return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);\r\n    }\r\n\r\n    bool Search(const Ch* s) {\r\n        GenericStringStream<Encoding> is(s);\r\n        return Search(is);\r\n    }\r\n\r\nprivate:\r\n    typedef typename RegexType::State State;\r\n    typedef typename RegexType::Range Range;\r\n\r\n    template <typename InputStream>\r\n    bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {\r\n        DecodedStream<InputStream, Encoding> ds(is);\r\n\r\n        state0_.Clear();\r\n        Stack<Allocator> *current = &state0_, *next = &state1_;\r\n        const size_t stateSetSize = GetStateSetSize();\r\n        std::memset(stateSet_, 0, stateSetSize);\r\n\r\n        bool matched = AddState(*current, regex_.root_);\r\n        unsigned codepoint;\r\n        while (!current->Empty() && (codepoint = ds.Take()) != 0) {\r\n            std::memset(stateSet_, 0, stateSetSize);\r\n            next->Clear();\r\n            matched = false;\r\n            for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {\r\n                const State& sr = regex_.GetState(*s);\r\n                if (sr.codepoint == codepoint ||\r\n                    sr.codepoint == RegexType::kAnyCharacterClass || \r\n                    (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))\r\n                {\r\n                    matched = AddState(*next, sr.out) || matched;\r\n                    if (!anchorEnd && matched)\r\n                        return true;\r\n                }\r\n                if (!anchorBegin)\r\n                    AddState(*next, regex_.root_);\r\n            }\r\n            internal::Swap(current, next);\r\n        }\r\n\r\n        return matched;\r\n    }\r\n\r\n    size_t GetStateSetSize() const {\r\n        return (regex_.stateCount_ + 31) / 32 * 4;\r\n    }\r\n\r\n    // Return whether the added states is a match state\r\n    bool AddState(Stack<Allocator>& l, SizeType index) {\r\n        RAPIDJSON_ASSERT(index != kRegexInvalidState);\r\n\r\n        const State& s = regex_.GetState(index);\r\n        if (s.out1 != kRegexInvalidState) { // Split\r\n            bool matched = AddState(l, s.out);\r\n            return AddState(l, s.out1) || matched;\r\n        }\r\n        else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {\r\n            stateSet_[index >> 5] |= (1u << (index & 31));\r\n            *l.template PushUnsafe<SizeType>() = index;\r\n        }\r\n        return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.\r\n    }\r\n\r\n    bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {\r\n        bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;\r\n        while (rangeIndex != kRegexInvalidRange) {\r\n            const Range& r = regex_.GetRange(rangeIndex);\r\n            if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)\r\n                return yes;\r\n            rangeIndex = r.next;\r\n        }\r\n        return !yes;\r\n    }\r\n\r\n    const RegexType& regex_;\r\n    Allocator* allocator_;\r\n    Allocator* ownAllocator_;\r\n    Stack<Allocator> state0_;\r\n    Stack<Allocator> state1_;\r\n    uint32_t* stateSet_;\r\n};\r\n\r\ntypedef GenericRegex<UTF8<> > Regex;\r\ntypedef GenericRegexSearch<Regex> RegexSearch;\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_INTERNAL_REGEX_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/stack.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_INTERNAL_STACK_H_\r\n#define RAPIDJSON_INTERNAL_STACK_H_\r\n\r\n#include \"../allocators.h\"\r\n#include \"swap.h\"\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(c++98-compat)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Stack\r\n\r\n//! A type-unsafe stack for storing different types of data.\r\n/*! \\tparam Allocator Allocator for allocating stack memory.\r\n*/\r\ntemplate <typename Allocator>\r\nclass Stack {\r\npublic:\r\n    // Optimization note: Do not allocate memory for stack_ in constructor.\r\n    // Do it lazily when first Push() -> Expand() -> Resize().\r\n    Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    Stack(Stack&& rhs)\r\n        : allocator_(rhs.allocator_),\r\n          ownAllocator_(rhs.ownAllocator_),\r\n          stack_(rhs.stack_),\r\n          stackTop_(rhs.stackTop_),\r\n          stackEnd_(rhs.stackEnd_),\r\n          initialCapacity_(rhs.initialCapacity_)\r\n    {\r\n        rhs.allocator_ = 0;\r\n        rhs.ownAllocator_ = 0;\r\n        rhs.stack_ = 0;\r\n        rhs.stackTop_ = 0;\r\n        rhs.stackEnd_ = 0;\r\n        rhs.initialCapacity_ = 0;\r\n    }\r\n#endif\r\n\r\n    ~Stack() {\r\n        Destroy();\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    Stack& operator=(Stack&& rhs) {\r\n        if (&rhs != this)\r\n        {\r\n            Destroy();\r\n\r\n            allocator_ = rhs.allocator_;\r\n            ownAllocator_ = rhs.ownAllocator_;\r\n            stack_ = rhs.stack_;\r\n            stackTop_ = rhs.stackTop_;\r\n            stackEnd_ = rhs.stackEnd_;\r\n            initialCapacity_ = rhs.initialCapacity_;\r\n\r\n            rhs.allocator_ = 0;\r\n            rhs.ownAllocator_ = 0;\r\n            rhs.stack_ = 0;\r\n            rhs.stackTop_ = 0;\r\n            rhs.stackEnd_ = 0;\r\n            rhs.initialCapacity_ = 0;\r\n        }\r\n        return *this;\r\n    }\r\n#endif\r\n\r\n    void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {\r\n        internal::Swap(allocator_, rhs.allocator_);\r\n        internal::Swap(ownAllocator_, rhs.ownAllocator_);\r\n        internal::Swap(stack_, rhs.stack_);\r\n        internal::Swap(stackTop_, rhs.stackTop_);\r\n        internal::Swap(stackEnd_, rhs.stackEnd_);\r\n        internal::Swap(initialCapacity_, rhs.initialCapacity_);\r\n    }\r\n\r\n    void Clear() { stackTop_ = stack_; }\r\n\r\n    void ShrinkToFit() { \r\n        if (Empty()) {\r\n            // If the stack is empty, completely deallocate the memory.\r\n            Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)\r\n            stack_ = 0;\r\n            stackTop_ = 0;\r\n            stackEnd_ = 0;\r\n        }\r\n        else\r\n            Resize(GetSize());\r\n    }\r\n\r\n    // Optimization note: try to minimize the size of this function for force inline.\r\n    // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.\r\n    template<typename T>\r\n    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {\r\n         // Expand the stack if needed\r\n        if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))\r\n            Expand<T>(count);\r\n    }\r\n\r\n    template<typename T>\r\n    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {\r\n        Reserve<T>(count);\r\n        return PushUnsafe<T>(count);\r\n    }\r\n\r\n    template<typename T>\r\n    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {\r\n        RAPIDJSON_ASSERT(stackTop_);\r\n        RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);\r\n        T* ret = reinterpret_cast<T*>(stackTop_);\r\n        stackTop_ += sizeof(T) * count;\r\n        return ret;\r\n    }\r\n\r\n    template<typename T>\r\n    T* Pop(size_t count) {\r\n        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));\r\n        stackTop_ -= count * sizeof(T);\r\n        return reinterpret_cast<T*>(stackTop_);\r\n    }\r\n\r\n    template<typename T>\r\n    T* Top() { \r\n        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));\r\n        return reinterpret_cast<T*>(stackTop_ - sizeof(T));\r\n    }\r\n\r\n    template<typename T>\r\n    const T* Top() const {\r\n        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));\r\n        return reinterpret_cast<T*>(stackTop_ - sizeof(T));\r\n    }\r\n\r\n    template<typename T>\r\n    T* End() { return reinterpret_cast<T*>(stackTop_); }\r\n\r\n    template<typename T>\r\n    const T* End() const { return reinterpret_cast<T*>(stackTop_); }\r\n\r\n    template<typename T>\r\n    T* Bottom() { return reinterpret_cast<T*>(stack_); }\r\n\r\n    template<typename T>\r\n    const T* Bottom() const { return reinterpret_cast<T*>(stack_); }\r\n\r\n    bool HasAllocator() const {\r\n        return allocator_ != 0;\r\n    }\r\n\r\n    Allocator& GetAllocator() {\r\n        RAPIDJSON_ASSERT(allocator_);\r\n        return *allocator_;\r\n    }\r\n\r\n    bool Empty() const { return stackTop_ == stack_; }\r\n    size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }\r\n    size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }\r\n\r\nprivate:\r\n    template<typename T>\r\n    void Expand(size_t count) {\r\n        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.\r\n        size_t newCapacity;\r\n        if (stack_ == 0) {\r\n            if (!allocator_)\r\n                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n            newCapacity = initialCapacity_;\r\n        } else {\r\n            newCapacity = GetCapacity();\r\n            newCapacity += (newCapacity + 1) / 2;\r\n        }\r\n        size_t newSize = GetSize() + sizeof(T) * count;\r\n        if (newCapacity < newSize)\r\n            newCapacity = newSize;\r\n\r\n        Resize(newCapacity);\r\n    }\r\n\r\n    void Resize(size_t newCapacity) {\r\n        const size_t size = GetSize();  // Backup the current size\r\n        stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));\r\n        stackTop_ = stack_ + size;\r\n        stackEnd_ = stack_ + newCapacity;\r\n    }\r\n\r\n    void Destroy() {\r\n        Allocator::Free(stack_);\r\n        RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack\r\n    }\r\n\r\n    // Prohibit copy constructor & assignment operator.\r\n    Stack(const Stack&);\r\n    Stack& operator=(const Stack&);\r\n\r\n    Allocator* allocator_;\r\n    Allocator* ownAllocator_;\r\n    char *stack_;\r\n    char *stackTop_;\r\n    char *stackEnd_;\r\n    size_t initialCapacity_;\r\n};\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_STACK_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/strfunc.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_\r\n#define RAPIDJSON_INTERNAL_STRFUNC_H_\r\n\r\n#include \"../stream.h\"\r\n#include <cwchar>\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n//! Custom strlen() which works on different character types.\r\n/*! \\tparam Ch Character type (e.g. char, wchar_t, short)\r\n    \\param s Null-terminated input string.\r\n    \\return Number of characters in the string. \r\n    \\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.\r\n*/\r\ntemplate <typename Ch>\r\ninline SizeType StrLen(const Ch* s) {\r\n    RAPIDJSON_ASSERT(s != 0);\r\n    const Ch* p = s;\r\n    while (*p) ++p;\r\n    return SizeType(p - s);\r\n}\r\n\r\ntemplate <>\r\ninline SizeType StrLen(const char* s) {\r\n    return SizeType(std::strlen(s));\r\n}\r\n\r\ntemplate <>\r\ninline SizeType StrLen(const wchar_t* s) {\r\n    return SizeType(std::wcslen(s));\r\n}\r\n\r\n//! Returns number of code points in a encoded string.\r\ntemplate<typename Encoding>\r\nbool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {\r\n    RAPIDJSON_ASSERT(s != 0);\r\n    RAPIDJSON_ASSERT(outCount != 0);\r\n    GenericStringStream<Encoding> is(s);\r\n    const typename Encoding::Ch* end = s + length;\r\n    SizeType count = 0;\r\n    while (is.src_ < end) {\r\n        unsigned codepoint;\r\n        if (!Encoding::Decode(is, &codepoint))\r\n            return false;\r\n        count++;\r\n    }\r\n    *outCount = count;\r\n    return true;\r\n}\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_INTERNAL_STRFUNC_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/strtod.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_STRTOD_\r\n#define RAPIDJSON_STRTOD_\r\n\r\n#include \"ieee754.h\"\r\n#include \"biginteger.h\"\r\n#include \"diyfp.h\"\r\n#include \"pow10.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\ninline double FastPath(double significand, int exp) {\r\n    if (exp < -308)\r\n        return 0.0;\r\n    else if (exp >= 0)\r\n        return significand * internal::Pow10(exp);\r\n    else\r\n        return significand / internal::Pow10(-exp);\r\n}\r\n\r\ninline double StrtodNormalPrecision(double d, int p) {\r\n    if (p < -308) {\r\n        // Prevent expSum < -308, making Pow10(p) = 0\r\n        d = FastPath(d, -308);\r\n        d = FastPath(d, p + 308);\r\n    }\r\n    else\r\n        d = FastPath(d, p);\r\n    return d;\r\n}\r\n\r\ntemplate <typename T>\r\ninline T Min3(T a, T b, T c) {\r\n    T m = a;\r\n    if (m > b) m = b;\r\n    if (m > c) m = c;\r\n    return m;\r\n}\r\n\r\ninline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {\r\n    const Double db(b);\r\n    const uint64_t bInt = db.IntegerSignificand();\r\n    const int bExp = db.IntegerExponent();\r\n    const int hExp = bExp - 1;\r\n\r\n    int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;\r\n\r\n    // Adjust for decimal exponent\r\n    if (dExp >= 0) {\r\n        dS_Exp2 += dExp;\r\n        dS_Exp5 += dExp;\r\n    }\r\n    else {\r\n        bS_Exp2 -= dExp;\r\n        bS_Exp5 -= dExp;\r\n        hS_Exp2 -= dExp;\r\n        hS_Exp5 -= dExp;\r\n    }\r\n\r\n    // Adjust for binary exponent\r\n    if (bExp >= 0)\r\n        bS_Exp2 += bExp;\r\n    else {\r\n        dS_Exp2 -= bExp;\r\n        hS_Exp2 -= bExp;\r\n    }\r\n\r\n    // Adjust for half ulp exponent\r\n    if (hExp >= 0)\r\n        hS_Exp2 += hExp;\r\n    else {\r\n        dS_Exp2 -= hExp;\r\n        bS_Exp2 -= hExp;\r\n    }\r\n\r\n    // Remove common power of two factor from all three scaled values\r\n    int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);\r\n    dS_Exp2 -= common_Exp2;\r\n    bS_Exp2 -= common_Exp2;\r\n    hS_Exp2 -= common_Exp2;\r\n\r\n    BigInteger dS = d;\r\n    dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);\r\n\r\n    BigInteger bS(bInt);\r\n    bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);\r\n\r\n    BigInteger hS(1);\r\n    hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);\r\n\r\n    BigInteger delta(0);\r\n    dS.Difference(bS, &delta);\r\n\r\n    return delta.Compare(hS);\r\n}\r\n\r\ninline bool StrtodFast(double d, int p, double* result) {\r\n    // Use fast path for string-to-double conversion if possible\r\n    // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/\r\n    if (p > 22  && p < 22 + 16) {\r\n        // Fast Path Cases In Disguise\r\n        d *= internal::Pow10(p - 22);\r\n        p = 22;\r\n    }\r\n\r\n    if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1\r\n        *result = FastPath(d, p);\r\n        return true;\r\n    }\r\n    else\r\n        return false;\r\n}\r\n\r\n// Compute an approximation and see if it is within 1/2 ULP\r\ninline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {\r\n    uint64_t significand = 0;\r\n    size_t i = 0;   // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999    \r\n    for (; i < length; i++) {\r\n        if (significand  >  RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||\r\n            (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))\r\n            break;\r\n        significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');\r\n    }\r\n    \r\n    if (i < length && decimals[i] >= '5') // Rounding\r\n        significand++;\r\n\r\n    size_t remaining = length - i;\r\n    const int kUlpShift = 3;\r\n    const int kUlp = 1 << kUlpShift;\r\n    int64_t error = (remaining == 0) ? 0 : kUlp / 2;\r\n\r\n    DiyFp v(significand, 0);\r\n    v = v.Normalize();\r\n    error <<= -v.e;\r\n\r\n    const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;\r\n\r\n    int actualExp;\r\n    DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);\r\n    if (actualExp != dExp) {\r\n        static const DiyFp kPow10[] = {\r\n            DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60),  // 10^1\r\n            DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57),  // 10^2\r\n            DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54),  // 10^3\r\n            DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50),  // 10^4\r\n            DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47),  // 10^5\r\n            DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44),  // 10^6\r\n            DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40)   // 10^7\r\n        };\r\n        int  adjustment = dExp - actualExp - 1;\r\n        RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);\r\n        v = v * kPow10[adjustment];\r\n        if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit\r\n            error += kUlp / 2;\r\n    }\r\n\r\n    v = v * cachedPower;\r\n\r\n    error += kUlp + (error == 0 ? 0 : 1);\r\n\r\n    const int oldExp = v.e;\r\n    v = v.Normalize();\r\n    error <<= oldExp - v.e;\r\n\r\n    const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);\r\n    int precisionSize = 64 - effectiveSignificandSize;\r\n    if (precisionSize + kUlpShift >= 64) {\r\n        int scaleExp = (precisionSize + kUlpShift) - 63;\r\n        v.f >>= scaleExp;\r\n        v.e += scaleExp; \r\n        error = (error >> scaleExp) + 1 + kUlp;\r\n        precisionSize -= scaleExp;\r\n    }\r\n\r\n    DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);\r\n    const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;\r\n    const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;\r\n    if (precisionBits >= halfWay + static_cast<unsigned>(error)) {\r\n        rounded.f++;\r\n        if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)\r\n            rounded.f >>= 1;\r\n            rounded.e++;\r\n        }\r\n    }\r\n\r\n    *result = rounded.ToDouble();\r\n\r\n    return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);\r\n}\r\n\r\ninline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {\r\n    const BigInteger dInt(decimals, length);\r\n    const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;\r\n    Double a(approx);\r\n    int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);\r\n    if (cmp < 0)\r\n        return a.Value();  // within half ULP\r\n    else if (cmp == 0) {\r\n        // Round towards even\r\n        if (a.Significand() & 1)\r\n            return a.NextPositiveDouble();\r\n        else\r\n            return a.Value();\r\n    }\r\n    else // adjustment\r\n        return a.NextPositiveDouble();\r\n}\r\n\r\ninline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {\r\n    RAPIDJSON_ASSERT(d >= 0.0);\r\n    RAPIDJSON_ASSERT(length >= 1);\r\n\r\n    double result;\r\n    if (StrtodFast(d, p, &result))\r\n        return result;\r\n\r\n    // Trim leading zeros\r\n    while (*decimals == '0' && length > 1) {\r\n        length--;\r\n        decimals++;\r\n        decimalPosition--;\r\n    }\r\n\r\n    // Trim trailing zeros\r\n    while (decimals[length - 1] == '0' && length > 1) {\r\n        length--;\r\n        decimalPosition--;\r\n        exp++;\r\n    }\r\n\r\n    // Trim right-most digits\r\n    const int kMaxDecimalDigit = 780;\r\n    if (static_cast<int>(length) > kMaxDecimalDigit) {\r\n        int delta = (static_cast<int>(length) - kMaxDecimalDigit);\r\n        exp += delta;\r\n        decimalPosition -= static_cast<unsigned>(delta);\r\n        length = kMaxDecimalDigit;\r\n    }\r\n\r\n    // If too small, underflow to zero\r\n    if (int(length) + exp < -324)\r\n        return 0.0;\r\n\r\n    if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))\r\n        return result;\r\n\r\n    // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison\r\n    return StrtodBigInteger(result, decimals, length, decimalPosition, exp);\r\n}\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_STRTOD_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/internal/swap.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n//\r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed\r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_INTERNAL_SWAP_H_\r\n#define RAPIDJSON_INTERNAL_SWAP_H_\r\n\r\n#include \"../rapidjson.h\"\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(c++98-compat)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nnamespace internal {\r\n\r\n//! Custom swap() to avoid dependency on C++ <algorithm> header\r\n/*! \\tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.\r\n    \\note This has the same semantics as std::swap().\r\n*/\r\ntemplate <typename T>\r\ninline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {\r\n    T tmp = a;\r\n        a = b;\r\n        b = tmp;\r\n}\r\n\r\n} // namespace internal\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_INTERNAL_SWAP_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/istreamwrapper.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_ISTREAMWRAPPER_H_\r\n#define RAPIDJSON_ISTREAMWRAPPER_H_\r\n\r\n#include \"stream.h\"\r\n#include <iosfwd>\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Wrapper of \\c std::basic_istream into RapidJSON's Stream concept.\r\n/*!\r\n    The classes can be wrapped including but not limited to:\r\n\r\n    - \\c std::istringstream\r\n    - \\c std::stringstream\r\n    - \\c std::wistringstream\r\n    - \\c std::wstringstream\r\n    - \\c std::ifstream\r\n    - \\c std::fstream\r\n    - \\c std::wifstream\r\n    - \\c std::wfstream\r\n\r\n    \\tparam StreamType Class derived from \\c std::basic_istream.\r\n*/\r\n   \r\ntemplate <typename StreamType>\r\nclass BasicIStreamWrapper {\r\npublic:\r\n    typedef typename StreamType::char_type Ch;\r\n    BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}\r\n\r\n    Ch Peek() const { \r\n        typename StreamType::int_type c = stream_.peek();\r\n        return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : static_cast<Ch>('\\0');\r\n    }\r\n\r\n    Ch Take() { \r\n        typename StreamType::int_type c = stream_.get();\r\n        if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {\r\n            count_++;\r\n            return static_cast<Ch>(c);\r\n        }\r\n        else\r\n            return '\\0';\r\n    }\r\n\r\n    // tellg() may return -1 when failed. So we count by ourself.\r\n    size_t Tell() const { return count_; }\r\n\r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    void Put(Ch) { RAPIDJSON_ASSERT(false); }\r\n    void Flush() { RAPIDJSON_ASSERT(false); }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\n    // For encoding detection only.\r\n    const Ch* Peek4() const {\r\n        RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.\r\n        int i;\r\n        bool hasError = false;\r\n        for (i = 0; i < 4; ++i) {\r\n            typename StreamType::int_type c = stream_.get();\r\n            if (c == StreamType::traits_type::eof()) {\r\n                hasError = true;\r\n                stream_.clear();\r\n                break;\r\n            }\r\n            peekBuffer_[i] = static_cast<Ch>(c);\r\n        }\r\n        for (--i; i >= 0; --i)\r\n            stream_.putback(peekBuffer_[i]);\r\n        return !hasError ? peekBuffer_ : 0;\r\n    }\r\n\r\nprivate:\r\n    BasicIStreamWrapper(const BasicIStreamWrapper&);\r\n    BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);\r\n\r\n    StreamType& stream_;\r\n    size_t count_;  //!< Number of characters read. Note:\r\n    mutable Ch peekBuffer_[4];\r\n};\r\n\r\ntypedef BasicIStreamWrapper<std::istream> IStreamWrapper;\r\ntypedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;\r\n\r\n#if defined(__clang__) || defined(_MSC_VER)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_ISTREAMWRAPPER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/memorybuffer.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_MEMORYBUFFER_H_\r\n#define RAPIDJSON_MEMORYBUFFER_H_\r\n\r\n#include \"stream.h\"\r\n#include \"internal/stack.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Represents an in-memory output byte stream.\r\n/*!\r\n    This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.\r\n\r\n    It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.\r\n\r\n    Differences between MemoryBuffer and StringBuffer:\r\n    1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. \r\n    2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.\r\n\r\n    \\tparam Allocator type for allocating memory buffer.\r\n    \\note implements Stream concept\r\n*/\r\ntemplate <typename Allocator = CrtAllocator>\r\nstruct GenericMemoryBuffer {\r\n    typedef char Ch; // byte\r\n\r\n    GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}\r\n\r\n    void Put(Ch c) { *stack_.template Push<Ch>() = c; }\r\n    void Flush() {}\r\n\r\n    void Clear() { stack_.Clear(); }\r\n    void ShrinkToFit() { stack_.ShrinkToFit(); }\r\n    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }\r\n    void Pop(size_t count) { stack_.template Pop<Ch>(count); }\r\n\r\n    const Ch* GetBuffer() const {\r\n        return stack_.template Bottom<Ch>();\r\n    }\r\n\r\n    size_t GetSize() const { return stack_.GetSize(); }\r\n\r\n    static const size_t kDefaultCapacity = 256;\r\n    mutable internal::Stack<Allocator> stack_;\r\n};\r\n\r\ntypedef GenericMemoryBuffer<> MemoryBuffer;\r\n\r\n//! Implement specialized version of PutN() with memset() for better performance.\r\ntemplate<>\r\ninline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {\r\n    std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));\r\n}\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_MEMORYBUFFER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/memorystream.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_MEMORYSTREAM_H_\r\n#define RAPIDJSON_MEMORYSTREAM_H_\r\n\r\n#include \"stream.h\"\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(unreachable-code)\r\nRAPIDJSON_DIAG_OFF(missing-noreturn)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Represents an in-memory input byte stream.\r\n/*!\r\n    This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.\r\n\r\n    It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.\r\n\r\n    Differences between MemoryStream and StringStream:\r\n    1. StringStream has encoding but MemoryStream is a byte stream.\r\n    2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.\r\n    3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().\r\n    \\note implements Stream concept\r\n*/\r\nstruct MemoryStream {\r\n    typedef char Ch; // byte\r\n\r\n    MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}\r\n\r\n    Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\\0' : *src_; }\r\n    Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\\0' : *src_++; }\r\n    size_t Tell() const { return static_cast<size_t>(src_ - begin_); }\r\n\r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    void Put(Ch) { RAPIDJSON_ASSERT(false); }\r\n    void Flush() { RAPIDJSON_ASSERT(false); }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\n    // For encoding detection only.\r\n    const Ch* Peek4() const {\r\n        return Tell() + 4 <= size_ ? src_ : 0;\r\n    }\r\n\r\n    const Ch* src_;     //!< Current read position.\r\n    const Ch* begin_;   //!< Original head of the string.\r\n    const Ch* end_;     //!< End of stream.\r\n    size_t size_;       //!< Size of the stream.\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_MEMORYBUFFER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/msinttypes/inttypes.h",
    "content": "// ISO C9x  compliant inttypes.h for Microsoft Visual Studio\r\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 \r\n// \r\n//  Copyright (c) 2006-2013 Alexander Chemeris\r\n// \r\n// Redistribution and use in source and binary forms, with or without\r\n// modification, are permitted provided that the following conditions are met:\r\n// \r\n//   1. Redistributions of source code must retain the above copyright notice,\r\n//      this list of conditions and the following disclaimer.\r\n// \r\n//   2. Redistributions in binary form must reproduce the above copyright\r\n//      notice, this list of conditions and the following disclaimer in the\r\n//      documentation and/or other materials provided with the distribution.\r\n// \r\n//   3. Neither the name of the product nor the names of its contributors may\r\n//      be used to endorse or promote products derived from this software\r\n//      without specific prior written permission.\r\n// \r\n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r\n// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\r\n// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r\n// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \r\n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r\n// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n// \r\n///////////////////////////////////////////////////////////////////////////////\r\n\r\n// The above software in this distribution may have been modified by \r\n// THL A29 Limited (\"Tencent Modifications\"). \r\n// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.\r\n\r\n#ifndef _MSC_VER // [\r\n#error \"Use this header only with Microsoft Visual C++ compilers!\"\r\n#endif // _MSC_VER ]\r\n\r\n#ifndef _MSC_INTTYPES_H_ // [\r\n#define _MSC_INTTYPES_H_\r\n\r\n#if _MSC_VER > 1000\r\n#pragma once\r\n#endif\r\n\r\n#include \"stdint.h\"\r\n\r\n// miloyip: VC supports inttypes.h since VC2013\r\n#if _MSC_VER >= 1800\r\n#include <inttypes.h>\r\n#else\r\n\r\n// 7.8 Format conversion of integer types\r\n\r\ntypedef struct {\r\n   intmax_t quot;\r\n   intmax_t rem;\r\n} imaxdiv_t;\r\n\r\n// 7.8.1 Macros for format specifiers\r\n\r\n#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198\r\n\r\n// The fprintf macros for signed integers are:\r\n#define PRId8       \"d\"\r\n#define PRIi8       \"i\"\r\n#define PRIdLEAST8  \"d\"\r\n#define PRIiLEAST8  \"i\"\r\n#define PRIdFAST8   \"d\"\r\n#define PRIiFAST8   \"i\"\r\n\r\n#define PRId16       \"hd\"\r\n#define PRIi16       \"hi\"\r\n#define PRIdLEAST16  \"hd\"\r\n#define PRIiLEAST16  \"hi\"\r\n#define PRIdFAST16   \"hd\"\r\n#define PRIiFAST16   \"hi\"\r\n\r\n#define PRId32       \"I32d\"\r\n#define PRIi32       \"I32i\"\r\n#define PRIdLEAST32  \"I32d\"\r\n#define PRIiLEAST32  \"I32i\"\r\n#define PRIdFAST32   \"I32d\"\r\n#define PRIiFAST32   \"I32i\"\r\n\r\n#define PRId64       \"I64d\"\r\n#define PRIi64       \"I64i\"\r\n#define PRIdLEAST64  \"I64d\"\r\n#define PRIiLEAST64  \"I64i\"\r\n#define PRIdFAST64   \"I64d\"\r\n#define PRIiFAST64   \"I64i\"\r\n\r\n#define PRIdMAX     \"I64d\"\r\n#define PRIiMAX     \"I64i\"\r\n\r\n#define PRIdPTR     \"Id\"\r\n#define PRIiPTR     \"Ii\"\r\n\r\n// The fprintf macros for unsigned integers are:\r\n#define PRIo8       \"o\"\r\n#define PRIu8       \"u\"\r\n#define PRIx8       \"x\"\r\n#define PRIX8       \"X\"\r\n#define PRIoLEAST8  \"o\"\r\n#define PRIuLEAST8  \"u\"\r\n#define PRIxLEAST8  \"x\"\r\n#define PRIXLEAST8  \"X\"\r\n#define PRIoFAST8   \"o\"\r\n#define PRIuFAST8   \"u\"\r\n#define PRIxFAST8   \"x\"\r\n#define PRIXFAST8   \"X\"\r\n\r\n#define PRIo16       \"ho\"\r\n#define PRIu16       \"hu\"\r\n#define PRIx16       \"hx\"\r\n#define PRIX16       \"hX\"\r\n#define PRIoLEAST16  \"ho\"\r\n#define PRIuLEAST16  \"hu\"\r\n#define PRIxLEAST16  \"hx\"\r\n#define PRIXLEAST16  \"hX\"\r\n#define PRIoFAST16   \"ho\"\r\n#define PRIuFAST16   \"hu\"\r\n#define PRIxFAST16   \"hx\"\r\n#define PRIXFAST16   \"hX\"\r\n\r\n#define PRIo32       \"I32o\"\r\n#define PRIu32       \"I32u\"\r\n#define PRIx32       \"I32x\"\r\n#define PRIX32       \"I32X\"\r\n#define PRIoLEAST32  \"I32o\"\r\n#define PRIuLEAST32  \"I32u\"\r\n#define PRIxLEAST32  \"I32x\"\r\n#define PRIXLEAST32  \"I32X\"\r\n#define PRIoFAST32   \"I32o\"\r\n#define PRIuFAST32   \"I32u\"\r\n#define PRIxFAST32   \"I32x\"\r\n#define PRIXFAST32   \"I32X\"\r\n\r\n#define PRIo64       \"I64o\"\r\n#define PRIu64       \"I64u\"\r\n#define PRIx64       \"I64x\"\r\n#define PRIX64       \"I64X\"\r\n#define PRIoLEAST64  \"I64o\"\r\n#define PRIuLEAST64  \"I64u\"\r\n#define PRIxLEAST64  \"I64x\"\r\n#define PRIXLEAST64  \"I64X\"\r\n#define PRIoFAST64   \"I64o\"\r\n#define PRIuFAST64   \"I64u\"\r\n#define PRIxFAST64   \"I64x\"\r\n#define PRIXFAST64   \"I64X\"\r\n\r\n#define PRIoMAX     \"I64o\"\r\n#define PRIuMAX     \"I64u\"\r\n#define PRIxMAX     \"I64x\"\r\n#define PRIXMAX     \"I64X\"\r\n\r\n#define PRIoPTR     \"Io\"\r\n#define PRIuPTR     \"Iu\"\r\n#define PRIxPTR     \"Ix\"\r\n#define PRIXPTR     \"IX\"\r\n\r\n// The fscanf macros for signed integers are:\r\n#define SCNd8       \"d\"\r\n#define SCNi8       \"i\"\r\n#define SCNdLEAST8  \"d\"\r\n#define SCNiLEAST8  \"i\"\r\n#define SCNdFAST8   \"d\"\r\n#define SCNiFAST8   \"i\"\r\n\r\n#define SCNd16       \"hd\"\r\n#define SCNi16       \"hi\"\r\n#define SCNdLEAST16  \"hd\"\r\n#define SCNiLEAST16  \"hi\"\r\n#define SCNdFAST16   \"hd\"\r\n#define SCNiFAST16   \"hi\"\r\n\r\n#define SCNd32       \"ld\"\r\n#define SCNi32       \"li\"\r\n#define SCNdLEAST32  \"ld\"\r\n#define SCNiLEAST32  \"li\"\r\n#define SCNdFAST32   \"ld\"\r\n#define SCNiFAST32   \"li\"\r\n\r\n#define SCNd64       \"I64d\"\r\n#define SCNi64       \"I64i\"\r\n#define SCNdLEAST64  \"I64d\"\r\n#define SCNiLEAST64  \"I64i\"\r\n#define SCNdFAST64   \"I64d\"\r\n#define SCNiFAST64   \"I64i\"\r\n\r\n#define SCNdMAX     \"I64d\"\r\n#define SCNiMAX     \"I64i\"\r\n\r\n#ifdef _WIN64 // [\r\n#  define SCNdPTR     \"I64d\"\r\n#  define SCNiPTR     \"I64i\"\r\n#else  // _WIN64 ][\r\n#  define SCNdPTR     \"ld\"\r\n#  define SCNiPTR     \"li\"\r\n#endif  // _WIN64 ]\r\n\r\n// The fscanf macros for unsigned integers are:\r\n#define SCNo8       \"o\"\r\n#define SCNu8       \"u\"\r\n#define SCNx8       \"x\"\r\n#define SCNX8       \"X\"\r\n#define SCNoLEAST8  \"o\"\r\n#define SCNuLEAST8  \"u\"\r\n#define SCNxLEAST8  \"x\"\r\n#define SCNXLEAST8  \"X\"\r\n#define SCNoFAST8   \"o\"\r\n#define SCNuFAST8   \"u\"\r\n#define SCNxFAST8   \"x\"\r\n#define SCNXFAST8   \"X\"\r\n\r\n#define SCNo16       \"ho\"\r\n#define SCNu16       \"hu\"\r\n#define SCNx16       \"hx\"\r\n#define SCNX16       \"hX\"\r\n#define SCNoLEAST16  \"ho\"\r\n#define SCNuLEAST16  \"hu\"\r\n#define SCNxLEAST16  \"hx\"\r\n#define SCNXLEAST16  \"hX\"\r\n#define SCNoFAST16   \"ho\"\r\n#define SCNuFAST16   \"hu\"\r\n#define SCNxFAST16   \"hx\"\r\n#define SCNXFAST16   \"hX\"\r\n\r\n#define SCNo32       \"lo\"\r\n#define SCNu32       \"lu\"\r\n#define SCNx32       \"lx\"\r\n#define SCNX32       \"lX\"\r\n#define SCNoLEAST32  \"lo\"\r\n#define SCNuLEAST32  \"lu\"\r\n#define SCNxLEAST32  \"lx\"\r\n#define SCNXLEAST32  \"lX\"\r\n#define SCNoFAST32   \"lo\"\r\n#define SCNuFAST32   \"lu\"\r\n#define SCNxFAST32   \"lx\"\r\n#define SCNXFAST32   \"lX\"\r\n\r\n#define SCNo64       \"I64o\"\r\n#define SCNu64       \"I64u\"\r\n#define SCNx64       \"I64x\"\r\n#define SCNX64       \"I64X\"\r\n#define SCNoLEAST64  \"I64o\"\r\n#define SCNuLEAST64  \"I64u\"\r\n#define SCNxLEAST64  \"I64x\"\r\n#define SCNXLEAST64  \"I64X\"\r\n#define SCNoFAST64   \"I64o\"\r\n#define SCNuFAST64   \"I64u\"\r\n#define SCNxFAST64   \"I64x\"\r\n#define SCNXFAST64   \"I64X\"\r\n\r\n#define SCNoMAX     \"I64o\"\r\n#define SCNuMAX     \"I64u\"\r\n#define SCNxMAX     \"I64x\"\r\n#define SCNXMAX     \"I64X\"\r\n\r\n#ifdef _WIN64 // [\r\n#  define SCNoPTR     \"I64o\"\r\n#  define SCNuPTR     \"I64u\"\r\n#  define SCNxPTR     \"I64x\"\r\n#  define SCNXPTR     \"I64X\"\r\n#else  // _WIN64 ][\r\n#  define SCNoPTR     \"lo\"\r\n#  define SCNuPTR     \"lu\"\r\n#  define SCNxPTR     \"lx\"\r\n#  define SCNXPTR     \"lX\"\r\n#endif  // _WIN64 ]\r\n\r\n#endif // __STDC_FORMAT_MACROS ]\r\n\r\n// 7.8.2 Functions for greatest-width integer types\r\n\r\n// 7.8.2.1 The imaxabs function\r\n#define imaxabs _abs64\r\n\r\n// 7.8.2.2 The imaxdiv function\r\n\r\n// This is modified version of div() function from Microsoft's div.c found\r\n// in %MSVC.NET%\\crt\\src\\div.c\r\n#ifdef STATIC_IMAXDIV // [\r\nstatic\r\n#else // STATIC_IMAXDIV ][\r\n_inline\r\n#endif // STATIC_IMAXDIV ]\r\nimaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)\r\n{\r\n   imaxdiv_t result;\r\n\r\n   result.quot = numer / denom;\r\n   result.rem = numer % denom;\r\n\r\n   if (numer < 0 && result.rem > 0) {\r\n      // did division wrong; must fix up\r\n      ++result.quot;\r\n      result.rem -= denom;\r\n   }\r\n\r\n   return result;\r\n}\r\n\r\n// 7.8.2.3 The strtoimax and strtoumax functions\r\n#define strtoimax _strtoi64\r\n#define strtoumax _strtoui64\r\n\r\n// 7.8.2.4 The wcstoimax and wcstoumax functions\r\n#define wcstoimax _wcstoi64\r\n#define wcstoumax _wcstoui64\r\n\r\n#endif // _MSC_VER >= 1800\r\n\r\n#endif // _MSC_INTTYPES_H_ ]\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/msinttypes/stdint.h",
    "content": "// ISO C9x  compliant stdint.h for Microsoft Visual Studio\r\n// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 \r\n// \r\n//  Copyright (c) 2006-2013 Alexander Chemeris\r\n// \r\n// Redistribution and use in source and binary forms, with or without\r\n// modification, are permitted provided that the following conditions are met:\r\n// \r\n//   1. Redistributions of source code must retain the above copyright notice,\r\n//      this list of conditions and the following disclaimer.\r\n// \r\n//   2. Redistributions in binary form must reproduce the above copyright\r\n//      notice, this list of conditions and the following disclaimer in the\r\n//      documentation and/or other materials provided with the distribution.\r\n// \r\n//   3. Neither the name of the product nor the names of its contributors may\r\n//      be used to endorse or promote products derived from this software\r\n//      without specific prior written permission.\r\n// \r\n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r\n// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\r\n// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r\n// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \r\n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r\n// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r\n// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n// \r\n///////////////////////////////////////////////////////////////////////////////\r\n\r\n// The above software in this distribution may have been modified by \r\n// THL A29 Limited (\"Tencent Modifications\"). \r\n// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.\r\n\r\n#ifndef _MSC_VER // [\r\n#error \"Use this header only with Microsoft Visual C++ compilers!\"\r\n#endif // _MSC_VER ]\r\n\r\n#ifndef _MSC_STDINT_H_ // [\r\n#define _MSC_STDINT_H_\r\n\r\n#if _MSC_VER > 1000\r\n#pragma once\r\n#endif\r\n\r\n// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.\r\n#if _MSC_VER >= 1600 // [\r\n#include <stdint.h>\r\n\r\n#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260\r\n\r\n#undef INT8_C\r\n#undef INT16_C\r\n#undef INT32_C\r\n#undef INT64_C\r\n#undef UINT8_C\r\n#undef UINT16_C\r\n#undef UINT32_C\r\n#undef UINT64_C\r\n\r\n// 7.18.4.1 Macros for minimum-width integer constants\r\n\r\n#define INT8_C(val)  val##i8\r\n#define INT16_C(val) val##i16\r\n#define INT32_C(val) val##i32\r\n#define INT64_C(val) val##i64\r\n\r\n#define UINT8_C(val)  val##ui8\r\n#define UINT16_C(val) val##ui16\r\n#define UINT32_C(val) val##ui32\r\n#define UINT64_C(val) val##ui64\r\n\r\n// 7.18.4.2 Macros for greatest-width integer constants\r\n// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.\r\n// Check out Issue 9 for the details.\r\n#ifndef INTMAX_C //   [\r\n#  define INTMAX_C   INT64_C\r\n#endif // INTMAX_C    ]\r\n#ifndef UINTMAX_C //  [\r\n#  define UINTMAX_C  UINT64_C\r\n#endif // UINTMAX_C   ]\r\n\r\n#endif // __STDC_CONSTANT_MACROS ]\r\n\r\n#else // ] _MSC_VER >= 1700 [\r\n\r\n#include <limits.h>\r\n\r\n// For Visual Studio 6 in C++ mode and for many Visual Studio versions when\r\n// compiling for ARM we have to wrap <wchar.h> include with 'extern \"C++\" {}'\r\n// or compiler would give many errors like this:\r\n//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed\r\n#if defined(__cplusplus) && !defined(_M_ARM)\r\nextern \"C\" {\r\n#endif\r\n#  include <wchar.h>\r\n#if defined(__cplusplus) && !defined(_M_ARM)\r\n}\r\n#endif\r\n\r\n// Define _W64 macros to mark types changing their size, like intptr_t.\r\n#ifndef _W64\r\n#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300\r\n#     define _W64 __w64\r\n#  else\r\n#     define _W64\r\n#  endif\r\n#endif\r\n\r\n\r\n// 7.18.1 Integer types\r\n\r\n// 7.18.1.1 Exact-width integer types\r\n\r\n// Visual Studio 6 and Embedded Visual C++ 4 doesn't\r\n// realize that, e.g. char has the same size as __int8\r\n// so we give up on __intX for them.\r\n#if (_MSC_VER < 1300)\r\n   typedef signed char       int8_t;\r\n   typedef signed short      int16_t;\r\n   typedef signed int        int32_t;\r\n   typedef unsigned char     uint8_t;\r\n   typedef unsigned short    uint16_t;\r\n   typedef unsigned int      uint32_t;\r\n#else\r\n   typedef signed __int8     int8_t;\r\n   typedef signed __int16    int16_t;\r\n   typedef signed __int32    int32_t;\r\n   typedef unsigned __int8   uint8_t;\r\n   typedef unsigned __int16  uint16_t;\r\n   typedef unsigned __int32  uint32_t;\r\n#endif\r\ntypedef signed __int64       int64_t;\r\ntypedef unsigned __int64     uint64_t;\r\n\r\n\r\n// 7.18.1.2 Minimum-width integer types\r\ntypedef int8_t    int_least8_t;\r\ntypedef int16_t   int_least16_t;\r\ntypedef int32_t   int_least32_t;\r\ntypedef int64_t   int_least64_t;\r\ntypedef uint8_t   uint_least8_t;\r\ntypedef uint16_t  uint_least16_t;\r\ntypedef uint32_t  uint_least32_t;\r\ntypedef uint64_t  uint_least64_t;\r\n\r\n// 7.18.1.3 Fastest minimum-width integer types\r\ntypedef int8_t    int_fast8_t;\r\ntypedef int16_t   int_fast16_t;\r\ntypedef int32_t   int_fast32_t;\r\ntypedef int64_t   int_fast64_t;\r\ntypedef uint8_t   uint_fast8_t;\r\ntypedef uint16_t  uint_fast16_t;\r\ntypedef uint32_t  uint_fast32_t;\r\ntypedef uint64_t  uint_fast64_t;\r\n\r\n// 7.18.1.4 Integer types capable of holding object pointers\r\n#ifdef _WIN64 // [\r\n   typedef signed __int64    intptr_t;\r\n   typedef unsigned __int64  uintptr_t;\r\n#else // _WIN64 ][\r\n   typedef _W64 signed int   intptr_t;\r\n   typedef _W64 unsigned int uintptr_t;\r\n#endif // _WIN64 ]\r\n\r\n// 7.18.1.5 Greatest-width integer types\r\ntypedef int64_t   intmax_t;\r\ntypedef uint64_t  uintmax_t;\r\n\r\n\r\n// 7.18.2 Limits of specified-width integer types\r\n\r\n#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259\r\n\r\n// 7.18.2.1 Limits of exact-width integer types\r\n#define INT8_MIN     ((int8_t)_I8_MIN)\r\n#define INT8_MAX     _I8_MAX\r\n#define INT16_MIN    ((int16_t)_I16_MIN)\r\n#define INT16_MAX    _I16_MAX\r\n#define INT32_MIN    ((int32_t)_I32_MIN)\r\n#define INT32_MAX    _I32_MAX\r\n#define INT64_MIN    ((int64_t)_I64_MIN)\r\n#define INT64_MAX    _I64_MAX\r\n#define UINT8_MAX    _UI8_MAX\r\n#define UINT16_MAX   _UI16_MAX\r\n#define UINT32_MAX   _UI32_MAX\r\n#define UINT64_MAX   _UI64_MAX\r\n\r\n// 7.18.2.2 Limits of minimum-width integer types\r\n#define INT_LEAST8_MIN    INT8_MIN\r\n#define INT_LEAST8_MAX    INT8_MAX\r\n#define INT_LEAST16_MIN   INT16_MIN\r\n#define INT_LEAST16_MAX   INT16_MAX\r\n#define INT_LEAST32_MIN   INT32_MIN\r\n#define INT_LEAST32_MAX   INT32_MAX\r\n#define INT_LEAST64_MIN   INT64_MIN\r\n#define INT_LEAST64_MAX   INT64_MAX\r\n#define UINT_LEAST8_MAX   UINT8_MAX\r\n#define UINT_LEAST16_MAX  UINT16_MAX\r\n#define UINT_LEAST32_MAX  UINT32_MAX\r\n#define UINT_LEAST64_MAX  UINT64_MAX\r\n\r\n// 7.18.2.3 Limits of fastest minimum-width integer types\r\n#define INT_FAST8_MIN    INT8_MIN\r\n#define INT_FAST8_MAX    INT8_MAX\r\n#define INT_FAST16_MIN   INT16_MIN\r\n#define INT_FAST16_MAX   INT16_MAX\r\n#define INT_FAST32_MIN   INT32_MIN\r\n#define INT_FAST32_MAX   INT32_MAX\r\n#define INT_FAST64_MIN   INT64_MIN\r\n#define INT_FAST64_MAX   INT64_MAX\r\n#define UINT_FAST8_MAX   UINT8_MAX\r\n#define UINT_FAST16_MAX  UINT16_MAX\r\n#define UINT_FAST32_MAX  UINT32_MAX\r\n#define UINT_FAST64_MAX  UINT64_MAX\r\n\r\n// 7.18.2.4 Limits of integer types capable of holding object pointers\r\n#ifdef _WIN64 // [\r\n#  define INTPTR_MIN   INT64_MIN\r\n#  define INTPTR_MAX   INT64_MAX\r\n#  define UINTPTR_MAX  UINT64_MAX\r\n#else // _WIN64 ][\r\n#  define INTPTR_MIN   INT32_MIN\r\n#  define INTPTR_MAX   INT32_MAX\r\n#  define UINTPTR_MAX  UINT32_MAX\r\n#endif // _WIN64 ]\r\n\r\n// 7.18.2.5 Limits of greatest-width integer types\r\n#define INTMAX_MIN   INT64_MIN\r\n#define INTMAX_MAX   INT64_MAX\r\n#define UINTMAX_MAX  UINT64_MAX\r\n\r\n// 7.18.3 Limits of other integer types\r\n\r\n#ifdef _WIN64 // [\r\n#  define PTRDIFF_MIN  _I64_MIN\r\n#  define PTRDIFF_MAX  _I64_MAX\r\n#else  // _WIN64 ][\r\n#  define PTRDIFF_MIN  _I32_MIN\r\n#  define PTRDIFF_MAX  _I32_MAX\r\n#endif  // _WIN64 ]\r\n\r\n#define SIG_ATOMIC_MIN  INT_MIN\r\n#define SIG_ATOMIC_MAX  INT_MAX\r\n\r\n#ifndef SIZE_MAX // [\r\n#  ifdef _WIN64 // [\r\n#     define SIZE_MAX  _UI64_MAX\r\n#  else // _WIN64 ][\r\n#     define SIZE_MAX  _UI32_MAX\r\n#  endif // _WIN64 ]\r\n#endif // SIZE_MAX ]\r\n\r\n// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>\r\n#ifndef WCHAR_MIN // [\r\n#  define WCHAR_MIN  0\r\n#endif  // WCHAR_MIN ]\r\n#ifndef WCHAR_MAX // [\r\n#  define WCHAR_MAX  _UI16_MAX\r\n#endif  // WCHAR_MAX ]\r\n\r\n#define WINT_MIN  0\r\n#define WINT_MAX  _UI16_MAX\r\n\r\n#endif // __STDC_LIMIT_MACROS ]\r\n\r\n\r\n// 7.18.4 Limits of other integer types\r\n\r\n#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260\r\n\r\n// 7.18.4.1 Macros for minimum-width integer constants\r\n\r\n#define INT8_C(val)  val##i8\r\n#define INT16_C(val) val##i16\r\n#define INT32_C(val) val##i32\r\n#define INT64_C(val) val##i64\r\n\r\n#define UINT8_C(val)  val##ui8\r\n#define UINT16_C(val) val##ui16\r\n#define UINT32_C(val) val##ui32\r\n#define UINT64_C(val) val##ui64\r\n\r\n// 7.18.4.2 Macros for greatest-width integer constants\r\n// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.\r\n// Check out Issue 9 for the details.\r\n#ifndef INTMAX_C //   [\r\n#  define INTMAX_C   INT64_C\r\n#endif // INTMAX_C    ]\r\n#ifndef UINTMAX_C //  [\r\n#  define UINTMAX_C  UINT64_C\r\n#endif // UINTMAX_C   ]\r\n\r\n#endif // __STDC_CONSTANT_MACROS ]\r\n\r\n#endif // _MSC_VER >= 1600 ]\r\n\r\n#endif // _MSC_STDINT_H_ ]\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/ostreamwrapper.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_OSTREAMWRAPPER_H_\r\n#define RAPIDJSON_OSTREAMWRAPPER_H_\r\n\r\n#include \"stream.h\"\r\n#include <iosfwd>\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Wrapper of \\c std::basic_ostream into RapidJSON's Stream concept.\r\n/*!\r\n    The classes can be wrapped including but not limited to:\r\n\r\n    - \\c std::ostringstream\r\n    - \\c std::stringstream\r\n    - \\c std::wpstringstream\r\n    - \\c std::wstringstream\r\n    - \\c std::ifstream\r\n    - \\c std::fstream\r\n    - \\c std::wofstream\r\n    - \\c std::wfstream\r\n\r\n    \\tparam StreamType Class derived from \\c std::basic_ostream.\r\n*/\r\n   \r\ntemplate <typename StreamType>\r\nclass BasicOStreamWrapper {\r\npublic:\r\n    typedef typename StreamType::char_type Ch;\r\n    BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}\r\n\r\n    void Put(Ch c) {\r\n        stream_.put(c);\r\n    }\r\n\r\n    void Flush() {\r\n        stream_.flush();\r\n    }\r\n\r\n    // Not implemented\r\n    char Peek() const { RAPIDJSON_ASSERT(false); return 0; }\r\n    char Take() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }\r\n    char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\nprivate:\r\n    BasicOStreamWrapper(const BasicOStreamWrapper&);\r\n    BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);\r\n\r\n    StreamType& stream_;\r\n};\r\n\r\ntypedef BasicOStreamWrapper<std::ostream> OStreamWrapper;\r\ntypedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_OSTREAMWRAPPER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/pointer.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_POINTER_H_\r\n#define RAPIDJSON_POINTER_H_\r\n\r\n#include \"document.h\"\r\n#include \"internal/itoa.h\"\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(switch-enum)\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\nstatic const SizeType kPointerInvalidIndex = ~SizeType(0);  //!< Represents an invalid index in GenericPointer::Token\r\n\r\n//! Error code of parsing.\r\n/*! \\ingroup RAPIDJSON_ERRORS\r\n    \\see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode\r\n*/\r\nenum PointerParseErrorCode {\r\n    kPointerParseErrorNone = 0,                     //!< The parse is successful\r\n\r\n    kPointerParseErrorTokenMustBeginWithSolidus,    //!< A token must begin with a '/'\r\n    kPointerParseErrorInvalidEscape,                //!< Invalid escape\r\n    kPointerParseErrorInvalidPercentEncoding,       //!< Invalid percent encoding in URI fragment\r\n    kPointerParseErrorCharacterMustPercentEncode    //!< A character must percent encoded in URI fragment\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericPointer\r\n\r\n//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.\r\n/*!\r\n    This class implements RFC 6901 \"JavaScript Object Notation (JSON) Pointer\" \r\n    (https://tools.ietf.org/html/rfc6901).\r\n\r\n    A JSON pointer is for identifying a specific value in a JSON document\r\n    (GenericDocument). It can simplify coding of DOM tree manipulation, because it\r\n    can access multiple-level depth of DOM tree with single API call.\r\n\r\n    After it parses a string representation (e.g. \"/foo/0\" or URI fragment \r\n    representation (e.g. \"#/foo/0\") into its internal representation (tokens),\r\n    it can be used to resolve a specific value in multiple documents, or sub-tree \r\n    of documents.\r\n\r\n    Contrary to GenericValue, Pointer can be copy constructed and copy assigned.\r\n    Apart from assignment, a Pointer cannot be modified after construction.\r\n\r\n    Although Pointer is very convenient, please aware that constructing Pointer\r\n    involves parsing and dynamic memory allocation. A special constructor with user-\r\n    supplied tokens eliminates these.\r\n\r\n    GenericPointer depends on GenericDocument and GenericValue.\r\n    \r\n    \\tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >\r\n    \\tparam Allocator The allocator type for allocating memory for internal representation.\r\n    \r\n    \\note GenericPointer uses same encoding of ValueType.\r\n    However, Allocator of GenericPointer is independent of Allocator of Value.\r\n*/\r\ntemplate <typename ValueType, typename Allocator = CrtAllocator>\r\nclass GenericPointer {\r\npublic:\r\n    typedef typename ValueType::EncodingType EncodingType;  //!< Encoding type from Value\r\n    typedef typename ValueType::Ch Ch;                      //!< Character type from Value\r\n\r\n    //! A token is the basic units of internal representation.\r\n    /*!\r\n        A JSON pointer string representation \"/foo/123\" is parsed to two tokens: \r\n        \"foo\" and 123. 123 will be represented in both numeric form and string form.\r\n        They are resolved according to the actual value type (object or array).\r\n\r\n        For token that are not numbers, or the numeric value is out of bound\r\n        (greater than limits of SizeType), they are only treated as string form\r\n        (i.e. the token's index will be equal to kPointerInvalidIndex).\r\n\r\n        This struct is public so that user can create a Pointer without parsing and \r\n        allocation, using a special constructor.\r\n    */\r\n    struct Token {\r\n        const Ch* name;             //!< Name of the token. It has null character at the end but it can contain null character.\r\n        SizeType length;            //!< Length of the name.\r\n        SizeType index;             //!< A valid array index, if it is not equal to kPointerInvalidIndex.\r\n    };\r\n\r\n    //!@name Constructors and destructor.\r\n    //@{\r\n\r\n    //! Default constructor.\r\n    GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}\r\n\r\n    //! Constructor that parses a string or URI fragment representation.\r\n    /*!\r\n        \\param source A null-terminated, string or URI fragment representation of JSON pointer.\r\n        \\param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.\r\n    */\r\n    explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {\r\n        Parse(source, internal::StrLen(source));\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Constructor that parses a string or URI fragment representation.\r\n    /*!\r\n        \\param source A string or URI fragment representation of JSON pointer.\r\n        \\param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.\r\n        \\note Requires the definition of the preprocessor symbol \\ref RAPIDJSON_HAS_STDSTRING.\r\n    */\r\n    explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {\r\n        Parse(source.c_str(), source.size());\r\n    }\r\n#endif\r\n\r\n    //! Constructor that parses a string or URI fragment representation, with length of the source string.\r\n    /*!\r\n        \\param source A string or URI fragment representation of JSON pointer.\r\n        \\param length Length of source.\r\n        \\param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.\r\n        \\note Slightly faster than the overload without length.\r\n    */\r\n    GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {\r\n        Parse(source, length);\r\n    }\r\n\r\n    //! Constructor with user-supplied tokens.\r\n    /*!\r\n        This constructor let user supplies const array of tokens.\r\n        This prevents the parsing process and eliminates allocation.\r\n        This is preferred for memory constrained environments.\r\n\r\n        \\param tokens An constant array of tokens representing the JSON pointer.\r\n        \\param tokenCount Number of tokens.\r\n\r\n        \\b Example\r\n        \\code\r\n        #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }\r\n        #define INDEX(i) { #i, sizeof(#i) - 1, i }\r\n\r\n        static const Pointer::Token kTokens[] = { NAME(\"foo\"), INDEX(123) };\r\n        static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));\r\n        // Equivalent to static const Pointer p(\"/foo/123\");\r\n\r\n        #undef NAME\r\n        #undef INDEX\r\n        \\endcode\r\n    */\r\n    GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}\r\n\r\n    //! Copy constructor.\r\n    GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {\r\n        *this = rhs;\r\n    }\r\n\r\n    //! Copy constructor.\r\n    GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {\r\n        *this = rhs;\r\n    }\r\n\r\n    //! Destructor.\r\n    ~GenericPointer() {\r\n        if (nameBuffer_)    // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.\r\n            Allocator::Free(tokens_);\r\n        RAPIDJSON_DELETE(ownAllocator_);\r\n    }\r\n\r\n    //! Assignment operator.\r\n    GenericPointer& operator=(const GenericPointer& rhs) {\r\n        if (this != &rhs) {\r\n            // Do not delete ownAllcator\r\n            if (nameBuffer_)\r\n                Allocator::Free(tokens_);\r\n\r\n            tokenCount_ = rhs.tokenCount_;\r\n            parseErrorOffset_ = rhs.parseErrorOffset_;\r\n            parseErrorCode_ = rhs.parseErrorCode_;\r\n\r\n            if (rhs.nameBuffer_)\r\n                CopyFromRaw(rhs); // Normally parsed tokens.\r\n            else {\r\n                tokens_ = rhs.tokens_; // User supplied const tokens.\r\n                nameBuffer_ = 0;\r\n            }\r\n        }\r\n        return *this;\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Append token\r\n    //@{\r\n\r\n    //! Append a token and return a new Pointer\r\n    /*!\r\n        \\param token Token to be appended.\r\n        \\param allocator Allocator for the newly return Pointer.\r\n        \\return A new Pointer with appended token.\r\n    */\r\n    GenericPointer Append(const Token& token, Allocator* allocator = 0) const {\r\n        GenericPointer r;\r\n        r.allocator_ = allocator;\r\n        Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);\r\n        std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));\r\n        r.tokens_[tokenCount_].name = p;\r\n        r.tokens_[tokenCount_].length = token.length;\r\n        r.tokens_[tokenCount_].index = token.index;\r\n        return r;\r\n    }\r\n\r\n    //! Append a name token with length, and return a new Pointer\r\n    /*!\r\n        \\param name Name to be appended.\r\n        \\param length Length of name.\r\n        \\param allocator Allocator for the newly return Pointer.\r\n        \\return A new Pointer with appended token.\r\n    */\r\n    GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {\r\n        Token token = { name, length, kPointerInvalidIndex };\r\n        return Append(token, allocator);\r\n    }\r\n\r\n    //! Append a name token without length, and return a new Pointer\r\n    /*!\r\n        \\param name Name (const Ch*) to be appended.\r\n        \\param allocator Allocator for the newly return Pointer.\r\n        \\return A new Pointer with appended token.\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))\r\n    Append(T* name, Allocator* allocator = 0) const {\r\n        return Append(name, internal::StrLen(name), allocator);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Append a name token, and return a new Pointer\r\n    /*!\r\n        \\param name Name to be appended.\r\n        \\param allocator Allocator for the newly return Pointer.\r\n        \\return A new Pointer with appended token.\r\n    */\r\n    GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {\r\n        return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);\r\n    }\r\n#endif\r\n\r\n    //! Append a index token, and return a new Pointer\r\n    /*!\r\n        \\param index Index to be appended.\r\n        \\param allocator Allocator for the newly return Pointer.\r\n        \\return A new Pointer with appended token.\r\n    */\r\n    GenericPointer Append(SizeType index, Allocator* allocator = 0) const {\r\n        char buffer[21];\r\n        char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);\r\n        SizeType length = static_cast<SizeType>(end - buffer);\r\n        buffer[length] = '\\0';\r\n\r\n        if (sizeof(Ch) == 1) {\r\n            Token token = { reinterpret_cast<Ch*>(buffer), length, index };\r\n            return Append(token, allocator);\r\n        }\r\n        else {\r\n            Ch name[21];\r\n            for (size_t i = 0; i <= length; i++)\r\n                name[i] = static_cast<Ch>(buffer[i]);\r\n            Token token = { name, length, index };\r\n            return Append(token, allocator);\r\n        }\r\n    }\r\n\r\n    //! Append a token by value, and return a new Pointer\r\n    /*!\r\n        \\param token token to be appended.\r\n        \\param allocator Allocator for the newly return Pointer.\r\n        \\return A new Pointer with appended token.\r\n    */\r\n    GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {\r\n        if (token.IsString())\r\n            return Append(token.GetString(), token.GetStringLength(), allocator);\r\n        else {\r\n            RAPIDJSON_ASSERT(token.IsUint64());\r\n            RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));\r\n            return Append(static_cast<SizeType>(token.GetUint64()), allocator);\r\n        }\r\n    }\r\n\r\n    //!@name Handling Parse Error\r\n    //@{\r\n\r\n    //! Check whether this is a valid pointer.\r\n    bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }\r\n\r\n    //! Get the parsing error offset in code unit.\r\n    size_t GetParseErrorOffset() const { return parseErrorOffset_; }\r\n\r\n    //! Get the parsing error code.\r\n    PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }\r\n\r\n    //@}\r\n\r\n    //! Get the allocator of this pointer.\r\n    Allocator& GetAllocator() { return *allocator_; }\r\n\r\n    //!@name Tokens\r\n    //@{\r\n\r\n    //! Get the token array (const version only).\r\n    const Token* GetTokens() const { return tokens_; }\r\n\r\n    //! Get the number of tokens.\r\n    size_t GetTokenCount() const { return tokenCount_; }\r\n\r\n    //@}\r\n\r\n    //!@name Equality/inequality operators\r\n    //@{\r\n\r\n    //! Equality operator.\r\n    /*!\r\n        \\note When any pointers are invalid, always returns false.\r\n    */\r\n    bool operator==(const GenericPointer& rhs) const {\r\n        if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)\r\n            return false;\r\n\r\n        for (size_t i = 0; i < tokenCount_; i++) {\r\n            if (tokens_[i].index != rhs.tokens_[i].index ||\r\n                tokens_[i].length != rhs.tokens_[i].length || \r\n                (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))\r\n            {\r\n                return false;\r\n            }\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    //! Inequality operator.\r\n    /*!\r\n        \\note When any pointers are invalid, always returns true.\r\n    */\r\n    bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }\r\n\r\n    //@}\r\n\r\n    //!@name Stringify\r\n    //@{\r\n\r\n    //! Stringify the pointer into string representation.\r\n    /*!\r\n        \\tparam OutputStream Type of output stream.\r\n        \\param os The output stream.\r\n    */\r\n    template<typename OutputStream>\r\n    bool Stringify(OutputStream& os) const {\r\n        return Stringify<false, OutputStream>(os);\r\n    }\r\n\r\n    //! Stringify the pointer into URI fragment representation.\r\n    /*!\r\n        \\tparam OutputStream Type of output stream.\r\n        \\param os The output stream.\r\n    */\r\n    template<typename OutputStream>\r\n    bool StringifyUriFragment(OutputStream& os) const {\r\n        return Stringify<true, OutputStream>(os);\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Create value\r\n    //@{\r\n\r\n    //! Create a value in a subtree.\r\n    /*!\r\n        If the value is not exist, it creates all parent values and a JSON Null value.\r\n        So it always succeed and return the newly created or existing value.\r\n\r\n        Remind that it may change types of parents according to tokens, so it \r\n        potentially removes previously stored values. For example, if a document \r\n        was an array, and \"/foo\" is used to create a value, then the document \r\n        will be changed to an object, and all existing array elements are lost.\r\n\r\n        \\param root Root value of a DOM subtree to be resolved. It can be any value other than document root.\r\n        \\param allocator Allocator for creating the values if the specified value or its parents are not exist.\r\n        \\param alreadyExist If non-null, it stores whether the resolved value is already exist.\r\n        \\return The resolved newly created (a JSON Null value), or already exists value.\r\n    */\r\n    ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {\r\n        RAPIDJSON_ASSERT(IsValid());\r\n        ValueType* v = &root;\r\n        bool exist = true;\r\n        for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {\r\n            if (v->IsArray() && t->name[0] == '-' && t->length == 1) {\r\n                v->PushBack(ValueType().Move(), allocator);\r\n                v = &((*v)[v->Size() - 1]);\r\n                exist = false;\r\n            }\r\n            else {\r\n                if (t->index == kPointerInvalidIndex) { // must be object name\r\n                    if (!v->IsObject())\r\n                        v->SetObject(); // Change to Object\r\n                }\r\n                else { // object name or array index\r\n                    if (!v->IsArray() && !v->IsObject())\r\n                        v->SetArray(); // Change to Array\r\n                }\r\n\r\n                if (v->IsArray()) {\r\n                    if (t->index >= v->Size()) {\r\n                        v->Reserve(t->index + 1, allocator);\r\n                        while (t->index >= v->Size())\r\n                            v->PushBack(ValueType().Move(), allocator);\r\n                        exist = false;\r\n                    }\r\n                    v = &((*v)[t->index]);\r\n                }\r\n                else {\r\n                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));\r\n                    if (m == v->MemberEnd()) {\r\n                        v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);\r\n                        v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end\r\n                        exist = false;\r\n                    }\r\n                    else\r\n                        v = &m->value;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (alreadyExist)\r\n            *alreadyExist = exist;\r\n\r\n        return *v;\r\n    }\r\n\r\n    //! Creates a value in a document.\r\n    /*!\r\n        \\param document A document to be resolved.\r\n        \\param alreadyExist If non-null, it stores whether the resolved value is already exist.\r\n        \\return The resolved newly created, or already exists value.\r\n    */\r\n    template <typename stackAllocator>\r\n    ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {\r\n        return Create(document, document.GetAllocator(), alreadyExist);\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Query value\r\n    //@{\r\n\r\n    //! Query a value in a subtree.\r\n    /*!\r\n        \\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.\r\n        \\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.\r\n        \\return Pointer to the value if it can be resolved. Otherwise null.\r\n\r\n        \\note\r\n        There are only 3 situations when a value cannot be resolved:\r\n        1. A value in the path is not an array nor object.\r\n        2. An object value does not contain the token.\r\n        3. A token is out of range of an array value.\r\n\r\n        Use unresolvedTokenIndex to retrieve the token index.\r\n    */\r\n    ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {\r\n        RAPIDJSON_ASSERT(IsValid());\r\n        ValueType* v = &root;\r\n        for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {\r\n            switch (v->GetType()) {\r\n            case kObjectType:\r\n                {\r\n                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));\r\n                    if (m == v->MemberEnd())\r\n                        break;\r\n                    v = &m->value;\r\n                }\r\n                continue;\r\n            case kArrayType:\r\n                if (t->index == kPointerInvalidIndex || t->index >= v->Size())\r\n                    break;\r\n                v = &((*v)[t->index]);\r\n                continue;\r\n            default:\r\n                break;\r\n            }\r\n\r\n            // Error: unresolved token\r\n            if (unresolvedTokenIndex)\r\n                *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);\r\n            return 0;\r\n        }\r\n        return v;\r\n    }\r\n\r\n    //! Query a const value in a const subtree.\r\n    /*!\r\n        \\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.\r\n        \\return Pointer to the value if it can be resolved. Otherwise null.\r\n    */\r\n    const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { \r\n        return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Query a value with default\r\n    //@{\r\n\r\n    //! Query a value in a subtree with default value.\r\n    /*!\r\n        Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.\r\n        So that this function always succeed.\r\n\r\n        \\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.\r\n        \\param defaultValue Default value to be cloned if the value was not exists.\r\n        \\param allocator Allocator for creating the values if the specified value or its parents are not exist.\r\n        \\see Create()\r\n    */\r\n    ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {\r\n        bool alreadyExist;\r\n        ValueType& v = Create(root, allocator, &alreadyExist);\r\n        return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);\r\n    }\r\n\r\n    //! Query a value in a subtree with default null-terminated string.\r\n    ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {\r\n        bool alreadyExist;\r\n        ValueType& v = Create(root, allocator, &alreadyExist);\r\n        return alreadyExist ? v : v.SetString(defaultValue, allocator);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Query a value in a subtree with default std::basic_string.\r\n    ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {\r\n        bool alreadyExist;\r\n        ValueType& v = Create(root, allocator, &alreadyExist);\r\n        return alreadyExist ? v : v.SetString(defaultValue, allocator);\r\n    }\r\n#endif\r\n\r\n    //! Query a value in a subtree with default primitive value.\r\n    /*!\r\n        \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t, \\c bool\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))\r\n    GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {\r\n        return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);\r\n    }\r\n\r\n    //! Query a value in a document with default value.\r\n    template <typename stackAllocator>\r\n    ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {\r\n        return GetWithDefault(document, defaultValue, document.GetAllocator());\r\n    }\r\n\r\n    //! Query a value in a document with default null-terminated string.\r\n    template <typename stackAllocator>\r\n    ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {\r\n        return GetWithDefault(document, defaultValue, document.GetAllocator());\r\n    }\r\n    \r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Query a value in a document with default std::basic_string.\r\n    template <typename stackAllocator>\r\n    ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {\r\n        return GetWithDefault(document, defaultValue, document.GetAllocator());\r\n    }\r\n#endif\r\n\r\n    //! Query a value in a document with default primitive value.\r\n    /*!\r\n        \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t, \\c bool\r\n    */\r\n    template <typename T, typename stackAllocator>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))\r\n    GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {\r\n        return GetWithDefault(document, defaultValue, document.GetAllocator());\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Set a value\r\n    //@{\r\n\r\n    //! Set a value in a subtree, with move semantics.\r\n    /*!\r\n        It creates all parents if they are not exist or types are different to the tokens.\r\n        So this function always succeeds but potentially remove existing values.\r\n\r\n        \\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.\r\n        \\param value Value to be set.\r\n        \\param allocator Allocator for creating the values if the specified value or its parents are not exist.\r\n        \\see Create()\r\n    */\r\n    ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {\r\n        return Create(root, allocator) = value;\r\n    }\r\n\r\n    //! Set a value in a subtree, with copy semantics.\r\n    ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {\r\n        return Create(root, allocator).CopyFrom(value, allocator);\r\n    }\r\n\r\n    //! Set a null-terminated string in a subtree.\r\n    ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {\r\n        return Create(root, allocator) = ValueType(value, allocator).Move();\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Set a std::basic_string in a subtree.\r\n    ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {\r\n        return Create(root, allocator) = ValueType(value, allocator).Move();\r\n    }\r\n#endif\r\n\r\n    //! Set a primitive value in a subtree.\r\n    /*!\r\n        \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t, \\c bool\r\n    */\r\n    template <typename T>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))\r\n    Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {\r\n        return Create(root, allocator) = ValueType(value).Move();\r\n    }\r\n\r\n    //! Set a value in a document, with move semantics.\r\n    template <typename stackAllocator>\r\n    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {\r\n        return Create(document) = value;\r\n    }\r\n\r\n    //! Set a value in a document, with copy semantics.\r\n    template <typename stackAllocator>\r\n    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {\r\n        return Create(document).CopyFrom(value, document.GetAllocator());\r\n    }\r\n\r\n    //! Set a null-terminated string in a document.\r\n    template <typename stackAllocator>\r\n    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {\r\n        return Create(document) = ValueType(value, document.GetAllocator()).Move();\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    //! Sets a std::basic_string in a document.\r\n    template <typename stackAllocator>\r\n    ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {\r\n        return Create(document) = ValueType(value, document.GetAllocator()).Move();\r\n    }\r\n#endif\r\n\r\n    //! Set a primitive value in a document.\r\n    /*!\r\n    \\tparam T Either \\ref Type, \\c int, \\c unsigned, \\c int64_t, \\c uint64_t, \\c bool\r\n    */\r\n    template <typename T, typename stackAllocator>\r\n    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))\r\n        Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {\r\n            return Create(document) = value;\r\n    }\r\n\r\n    //@}\r\n\r\n    //!@name Swap a value\r\n    //@{\r\n\r\n    //! Swap a value with a value in a subtree.\r\n    /*!\r\n        It creates all parents if they are not exist or types are different to the tokens.\r\n        So this function always succeeds but potentially remove existing values.\r\n\r\n        \\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.\r\n        \\param value Value to be swapped.\r\n        \\param allocator Allocator for creating the values if the specified value or its parents are not exist.\r\n        \\see Create()\r\n    */\r\n    ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {\r\n        return Create(root, allocator).Swap(value);\r\n    }\r\n\r\n    //! Swap a value with a value in a document.\r\n    template <typename stackAllocator>\r\n    ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {\r\n        return Create(document).Swap(value);\r\n    }\r\n\r\n    //@}\r\n\r\n    //! Erase a value in a subtree.\r\n    /*!\r\n        \\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.\r\n        \\return Whether the resolved value is found and erased.\r\n\r\n        \\note Erasing with an empty pointer \\c Pointer(\"\"), i.e. the root, always fail and return false.\r\n    */\r\n    bool Erase(ValueType& root) const {\r\n        RAPIDJSON_ASSERT(IsValid());\r\n        if (tokenCount_ == 0) // Cannot erase the root\r\n            return false;\r\n\r\n        ValueType* v = &root;\r\n        const Token* last = tokens_ + (tokenCount_ - 1);\r\n        for (const Token *t = tokens_; t != last; ++t) {\r\n            switch (v->GetType()) {\r\n            case kObjectType:\r\n                {\r\n                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));\r\n                    if (m == v->MemberEnd())\r\n                        return false;\r\n                    v = &m->value;\r\n                }\r\n                break;\r\n            case kArrayType:\r\n                if (t->index == kPointerInvalidIndex || t->index >= v->Size())\r\n                    return false;\r\n                v = &((*v)[t->index]);\r\n                break;\r\n            default:\r\n                return false;\r\n            }\r\n        }\r\n\r\n        switch (v->GetType()) {\r\n        case kObjectType:\r\n            return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));\r\n        case kArrayType:\r\n            if (last->index == kPointerInvalidIndex || last->index >= v->Size())\r\n                return false;\r\n            v->Erase(v->Begin() + last->index);\r\n            return true;\r\n        default:\r\n            return false;\r\n        }\r\n    }\r\n\r\nprivate:\r\n    //! Clone the content from rhs to this.\r\n    /*!\r\n        \\param rhs Source pointer.\r\n        \\param extraToken Extra tokens to be allocated.\r\n        \\param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.\r\n        \\return Start of non-occupied name buffer, for storing extra names.\r\n    */\r\n    Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {\r\n        if (!allocator_) // allocator is independently owned.\r\n            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n\r\n        size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens\r\n        for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)\r\n            nameBufferSize += t->length;\r\n\r\n        tokenCount_ = rhs.tokenCount_ + extraToken;\r\n        tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));\r\n        nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);\r\n        if (rhs.tokenCount_ > 0) {\r\n            std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));\r\n        }\r\n        if (nameBufferSize > 0) {\r\n            std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));\r\n        }\r\n\r\n        // Adjust pointers to name buffer\r\n        std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;\r\n        for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)\r\n            t->name += diff;\r\n\r\n        return nameBuffer_ + nameBufferSize;\r\n    }\r\n\r\n    //! Check whether a character should be percent-encoded.\r\n    /*!\r\n        According to RFC 3986 2.3 Unreserved Characters.\r\n        \\param c The character (code unit) to be tested.\r\n    */\r\n    bool NeedPercentEncode(Ch c) const {\r\n        return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');\r\n    }\r\n\r\n    //! Parse a JSON String or its URI fragment representation into tokens.\r\n#ifndef __clang__ // -Wdocumentation\r\n    /*!\r\n        \\param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.\r\n        \\param length Length of the source string.\r\n        \\note Source cannot be JSON String Representation of JSON Pointer, e.g. In \"/\\u0000\", \\u0000 will not be unescaped.\r\n    */\r\n#endif\r\n    void Parse(const Ch* source, size_t length) {\r\n        RAPIDJSON_ASSERT(source != NULL);\r\n        RAPIDJSON_ASSERT(nameBuffer_ == 0);\r\n        RAPIDJSON_ASSERT(tokens_ == 0);\r\n\r\n        // Create own allocator if user did not supply.\r\n        if (!allocator_)\r\n            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n\r\n        // Count number of '/' as tokenCount\r\n        tokenCount_ = 0;\r\n        for (const Ch* s = source; s != source + length; s++) \r\n            if (*s == '/')\r\n                tokenCount_++;\r\n\r\n        Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));\r\n        Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);\r\n        size_t i = 0;\r\n\r\n        // Detect if it is a URI fragment\r\n        bool uriFragment = false;\r\n        if (source[i] == '#') {\r\n            uriFragment = true;\r\n            i++;\r\n        }\r\n\r\n        if (i != length && source[i] != '/') {\r\n            parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;\r\n            goto error;\r\n        }\r\n\r\n        while (i < length) {\r\n            RAPIDJSON_ASSERT(source[i] == '/');\r\n            i++; // consumes '/'\r\n\r\n            token->name = name;\r\n            bool isNumber = true;\r\n\r\n            while (i < length && source[i] != '/') {\r\n                Ch c = source[i];\r\n                if (uriFragment) {\r\n                    // Decoding percent-encoding for URI fragment\r\n                    if (c == '%') {\r\n                        PercentDecodeStream is(&source[i], source + length);\r\n                        GenericInsituStringStream<EncodingType> os(name);\r\n                        Ch* begin = os.PutBegin();\r\n                        if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {\r\n                            parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;\r\n                            goto error;\r\n                        }\r\n                        size_t len = os.PutEnd(begin);\r\n                        i += is.Tell() - 1;\r\n                        if (len == 1)\r\n                            c = *name;\r\n                        else {\r\n                            name += len;\r\n                            isNumber = false;\r\n                            i++;\r\n                            continue;\r\n                        }\r\n                    }\r\n                    else if (NeedPercentEncode(c)) {\r\n                        parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;\r\n                        goto error;\r\n                    }\r\n                }\r\n\r\n                i++;\r\n                \r\n                // Escaping \"~0\" -> '~', \"~1\" -> '/'\r\n                if (c == '~') {\r\n                    if (i < length) {\r\n                        c = source[i];\r\n                        if (c == '0')       c = '~';\r\n                        else if (c == '1')  c = '/';\r\n                        else {\r\n                            parseErrorCode_ = kPointerParseErrorInvalidEscape;\r\n                            goto error;\r\n                        }\r\n                        i++;\r\n                    }\r\n                    else {\r\n                        parseErrorCode_ = kPointerParseErrorInvalidEscape;\r\n                        goto error;\r\n                    }\r\n                }\r\n\r\n                // First check for index: all of characters are digit\r\n                if (c < '0' || c > '9')\r\n                    isNumber = false;\r\n\r\n                *name++ = c;\r\n            }\r\n            token->length = static_cast<SizeType>(name - token->name);\r\n            if (token->length == 0)\r\n                isNumber = false;\r\n            *name++ = '\\0'; // Null terminator\r\n\r\n            // Second check for index: more than one digit cannot have leading zero\r\n            if (isNumber && token->length > 1 && token->name[0] == '0')\r\n                isNumber = false;\r\n\r\n            // String to SizeType conversion\r\n            SizeType n = 0;\r\n            if (isNumber) {\r\n                for (size_t j = 0; j < token->length; j++) {\r\n                    SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');\r\n                    if (m < n) {   // overflow detection\r\n                        isNumber = false;\r\n                        break;\r\n                    }\r\n                    n = m;\r\n                }\r\n            }\r\n\r\n            token->index = isNumber ? n : kPointerInvalidIndex;\r\n            token++;\r\n        }\r\n\r\n        RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer\r\n        parseErrorCode_ = kPointerParseErrorNone;\r\n        return;\r\n\r\n    error:\r\n        Allocator::Free(tokens_);\r\n        nameBuffer_ = 0;\r\n        tokens_ = 0;\r\n        tokenCount_ = 0;\r\n        parseErrorOffset_ = i;\r\n        return;\r\n    }\r\n\r\n    //! Stringify to string or URI fragment representation.\r\n    /*!\r\n        \\tparam uriFragment True for stringifying to URI fragment representation. False for string representation.\r\n        \\tparam OutputStream type of output stream.\r\n        \\param os The output stream.\r\n    */\r\n    template<bool uriFragment, typename OutputStream>\r\n    bool Stringify(OutputStream& os) const {\r\n        RAPIDJSON_ASSERT(IsValid());\r\n\r\n        if (uriFragment)\r\n            os.Put('#');\r\n\r\n        for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {\r\n            os.Put('/');\r\n            for (size_t j = 0; j < t->length; j++) {\r\n                Ch c = t->name[j];\r\n                if (c == '~') {\r\n                    os.Put('~');\r\n                    os.Put('0');\r\n                }\r\n                else if (c == '/') {\r\n                    os.Put('~');\r\n                    os.Put('1');\r\n                }\r\n                else if (uriFragment && NeedPercentEncode(c)) { \r\n                    // Transcode to UTF8 sequence\r\n                    GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);\r\n                    PercentEncodeStream<OutputStream> target(os);\r\n                    if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))\r\n                        return false;\r\n                    j += source.Tell() - 1;\r\n                }\r\n                else\r\n                    os.Put(c);\r\n            }\r\n        }\r\n        return true;\r\n    }\r\n\r\n    //! A helper stream for decoding a percent-encoded sequence into code unit.\r\n    /*!\r\n        This stream decodes %XY triplet into code unit (0-255).\r\n        If it encounters invalid characters, it sets output code unit as 0 and \r\n        mark invalid, and to be checked by IsValid().\r\n    */\r\n    class PercentDecodeStream {\r\n    public:\r\n        typedef typename ValueType::Ch Ch;\r\n\r\n        //! Constructor\r\n        /*!\r\n            \\param source Start of the stream\r\n            \\param end Past-the-end of the stream.\r\n        */\r\n        PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}\r\n\r\n        Ch Take() {\r\n            if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet\r\n                valid_ = false;\r\n                return 0;\r\n            }\r\n            src_++;\r\n            Ch c = 0;\r\n            for (int j = 0; j < 2; j++) {\r\n                c = static_cast<Ch>(c << 4);\r\n                Ch h = *src_;\r\n                if      (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');\r\n                else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);\r\n                else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);\r\n                else {\r\n                    valid_ = false;\r\n                    return 0;\r\n                }\r\n                src_++;\r\n            }\r\n            return c;\r\n        }\r\n\r\n        size_t Tell() const { return static_cast<size_t>(src_ - head_); }\r\n        bool IsValid() const { return valid_; }\r\n\r\n    private:\r\n        const Ch* src_;     //!< Current read position.\r\n        const Ch* head_;    //!< Original head of the string.\r\n        const Ch* end_;     //!< Past-the-end position.\r\n        bool valid_;        //!< Whether the parsing is valid.\r\n    };\r\n\r\n    //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.\r\n    template <typename OutputStream>\r\n    class PercentEncodeStream {\r\n    public:\r\n        PercentEncodeStream(OutputStream& os) : os_(os) {}\r\n        void Put(char c) { // UTF-8 must be byte\r\n            unsigned char u = static_cast<unsigned char>(c);\r\n            static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };\r\n            os_.Put('%');\r\n            os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));\r\n            os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));\r\n        }\r\n    private:\r\n        OutputStream& os_;\r\n    };\r\n\r\n    Allocator* allocator_;                  //!< The current allocator. It is either user-supplied or equal to ownAllocator_.\r\n    Allocator* ownAllocator_;               //!< Allocator owned by this Pointer.\r\n    Ch* nameBuffer_;                        //!< A buffer containing all names in tokens.\r\n    Token* tokens_;                         //!< A list of tokens.\r\n    size_t tokenCount_;                     //!< Number of tokens in tokens_.\r\n    size_t parseErrorOffset_;               //!< Offset in code unit when parsing fail.\r\n    PointerParseErrorCode parseErrorCode_;  //!< Parsing error code.\r\n};\r\n\r\n//! GenericPointer for Value (UTF-8, default allocator).\r\ntypedef GenericPointer<Value> Pointer;\r\n\r\n//!@name Helper functions for GenericPointer\r\n//@{\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {\r\n    return pointer.Create(root, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);\r\n}\r\n\r\n// No allocator parameter\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {\r\n    return pointer.Create(document);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {\r\n    return pointer.Get(root, unresolvedTokenIndex);\r\n}\r\n\r\ntemplate <typename T>\r\nconst typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {\r\n    return pointer.Get(root, unresolvedTokenIndex);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\nconst typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {\r\n    return pointer.GetWithDefault(root, defaultValue, a);\r\n}\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {\r\n    return pointer.GetWithDefault(root, defaultValue, a);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename T>\r\ntypename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {\r\n    return pointer.GetWithDefault(root, defaultValue, a);\r\n}\r\n#endif\r\n\r\ntemplate <typename T, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))\r\nGetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {\r\n    return pointer.GetWithDefault(root, defaultValue, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);\r\n}\r\n#endif\r\n\r\ntemplate <typename T, typename CharType, size_t N, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))\r\nGetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);\r\n}\r\n\r\n// No allocator parameter\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {\r\n    return pointer.GetWithDefault(document, defaultValue);\r\n}\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {\r\n    return pointer.GetWithDefault(document, defaultValue);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {\r\n    return pointer.GetWithDefault(document, defaultValue);\r\n}\r\n#endif\r\n\r\ntemplate <typename DocumentType, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))\r\nGetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {\r\n    return pointer.GetWithDefault(document, defaultValue);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);\r\n}\r\n#endif\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))\r\nGetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {\r\n    return pointer.Set(root, value, a);\r\n}\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {\r\n    return pointer.Set(root, value, a);\r\n}\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {\r\n    return pointer.Set(root, value, a);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename T>\r\ntypename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {\r\n    return pointer.Set(root, value, a);\r\n}\r\n#endif\r\n\r\ntemplate <typename T, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))\r\nSetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {\r\n    return pointer.Set(root, value, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);\r\n}\r\n#endif\r\n\r\ntemplate <typename T, typename CharType, size_t N, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))\r\nSetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);\r\n}\r\n\r\n// No allocator parameter\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {\r\n    return pointer.Set(document, value);\r\n}\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {\r\n    return pointer.Set(document, value);\r\n}\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {\r\n    return pointer.Set(document, value);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {\r\n    return pointer.Set(document, value);\r\n}\r\n#endif\r\n\r\ntemplate <typename DocumentType, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))\r\nSetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {\r\n    return pointer.Set(document, value);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);\r\n}\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);\r\n}\r\n#endif\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N, typename T2>\r\nRAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))\r\nSetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n\r\ntemplate <typename T>\r\ntypename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {\r\n    return pointer.Swap(root, value, a);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\ntypename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);\r\n}\r\n\r\ntemplate <typename DocumentType>\r\ntypename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {\r\n    return pointer.Swap(document, value);\r\n}\r\n\r\ntemplate <typename DocumentType, typename CharType, size_t N>\r\ntypename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {\r\n    return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);\r\n}\r\n\r\n//////////////////////////////////////////////////////////////////////////////\r\n\r\ntemplate <typename T>\r\nbool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {\r\n    return pointer.Erase(root);\r\n}\r\n\r\ntemplate <typename T, typename CharType, size_t N>\r\nbool EraseValueByPointer(T& root, const CharType(&source)[N]) {\r\n    return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);\r\n}\r\n\r\n//@}\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_POINTER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/prettywriter.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_PRETTYWRITER_H_\r\n#define RAPIDJSON_PRETTYWRITER_H_\r\n\r\n#include \"writer.h\"\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(c++98-compat)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Combination of PrettyWriter format flags.\r\n/*! \\see PrettyWriter::SetFormatOptions\r\n */\r\nenum PrettyFormatOptions {\r\n    kFormatDefault = 0,         //!< Default pretty formatting.\r\n    kFormatSingleLineArray = 1  //!< Format arrays on a single line.\r\n};\r\n\r\n//! Writer with indentation and spacing.\r\n/*!\r\n    \\tparam OutputStream Type of output os.\r\n    \\tparam SourceEncoding Encoding of source string.\r\n    \\tparam TargetEncoding Encoding of output stream.\r\n    \\tparam StackAllocator Type of allocator for allocating memory of stack.\r\n*/\r\ntemplate<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>\r\nclass PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {\r\npublic:\r\n    typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;\r\n    typedef typename Base::Ch Ch;\r\n\r\n    //! Constructor\r\n    /*! \\param os Output stream.\r\n        \\param allocator User supplied allocator. If it is null, it will create a private one.\r\n        \\param levelDepth Initial capacity of stack.\r\n    */\r\n    explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : \r\n        Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}\r\n\r\n\r\n    explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : \r\n        Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    PrettyWriter(PrettyWriter&& rhs) :\r\n        Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}\r\n#endif\r\n\r\n    //! Set custom indentation.\r\n    /*! \\param indentChar       Character for indentation. Must be whitespace character (' ', '\\\\t', '\\\\n', '\\\\r').\r\n        \\param indentCharCount  Number of indent characters for each indentation level.\r\n        \\note The default indentation is 4 spaces.\r\n    */\r\n    PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {\r\n        RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\\t' || indentChar == '\\n' || indentChar == '\\r');\r\n        indentChar_ = indentChar;\r\n        indentCharCount_ = indentCharCount;\r\n        return *this;\r\n    }\r\n\r\n    //! Set pretty writer formatting options.\r\n    /*! \\param options Formatting options.\r\n    */\r\n    PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {\r\n        formatOptions_ = options;\r\n        return *this;\r\n    }\r\n\r\n    /*! @name Implementation of Handler\r\n        \\see Handler\r\n    */\r\n    //@{\r\n\r\n    bool Null()                 { PrettyPrefix(kNullType);   return Base::WriteNull(); }\r\n    bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }\r\n    bool Int(int i)             { PrettyPrefix(kNumberType); return Base::WriteInt(i); }\r\n    bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::WriteUint(u); }\r\n    bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }\r\n    bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::WriteUint64(u64);  }\r\n    bool Double(double d)       { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }\r\n\r\n    bool RawNumber(const Ch* str, SizeType length, bool copy = false) {\r\n        RAPIDJSON_ASSERT(str != 0);\r\n        (void)copy;\r\n        PrettyPrefix(kNumberType);\r\n        return Base::WriteString(str, length);\r\n    }\r\n\r\n    bool String(const Ch* str, SizeType length, bool copy = false) {\r\n        RAPIDJSON_ASSERT(str != 0);\r\n        (void)copy;\r\n        PrettyPrefix(kStringType);\r\n        return Base::WriteString(str, length);\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool String(const std::basic_string<Ch>& str) {\r\n        return String(str.data(), SizeType(str.size()));\r\n    }\r\n#endif\r\n\r\n    bool StartObject() {\r\n        PrettyPrefix(kObjectType);\r\n        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);\r\n        return Base::WriteStartObject();\r\n    }\r\n\r\n    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool Key(const std::basic_string<Ch>& str) {\r\n        return Key(str.data(), SizeType(str.size()));\r\n    }\r\n#endif\r\n\t\r\n    bool EndObject(SizeType memberCount = 0) {\r\n        (void)memberCount;\r\n        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object\r\n        RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object\r\n        RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value\r\n       \r\n        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;\r\n\r\n        if (!empty) {\r\n            Base::os_->Put('\\n');\r\n            WriteIndent();\r\n        }\r\n        bool ret = Base::WriteEndObject();\r\n        (void)ret;\r\n        RAPIDJSON_ASSERT(ret == true);\r\n        if (Base::level_stack_.Empty()) // end of json text\r\n            Base::Flush();\r\n        return true;\r\n    }\r\n\r\n    bool StartArray() {\r\n        PrettyPrefix(kArrayType);\r\n        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);\r\n        return Base::WriteStartArray();\r\n    }\r\n\r\n    bool EndArray(SizeType memberCount = 0) {\r\n        (void)memberCount;\r\n        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));\r\n        RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);\r\n        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;\r\n\r\n        if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {\r\n            Base::os_->Put('\\n');\r\n            WriteIndent();\r\n        }\r\n        bool ret = Base::WriteEndArray();\r\n        (void)ret;\r\n        RAPIDJSON_ASSERT(ret == true);\r\n        if (Base::level_stack_.Empty()) // end of json text\r\n            Base::Flush();\r\n        return true;\r\n    }\r\n\r\n    //@}\r\n\r\n    /*! @name Convenience extensions */\r\n    //@{\r\n\r\n    //! Simpler but slower overload.\r\n    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }\r\n    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }\r\n\r\n    //@}\r\n\r\n    //! Write a raw JSON value.\r\n    /*!\r\n        For user to write a stringified JSON as a value.\r\n\r\n        \\param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.\r\n        \\param length Length of the json.\r\n        \\param type Type of the root of json.\r\n        \\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.\r\n    */\r\n    bool RawValue(const Ch* json, size_t length, Type type) {\r\n        RAPIDJSON_ASSERT(json != 0);\r\n        PrettyPrefix(type);\r\n        return Base::WriteRawValue(json, length);\r\n    }\r\n\r\nprotected:\r\n    void PrettyPrefix(Type type) {\r\n        (void)type;\r\n        if (Base::level_stack_.GetSize() != 0) { // this value is not at root\r\n            typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();\r\n\r\n            if (level->inArray) {\r\n                if (level->valueCount > 0) {\r\n                    Base::os_->Put(','); // add comma if it is not the first element in array\r\n                    if (formatOptions_ & kFormatSingleLineArray)\r\n                        Base::os_->Put(' ');\r\n                }\r\n\r\n                if (!(formatOptions_ & kFormatSingleLineArray)) {\r\n                    Base::os_->Put('\\n');\r\n                    WriteIndent();\r\n                }\r\n            }\r\n            else {  // in object\r\n                if (level->valueCount > 0) {\r\n                    if (level->valueCount % 2 == 0) {\r\n                        Base::os_->Put(',');\r\n                        Base::os_->Put('\\n');\r\n                    }\r\n                    else {\r\n                        Base::os_->Put(':');\r\n                        Base::os_->Put(' ');\r\n                    }\r\n                }\r\n                else\r\n                    Base::os_->Put('\\n');\r\n\r\n                if (level->valueCount % 2 == 0)\r\n                    WriteIndent();\r\n            }\r\n            if (!level->inArray && level->valueCount % 2 == 0)\r\n                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name\r\n            level->valueCount++;\r\n        }\r\n        else {\r\n            RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root.\r\n            Base::hasRoot_ = true;\r\n        }\r\n    }\r\n\r\n    void WriteIndent()  {\r\n        size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;\r\n        PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);\r\n    }\r\n\r\n    Ch indentChar_;\r\n    unsigned indentCharCount_;\r\n    PrettyFormatOptions formatOptions_;\r\n\r\nprivate:\r\n    // Prohibit copy constructor & assignment operator.\r\n    PrettyWriter(const PrettyWriter&);\r\n    PrettyWriter& operator=(const PrettyWriter&);\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_RAPIDJSON_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/rapidjson.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_RAPIDJSON_H_\r\n#define RAPIDJSON_RAPIDJSON_H_\r\n\r\n/*!\\file rapidjson.h\r\n    \\brief common definitions and configuration\r\n    \r\n    \\see RAPIDJSON_CONFIG\r\n */\r\n\r\n/*! \\defgroup RAPIDJSON_CONFIG RapidJSON configuration\r\n    \\brief Configuration macros for library features\r\n\r\n    Some RapidJSON features are configurable to adapt the library to a wide\r\n    variety of platforms, environments and usage scenarios.  Most of the\r\n    features can be configured in terms of overridden or predefined\r\n    preprocessor macros at compile-time.\r\n\r\n    Some additional customization is available in the \\ref RAPIDJSON_ERRORS APIs.\r\n\r\n    \\note These macros should be given on the compiler command-line\r\n          (where applicable)  to avoid inconsistent values when compiling\r\n          different translation units of a single application.\r\n */\r\n\r\n#include <cstdlib>  // malloc(), realloc(), free(), size_t\r\n#include <cstring>  // memset(), memcpy(), memmove(), memcmp()\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_VERSION_STRING\r\n//\r\n// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.\r\n//\r\n\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n// token stringification\r\n#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)\r\n#define RAPIDJSON_DO_STRINGIFY(x) #x\r\n\r\n// token concatenation\r\n#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)\r\n#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)\r\n#define RAPIDJSON_DO_JOIN2(X, Y) X##Y\r\n//!@endcond\r\n\r\n/*! \\def RAPIDJSON_MAJOR_VERSION\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Major version of RapidJSON in integer.\r\n*/\r\n/*! \\def RAPIDJSON_MINOR_VERSION\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Minor version of RapidJSON in integer.\r\n*/\r\n/*! \\def RAPIDJSON_PATCH_VERSION\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Patch version of RapidJSON in integer.\r\n*/\r\n/*! \\def RAPIDJSON_VERSION_STRING\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Version of RapidJSON in \"<major>.<minor>.<patch>\" string format.\r\n*/\r\n#define RAPIDJSON_MAJOR_VERSION 1\r\n#define RAPIDJSON_MINOR_VERSION 1\r\n#define RAPIDJSON_PATCH_VERSION 0\r\n#define RAPIDJSON_VERSION_STRING \\\r\n    RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_NAMESPACE_(BEGIN|END)\r\n/*! \\def RAPIDJSON_NAMESPACE\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief   provide custom rapidjson namespace\r\n\r\n    In order to avoid symbol clashes and/or \"One Definition Rule\" errors\r\n    between multiple inclusions of (different versions of) RapidJSON in\r\n    a single binary, users can customize the name of the main RapidJSON\r\n    namespace.\r\n\r\n    In case of a single nesting level, defining \\c RAPIDJSON_NAMESPACE\r\n    to a custom name (e.g. \\c MyRapidJSON) is sufficient.  If multiple\r\n    levels are needed, both \\ref RAPIDJSON_NAMESPACE_BEGIN and \\ref\r\n    RAPIDJSON_NAMESPACE_END need to be defined as well:\r\n\r\n    \\code\r\n    // in some .cpp file\r\n    #define RAPIDJSON_NAMESPACE my::rapidjson\r\n    #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {\r\n    #define RAPIDJSON_NAMESPACE_END   } }\r\n    #include \"rapidjson/...\"\r\n    \\endcode\r\n\r\n    \\see rapidjson\r\n */\r\n/*! \\def RAPIDJSON_NAMESPACE_BEGIN\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief   provide custom rapidjson namespace (opening expression)\r\n    \\see RAPIDJSON_NAMESPACE\r\n*/\r\n/*! \\def RAPIDJSON_NAMESPACE_END\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief   provide custom rapidjson namespace (closing expression)\r\n    \\see RAPIDJSON_NAMESPACE\r\n*/\r\n#ifndef RAPIDJSON_NAMESPACE\r\n#define RAPIDJSON_NAMESPACE rapidjson\r\n#endif\r\n#ifndef RAPIDJSON_NAMESPACE_BEGIN\r\n#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {\r\n#endif\r\n#ifndef RAPIDJSON_NAMESPACE_END\r\n#define RAPIDJSON_NAMESPACE_END }\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_HAS_STDSTRING\r\n\r\n#ifndef RAPIDJSON_HAS_STDSTRING\r\n#ifdef RAPIDJSON_DOXYGEN_RUNNING\r\n#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation\r\n#else\r\n#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default\r\n#endif\r\n/*! \\def RAPIDJSON_HAS_STDSTRING\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Enable RapidJSON support for \\c std::string\r\n\r\n    By defining this preprocessor symbol to \\c 1, several convenience functions for using\r\n    \\ref rapidjson::GenericValue with \\c std::string are enabled, especially\r\n    for construction and comparison.\r\n\r\n    \\hideinitializer\r\n*/\r\n#endif // !defined(RAPIDJSON_HAS_STDSTRING)\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n#include <string>\r\n#endif // RAPIDJSON_HAS_STDSTRING\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_NO_INT64DEFINE\r\n\r\n/*! \\def RAPIDJSON_NO_INT64DEFINE\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Use external 64-bit integer types.\r\n\r\n    RapidJSON requires the 64-bit integer types \\c int64_t and  \\c uint64_t types\r\n    to be available at global scope.\r\n\r\n    If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to\r\n    prevent RapidJSON from defining its own types.\r\n*/\r\n#ifndef RAPIDJSON_NO_INT64DEFINE\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n#if defined(_MSC_VER) && (_MSC_VER < 1800)\t// Visual Studio 2013\r\n#include \"msinttypes/stdint.h\"\r\n#include \"msinttypes/inttypes.h\"\r\n#else\r\n// Other compilers should have this.\r\n#include <stdint.h>\r\n#include <inttypes.h>\r\n#endif\r\n//!@endcond\r\n#ifdef RAPIDJSON_DOXYGEN_RUNNING\r\n#define RAPIDJSON_NO_INT64DEFINE\r\n#endif\r\n#endif // RAPIDJSON_NO_INT64TYPEDEF\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_FORCEINLINE\r\n\r\n#ifndef RAPIDJSON_FORCEINLINE\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n#if defined(_MSC_VER) && defined(NDEBUG)\r\n#define RAPIDJSON_FORCEINLINE __forceinline\r\n#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)\r\n#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))\r\n#else\r\n#define RAPIDJSON_FORCEINLINE\r\n#endif\r\n//!@endcond\r\n#endif // RAPIDJSON_FORCEINLINE\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_ENDIAN\r\n#define RAPIDJSON_LITTLEENDIAN  0   //!< Little endian machine\r\n#define RAPIDJSON_BIGENDIAN     1   //!< Big endian machine\r\n\r\n//! Endianness of the machine.\r\n/*!\r\n    \\def RAPIDJSON_ENDIAN\r\n    \\ingroup RAPIDJSON_CONFIG\r\n\r\n    GCC 4.6 provided macro for detecting endianness of the target machine. But other\r\n    compilers may not have this. User can define RAPIDJSON_ENDIAN to either\r\n    \\ref RAPIDJSON_LITTLEENDIAN or \\ref RAPIDJSON_BIGENDIAN.\r\n\r\n    Default detection implemented with reference to\r\n    \\li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html\r\n    \\li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp\r\n*/\r\n#ifndef RAPIDJSON_ENDIAN\r\n// Detect with GCC 4.6's macro\r\n#  ifdef __BYTE_ORDER__\r\n#    if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\r\n#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN\r\n#    elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\r\n#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN\r\n#    else\r\n#      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.\r\n#    endif // __BYTE_ORDER__\r\n// Detect with GLIBC's endian.h\r\n#  elif defined(__GLIBC__)\r\n#    include <endian.h>\r\n#    if (__BYTE_ORDER == __LITTLE_ENDIAN)\r\n#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN\r\n#    elif (__BYTE_ORDER == __BIG_ENDIAN)\r\n#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN\r\n#    else\r\n#      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.\r\n#   endif // __GLIBC__\r\n// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro\r\n#  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)\r\n#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN\r\n#  elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)\r\n#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN\r\n// Detect with architecture macros\r\n#  elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)\r\n#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN\r\n#  elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)\r\n#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN\r\n#  elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))\r\n#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN\r\n#  elif defined(RAPIDJSON_DOXYGEN_RUNNING)\r\n#    define RAPIDJSON_ENDIAN\r\n#  else\r\n#    error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.   \r\n#  endif\r\n#endif // RAPIDJSON_ENDIAN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_64BIT\r\n\r\n//! Whether using 64-bit architecture\r\n#ifndef RAPIDJSON_64BIT\r\n#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)\r\n#define RAPIDJSON_64BIT 1\r\n#else\r\n#define RAPIDJSON_64BIT 0\r\n#endif\r\n#endif // RAPIDJSON_64BIT\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_ALIGN\r\n\r\n//! Data alignment of the machine.\r\n/*! \\ingroup RAPIDJSON_CONFIG\r\n    \\param x pointer to align\r\n\r\n    Some machines require strict data alignment. Currently the default uses 4 bytes\r\n    alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.\r\n    User can customize by defining the RAPIDJSON_ALIGN function macro.\r\n*/\r\n#ifndef RAPIDJSON_ALIGN\r\n#if RAPIDJSON_64BIT == 1\r\n#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))\r\n#else\r\n#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)\r\n#endif\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_UINT64_C2\r\n\r\n//! Construct a 64-bit literal by a pair of 32-bit integer.\r\n/*!\r\n    64-bit literal with or without ULL suffix is prone to compiler warnings.\r\n    UINT64_C() is C macro which cause compilation problems.\r\n    Use this macro to define 64-bit constants by a pair of 32-bit integer.\r\n*/\r\n#ifndef RAPIDJSON_UINT64_C2\r\n#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_48BITPOINTER_OPTIMIZATION\r\n\r\n//! Use only lower 48-bit address for some pointers.\r\n/*!\r\n    \\ingroup RAPIDJSON_CONFIG\r\n\r\n    This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.\r\n    The higher 16-bit can be used for storing other data.\r\n    \\c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.\r\n*/\r\n#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION\r\n#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)\r\n#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1\r\n#else\r\n#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0\r\n#endif\r\n#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION\r\n\r\n#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1\r\n#if RAPIDJSON_64BIT != 1\r\n#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1\r\n#endif\r\n#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))\r\n#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))\r\n#else\r\n#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))\r\n#define RAPIDJSON_GETPOINTER(type, p) (p)\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD\r\n\r\n/*! \\def RAPIDJSON_SIMD\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief Enable SSE2/SSE4.2/Neon optimization.\r\n\r\n    RapidJSON supports optimized implementations for some parsing operations\r\n    based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel\r\n    or ARM compatible processors.\r\n\r\n    To enable these optimizations, three different symbols can be defined;\r\n    \\code\r\n    // Enable SSE2 optimization.\r\n    #define RAPIDJSON_SSE2\r\n\r\n    // Enable SSE4.2 optimization.\r\n    #define RAPIDJSON_SSE42\r\n    \\endcode\r\n\r\n    // Enable ARM Neon optimization.\r\n    #define RAPIDJSON_NEON\r\n    \\endcode\r\n\r\n    \\c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.\r\n\r\n    If any of these symbols is defined, RapidJSON defines the macro\r\n    \\c RAPIDJSON_SIMD to indicate the availability of the optimized code.\r\n*/\r\n#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \\\r\n    || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)\r\n#define RAPIDJSON_SIMD\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_NO_SIZETYPEDEFINE\r\n\r\n#ifndef RAPIDJSON_NO_SIZETYPEDEFINE\r\n/*! \\def RAPIDJSON_NO_SIZETYPEDEFINE\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief User-provided \\c SizeType definition.\r\n\r\n    In order to avoid using 32-bit size types for indexing strings and arrays,\r\n    define this preprocessor symbol and provide the type rapidjson::SizeType\r\n    before including RapidJSON:\r\n    \\code\r\n    #define RAPIDJSON_NO_SIZETYPEDEFINE\r\n    namespace rapidjson { typedef ::std::size_t SizeType; }\r\n    #include \"rapidjson/...\"\r\n    \\endcode\r\n\r\n    \\see rapidjson::SizeType\r\n*/\r\n#ifdef RAPIDJSON_DOXYGEN_RUNNING\r\n#define RAPIDJSON_NO_SIZETYPEDEFINE\r\n#endif\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n//! Size type (for string lengths, array sizes, etc.)\r\n/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,\r\n    instead of using \\c size_t. Users may override the SizeType by defining\r\n    \\ref RAPIDJSON_NO_SIZETYPEDEFINE.\r\n*/\r\ntypedef unsigned SizeType;\r\nRAPIDJSON_NAMESPACE_END\r\n#endif\r\n\r\n// always import std::size_t to rapidjson namespace\r\nRAPIDJSON_NAMESPACE_BEGIN\r\nusing std::size_t;\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_ASSERT\r\n\r\n//! Assertion.\r\n/*! \\ingroup RAPIDJSON_CONFIG\r\n    By default, rapidjson uses C \\c assert() for internal assertions.\r\n    User can override it by defining RAPIDJSON_ASSERT(x) macro.\r\n\r\n    \\note Parsing errors are handled and can be customized by the\r\n          \\ref RAPIDJSON_ERRORS APIs.\r\n*/\r\n#ifndef RAPIDJSON_ASSERT\r\n#include <cassert>\r\n#define RAPIDJSON_ASSERT(x) assert(x)\r\n#endif // RAPIDJSON_ASSERT\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_STATIC_ASSERT\r\n\r\n// Prefer C++11 static_assert, if available\r\n#ifndef RAPIDJSON_STATIC_ASSERT\r\n#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )\r\n#define RAPIDJSON_STATIC_ASSERT(x) \\\r\n   static_assert(x, RAPIDJSON_STRINGIFY(x))\r\n#endif // C++11\r\n#endif // RAPIDJSON_STATIC_ASSERT\r\n\r\n// Adopt C++03 implementation from boost\r\n#ifndef RAPIDJSON_STATIC_ASSERT\r\n#ifndef __clang__\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n#endif\r\nRAPIDJSON_NAMESPACE_BEGIN\r\ntemplate <bool x> struct STATIC_ASSERTION_FAILURE;\r\ntemplate <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };\r\ntemplate <size_t x> struct StaticAssertTest {};\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#if defined(__GNUC__)\r\n#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))\r\n#else\r\n#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE \r\n#endif\r\n#ifndef __clang__\r\n//!@endcond\r\n#endif\r\n\r\n/*! \\def RAPIDJSON_STATIC_ASSERT\r\n    \\brief (Internal) macro to check for conditions at compile-time\r\n    \\param x compile-time condition\r\n    \\hideinitializer\r\n */\r\n#define RAPIDJSON_STATIC_ASSERT(x) \\\r\n    typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \\\r\n      sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \\\r\n    RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE\r\n#endif // RAPIDJSON_STATIC_ASSERT\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY\r\n\r\n//! Compiler branching hint for expression with high probability to be true.\r\n/*!\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\param x Boolean expression likely to be true.\r\n*/\r\n#ifndef RAPIDJSON_LIKELY\r\n#if defined(__GNUC__) || defined(__clang__)\r\n#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)\r\n#else\r\n#define RAPIDJSON_LIKELY(x) (x)\r\n#endif\r\n#endif\r\n\r\n//! Compiler branching hint for expression with low probability to be true.\r\n/*!\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\param x Boolean expression unlikely to be true.\r\n*/\r\n#ifndef RAPIDJSON_UNLIKELY\r\n#if defined(__GNUC__) || defined(__clang__)\r\n#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)\r\n#else\r\n#define RAPIDJSON_UNLIKELY(x) (x)\r\n#endif\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Helpers\r\n\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n\r\n#define RAPIDJSON_MULTILINEMACRO_BEGIN do {  \r\n#define RAPIDJSON_MULTILINEMACRO_END \\\r\n} while((void)0, 0)\r\n\r\n// adopted from Boost\r\n#define RAPIDJSON_VERSION_CODE(x,y,z) \\\r\n  (((x)*100000) + ((y)*100) + (z))\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF\r\n\r\n#if defined(__GNUC__)\r\n#define RAPIDJSON_GNUC \\\r\n    RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)\r\n#endif\r\n\r\n#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))\r\n\r\n#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))\r\n#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)\r\n#define RAPIDJSON_DIAG_OFF(x) \\\r\n    RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))\r\n\r\n// push/pop support in Clang and GCC>=4.6\r\n#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))\r\n#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)\r\n#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)\r\n#else // GCC >= 4.2, < 4.6\r\n#define RAPIDJSON_DIAG_PUSH /* ignored */\r\n#define RAPIDJSON_DIAG_POP /* ignored */\r\n#endif\r\n\r\n#elif defined(_MSC_VER)\r\n\r\n// pragma (MSVC specific)\r\n#define RAPIDJSON_PRAGMA(x) __pragma(x)\r\n#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))\r\n\r\n#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)\r\n#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)\r\n#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)\r\n\r\n#else\r\n\r\n#define RAPIDJSON_DIAG_OFF(x) /* ignored */\r\n#define RAPIDJSON_DIAG_PUSH   /* ignored */\r\n#define RAPIDJSON_DIAG_POP    /* ignored */\r\n\r\n#endif // RAPIDJSON_DIAG_*\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// C++11 features\r\n\r\n#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n#if defined(__clang__)\r\n#if __has_feature(cxx_rvalue_references) && \\\r\n    (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)\r\n#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1\r\n#else\r\n#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0\r\n#endif\r\n#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \\\r\n      (defined(_MSC_VER) && _MSC_VER >= 1600)\r\n\r\n#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1\r\n#else\r\n#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0\r\n#endif\r\n#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n\r\n#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT\r\n#if defined(__clang__)\r\n#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)\r\n#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))\r\n//    (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported\r\n#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1\r\n#else\r\n#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0\r\n#endif\r\n#endif\r\n#if RAPIDJSON_HAS_CXX11_NOEXCEPT\r\n#define RAPIDJSON_NOEXCEPT noexcept\r\n#else\r\n#define RAPIDJSON_NOEXCEPT /* noexcept */\r\n#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT\r\n\r\n// no automatic detection, yet\r\n#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS\r\n#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0\r\n#endif\r\n\r\n#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR\r\n#if defined(__clang__)\r\n#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)\r\n#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \\\r\n      (defined(_MSC_VER) && _MSC_VER >= 1700)\r\n#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1\r\n#else\r\n#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0\r\n#endif\r\n#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR\r\n\r\n//!@endcond\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// new/delete\r\n\r\n#ifndef RAPIDJSON_NEW\r\n///! customization point for global \\c new\r\n#define RAPIDJSON_NEW(TypeName) new TypeName\r\n#endif\r\n#ifndef RAPIDJSON_DELETE\r\n///! customization point for global \\c delete\r\n#define RAPIDJSON_DELETE(x) delete x\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Type\r\n\r\n/*! \\namespace rapidjson\r\n    \\brief main RapidJSON namespace\r\n    \\see RAPIDJSON_NAMESPACE\r\n*/\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Type of JSON value\r\nenum Type {\r\n    kNullType = 0,      //!< null\r\n    kFalseType = 1,     //!< false\r\n    kTrueType = 2,      //!< true\r\n    kObjectType = 3,    //!< object\r\n    kArrayType = 4,     //!< array \r\n    kStringType = 5,    //!< string\r\n    kNumberType = 6     //!< number\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_RAPIDJSON_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/reader.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n//\r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed\r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_READER_H_\r\n#define RAPIDJSON_READER_H_\r\n\r\n/*! \\file reader.h */\r\n\r\n#include \"allocators.h\"\r\n#include \"stream.h\"\r\n#include \"encodedstream.h\"\r\n#include \"internal/meta.h\"\r\n#include \"internal/stack.h\"\r\n#include \"internal/strtod.h\"\r\n#include <limits>\r\n\r\n#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)\r\n#include <intrin.h>\r\n#pragma intrinsic(_BitScanForward)\r\n#endif\r\n#ifdef RAPIDJSON_SSE42\r\n#include <nmmintrin.h>\r\n#elif defined(RAPIDJSON_SSE2)\r\n#include <emmintrin.h>\r\n#elif defined(RAPIDJSON_NEON)\r\n#include <arm_neon.h>\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4127)  // conditional expression is constant\r\nRAPIDJSON_DIAG_OFF(4702)  // unreachable code\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(old-style-cast)\r\nRAPIDJSON_DIAG_OFF(padded)\r\nRAPIDJSON_DIAG_OFF(switch-enum)\r\n#endif\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n#define RAPIDJSON_NOTHING /* deliberately empty */\r\n#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN\r\n#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \\\r\n    RAPIDJSON_MULTILINEMACRO_BEGIN \\\r\n    if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \\\r\n    RAPIDJSON_MULTILINEMACRO_END\r\n#endif\r\n#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \\\r\n    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)\r\n//!@endcond\r\n\r\n/*! \\def RAPIDJSON_PARSE_ERROR_NORETURN\r\n    \\ingroup RAPIDJSON_ERRORS\r\n    \\brief Macro to indicate a parse error.\r\n    \\param parseErrorCode \\ref rapidjson::ParseErrorCode of the error\r\n    \\param offset  position of the error in JSON input (\\c size_t)\r\n\r\n    This macros can be used as a customization point for the internal\r\n    error handling mechanism of RapidJSON.\r\n\r\n    A common usage model is to throw an exception instead of requiring the\r\n    caller to explicitly check the \\ref rapidjson::GenericReader::Parse's\r\n    return value:\r\n\r\n    \\code\r\n    #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \\\r\n       throw ParseException(parseErrorCode, #parseErrorCode, offset)\r\n\r\n    #include <stdexcept>               // std::runtime_error\r\n    #include \"rapidjson/error/error.h\" // rapidjson::ParseResult\r\n\r\n    struct ParseException : std::runtime_error, rapidjson::ParseResult {\r\n      ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)\r\n        : std::runtime_error(msg), ParseResult(code, offset) {}\r\n    };\r\n\r\n    #include \"rapidjson/reader.h\"\r\n    \\endcode\r\n\r\n    \\see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse\r\n */\r\n#ifndef RAPIDJSON_PARSE_ERROR_NORETURN\r\n#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \\\r\n    RAPIDJSON_MULTILINEMACRO_BEGIN \\\r\n    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \\\r\n    SetParseError(parseErrorCode, offset); \\\r\n    RAPIDJSON_MULTILINEMACRO_END\r\n#endif\r\n\r\n/*! \\def RAPIDJSON_PARSE_ERROR\r\n    \\ingroup RAPIDJSON_ERRORS\r\n    \\brief (Internal) macro to indicate and handle a parse error.\r\n    \\param parseErrorCode \\ref rapidjson::ParseErrorCode of the error\r\n    \\param offset  position of the error in JSON input (\\c size_t)\r\n\r\n    Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.\r\n\r\n    \\see RAPIDJSON_PARSE_ERROR_NORETURN\r\n    \\hideinitializer\r\n */\r\n#ifndef RAPIDJSON_PARSE_ERROR\r\n#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \\\r\n    RAPIDJSON_MULTILINEMACRO_BEGIN \\\r\n    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \\\r\n    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \\\r\n    RAPIDJSON_MULTILINEMACRO_END\r\n#endif\r\n\r\n#include \"error/error.h\" // ParseErrorCode, ParseResult\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// ParseFlag\r\n\r\n/*! \\def RAPIDJSON_PARSE_DEFAULT_FLAGS\r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief User-defined kParseDefaultFlags definition.\r\n\r\n    User can define this as any \\c ParseFlag combinations.\r\n*/\r\n#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS\r\n#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags\r\n#endif\r\n\r\n//! Combination of parseFlags\r\n/*! \\see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream\r\n */\r\nenum ParseFlag {\r\n    kParseNoFlags = 0,              //!< No flags are set.\r\n    kParseInsituFlag = 1,           //!< In-situ(destructive) parsing.\r\n    kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.\r\n    kParseIterativeFlag = 4,        //!< Iterative(constant complexity in terms of function call stack size) parsing.\r\n    kParseStopWhenDoneFlag = 8,     //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.\r\n    kParseFullPrecisionFlag = 16,   //!< Parse number in full precision (but slower).\r\n    kParseCommentsFlag = 32,        //!< Allow one-line (//) and multi-line (/**/) comments.\r\n    kParseNumbersAsStringsFlag = 64,    //!< Parse all numbers (ints/doubles) as strings.\r\n    kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.\r\n    kParseNanAndInfFlag = 256,      //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.\r\n    kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS  //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Handler\r\n\r\n/*! \\class rapidjson::Handler\r\n    \\brief Concept for receiving events from GenericReader upon parsing.\r\n    The functions return true if no error occurs. If they return false,\r\n    the event publisher should terminate the process.\r\n\\code\r\nconcept Handler {\r\n    typename Ch;\r\n\r\n    bool Null();\r\n    bool Bool(bool b);\r\n    bool Int(int i);\r\n    bool Uint(unsigned i);\r\n    bool Int64(int64_t i);\r\n    bool Uint64(uint64_t i);\r\n    bool Double(double d);\r\n    /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)\r\n    bool RawNumber(const Ch* str, SizeType length, bool copy);\r\n    bool String(const Ch* str, SizeType length, bool copy);\r\n    bool StartObject();\r\n    bool Key(const Ch* str, SizeType length, bool copy);\r\n    bool EndObject(SizeType memberCount);\r\n    bool StartArray();\r\n    bool EndArray(SizeType elementCount);\r\n};\r\n\\endcode\r\n*/\r\n///////////////////////////////////////////////////////////////////////////////\r\n// BaseReaderHandler\r\n\r\n//! Default implementation of Handler.\r\n/*! This can be used as base class of any reader handler.\r\n    \\note implements Handler concept\r\n*/\r\ntemplate<typename Encoding = UTF8<>, typename Derived = void>\r\nstruct BaseReaderHandler {\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;\r\n\r\n    bool Default() { return true; }\r\n    bool Null() { return static_cast<Override&>(*this).Default(); }\r\n    bool Bool(bool) { return static_cast<Override&>(*this).Default(); }\r\n    bool Int(int) { return static_cast<Override&>(*this).Default(); }\r\n    bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }\r\n    bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }\r\n    bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }\r\n    bool Double(double) { return static_cast<Override&>(*this).Default(); }\r\n    /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)\r\n    bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }\r\n    bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }\r\n    bool StartObject() { return static_cast<Override&>(*this).Default(); }\r\n    bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }\r\n    bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }\r\n    bool StartArray() { return static_cast<Override&>(*this).Default(); }\r\n    bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// StreamLocalCopy\r\n\r\nnamespace internal {\r\n\r\ntemplate<typename Stream, int = StreamTraits<Stream>::copyOptimization>\r\nclass StreamLocalCopy;\r\n\r\n//! Do copy optimization.\r\ntemplate<typename Stream>\r\nclass StreamLocalCopy<Stream, 1> {\r\npublic:\r\n    StreamLocalCopy(Stream& original) : s(original), original_(original) {}\r\n    ~StreamLocalCopy() { original_ = s; }\r\n\r\n    Stream s;\r\n\r\nprivate:\r\n    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;\r\n\r\n    Stream& original_;\r\n};\r\n\r\n//! Keep reference.\r\ntemplate<typename Stream>\r\nclass StreamLocalCopy<Stream, 0> {\r\npublic:\r\n    StreamLocalCopy(Stream& original) : s(original) {}\r\n\r\n    Stream& s;\r\n\r\nprivate:\r\n    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;\r\n};\r\n\r\n} // namespace internal\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// SkipWhitespace\r\n\r\n//! Skip the JSON white spaces in a stream.\r\n/*! \\param is A input stream for skipping white spaces.\r\n    \\note This function has SSE2/SSE4.2 specialization.\r\n*/\r\ntemplate<typename InputStream>\r\nvoid SkipWhitespace(InputStream& is) {\r\n    internal::StreamLocalCopy<InputStream> copy(is);\r\n    InputStream& s(copy.s);\r\n\r\n    typename InputStream::Ch c;\r\n    while ((c = s.Peek()) == ' ' || c == '\\n' || c == '\\r' || c == '\\t')\r\n        s.Take();\r\n}\r\n\r\ninline const char* SkipWhitespace(const char* p, const char* end) {\r\n    while (p != end && (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t'))\r\n        ++p;\r\n    return p;\r\n}\r\n\r\n#ifdef RAPIDJSON_SSE42\r\n//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.\r\ninline const char *SkipWhitespace_SIMD(const char* p) {\r\n    // Fast return for single non-whitespace\r\n    if (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t')\r\n        ++p;\r\n    else\r\n        return p;\r\n\r\n    // 16-byte align to the next boundary\r\n    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n    while (p != nextAligned)\r\n        if (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t')\r\n            ++p;\r\n        else\r\n            return p;\r\n\r\n    // The rest of string using SIMD\r\n    static const char whitespace[16] = \" \\n\\r\\t\";\r\n    const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));\r\n\r\n    for (;; p += 16) {\r\n        const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));\r\n        const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);\r\n        if (r != 16)    // some of characters is non-whitespace\r\n            return p + r;\r\n    }\r\n}\r\n\r\ninline const char *SkipWhitespace_SIMD(const char* p, const char* end) {\r\n    // Fast return for single non-whitespace\r\n    if (p != end && (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t'))\r\n        ++p;\r\n    else\r\n        return p;\r\n\r\n    // The middle of string using SIMD\r\n    static const char whitespace[16] = \" \\n\\r\\t\";\r\n    const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));\r\n\r\n    for (; p <= end - 16; p += 16) {\r\n        const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));\r\n        const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);\r\n        if (r != 16)    // some of characters is non-whitespace\r\n            return p + r;\r\n    }\r\n\r\n    return SkipWhitespace(p, end);\r\n}\r\n\r\n#elif defined(RAPIDJSON_SSE2)\r\n\r\n//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.\r\ninline const char *SkipWhitespace_SIMD(const char* p) {\r\n    // Fast return for single non-whitespace\r\n    if (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t')\r\n        ++p;\r\n    else\r\n        return p;\r\n\r\n    // 16-byte align to the next boundary\r\n    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n    while (p != nextAligned)\r\n        if (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t')\r\n            ++p;\r\n        else\r\n            return p;\r\n\r\n    // The rest of string\r\n    #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }\r\n    static const char whitespaces[4][16] = { C16(' '), C16('\\n'), C16('\\r'), C16('\\t') };\r\n    #undef C16\r\n\r\n    const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));\r\n    const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));\r\n    const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));\r\n    const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));\r\n\r\n    for (;; p += 16) {\r\n        const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));\r\n        __m128i x = _mm_cmpeq_epi8(s, w0);\r\n        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));\r\n        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));\r\n        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));\r\n        unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));\r\n        if (r != 0) {   // some of characters may be non-whitespace\r\n#ifdef _MSC_VER         // Find the index of first non-whitespace\r\n            unsigned long offset;\r\n            _BitScanForward(&offset, r);\r\n            return p + offset;\r\n#else\r\n            return p + __builtin_ffs(r) - 1;\r\n#endif\r\n        }\r\n    }\r\n}\r\n\r\ninline const char *SkipWhitespace_SIMD(const char* p, const char* end) {\r\n    // Fast return for single non-whitespace\r\n    if (p != end && (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t'))\r\n        ++p;\r\n    else\r\n        return p;\r\n\r\n    // The rest of string\r\n    #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }\r\n    static const char whitespaces[4][16] = { C16(' '), C16('\\n'), C16('\\r'), C16('\\t') };\r\n    #undef C16\r\n\r\n    const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));\r\n    const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));\r\n    const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));\r\n    const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));\r\n\r\n    for (; p <= end - 16; p += 16) {\r\n        const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));\r\n        __m128i x = _mm_cmpeq_epi8(s, w0);\r\n        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));\r\n        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));\r\n        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));\r\n        unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));\r\n        if (r != 0) {   // some of characters may be non-whitespace\r\n#ifdef _MSC_VER         // Find the index of first non-whitespace\r\n            unsigned long offset;\r\n            _BitScanForward(&offset, r);\r\n            return p + offset;\r\n#else\r\n            return p + __builtin_ffs(r) - 1;\r\n#endif\r\n        }\r\n    }\r\n\r\n    return SkipWhitespace(p, end);\r\n}\r\n\r\n#elif defined(RAPIDJSON_NEON)\r\n\r\n//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once.\r\ninline const char *SkipWhitespace_SIMD(const char* p) {\r\n    // Fast return for single non-whitespace\r\n    if (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t')\r\n        ++p;\r\n    else\r\n        return p;\r\n\r\n    // 16-byte align to the next boundary\r\n    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n    while (p != nextAligned)\r\n        if (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t')\r\n            ++p;\r\n        else\r\n            return p;\r\n\r\n    const uint8x16_t w0 = vmovq_n_u8(' ');\r\n    const uint8x16_t w1 = vmovq_n_u8('\\n');\r\n    const uint8x16_t w2 = vmovq_n_u8('\\r');\r\n    const uint8x16_t w3 = vmovq_n_u8('\\t');\r\n\r\n    for (;; p += 16) {\r\n        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));\r\n        uint8x16_t x = vceqq_u8(s, w0);\r\n        x = vorrq_u8(x, vceqq_u8(s, w1));\r\n        x = vorrq_u8(x, vceqq_u8(s, w2));\r\n        x = vorrq_u8(x, vceqq_u8(s, w3));\r\n\r\n        x = vmvnq_u8(x);                       // Negate\r\n        x = vrev64q_u8(x);                     // Rev in 64\r\n        uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract\r\n        uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract\r\n\r\n        if (low == 0) {\r\n            if (high != 0) {\r\n                int lz =__builtin_clzll(high);;\r\n                return p + 8 + (lz >> 3);\r\n            }\r\n        } else {\r\n            int lz = __builtin_clzll(low);;\r\n            return p + (lz >> 3);\r\n        }\r\n    }\r\n}\r\n\r\ninline const char *SkipWhitespace_SIMD(const char* p, const char* end) {\r\n    // Fast return for single non-whitespace\r\n    if (p != end && (*p == ' ' || *p == '\\n' || *p == '\\r' || *p == '\\t'))\r\n        ++p;\r\n    else\r\n        return p;\r\n\r\n    const uint8x16_t w0 = vmovq_n_u8(' ');\r\n    const uint8x16_t w1 = vmovq_n_u8('\\n');\r\n    const uint8x16_t w2 = vmovq_n_u8('\\r');\r\n    const uint8x16_t w3 = vmovq_n_u8('\\t');\r\n\r\n    for (; p <= end - 16; p += 16) {\r\n        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));\r\n        uint8x16_t x = vceqq_u8(s, w0);\r\n        x = vorrq_u8(x, vceqq_u8(s, w1));\r\n        x = vorrq_u8(x, vceqq_u8(s, w2));\r\n        x = vorrq_u8(x, vceqq_u8(s, w3));\r\n\r\n        x = vmvnq_u8(x);                       // Negate\r\n        x = vrev64q_u8(x);                     // Rev in 64\r\n        uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract\r\n        uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract\r\n\r\n        if (low == 0) {\r\n            if (high != 0) {\r\n                int lz = __builtin_clzll(high);\r\n                return p + 8 + (lz >> 3);\r\n            }\r\n        } else {\r\n            int lz = __builtin_clzll(low);\r\n            return p + (lz >> 3);\r\n        }\r\n    }\r\n\r\n    return SkipWhitespace(p, end);\r\n}\r\n\r\n#endif // RAPIDJSON_NEON\r\n\r\n#ifdef RAPIDJSON_SIMD\r\n//! Template function specialization for InsituStringStream\r\ntemplate<> inline void SkipWhitespace(InsituStringStream& is) {\r\n    is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));\r\n}\r\n\r\n//! Template function specialization for StringStream\r\ntemplate<> inline void SkipWhitespace(StringStream& is) {\r\n    is.src_ = SkipWhitespace_SIMD(is.src_);\r\n}\r\n\r\ntemplate<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {\r\n    is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);\r\n}\r\n#endif // RAPIDJSON_SIMD\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericReader\r\n\r\n//! SAX-style JSON parser. Use \\ref Reader for UTF8 encoding and default allocator.\r\n/*! GenericReader parses JSON text from a stream, and send events synchronously to an\r\n    object implementing Handler concept.\r\n\r\n    It needs to allocate a stack for storing a single decoded string during\r\n    non-destructive parsing.\r\n\r\n    For in-situ parsing, the decoded string is directly written to the source\r\n    text string, no temporary buffer is required.\r\n\r\n    A GenericReader object can be reused for parsing multiple JSON text.\r\n\r\n    \\tparam SourceEncoding Encoding of the input stream.\r\n    \\tparam TargetEncoding Encoding of the parse output.\r\n    \\tparam StackAllocator Allocator type for stack.\r\n*/\r\ntemplate <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>\r\nclass GenericReader {\r\npublic:\r\n    typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type\r\n\r\n    //! Constructor.\r\n    /*! \\param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)\r\n        \\param stackCapacity stack capacity in bytes for storing a single decoded string.  (Only use for non-destructive parsing)\r\n    */\r\n    GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) :\r\n        stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}\r\n\r\n    //! Parse JSON text.\r\n    /*! \\tparam parseFlags Combination of \\ref ParseFlag.\r\n        \\tparam InputStream Type of input stream, implementing Stream concept.\r\n        \\tparam Handler Type of handler, implementing Handler concept.\r\n        \\param is Input stream to be parsed.\r\n        \\param handler The handler to receive events.\r\n        \\return Whether the parsing is successful.\r\n    */\r\n    template <unsigned parseFlags, typename InputStream, typename Handler>\r\n    ParseResult Parse(InputStream& is, Handler& handler) {\r\n        if (parseFlags & kParseIterativeFlag)\r\n            return IterativeParse<parseFlags>(is, handler);\r\n\r\n        parseResult_.Clear();\r\n\r\n        ClearStackOnExit scope(*this);\r\n\r\n        SkipWhitespaceAndComments<parseFlags>(is);\r\n        RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n\r\n        if (RAPIDJSON_UNLIKELY(is.Peek() == '\\0')) {\r\n            RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n        }\r\n        else {\r\n            ParseValue<parseFlags>(is, handler);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n\r\n            if (!(parseFlags & kParseStopWhenDoneFlag)) {\r\n                SkipWhitespaceAndComments<parseFlags>(is);\r\n                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n\r\n                if (RAPIDJSON_UNLIKELY(is.Peek() != '\\0')) {\r\n                    RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());\r\n                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n                }\r\n            }\r\n        }\r\n\r\n        return parseResult_;\r\n    }\r\n\r\n    //! Parse JSON text (with \\ref kParseDefaultFlags)\r\n    /*! \\tparam InputStream Type of input stream, implementing Stream concept\r\n        \\tparam Handler Type of handler, implementing Handler concept.\r\n        \\param is Input stream to be parsed.\r\n        \\param handler The handler to receive events.\r\n        \\return Whether the parsing is successful.\r\n    */\r\n    template <typename InputStream, typename Handler>\r\n    ParseResult Parse(InputStream& is, Handler& handler) {\r\n        return Parse<kParseDefaultFlags>(is, handler);\r\n    }\r\n\r\n    //! Initialize JSON text token-by-token parsing\r\n    /*!\r\n     */\r\n    void IterativeParseInit() {\r\n        parseResult_.Clear();\r\n        state_ = IterativeParsingStartState;\r\n    }\r\n    \r\n    //! Parse one token from JSON text\r\n    /*! \\tparam InputStream Type of input stream, implementing Stream concept\r\n        \\tparam Handler Type of handler, implementing Handler concept.\r\n        \\param is Input stream to be parsed.\r\n        \\param handler The handler to receive events.\r\n        \\return Whether the parsing is successful.\r\n     */\r\n    template <unsigned parseFlags, typename InputStream, typename Handler>\r\n    bool IterativeParseNext(InputStream& is, Handler& handler) {\r\n        while (RAPIDJSON_LIKELY(is.Peek() != '\\0')) {\r\n            SkipWhitespaceAndComments<parseFlags>(is);\r\n            \r\n            Token t = Tokenize(is.Peek());\r\n            IterativeParsingState n = Predict(state_, t);\r\n            IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);\r\n            \r\n            // If we've finished or hit an error...\r\n            if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) {\r\n                // Report errors.\r\n                if (d == IterativeParsingErrorState) {\r\n                    HandleError(state_, is);\r\n                    return false;\r\n                }\r\n            \r\n                // Transition to the finish state.\r\n                RAPIDJSON_ASSERT(d == IterativeParsingFinishState);\r\n                state_ = d;\r\n                \r\n                // If StopWhenDone is not set...\r\n                if (!(parseFlags & kParseStopWhenDoneFlag)) {\r\n                    // ... and extra non-whitespace data is found...\r\n                    SkipWhitespaceAndComments<parseFlags>(is);\r\n                    if (is.Peek() != '\\0') {\r\n                        // ... this is considered an error.\r\n                        HandleError(state_, is);\r\n                        return false;\r\n                    }\r\n                }\r\n                \r\n                // Success! We are done!\r\n                return true;\r\n            }\r\n            \r\n            // Transition to the new state.\r\n            state_ = d;\r\n\r\n            // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.\r\n            if (!IsIterativeParsingDelimiterState(n))\r\n                return true;\r\n        }\r\n        \r\n        // We reached the end of file.\r\n        stack_.Clear();\r\n\r\n        if (state_ != IterativeParsingFinishState) {\r\n            HandleError(state_, is);\r\n            return false;\r\n        }\r\n        \r\n        return true;\r\n    }\r\n    \r\n    //! Check if token-by-token parsing JSON text is complete\r\n    /*! \\return Whether the JSON has been fully decoded.\r\n     */\r\n    RAPIDJSON_FORCEINLINE bool IterativeParseComplete() {\r\n        return IsIterativeParsingCompleteState(state_);\r\n    }\r\n\r\n    //! Whether a parse error has occurred in the last parsing.\r\n    bool HasParseError() const { return parseResult_.IsError(); }\r\n\r\n    //! Get the \\ref ParseErrorCode of last parsing.\r\n    ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }\r\n\r\n    //! Get the position of last parsing error in input, 0 otherwise.\r\n    size_t GetErrorOffset() const { return parseResult_.Offset(); }\r\n\r\nprotected:\r\n    void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }\r\n\r\nprivate:\r\n    // Prohibit copy constructor & assignment operator.\r\n    GenericReader(const GenericReader&);\r\n    GenericReader& operator=(const GenericReader&);\r\n\r\n    void ClearStack() { stack_.Clear(); }\r\n\r\n    // clear stack on any exit from ParseStream, e.g. due to exception\r\n    struct ClearStackOnExit {\r\n        explicit ClearStackOnExit(GenericReader& r) : r_(r) {}\r\n        ~ClearStackOnExit() { r_.ClearStack(); }\r\n    private:\r\n        GenericReader& r_;\r\n        ClearStackOnExit(const ClearStackOnExit&);\r\n        ClearStackOnExit& operator=(const ClearStackOnExit&);\r\n    };\r\n\r\n    template<unsigned parseFlags, typename InputStream>\r\n    void SkipWhitespaceAndComments(InputStream& is) {\r\n        SkipWhitespace(is);\r\n\r\n        if (parseFlags & kParseCommentsFlag) {\r\n            while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {\r\n                if (Consume(is, '*')) {\r\n                    while (true) {\r\n                        if (RAPIDJSON_UNLIKELY(is.Peek() == '\\0'))\r\n                            RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());\r\n                        else if (Consume(is, '*')) {\r\n                            if (Consume(is, '/'))\r\n                                break;\r\n                        }\r\n                        else\r\n                            is.Take();\r\n                    }\r\n                }\r\n                else if (RAPIDJSON_LIKELY(Consume(is, '/')))\r\n                    while (is.Peek() != '\\0' && is.Take() != '\\n') {}\r\n                else\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());\r\n\r\n                SkipWhitespace(is);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Parse object: { string : value, ... }\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseObject(InputStream& is, Handler& handler) {\r\n        RAPIDJSON_ASSERT(is.Peek() == '{');\r\n        is.Take();  // Skip '{'\r\n\r\n        if (RAPIDJSON_UNLIKELY(!handler.StartObject()))\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n\r\n        SkipWhitespaceAndComments<parseFlags>(is);\r\n        RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n        if (Consume(is, '}')) {\r\n            if (RAPIDJSON_UNLIKELY(!handler.EndObject(0)))  // empty object\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n            return;\r\n        }\r\n\r\n        for (SizeType memberCount = 0;;) {\r\n            if (RAPIDJSON_UNLIKELY(is.Peek() != '\"'))\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());\r\n\r\n            ParseString<parseFlags>(is, handler, true);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            SkipWhitespaceAndComments<parseFlags>(is);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());\r\n\r\n            SkipWhitespaceAndComments<parseFlags>(is);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            ParseValue<parseFlags>(is, handler);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            SkipWhitespaceAndComments<parseFlags>(is);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            ++memberCount;\r\n\r\n            switch (is.Peek()) {\r\n                case ',':\r\n                    is.Take();\r\n                    SkipWhitespaceAndComments<parseFlags>(is);\r\n                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n                    break;\r\n                case '}':\r\n                    is.Take();\r\n                    if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))\r\n                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n                    return;\r\n                default:\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy\r\n            }\r\n\r\n            if (parseFlags & kParseTrailingCommasFlag) {\r\n                if (is.Peek() == '}') {\r\n                    if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))\r\n                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n                    is.Take();\r\n                    return;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    // Parse array: [ value, ... ]\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseArray(InputStream& is, Handler& handler) {\r\n        RAPIDJSON_ASSERT(is.Peek() == '[');\r\n        is.Take();  // Skip '['\r\n\r\n        if (RAPIDJSON_UNLIKELY(!handler.StartArray()))\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n\r\n        SkipWhitespaceAndComments<parseFlags>(is);\r\n        RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n        if (Consume(is, ']')) {\r\n            if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n            return;\r\n        }\r\n\r\n        for (SizeType elementCount = 0;;) {\r\n            ParseValue<parseFlags>(is, handler);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            ++elementCount;\r\n            SkipWhitespaceAndComments<parseFlags>(is);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n\r\n            if (Consume(is, ',')) {\r\n                SkipWhitespaceAndComments<parseFlags>(is);\r\n                RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n            }\r\n            else if (Consume(is, ']')) {\r\n                if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n                return;\r\n            }\r\n            else\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());\r\n\r\n            if (parseFlags & kParseTrailingCommasFlag) {\r\n                if (is.Peek() == ']') {\r\n                    if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))\r\n                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n                    is.Take();\r\n                    return;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseNull(InputStream& is, Handler& handler) {\r\n        RAPIDJSON_ASSERT(is.Peek() == 'n');\r\n        is.Take();\r\n\r\n        if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {\r\n            if (RAPIDJSON_UNLIKELY(!handler.Null()))\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n        }\r\n        else\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());\r\n    }\r\n\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseTrue(InputStream& is, Handler& handler) {\r\n        RAPIDJSON_ASSERT(is.Peek() == 't');\r\n        is.Take();\r\n\r\n        if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {\r\n            if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n        }\r\n        else\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());\r\n    }\r\n\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseFalse(InputStream& is, Handler& handler) {\r\n        RAPIDJSON_ASSERT(is.Peek() == 'f');\r\n        is.Take();\r\n\r\n        if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {\r\n            if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());\r\n        }\r\n        else\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());\r\n    }\r\n\r\n    template<typename InputStream>\r\n    RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {\r\n        if (RAPIDJSON_LIKELY(is.Peek() == expect)) {\r\n            is.Take();\r\n            return true;\r\n        }\r\n        else\r\n            return false;\r\n    }\r\n\r\n    // Helper function to parse four hexadecimal digits in \\uXXXX in ParseString().\r\n    template<typename InputStream>\r\n    unsigned ParseHex4(InputStream& is, size_t escapeOffset) {\r\n        unsigned codepoint = 0;\r\n        for (int i = 0; i < 4; i++) {\r\n            Ch c = is.Peek();\r\n            codepoint <<= 4;\r\n            codepoint += static_cast<unsigned>(c);\r\n            if (c >= '0' && c <= '9')\r\n                codepoint -= '0';\r\n            else if (c >= 'A' && c <= 'F')\r\n                codepoint -= 'A' - 10;\r\n            else if (c >= 'a' && c <= 'f')\r\n                codepoint -= 'a' - 10;\r\n            else {\r\n                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);\r\n                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);\r\n            }\r\n            is.Take();\r\n        }\r\n        return codepoint;\r\n    }\r\n\r\n    template <typename CharType>\r\n    class StackStream {\r\n    public:\r\n        typedef CharType Ch;\r\n\r\n        StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}\r\n        RAPIDJSON_FORCEINLINE void Put(Ch c) {\r\n            *stack_.template Push<Ch>() = c;\r\n            ++length_;\r\n        }\r\n\r\n        RAPIDJSON_FORCEINLINE void* Push(SizeType count) {\r\n            length_ += count;\r\n            return stack_.template Push<Ch>(count);\r\n        }\r\n\r\n        size_t Length() const { return length_; }\r\n\r\n        Ch* Pop() {\r\n            return stack_.template Pop<Ch>(length_);\r\n        }\r\n\r\n    private:\r\n        StackStream(const StackStream&);\r\n        StackStream& operator=(const StackStream&);\r\n\r\n        internal::Stack<StackAllocator>& stack_;\r\n        SizeType length_;\r\n    };\r\n\r\n    // Parse string and generate String event. Different code paths for kParseInsituFlag.\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseString(InputStream& is, Handler& handler, bool isKey = false) {\r\n        internal::StreamLocalCopy<InputStream> copy(is);\r\n        InputStream& s(copy.s);\r\n\r\n        RAPIDJSON_ASSERT(s.Peek() == '\\\"');\r\n        s.Take();  // Skip '\\\"'\r\n\r\n        bool success = false;\r\n        if (parseFlags & kParseInsituFlag) {\r\n            typename InputStream::Ch *head = s.PutBegin();\r\n            ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n            size_t length = s.PutEnd(head) - 1;\r\n            RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);\r\n            const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);\r\n            success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));\r\n        }\r\n        else {\r\n            StackStream<typename TargetEncoding::Ch> stackStream(stack_);\r\n            ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n            SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;\r\n            const typename TargetEncoding::Ch* const str = stackStream.Pop();\r\n            success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));\r\n        }\r\n        if (RAPIDJSON_UNLIKELY(!success))\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());\r\n    }\r\n\r\n    // Parse string to an output is\r\n    // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.\r\n    template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>\r\n    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\n        static const char escape[256] = {\r\n            Z16, Z16, 0, 0,'\\\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',\r\n            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\\\', 0, 0, 0,\r\n            0, 0,'\\b', 0, 0, 0,'\\f', 0, 0, 0, 0, 0, 0, 0,'\\n', 0,\r\n            0, 0,'\\r', 0,'\\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r\n            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16\r\n        };\r\n#undef Z16\r\n//!@endcond\r\n\r\n        for (;;) {\r\n            // Scan and copy string before \"\\\\\\\"\" or < 0x20. This is an optional optimzation.\r\n            if (!(parseFlags & kParseValidateEncodingFlag))\r\n                ScanCopyUnescapedString(is, os);\r\n\r\n            Ch c = is.Peek();\r\n            if (RAPIDJSON_UNLIKELY(c == '\\\\')) {    // Escape\r\n                size_t escapeOffset = is.Tell();    // For invalid escaping, report the initial '\\\\' as error offset\r\n                is.Take();\r\n                Ch e = is.Peek();\r\n                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {\r\n                    is.Take();\r\n                    os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));\r\n                }\r\n                else if (RAPIDJSON_LIKELY(e == 'u')) {    // Unicode\r\n                    is.Take();\r\n                    unsigned codepoint = ParseHex4(is, escapeOffset);\r\n                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n                    if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {\r\n                        // Handle UTF-16 surrogate pair\r\n                        if (RAPIDJSON_UNLIKELY(!Consume(is, '\\\\') || !Consume(is, 'u')))\r\n                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);\r\n                        unsigned codepoint2 = ParseHex4(is, escapeOffset);\r\n                        RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;\r\n                        if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))\r\n                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);\r\n                        codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;\r\n                    }\r\n                    TEncoding::Encode(os, codepoint);\r\n                }\r\n                else\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);\r\n            }\r\n            else if (RAPIDJSON_UNLIKELY(c == '\"')) {    // Closing double quote\r\n                is.Take();\r\n                os.Put('\\0');   // null-terminate the string\r\n                return;\r\n            }\r\n            else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF\r\n                if (c == '\\0')\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());\r\n                else\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());\r\n            }\r\n            else {\r\n                size_t offset = is.Tell();\r\n                if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?\r\n                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) :\r\n                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);\r\n            }\r\n        }\r\n    }\r\n\r\n    template<typename InputStream, typename OutputStream>\r\n    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {\r\n            // Do nothing for generic version\r\n    }\r\n\r\n#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)\r\n    // StringStream -> StackStream<char>\r\n    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {\r\n        const char* p = is.src_;\r\n\r\n        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)\r\n        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n        while (p != nextAligned)\r\n            if (RAPIDJSON_UNLIKELY(*p == '\\\"') || RAPIDJSON_UNLIKELY(*p == '\\\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {\r\n                is.src_ = p;\r\n                return;\r\n            }\r\n            else\r\n                os.Put(*p++);\r\n\r\n        // The rest of string using SIMD\r\n        static const char dquote[16] = { '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"' };\r\n        static const char bslash[16] = { '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\' };\r\n        static const char space[16]  = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };\r\n        const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));\r\n        const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));\r\n        const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));\r\n\r\n        for (;; p += 16) {\r\n            const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));\r\n            const __m128i t1 = _mm_cmpeq_epi8(s, dq);\r\n            const __m128i t2 = _mm_cmpeq_epi8(s, bs);\r\n            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F\r\n            const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);\r\n            unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));\r\n            if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped\r\n                SizeType length;\r\n    #ifdef _MSC_VER         // Find the index of first escaped\r\n                unsigned long offset;\r\n                _BitScanForward(&offset, r);\r\n                length = offset;\r\n    #else\r\n                length = static_cast<SizeType>(__builtin_ffs(r) - 1);\r\n    #endif\r\n                if (length != 0) {\r\n                    char* q = reinterpret_cast<char*>(os.Push(length));\r\n                    for (size_t i = 0; i < length; i++)\r\n                        q[i] = p[i];\r\n\r\n                    p += length;\r\n                }\r\n                break;\r\n            }\r\n            _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);\r\n        }\r\n\r\n        is.src_ = p;\r\n    }\r\n\r\n    // InsituStringStream -> InsituStringStream\r\n    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {\r\n        RAPIDJSON_ASSERT(&is == &os);\r\n        (void)os;\r\n\r\n        if (is.src_ == is.dst_) {\r\n            SkipUnescapedString(is);\r\n            return;\r\n        }\r\n\r\n        char* p = is.src_;\r\n        char *q = is.dst_;\r\n\r\n        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)\r\n        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n        while (p != nextAligned)\r\n            if (RAPIDJSON_UNLIKELY(*p == '\\\"') || RAPIDJSON_UNLIKELY(*p == '\\\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {\r\n                is.src_ = p;\r\n                is.dst_ = q;\r\n                return;\r\n            }\r\n            else\r\n                *q++ = *p++;\r\n\r\n        // The rest of string using SIMD\r\n        static const char dquote[16] = { '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"' };\r\n        static const char bslash[16] = { '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\' };\r\n        static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };\r\n        const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));\r\n        const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));\r\n        const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));\r\n\r\n        for (;; p += 16, q += 16) {\r\n            const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));\r\n            const __m128i t1 = _mm_cmpeq_epi8(s, dq);\r\n            const __m128i t2 = _mm_cmpeq_epi8(s, bs);\r\n            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F\r\n            const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);\r\n            unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));\r\n            if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped\r\n                size_t length;\r\n#ifdef _MSC_VER         // Find the index of first escaped\r\n                unsigned long offset;\r\n                _BitScanForward(&offset, r);\r\n                length = offset;\r\n#else\r\n                length = static_cast<size_t>(__builtin_ffs(r) - 1);\r\n#endif\r\n                for (const char* pend = p + length; p != pend; )\r\n                    *q++ = *p++;\r\n                break;\r\n            }\r\n            _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);\r\n        }\r\n\r\n        is.src_ = p;\r\n        is.dst_ = q;\r\n    }\r\n\r\n    // When read/write pointers are the same for insitu stream, just skip unescaped characters\r\n    static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {\r\n        RAPIDJSON_ASSERT(is.src_ == is.dst_);\r\n        char* p = is.src_;\r\n\r\n        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)\r\n        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n        for (; p != nextAligned; p++)\r\n            if (RAPIDJSON_UNLIKELY(*p == '\\\"') || RAPIDJSON_UNLIKELY(*p == '\\\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {\r\n                is.src_ = is.dst_ = p;\r\n                return;\r\n            }\r\n\r\n        // The rest of string using SIMD\r\n        static const char dquote[16] = { '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"' };\r\n        static const char bslash[16] = { '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\' };\r\n        static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };\r\n        const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));\r\n        const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));\r\n        const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));\r\n\r\n        for (;; p += 16) {\r\n            const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));\r\n            const __m128i t1 = _mm_cmpeq_epi8(s, dq);\r\n            const __m128i t2 = _mm_cmpeq_epi8(s, bs);\r\n            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F\r\n            const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);\r\n            unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));\r\n            if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped\r\n                size_t length;\r\n#ifdef _MSC_VER         // Find the index of first escaped\r\n                unsigned long offset;\r\n                _BitScanForward(&offset, r);\r\n                length = offset;\r\n#else\r\n                length = static_cast<size_t>(__builtin_ffs(r) - 1);\r\n#endif\r\n                p += length;\r\n                break;\r\n            }\r\n        }\r\n\r\n        is.src_ = is.dst_ = p;\r\n    }\r\n#elif defined(RAPIDJSON_NEON)\r\n    // StringStream -> StackStream<char>\r\n    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {\r\n        const char* p = is.src_;\r\n\r\n        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)\r\n        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n        while (p != nextAligned)\r\n            if (RAPIDJSON_UNLIKELY(*p == '\\\"') || RAPIDJSON_UNLIKELY(*p == '\\\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {\r\n                is.src_ = p;\r\n                return;\r\n            }\r\n            else\r\n                os.Put(*p++);\r\n\r\n        // The rest of string using SIMD\r\n        const uint8x16_t s0 = vmovq_n_u8('\"');\r\n        const uint8x16_t s1 = vmovq_n_u8('\\\\');\r\n        const uint8x16_t s2 = vmovq_n_u8('\\b');\r\n        const uint8x16_t s3 = vmovq_n_u8(32);\r\n\r\n        for (;; p += 16) {\r\n            const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));\r\n            uint8x16_t x = vceqq_u8(s, s0);\r\n            x = vorrq_u8(x, vceqq_u8(s, s1));\r\n            x = vorrq_u8(x, vceqq_u8(s, s2));\r\n            x = vorrq_u8(x, vcltq_u8(s, s3));\r\n\r\n            x = vrev64q_u8(x);                     // Rev in 64\r\n            uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract\r\n            uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract\r\n\r\n            SizeType length = 0;\r\n            bool escaped = false;\r\n            if (low == 0) {\r\n                if (high != 0) {\r\n                    unsigned lz = (unsigned)__builtin_clzll(high);;\r\n                    length = 8 + (lz >> 3);\r\n                    escaped = true;\r\n                }\r\n            } else {\r\n                unsigned lz = (unsigned)__builtin_clzll(low);;\r\n                length = lz >> 3;\r\n                escaped = true;\r\n            }\r\n            if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped\r\n                if (length != 0) {\r\n                    char* q = reinterpret_cast<char*>(os.Push(length));\r\n                    for (size_t i = 0; i < length; i++)\r\n                        q[i] = p[i];\r\n\r\n                    p += length;\r\n                }\r\n                break;\r\n            }\r\n            vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);\r\n        }\r\n\r\n        is.src_ = p;\r\n    }\r\n\r\n    // InsituStringStream -> InsituStringStream\r\n    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {\r\n        RAPIDJSON_ASSERT(&is == &os);\r\n        (void)os;\r\n\r\n        if (is.src_ == is.dst_) {\r\n            SkipUnescapedString(is);\r\n            return;\r\n        }\r\n\r\n        char* p = is.src_;\r\n        char *q = is.dst_;\r\n\r\n        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)\r\n        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n        while (p != nextAligned)\r\n            if (RAPIDJSON_UNLIKELY(*p == '\\\"') || RAPIDJSON_UNLIKELY(*p == '\\\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {\r\n                is.src_ = p;\r\n                is.dst_ = q;\r\n                return;\r\n            }\r\n            else\r\n                *q++ = *p++;\r\n\r\n        // The rest of string using SIMD\r\n        const uint8x16_t s0 = vmovq_n_u8('\"');\r\n        const uint8x16_t s1 = vmovq_n_u8('\\\\');\r\n        const uint8x16_t s2 = vmovq_n_u8('\\b');\r\n        const uint8x16_t s3 = vmovq_n_u8(32);\r\n\r\n        for (;; p += 16, q += 16) {\r\n            const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));\r\n            uint8x16_t x = vceqq_u8(s, s0);\r\n            x = vorrq_u8(x, vceqq_u8(s, s1));\r\n            x = vorrq_u8(x, vceqq_u8(s, s2));\r\n            x = vorrq_u8(x, vcltq_u8(s, s3));\r\n\r\n            x = vrev64q_u8(x);                     // Rev in 64\r\n            uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract\r\n            uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract\r\n\r\n            SizeType length = 0;\r\n            bool escaped = false;\r\n            if (low == 0) {\r\n                if (high != 0) {\r\n                    unsigned lz = (unsigned)__builtin_clzll(high);\r\n                    length = 8 + (lz >> 3);\r\n                    escaped = true;\r\n                }\r\n            } else {\r\n                unsigned lz = (unsigned)__builtin_clzll(low);\r\n                length = lz >> 3;\r\n                escaped = true;\r\n            }\r\n            if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped\r\n                for (const char* pend = p + length; p != pend; ) {\r\n                    *q++ = *p++;\r\n                }\r\n                break;\r\n            }\r\n            vst1q_u8(reinterpret_cast<uint8_t *>(q), s);\r\n        }\r\n\r\n        is.src_ = p;\r\n        is.dst_ = q;\r\n    }\r\n\r\n    // When read/write pointers are the same for insitu stream, just skip unescaped characters\r\n    static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {\r\n        RAPIDJSON_ASSERT(is.src_ == is.dst_);\r\n        char* p = is.src_;\r\n\r\n        // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)\r\n        const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n        for (; p != nextAligned; p++)\r\n            if (RAPIDJSON_UNLIKELY(*p == '\\\"') || RAPIDJSON_UNLIKELY(*p == '\\\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {\r\n                is.src_ = is.dst_ = p;\r\n                return;\r\n            }\r\n\r\n        // The rest of string using SIMD\r\n        const uint8x16_t s0 = vmovq_n_u8('\"');\r\n        const uint8x16_t s1 = vmovq_n_u8('\\\\');\r\n        const uint8x16_t s2 = vmovq_n_u8('\\b');\r\n        const uint8x16_t s3 = vmovq_n_u8(32);\r\n\r\n        for (;; p += 16) {\r\n            const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));\r\n            uint8x16_t x = vceqq_u8(s, s0);\r\n            x = vorrq_u8(x, vceqq_u8(s, s1));\r\n            x = vorrq_u8(x, vceqq_u8(s, s2));\r\n            x = vorrq_u8(x, vcltq_u8(s, s3));\r\n\r\n            x = vrev64q_u8(x);                     // Rev in 64\r\n            uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract\r\n            uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract\r\n\r\n            if (low == 0) {\r\n                if (high != 0) {\r\n                    int lz = __builtin_clzll(high);\r\n                    p += 8 + (lz >> 3);\r\n                    break;\r\n                }\r\n            } else {\r\n                int lz = __builtin_clzll(low);\r\n                p += lz >> 3;\r\n                break;\r\n            }\r\n        }\r\n\r\n        is.src_ = is.dst_ = p;\r\n    }\r\n#endif // RAPIDJSON_NEON\r\n\r\n    template<typename InputStream, bool backup, bool pushOnTake>\r\n    class NumberStream;\r\n\r\n    template<typename InputStream>\r\n    class NumberStream<InputStream, false, false> {\r\n    public:\r\n        typedef typename InputStream::Ch Ch;\r\n\r\n        NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader;  }\r\n\r\n        RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }\r\n        RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }\r\n        RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }\r\n\t\t  RAPIDJSON_FORCEINLINE void Push(char) {}\r\n\r\n        size_t Tell() { return is.Tell(); }\r\n        size_t Length() { return 0; }\r\n        const char* Pop() { return 0; }\r\n\r\n    protected:\r\n        NumberStream& operator=(const NumberStream&);\r\n\r\n        InputStream& is;\r\n    };\r\n\r\n    template<typename InputStream>\r\n    class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {\r\n        typedef NumberStream<InputStream, false, false> Base;\r\n    public:\r\n        NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}\r\n\r\n        RAPIDJSON_FORCEINLINE Ch TakePush() {\r\n            stackStream.Put(static_cast<char>(Base::is.Peek()));\r\n            return Base::is.Take();\r\n        }\r\n\r\n        RAPIDJSON_FORCEINLINE void Push(char c) {\r\n            stackStream.Put(c);\r\n        }\r\n\r\n        size_t Length() { return stackStream.Length(); }\r\n\r\n        const char* Pop() {\r\n            stackStream.Put('\\0');\r\n            return stackStream.Pop();\r\n        }\r\n\r\n    private:\r\n        StackStream<char> stackStream;\r\n    };\r\n\r\n    template<typename InputStream>\r\n    class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {\r\n        typedef NumberStream<InputStream, true, false> Base;\r\n    public:\r\n        NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}\r\n\r\n        RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }\r\n    };\r\n\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseNumber(InputStream& is, Handler& handler) {\r\n        internal::StreamLocalCopy<InputStream> copy(is);\r\n        NumberStream<InputStream,\r\n            ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?\r\n                ((parseFlags & kParseInsituFlag) == 0) :\r\n                ((parseFlags & kParseFullPrecisionFlag) != 0),\r\n            (parseFlags & kParseNumbersAsStringsFlag) != 0 &&\r\n                (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);\r\n\r\n        size_t startOffset = s.Tell();\r\n        double d = 0.0;\r\n        bool useNanOrInf = false;\r\n\r\n        // Parse minus\r\n        bool minus = Consume(s, '-');\r\n\r\n        // Parse int: zero / ( digit1-9 *DIGIT )\r\n        unsigned i = 0;\r\n        uint64_t i64 = 0;\r\n        bool use64bit = false;\r\n        int significandDigit = 0;\r\n        if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {\r\n            i = 0;\r\n            s.TakePush();\r\n        }\r\n        else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {\r\n            i = static_cast<unsigned>(s.TakePush() - '0');\r\n\r\n            if (minus)\r\n                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                    if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648\r\n                        if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {\r\n                            i64 = i;\r\n                            use64bit = true;\r\n                            break;\r\n                        }\r\n                    }\r\n                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');\r\n                    significandDigit++;\r\n                }\r\n            else\r\n                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                    if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295\r\n                        if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {\r\n                            i64 = i;\r\n                            use64bit = true;\r\n                            break;\r\n                        }\r\n                    }\r\n                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');\r\n                    significandDigit++;\r\n                }\r\n        }\r\n        // Parse NaN or Infinity here\r\n        else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {\r\n            if (Consume(s, 'N')) {\r\n                if (Consume(s, 'a') && Consume(s, 'N')) {\r\n                    d = std::numeric_limits<double>::quiet_NaN();\r\n                    useNanOrInf = true;\r\n                }\r\n            }\r\n            else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {\r\n                if (Consume(s, 'n') && Consume(s, 'f')) {\r\n                    d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());\r\n                    useNanOrInf = true;\r\n\r\n                    if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')\r\n                                                                && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {\r\n                        RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());\r\n            }\r\n        }\r\n        else\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());\r\n\r\n        // Parse 64bit int\r\n        bool useDouble = false;\r\n        if (use64bit) {\r\n            if (minus)\r\n                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                     if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808\r\n                        if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {\r\n                            d = static_cast<double>(i64);\r\n                            useDouble = true;\r\n                            break;\r\n                        }\r\n                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');\r\n                    significandDigit++;\r\n                }\r\n            else\r\n                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                    if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615\r\n                        if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {\r\n                            d = static_cast<double>(i64);\r\n                            useDouble = true;\r\n                            break;\r\n                        }\r\n                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');\r\n                    significandDigit++;\r\n                }\r\n        }\r\n\r\n        // Force double for big integer\r\n        if (useDouble) {\r\n            while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0\r\n                    RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);\r\n                d = d * 10 + (s.TakePush() - '0');\r\n            }\r\n        }\r\n\r\n        // Parse frac = decimal-point 1*DIGIT\r\n        int expFrac = 0;\r\n        size_t decimalPosition;\r\n        if (Consume(s, '.')) {\r\n            decimalPosition = s.Length();\r\n\r\n            if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());\r\n\r\n            if (!useDouble) {\r\n#if RAPIDJSON_64BIT\r\n                // Use i64 to store significand in 64-bit architecture\r\n                if (!use64bit)\r\n                    i64 = i;\r\n\r\n                while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                    if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path\r\n                        break;\r\n                    else {\r\n                        i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');\r\n                        --expFrac;\r\n                        if (i64 != 0)\r\n                            significandDigit++;\r\n                    }\r\n                }\r\n\r\n                d = static_cast<double>(i64);\r\n#else\r\n                // Use double to store significand in 32-bit architecture\r\n                d = static_cast<double>(use64bit ? i64 : i);\r\n#endif\r\n                useDouble = true;\r\n            }\r\n\r\n            while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                if (significandDigit < 17) {\r\n                    d = d * 10.0 + (s.TakePush() - '0');\r\n                    --expFrac;\r\n                    if (RAPIDJSON_LIKELY(d > 0.0))\r\n                        significandDigit++;\r\n                }\r\n                else\r\n                    s.TakePush();\r\n            }\r\n        }\r\n        else\r\n            decimalPosition = s.Length(); // decimal position at the end of integer.\r\n\r\n        // Parse exp = e [ minus / plus ] 1*DIGIT\r\n        int exp = 0;\r\n        if (Consume(s, 'e') || Consume(s, 'E')) {\r\n            if (!useDouble) {\r\n                d = static_cast<double>(use64bit ? i64 : i);\r\n                useDouble = true;\r\n            }\r\n\r\n            bool expMinus = false;\r\n            if (Consume(s, '+'))\r\n                ;\r\n            else if (Consume(s, '-'))\r\n                expMinus = true;\r\n\r\n            if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                exp = static_cast<int>(s.Take() - '0');\r\n                if (expMinus) {\r\n                    while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                        exp = exp * 10 + static_cast<int>(s.Take() - '0');\r\n                        if (exp >= 214748364) {                         // Issue #313: prevent overflow exponent\r\n                            while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9'))  // Consume the rest of exponent\r\n                                s.Take();\r\n                        }\r\n                    }\r\n                }\r\n                else {  // positive exp\r\n                    int maxExp = 308 - expFrac;\r\n                    while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {\r\n                        exp = exp * 10 + static_cast<int>(s.Take() - '0');\r\n                        if (RAPIDJSON_UNLIKELY(exp > maxExp))\r\n                            RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);\r\n                    }\r\n                }\r\n            }\r\n            else\r\n                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());\r\n\r\n            if (expMinus)\r\n                exp = -exp;\r\n        }\r\n\r\n        // Finish parsing, call event according to the type of number.\r\n        bool cont = true;\r\n\r\n        if (parseFlags & kParseNumbersAsStringsFlag) {\r\n            if (parseFlags & kParseInsituFlag) {\r\n                s.Pop();  // Pop stack no matter if it will be used or not.\r\n                typename InputStream::Ch* head = is.PutBegin();\r\n                const size_t length = s.Tell() - startOffset;\r\n                RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);\r\n                // unable to insert the \\0 character here, it will erase the comma after this number\r\n                const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);\r\n                cont = handler.RawNumber(str, SizeType(length), false);\r\n            }\r\n            else {\r\n                SizeType numCharsToCopy = static_cast<SizeType>(s.Length());\r\n                StringStream srcStream(s.Pop());\r\n                StackStream<typename TargetEncoding::Ch> dstStream(stack_);\r\n                while (numCharsToCopy--) {\r\n                    Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);\r\n                }\r\n                dstStream.Put('\\0');\r\n                const typename TargetEncoding::Ch* str = dstStream.Pop();\r\n                const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;\r\n                cont = handler.RawNumber(str, SizeType(length), true);\r\n            }\r\n        }\r\n        else {\r\n           size_t length = s.Length();\r\n           const char* decimal = s.Pop();  // Pop stack no matter if it will be used or not.\r\n\r\n           if (useDouble) {\r\n               int p = exp + expFrac;\r\n               if (parseFlags & kParseFullPrecisionFlag)\r\n                   d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);\r\n               else\r\n                   d = internal::StrtodNormalPrecision(d, p);\r\n\r\n               cont = handler.Double(minus ? -d : d);\r\n           }\r\n           else if (useNanOrInf) {\r\n               cont = handler.Double(d);\r\n           }\r\n           else {\r\n               if (use64bit) {\r\n                   if (minus)\r\n                       cont = handler.Int64(static_cast<int64_t>(~i64 + 1));\r\n                   else\r\n                       cont = handler.Uint64(i64);\r\n               }\r\n               else {\r\n                   if (minus)\r\n                       cont = handler.Int(static_cast<int32_t>(~i + 1));\r\n                   else\r\n                       cont = handler.Uint(i);\r\n               }\r\n           }\r\n        }\r\n        if (RAPIDJSON_UNLIKELY(!cont))\r\n            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);\r\n    }\r\n\r\n    // Parse any JSON value\r\n    template<unsigned parseFlags, typename InputStream, typename Handler>\r\n    void ParseValue(InputStream& is, Handler& handler) {\r\n        switch (is.Peek()) {\r\n            case 'n': ParseNull  <parseFlags>(is, handler); break;\r\n            case 't': ParseTrue  <parseFlags>(is, handler); break;\r\n            case 'f': ParseFalse <parseFlags>(is, handler); break;\r\n            case '\"': ParseString<parseFlags>(is, handler); break;\r\n            case '{': ParseObject<parseFlags>(is, handler); break;\r\n            case '[': ParseArray <parseFlags>(is, handler); break;\r\n            default :\r\n                      ParseNumber<parseFlags>(is, handler);\r\n                      break;\r\n\r\n        }\r\n    }\r\n\r\n    // Iterative Parsing\r\n\r\n    // States\r\n    enum IterativeParsingState {\r\n        IterativeParsingFinishState = 0, // sink states at top\r\n        IterativeParsingErrorState,      // sink states at top\r\n        IterativeParsingStartState,\r\n\r\n        // Object states\r\n        IterativeParsingObjectInitialState,\r\n        IterativeParsingMemberKeyState,\r\n        IterativeParsingMemberValueState,\r\n        IterativeParsingObjectFinishState,\r\n\r\n        // Array states\r\n        IterativeParsingArrayInitialState,\r\n        IterativeParsingElementState,\r\n        IterativeParsingArrayFinishState,\r\n\r\n        // Single value state\r\n        IterativeParsingValueState,\r\n        \r\n        // Delimiter states (at bottom)\r\n        IterativeParsingElementDelimiterState,\r\n        IterativeParsingMemberDelimiterState,\r\n        IterativeParsingKeyValueDelimiterState,\r\n        \r\n        cIterativeParsingStateCount\r\n    };\r\n\r\n    // Tokens\r\n    enum Token {\r\n        LeftBracketToken = 0,\r\n        RightBracketToken,\r\n\r\n        LeftCurlyBracketToken,\r\n        RightCurlyBracketToken,\r\n\r\n        CommaToken,\r\n        ColonToken,\r\n\r\n        StringToken,\r\n        FalseToken,\r\n        TrueToken,\r\n        NullToken,\r\n        NumberToken,\r\n\r\n        kTokenCount\r\n    };\r\n\r\n    RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {\r\n\r\n//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN\r\n#define N NumberToken\r\n#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N\r\n        // Maps from ASCII to Token\r\n        static const unsigned char tokenMap[256] = {\r\n            N16, // 00~0F\r\n            N16, // 10~1F\r\n            N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F\r\n            N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F\r\n            N16, // 40~4F\r\n            N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F\r\n            N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F\r\n            N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F\r\n            N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF\r\n        };\r\n#undef N\r\n#undef N16\r\n//!@endcond\r\n\r\n        if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)\r\n            return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);\r\n        else\r\n            return NumberToken;\r\n    }\r\n\r\n    RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {\r\n        // current state x one lookahead token -> new state\r\n        static const char G[cIterativeParsingStateCount][kTokenCount] = {\r\n            // Finish(sink state)\r\n            {\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState\r\n            },\r\n            // Error(sink state)\r\n            {\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState\r\n            },\r\n            // Start\r\n            {\r\n                IterativeParsingArrayInitialState,  // Left bracket\r\n                IterativeParsingErrorState,         // Right bracket\r\n                IterativeParsingObjectInitialState, // Left curly bracket\r\n                IterativeParsingErrorState,         // Right curly bracket\r\n                IterativeParsingErrorState,         // Comma\r\n                IterativeParsingErrorState,         // Colon\r\n                IterativeParsingValueState,         // String\r\n                IterativeParsingValueState,         // False\r\n                IterativeParsingValueState,         // True\r\n                IterativeParsingValueState,         // Null\r\n                IterativeParsingValueState          // Number\r\n            },\r\n            // ObjectInitial\r\n            {\r\n                IterativeParsingErrorState,         // Left bracket\r\n                IterativeParsingErrorState,         // Right bracket\r\n                IterativeParsingErrorState,         // Left curly bracket\r\n                IterativeParsingObjectFinishState,  // Right curly bracket\r\n                IterativeParsingErrorState,         // Comma\r\n                IterativeParsingErrorState,         // Colon\r\n                IterativeParsingMemberKeyState,     // String\r\n                IterativeParsingErrorState,         // False\r\n                IterativeParsingErrorState,         // True\r\n                IterativeParsingErrorState,         // Null\r\n                IterativeParsingErrorState          // Number\r\n            },\r\n            // MemberKey\r\n            {\r\n                IterativeParsingErrorState,             // Left bracket\r\n                IterativeParsingErrorState,             // Right bracket\r\n                IterativeParsingErrorState,             // Left curly bracket\r\n                IterativeParsingErrorState,             // Right curly bracket\r\n                IterativeParsingErrorState,             // Comma\r\n                IterativeParsingKeyValueDelimiterState, // Colon\r\n                IterativeParsingErrorState,             // String\r\n                IterativeParsingErrorState,             // False\r\n                IterativeParsingErrorState,             // True\r\n                IterativeParsingErrorState,             // Null\r\n                IterativeParsingErrorState              // Number\r\n            },\r\n            // MemberValue\r\n            {\r\n                IterativeParsingErrorState,             // Left bracket\r\n                IterativeParsingErrorState,             // Right bracket\r\n                IterativeParsingErrorState,             // Left curly bracket\r\n                IterativeParsingObjectFinishState,      // Right curly bracket\r\n                IterativeParsingMemberDelimiterState,   // Comma\r\n                IterativeParsingErrorState,             // Colon\r\n                IterativeParsingErrorState,             // String\r\n                IterativeParsingErrorState,             // False\r\n                IterativeParsingErrorState,             // True\r\n                IterativeParsingErrorState,             // Null\r\n                IterativeParsingErrorState              // Number\r\n            },\r\n            // ObjectFinish(sink state)\r\n            {\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState\r\n            },\r\n            // ArrayInitial\r\n            {\r\n                IterativeParsingArrayInitialState,      // Left bracket(push Element state)\r\n                IterativeParsingArrayFinishState,       // Right bracket\r\n                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)\r\n                IterativeParsingErrorState,             // Right curly bracket\r\n                IterativeParsingErrorState,             // Comma\r\n                IterativeParsingErrorState,             // Colon\r\n                IterativeParsingElementState,           // String\r\n                IterativeParsingElementState,           // False\r\n                IterativeParsingElementState,           // True\r\n                IterativeParsingElementState,           // Null\r\n                IterativeParsingElementState            // Number\r\n            },\r\n            // Element\r\n            {\r\n                IterativeParsingErrorState,             // Left bracket\r\n                IterativeParsingArrayFinishState,       // Right bracket\r\n                IterativeParsingErrorState,             // Left curly bracket\r\n                IterativeParsingErrorState,             // Right curly bracket\r\n                IterativeParsingElementDelimiterState,  // Comma\r\n                IterativeParsingErrorState,             // Colon\r\n                IterativeParsingErrorState,             // String\r\n                IterativeParsingErrorState,             // False\r\n                IterativeParsingErrorState,             // True\r\n                IterativeParsingErrorState,             // Null\r\n                IterativeParsingErrorState              // Number\r\n            },\r\n            // ArrayFinish(sink state)\r\n            {\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState\r\n            },\r\n            // Single Value (sink state)\r\n            {\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,\r\n                IterativeParsingErrorState\r\n            },\r\n            // ElementDelimiter\r\n            {\r\n                IterativeParsingArrayInitialState,      // Left bracket(push Element state)\r\n                IterativeParsingArrayFinishState,       // Right bracket\r\n                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)\r\n                IterativeParsingErrorState,             // Right curly bracket\r\n                IterativeParsingErrorState,             // Comma\r\n                IterativeParsingErrorState,             // Colon\r\n                IterativeParsingElementState,           // String\r\n                IterativeParsingElementState,           // False\r\n                IterativeParsingElementState,           // True\r\n                IterativeParsingElementState,           // Null\r\n                IterativeParsingElementState            // Number\r\n            },\r\n            // MemberDelimiter\r\n            {\r\n                IterativeParsingErrorState,         // Left bracket\r\n                IterativeParsingErrorState,         // Right bracket\r\n                IterativeParsingErrorState,         // Left curly bracket\r\n                IterativeParsingObjectFinishState,  // Right curly bracket\r\n                IterativeParsingErrorState,         // Comma\r\n                IterativeParsingErrorState,         // Colon\r\n                IterativeParsingMemberKeyState,     // String\r\n                IterativeParsingErrorState,         // False\r\n                IterativeParsingErrorState,         // True\r\n                IterativeParsingErrorState,         // Null\r\n                IterativeParsingErrorState          // Number\r\n            },\r\n            // KeyValueDelimiter\r\n            {\r\n                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)\r\n                IterativeParsingErrorState,             // Right bracket\r\n                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)\r\n                IterativeParsingErrorState,             // Right curly bracket\r\n                IterativeParsingErrorState,             // Comma\r\n                IterativeParsingErrorState,             // Colon\r\n                IterativeParsingMemberValueState,       // String\r\n                IterativeParsingMemberValueState,       // False\r\n                IterativeParsingMemberValueState,       // True\r\n                IterativeParsingMemberValueState,       // Null\r\n                IterativeParsingMemberValueState        // Number\r\n            },\r\n        }; // End of G\r\n\r\n        return static_cast<IterativeParsingState>(G[state][token]);\r\n    }\r\n\r\n    // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().\r\n    // May return a new state on state pop.\r\n    template <unsigned parseFlags, typename InputStream, typename Handler>\r\n    RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {\r\n        (void)token;\r\n\r\n        switch (dst) {\r\n        case IterativeParsingErrorState:\r\n            return dst;\r\n\r\n        case IterativeParsingObjectInitialState:\r\n        case IterativeParsingArrayInitialState:\r\n        {\r\n            // Push the state(Element or MemeberValue) if we are nested in another array or value of member.\r\n            // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.\r\n            IterativeParsingState n = src;\r\n            if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)\r\n                n = IterativeParsingElementState;\r\n            else if (src == IterativeParsingKeyValueDelimiterState)\r\n                n = IterativeParsingMemberValueState;\r\n            // Push current state.\r\n            *stack_.template Push<SizeType>(1) = n;\r\n            // Initialize and push the member/element count.\r\n            *stack_.template Push<SizeType>(1) = 0;\r\n            // Call handler\r\n            bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();\r\n            // On handler short circuits the parsing.\r\n            if (!hr) {\r\n                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());\r\n                return IterativeParsingErrorState;\r\n            }\r\n            else {\r\n                is.Take();\r\n                return dst;\r\n            }\r\n        }\r\n\r\n        case IterativeParsingMemberKeyState:\r\n            ParseString<parseFlags>(is, handler, true);\r\n            if (HasParseError())\r\n                return IterativeParsingErrorState;\r\n            else\r\n                return dst;\r\n\r\n        case IterativeParsingKeyValueDelimiterState:\r\n            RAPIDJSON_ASSERT(token == ColonToken);\r\n            is.Take();\r\n            return dst;\r\n\r\n        case IterativeParsingMemberValueState:\r\n            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.\r\n            ParseValue<parseFlags>(is, handler);\r\n            if (HasParseError()) {\r\n                return IterativeParsingErrorState;\r\n            }\r\n            return dst;\r\n\r\n        case IterativeParsingElementState:\r\n            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.\r\n            ParseValue<parseFlags>(is, handler);\r\n            if (HasParseError()) {\r\n                return IterativeParsingErrorState;\r\n            }\r\n            return dst;\r\n\r\n        case IterativeParsingMemberDelimiterState:\r\n        case IterativeParsingElementDelimiterState:\r\n            is.Take();\r\n            // Update member/element count.\r\n            *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;\r\n            return dst;\r\n\r\n        case IterativeParsingObjectFinishState:\r\n        {\r\n            // Transit from delimiter is only allowed when trailing commas are enabled\r\n            if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {\r\n                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());\r\n                return IterativeParsingErrorState;\r\n            }\r\n            // Get member count.\r\n            SizeType c = *stack_.template Pop<SizeType>(1);\r\n            // If the object is not empty, count the last member.\r\n            if (src == IterativeParsingMemberValueState)\r\n                ++c;\r\n            // Restore the state.\r\n            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));\r\n            // Transit to Finish state if this is the topmost scope.\r\n            if (n == IterativeParsingStartState)\r\n                n = IterativeParsingFinishState;\r\n            // Call handler\r\n            bool hr = handler.EndObject(c);\r\n            // On handler short circuits the parsing.\r\n            if (!hr) {\r\n                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());\r\n                return IterativeParsingErrorState;\r\n            }\r\n            else {\r\n                is.Take();\r\n                return n;\r\n            }\r\n        }\r\n\r\n        case IterativeParsingArrayFinishState:\r\n        {\r\n            // Transit from delimiter is only allowed when trailing commas are enabled\r\n            if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {\r\n                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());\r\n                return IterativeParsingErrorState;\r\n            }\r\n            // Get element count.\r\n            SizeType c = *stack_.template Pop<SizeType>(1);\r\n            // If the array is not empty, count the last element.\r\n            if (src == IterativeParsingElementState)\r\n                ++c;\r\n            // Restore the state.\r\n            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));\r\n            // Transit to Finish state if this is the topmost scope.\r\n            if (n == IterativeParsingStartState)\r\n                n = IterativeParsingFinishState;\r\n            // Call handler\r\n            bool hr = handler.EndArray(c);\r\n            // On handler short circuits the parsing.\r\n            if (!hr) {\r\n                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());\r\n                return IterativeParsingErrorState;\r\n            }\r\n            else {\r\n                is.Take();\r\n                return n;\r\n            }\r\n        }\r\n\r\n        default:\r\n            // This branch is for IterativeParsingValueState actually.\r\n            // Use `default:` rather than\r\n            // `case IterativeParsingValueState:` is for code coverage.\r\n\r\n            // The IterativeParsingStartState is not enumerated in this switch-case.\r\n            // It is impossible for that case. And it can be caught by following assertion.\r\n\r\n            // The IterativeParsingFinishState is not enumerated in this switch-case either.\r\n            // It is a \"derivative\" state which cannot triggered from Predict() directly.\r\n            // Therefore it cannot happen here. And it can be caught by following assertion.\r\n            RAPIDJSON_ASSERT(dst == IterativeParsingValueState);\r\n\r\n            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.\r\n            ParseValue<parseFlags>(is, handler);\r\n            if (HasParseError()) {\r\n                return IterativeParsingErrorState;\r\n            }\r\n            return IterativeParsingFinishState;\r\n        }\r\n    }\r\n\r\n    template <typename InputStream>\r\n    void HandleError(IterativeParsingState src, InputStream& is) {\r\n        if (HasParseError()) {\r\n            // Error flag has been set.\r\n            return;\r\n        }\r\n\r\n        switch (src) {\r\n        case IterativeParsingStartState:            RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;\r\n        case IterativeParsingFinishState:           RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;\r\n        case IterativeParsingObjectInitialState:\r\n        case IterativeParsingMemberDelimiterState:  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;\r\n        case IterativeParsingMemberKeyState:        RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;\r\n        case IterativeParsingMemberValueState:      RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;\r\n        case IterativeParsingKeyValueDelimiterState:\r\n        case IterativeParsingArrayInitialState:\r\n        case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;\r\n        default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;\r\n        }\r\n    }\r\n\r\n    RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) {\r\n        return s >= IterativeParsingElementDelimiterState;\r\n    }\r\n    \r\n    RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) {\r\n        return s <= IterativeParsingErrorState;\r\n    }\r\n    \r\n    template <unsigned parseFlags, typename InputStream, typename Handler>\r\n    ParseResult IterativeParse(InputStream& is, Handler& handler) {\r\n        parseResult_.Clear();\r\n        ClearStackOnExit scope(*this);\r\n        IterativeParsingState state = IterativeParsingStartState;\r\n        \r\n        SkipWhitespaceAndComments<parseFlags>(is);\r\n        RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n        while (is.Peek() != '\\0') {\r\n            Token t = Tokenize(is.Peek());\r\n            IterativeParsingState n = Predict(state, t);\r\n            IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);\r\n            \r\n            if (d == IterativeParsingErrorState) {\r\n                HandleError(state, is);\r\n                break;\r\n            }\r\n            \r\n            state = d;\r\n            \r\n            // Do not further consume streams if a root JSON has been parsed.\r\n            if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)\r\n                break;\r\n            \r\n            SkipWhitespaceAndComments<parseFlags>(is);\r\n            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);\r\n        }\r\n        \r\n        // Handle the end of file.\r\n        if (state != IterativeParsingFinishState)\r\n            HandleError(state, is);\r\n        \r\n        return parseResult_;\r\n    }\r\n\r\n    static const size_t kDefaultStackCapacity = 256;    //!< Default stack capacity in bytes for storing a single decoded string.\r\n    internal::Stack<StackAllocator> stack_;  //!< A stack for storing decoded string temporarily during non-destructive parsing.\r\n    ParseResult parseResult_;\r\n    IterativeParsingState state_;\r\n}; // class GenericReader\r\n\r\n//! Reader with UTF8 encoding and default allocator.\r\ntypedef GenericReader<UTF8<>, UTF8<> > Reader;\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n\r\n#ifdef __GNUC__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_READER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/schema.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available->\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License-> You may obtain a copy of the License at\r\n//\r\n// http://opensource->org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied-> See the License for the \r\n// specific language governing permissions and limitations under the License->\r\n\r\n#ifndef RAPIDJSON_SCHEMA_H_\r\n#define RAPIDJSON_SCHEMA_H_\r\n\r\n#include \"document.h\"\r\n#include \"pointer.h\"\r\n#include \"stringbuffer.h\"\r\n#include <cmath> // abs, floor\r\n\r\n#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)\r\n#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1\r\n#else\r\n#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0\r\n#endif\r\n\r\n#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))\r\n#define RAPIDJSON_SCHEMA_USE_STDREGEX 1\r\n#else\r\n#define RAPIDJSON_SCHEMA_USE_STDREGEX 0\r\n#endif\r\n\r\n#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX\r\n#include \"internal/regex.h\"\r\n#elif RAPIDJSON_SCHEMA_USE_STDREGEX\r\n#include <regex>\r\n#endif\r\n\r\n#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX\r\n#define RAPIDJSON_SCHEMA_HAS_REGEX 1\r\n#else\r\n#define RAPIDJSON_SCHEMA_HAS_REGEX 0\r\n#endif\r\n\r\n#ifndef RAPIDJSON_SCHEMA_VERBOSE\r\n#define RAPIDJSON_SCHEMA_VERBOSE 0\r\n#endif\r\n\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n#include \"stringbuffer.h\"\r\n#endif\r\n\r\nRAPIDJSON_DIAG_PUSH\r\n\r\n#if defined(__GNUC__)\r\nRAPIDJSON_DIAG_OFF(effc++)\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_OFF(weak-vtables)\r\nRAPIDJSON_DIAG_OFF(exit-time-destructors)\r\nRAPIDJSON_DIAG_OFF(c++98-compat-pedantic)\r\nRAPIDJSON_DIAG_OFF(variadic-macros)\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Verbose Utilities\r\n\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n\r\nnamespace internal {\r\n\r\ninline void PrintInvalidKeyword(const char* keyword) {\r\n    printf(\"Fail keyword: %s\\n\", keyword);\r\n}\r\n\r\ninline void PrintInvalidKeyword(const wchar_t* keyword) {\r\n    wprintf(L\"Fail keyword: %ls\\n\", keyword);\r\n}\r\n\r\ninline void PrintInvalidDocument(const char* document) {\r\n    printf(\"Fail document: %s\\n\\n\", document);\r\n}\r\n\r\ninline void PrintInvalidDocument(const wchar_t* document) {\r\n    wprintf(L\"Fail document: %ls\\n\\n\", document);\r\n}\r\n\r\ninline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {\r\n    printf(\"S: %*s%s\\nD: %*s%s\\n\\n\", depth * 4, \" \", s, depth * 4, \" \", d);\r\n}\r\n\r\ninline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {\r\n    wprintf(L\"S: %*ls%ls\\nD: %*ls%ls\\n\\n\", depth * 4, L\" \", s, depth * 4, L\" \", d);\r\n}\r\n\r\n} // namespace internal\r\n\r\n#endif // RAPIDJSON_SCHEMA_VERBOSE\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// RAPIDJSON_INVALID_KEYWORD_RETURN\r\n\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)\r\n#else\r\n#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)\r\n#endif\r\n\r\n#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\\\r\nRAPIDJSON_MULTILINEMACRO_BEGIN\\\r\n    context.invalidKeyword = keyword.GetString();\\\r\n    RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\\\r\n    return false;\\\r\nRAPIDJSON_MULTILINEMACRO_END\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Forward declarations\r\n\r\ntemplate <typename ValueType, typename Allocator>\r\nclass GenericSchemaDocument;\r\n\r\nnamespace internal {\r\n\r\ntemplate <typename SchemaDocumentType>\r\nclass Schema;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// ISchemaValidator\r\n\r\nclass ISchemaValidator {\r\npublic:\r\n    virtual ~ISchemaValidator() {}\r\n    virtual bool IsValid() const = 0;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// ISchemaStateFactory\r\n\r\ntemplate <typename SchemaType>\r\nclass ISchemaStateFactory {\r\npublic:\r\n    virtual ~ISchemaStateFactory() {}\r\n    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;\r\n    virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;\r\n    virtual void* CreateHasher() = 0;\r\n    virtual uint64_t GetHashCode(void* hasher) = 0;\r\n    virtual void DestroryHasher(void* hasher) = 0;\r\n    virtual void* MallocState(size_t size) = 0;\r\n    virtual void FreeState(void* p) = 0;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// IValidationErrorHandler\r\n\r\ntemplate <typename SchemaType>\r\nclass IValidationErrorHandler {\r\npublic:\r\n    typedef typename SchemaType::Ch Ch;\r\n    typedef typename SchemaType::SValue SValue;\r\n\r\n    virtual ~IValidationErrorHandler() {}\r\n\r\n    virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0;\r\n    virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0;\r\n    virtual void NotMultipleOf(double actual, const SValue& expected) = 0;\r\n    virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0;\r\n    virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0;\r\n    virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0;\r\n    virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0;\r\n    virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0;\r\n    virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0;\r\n\r\n    virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0;\r\n    virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0;\r\n    virtual void DoesNotMatch(const Ch* str, SizeType length) = 0;\r\n\r\n    virtual void DisallowedItem(SizeType index) = 0;\r\n    virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0;\r\n    virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0;\r\n    virtual void DuplicateItems(SizeType index1, SizeType index2) = 0;\r\n\r\n    virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0;\r\n    virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0;\r\n    virtual void StartMissingProperties() = 0;\r\n    virtual void AddMissingProperty(const SValue& name) = 0;\r\n    virtual bool EndMissingProperties() = 0;\r\n    virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0;\r\n    virtual void DisallowedProperty(const Ch* name, SizeType length) = 0;\r\n\r\n    virtual void StartDependencyErrors() = 0;\r\n    virtual void StartMissingDependentProperties() = 0;\r\n    virtual void AddMissingDependentProperty(const SValue& targetName) = 0;\r\n    virtual void EndMissingDependentProperties(const SValue& sourceName) = 0;\r\n    virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0;\r\n    virtual bool EndDependencyErrors() = 0;\r\n\r\n    virtual void DisallowedValue() = 0;\r\n    virtual void StartDisallowedType() = 0;\r\n    virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0;\r\n    virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0;\r\n    virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0;\r\n    virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;\r\n    virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0;\r\n    virtual void Disallowed() = 0;\r\n};\r\n\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Hasher\r\n\r\n// For comparison of compound value\r\ntemplate<typename Encoding, typename Allocator>\r\nclass Hasher {\r\npublic:\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}\r\n\r\n    bool Null() { return WriteType(kNullType); }\r\n    bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }\r\n    bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }\r\n    bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }\r\n    bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }\r\n    bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }\r\n    bool Double(double d) { \r\n        Number n; \r\n        if (d < 0) n.u.i = static_cast<int64_t>(d);\r\n        else       n.u.u = static_cast<uint64_t>(d); \r\n        n.d = d;\r\n        return WriteNumber(n);\r\n    }\r\n\r\n    bool RawNumber(const Ch* str, SizeType len, bool) {\r\n        WriteBuffer(kNumberType, str, len * sizeof(Ch));\r\n        return true;\r\n    }\r\n\r\n    bool String(const Ch* str, SizeType len, bool) {\r\n        WriteBuffer(kStringType, str, len * sizeof(Ch));\r\n        return true;\r\n    }\r\n\r\n    bool StartObject() { return true; }\r\n    bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }\r\n    bool EndObject(SizeType memberCount) { \r\n        uint64_t h = Hash(0, kObjectType);\r\n        uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);\r\n        for (SizeType i = 0; i < memberCount; i++)\r\n            h ^= Hash(kv[i * 2], kv[i * 2 + 1]);  // Use xor to achieve member order insensitive\r\n        *stack_.template Push<uint64_t>() = h;\r\n        return true;\r\n    }\r\n    \r\n    bool StartArray() { return true; }\r\n    bool EndArray(SizeType elementCount) { \r\n        uint64_t h = Hash(0, kArrayType);\r\n        uint64_t* e = stack_.template Pop<uint64_t>(elementCount);\r\n        for (SizeType i = 0; i < elementCount; i++)\r\n            h = Hash(h, e[i]); // Use hash to achieve element order sensitive\r\n        *stack_.template Push<uint64_t>() = h;\r\n        return true;\r\n    }\r\n\r\n    bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }\r\n\r\n    uint64_t GetHashCode() const {\r\n        RAPIDJSON_ASSERT(IsValid());\r\n        return *stack_.template Top<uint64_t>();\r\n    }\r\n\r\nprivate:\r\n    static const size_t kDefaultSize = 256;\r\n    struct Number {\r\n        union U {\r\n            uint64_t u;\r\n            int64_t i;\r\n        }u;\r\n        double d;\r\n    };\r\n\r\n    bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }\r\n    \r\n    bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }\r\n    \r\n    bool WriteBuffer(Type type, const void* data, size_t len) {\r\n        // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/\r\n        uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);\r\n        const unsigned char* d = static_cast<const unsigned char*>(data);\r\n        for (size_t i = 0; i < len; i++)\r\n            h = Hash(h, d[i]);\r\n        *stack_.template Push<uint64_t>() = h;\r\n        return true;\r\n    }\r\n\r\n    static uint64_t Hash(uint64_t h, uint64_t d) {\r\n        static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);\r\n        h ^= d;\r\n        h *= kPrime;\r\n        return h;\r\n    }\r\n\r\n    Stack<Allocator> stack_;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// SchemaValidationContext\r\n\r\ntemplate <typename SchemaDocumentType>\r\nstruct SchemaValidationContext {\r\n    typedef Schema<SchemaDocumentType> SchemaType;\r\n    typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;\r\n    typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;\r\n    typedef typename SchemaType::ValueType ValueType;\r\n    typedef typename ValueType::Ch Ch;\r\n\r\n    enum PatternValidatorType {\r\n        kPatternValidatorOnly,\r\n        kPatternValidatorWithProperty,\r\n        kPatternValidatorWithAdditionalProperty\r\n    };\r\n\r\n    SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) :\r\n        factory(f),\r\n        error_handler(eh),\r\n        schema(s),\r\n        valueSchema(),\r\n        invalidKeyword(),\r\n        hasher(),\r\n        arrayElementHashCodes(),\r\n        validators(),\r\n        validatorCount(),\r\n        patternPropertiesValidators(),\r\n        patternPropertiesValidatorCount(),\r\n        patternPropertiesSchemas(),\r\n        patternPropertiesSchemaCount(),\r\n        valuePatternValidatorType(kPatternValidatorOnly),\r\n        propertyExist(),\r\n        inArray(false),\r\n        valueUniqueness(false),\r\n        arrayUniqueness(false)\r\n    {\r\n    }\r\n\r\n    ~SchemaValidationContext() {\r\n        if (hasher)\r\n            factory.DestroryHasher(hasher);\r\n        if (validators) {\r\n            for (SizeType i = 0; i < validatorCount; i++)\r\n                factory.DestroySchemaValidator(validators[i]);\r\n            factory.FreeState(validators);\r\n        }\r\n        if (patternPropertiesValidators) {\r\n            for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)\r\n                factory.DestroySchemaValidator(patternPropertiesValidators[i]);\r\n            factory.FreeState(patternPropertiesValidators);\r\n        }\r\n        if (patternPropertiesSchemas)\r\n            factory.FreeState(patternPropertiesSchemas);\r\n        if (propertyExist)\r\n            factory.FreeState(propertyExist);\r\n    }\r\n\r\n    SchemaValidatorFactoryType& factory;\r\n    ErrorHandlerType& error_handler;\r\n    const SchemaType* schema;\r\n    const SchemaType* valueSchema;\r\n    const Ch* invalidKeyword;\r\n    void* hasher; // Only validator access\r\n    void* arrayElementHashCodes; // Only validator access this\r\n    ISchemaValidator** validators;\r\n    SizeType validatorCount;\r\n    ISchemaValidator** patternPropertiesValidators;\r\n    SizeType patternPropertiesValidatorCount;\r\n    const SchemaType** patternPropertiesSchemas;\r\n    SizeType patternPropertiesSchemaCount;\r\n    PatternValidatorType valuePatternValidatorType;\r\n    PatternValidatorType objectPatternValidatorType;\r\n    SizeType arrayElementIndex;\r\n    bool* propertyExist;\r\n    bool inArray;\r\n    bool valueUniqueness;\r\n    bool arrayUniqueness;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// Schema\r\n\r\ntemplate <typename SchemaDocumentType>\r\nclass Schema {\r\npublic:\r\n    typedef typename SchemaDocumentType::ValueType ValueType;\r\n    typedef typename SchemaDocumentType::AllocatorType AllocatorType;\r\n    typedef typename SchemaDocumentType::PointerType PointerType;\r\n    typedef typename ValueType::EncodingType EncodingType;\r\n    typedef typename EncodingType::Ch Ch;\r\n    typedef SchemaValidationContext<SchemaDocumentType> Context;\r\n    typedef Schema<SchemaDocumentType> SchemaType;\r\n    typedef GenericValue<EncodingType, AllocatorType> SValue;\r\n    typedef IValidationErrorHandler<Schema> ErrorHandler;\r\n    friend class GenericSchemaDocument<ValueType, AllocatorType>;\r\n\r\n    Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :\r\n        allocator_(allocator),\r\n        uri_(schemaDocument->GetURI(), *allocator),\r\n        pointer_(p),\r\n        typeless_(schemaDocument->GetTypeless()),\r\n        enum_(),\r\n        enumCount_(),\r\n        not_(),\r\n        type_((1 << kTotalSchemaType) - 1), // typeless\r\n        validatorCount_(),\r\n        notValidatorIndex_(),\r\n        properties_(),\r\n        additionalPropertiesSchema_(),\r\n        patternProperties_(),\r\n        patternPropertyCount_(),\r\n        propertyCount_(),\r\n        minProperties_(),\r\n        maxProperties_(SizeType(~0)),\r\n        additionalProperties_(true),\r\n        hasDependencies_(),\r\n        hasRequired_(),\r\n        hasSchemaDependencies_(),\r\n        additionalItemsSchema_(),\r\n        itemsList_(),\r\n        itemsTuple_(),\r\n        itemsTupleCount_(),\r\n        minItems_(),\r\n        maxItems_(SizeType(~0)),\r\n        additionalItems_(true),\r\n        uniqueItems_(false),\r\n        pattern_(),\r\n        minLength_(0),\r\n        maxLength_(~SizeType(0)),\r\n        exclusiveMinimum_(false),\r\n        exclusiveMaximum_(false)\r\n    {\r\n        typedef typename SchemaDocumentType::ValueType ValueType;\r\n        typedef typename ValueType::ConstValueIterator ConstValueIterator;\r\n        typedef typename ValueType::ConstMemberIterator ConstMemberIterator;\r\n\r\n        if (!value.IsObject())\r\n            return;\r\n\r\n        if (const ValueType* v = GetMember(value, GetTypeString())) {\r\n            type_ = 0;\r\n            if (v->IsString())\r\n                AddType(*v);\r\n            else if (v->IsArray())\r\n                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)\r\n                    AddType(*itr);\r\n        }\r\n\r\n        if (const ValueType* v = GetMember(value, GetEnumString()))\r\n            if (v->IsArray() && v->Size() > 0) {\r\n                enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));\r\n                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {\r\n                    typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;\r\n                    char buffer[256 + 24];\r\n                    MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));\r\n                    EnumHasherType h(&hasherAllocator, 256);\r\n                    itr->Accept(h);\r\n                    enum_[enumCount_++] = h.GetHashCode();\r\n                }\r\n            }\r\n\r\n        if (schemaDocument) {\r\n            AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);\r\n            AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);\r\n            AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);\r\n        }\r\n\r\n        if (const ValueType* v = GetMember(value, GetNotString())) {\r\n            schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);\r\n            notValidatorIndex_ = validatorCount_;\r\n            validatorCount_++;\r\n        }\r\n\r\n        // Object\r\n\r\n        const ValueType* properties = GetMember(value, GetPropertiesString());\r\n        const ValueType* required = GetMember(value, GetRequiredString());\r\n        const ValueType* dependencies = GetMember(value, GetDependenciesString());\r\n        {\r\n            // Gather properties from properties/required/dependencies\r\n            SValue allProperties(kArrayType);\r\n\r\n            if (properties && properties->IsObject())\r\n                for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)\r\n                    AddUniqueElement(allProperties, itr->name);\r\n            \r\n            if (required && required->IsArray())\r\n                for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)\r\n                    if (itr->IsString())\r\n                        AddUniqueElement(allProperties, *itr);\r\n\r\n            if (dependencies && dependencies->IsObject())\r\n                for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {\r\n                    AddUniqueElement(allProperties, itr->name);\r\n                    if (itr->value.IsArray())\r\n                        for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)\r\n                            if (i->IsString())\r\n                                AddUniqueElement(allProperties, *i);\r\n                }\r\n\r\n            if (allProperties.Size() > 0) {\r\n                propertyCount_ = allProperties.Size();\r\n                properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));\r\n                for (SizeType i = 0; i < propertyCount_; i++) {\r\n                    new (&properties_[i]) Property();\r\n                    properties_[i].name = allProperties[i];\r\n                    properties_[i].schema = typeless_;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (properties && properties->IsObject()) {\r\n            PointerType q = p.Append(GetPropertiesString(), allocator_);\r\n            for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {\r\n                SizeType index;\r\n                if (FindPropertyIndex(itr->name, &index))\r\n                    schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);\r\n            }\r\n        }\r\n\r\n        if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {\r\n            PointerType q = p.Append(GetPatternPropertiesString(), allocator_);\r\n            patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));\r\n            patternPropertyCount_ = 0;\r\n\r\n            for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {\r\n                new (&patternProperties_[patternPropertyCount_]) PatternProperty();\r\n                patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);\r\n                schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);\r\n                patternPropertyCount_++;\r\n            }\r\n        }\r\n\r\n        if (required && required->IsArray())\r\n            for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)\r\n                if (itr->IsString()) {\r\n                    SizeType index;\r\n                    if (FindPropertyIndex(*itr, &index)) {\r\n                        properties_[index].required = true;\r\n                        hasRequired_ = true;\r\n                    }\r\n                }\r\n\r\n        if (dependencies && dependencies->IsObject()) {\r\n            PointerType q = p.Append(GetDependenciesString(), allocator_);\r\n            hasDependencies_ = true;\r\n            for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {\r\n                SizeType sourceIndex;\r\n                if (FindPropertyIndex(itr->name, &sourceIndex)) {\r\n                    if (itr->value.IsArray()) {\r\n                        properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));\r\n                        std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);\r\n                        for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {\r\n                            SizeType targetIndex;\r\n                            if (FindPropertyIndex(*targetItr, &targetIndex))\r\n                                properties_[sourceIndex].dependencies[targetIndex] = true;\r\n                        }\r\n                    }\r\n                    else if (itr->value.IsObject()) {\r\n                        hasSchemaDependencies_ = true;\r\n                        schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);\r\n                        properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;\r\n                        validatorCount_++;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {\r\n            if (v->IsBool())\r\n                additionalProperties_ = v->GetBool();\r\n            else if (v->IsObject())\r\n                schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);\r\n        }\r\n\r\n        AssignIfExist(minProperties_, value, GetMinPropertiesString());\r\n        AssignIfExist(maxProperties_, value, GetMaxPropertiesString());\r\n\r\n        // Array\r\n        if (const ValueType* v = GetMember(value, GetItemsString())) {\r\n            PointerType q = p.Append(GetItemsString(), allocator_);\r\n            if (v->IsObject()) // List validation\r\n                schemaDocument->CreateSchema(&itemsList_, q, *v, document);\r\n            else if (v->IsArray()) { // Tuple validation\r\n                itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));\r\n                SizeType index = 0;\r\n                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)\r\n                    schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);\r\n            }\r\n        }\r\n\r\n        AssignIfExist(minItems_, value, GetMinItemsString());\r\n        AssignIfExist(maxItems_, value, GetMaxItemsString());\r\n\r\n        if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {\r\n            if (v->IsBool())\r\n                additionalItems_ = v->GetBool();\r\n            else if (v->IsObject())\r\n                schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);\r\n        }\r\n\r\n        AssignIfExist(uniqueItems_, value, GetUniqueItemsString());\r\n\r\n        // String\r\n        AssignIfExist(minLength_, value, GetMinLengthString());\r\n        AssignIfExist(maxLength_, value, GetMaxLengthString());\r\n\r\n        if (const ValueType* v = GetMember(value, GetPatternString()))\r\n            pattern_ = CreatePattern(*v);\r\n\r\n        // Number\r\n        if (const ValueType* v = GetMember(value, GetMinimumString()))\r\n            if (v->IsNumber())\r\n                minimum_.CopyFrom(*v, *allocator_);\r\n\r\n        if (const ValueType* v = GetMember(value, GetMaximumString()))\r\n            if (v->IsNumber())\r\n                maximum_.CopyFrom(*v, *allocator_);\r\n\r\n        AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());\r\n        AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());\r\n\r\n        if (const ValueType* v = GetMember(value, GetMultipleOfString()))\r\n            if (v->IsNumber() && v->GetDouble() > 0.0)\r\n                multipleOf_.CopyFrom(*v, *allocator_);\r\n    }\r\n\r\n    ~Schema() {\r\n        AllocatorType::Free(enum_);\r\n        if (properties_) {\r\n            for (SizeType i = 0; i < propertyCount_; i++)\r\n                properties_[i].~Property();\r\n            AllocatorType::Free(properties_);\r\n        }\r\n        if (patternProperties_) {\r\n            for (SizeType i = 0; i < patternPropertyCount_; i++)\r\n                patternProperties_[i].~PatternProperty();\r\n            AllocatorType::Free(patternProperties_);\r\n        }\r\n        AllocatorType::Free(itemsTuple_);\r\n#if RAPIDJSON_SCHEMA_HAS_REGEX\r\n        if (pattern_) {\r\n            pattern_->~RegexType();\r\n            AllocatorType::Free(pattern_);\r\n        }\r\n#endif\r\n    }\r\n\r\n    const SValue& GetURI() const {\r\n        return uri_;\r\n    }\r\n\r\n    const PointerType& GetPointer() const {\r\n        return pointer_;\r\n    }\r\n\r\n    bool BeginValue(Context& context) const {\r\n        if (context.inArray) {\r\n            if (uniqueItems_)\r\n                context.valueUniqueness = true;\r\n\r\n            if (itemsList_)\r\n                context.valueSchema = itemsList_;\r\n            else if (itemsTuple_) {\r\n                if (context.arrayElementIndex < itemsTupleCount_)\r\n                    context.valueSchema = itemsTuple_[context.arrayElementIndex];\r\n                else if (additionalItemsSchema_)\r\n                    context.valueSchema = additionalItemsSchema_;\r\n                else if (additionalItems_)\r\n                    context.valueSchema = typeless_;\r\n                else {\r\n                    context.error_handler.DisallowedItem(context.arrayElementIndex);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());\r\n                }\r\n            }\r\n            else\r\n                context.valueSchema = typeless_;\r\n\r\n            context.arrayElementIndex++;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {\r\n        if (context.patternPropertiesValidatorCount > 0) {\r\n            bool otherValid = false;\r\n            SizeType count = context.patternPropertiesValidatorCount;\r\n            if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)\r\n                otherValid = context.patternPropertiesValidators[--count]->IsValid();\r\n\r\n            bool patternValid = true;\r\n            for (SizeType i = 0; i < count; i++)\r\n                if (!context.patternPropertiesValidators[i]->IsValid()) {\r\n                    patternValid = false;\r\n                    break;\r\n                }\r\n\r\n            if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {\r\n                if (!patternValid) {\r\n                    context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());\r\n                }\r\n            }\r\n            else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {\r\n                if (!patternValid || !otherValid) {\r\n                    context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());\r\n                }\r\n            }\r\n            else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty)\r\n                context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);\r\n                RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());\r\n            }\r\n        }\r\n\r\n        if (enum_) {\r\n            const uint64_t h = context.factory.GetHashCode(context.hasher);\r\n            for (SizeType i = 0; i < enumCount_; i++)\r\n                if (enum_[i] == h)\r\n                    goto foundEnum;\r\n            context.error_handler.DisallowedValue();\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());\r\n            foundEnum:;\r\n        }\r\n\r\n        if (allOf_.schemas)\r\n            for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)\r\n                if (!context.validators[i]->IsValid()) {\r\n                    context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());\r\n                }\r\n        \r\n        if (anyOf_.schemas) {\r\n            for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)\r\n                if (context.validators[i]->IsValid())\r\n                    goto foundAny;\r\n            context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());\r\n            foundAny:;\r\n        }\r\n\r\n        if (oneOf_.schemas) {\r\n            bool oneValid = false;\r\n            for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)\r\n                if (context.validators[i]->IsValid()) {\r\n                    if (oneValid) {\r\n                        context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);\r\n                        RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());\r\n                    } else\r\n                        oneValid = true;\r\n                }\r\n            if (!oneValid) {\r\n                context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);\r\n                RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());\r\n            }\r\n        }\r\n\r\n        if (not_ && context.validators[notValidatorIndex_]->IsValid()) {\r\n            context.error_handler.Disallowed();\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    bool Null(Context& context) const {\r\n        if (!(type_ & (1 << kNullSchemaType))) {\r\n            DisallowedType(context, GetNullString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n        return CreateParallelValidator(context);\r\n    }\r\n    \r\n    bool Bool(Context& context, bool) const {\r\n        if (!(type_ & (1 << kBooleanSchemaType))) {\r\n            DisallowedType(context, GetBooleanString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool Int(Context& context, int i) const {\r\n        if (!CheckInt(context, i))\r\n            return false;\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool Uint(Context& context, unsigned u) const {\r\n        if (!CheckUint(context, u))\r\n            return false;\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool Int64(Context& context, int64_t i) const {\r\n        if (!CheckInt(context, i))\r\n            return false;\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool Uint64(Context& context, uint64_t u) const {\r\n        if (!CheckUint(context, u))\r\n            return false;\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool Double(Context& context, double d) const {\r\n        if (!(type_ & (1 << kNumberSchemaType))) {\r\n            DisallowedType(context, GetNumberString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n\r\n        if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))\r\n            return false;\r\n\r\n        if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))\r\n            return false;\r\n        \r\n        if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))\r\n            return false;\r\n        \r\n        return CreateParallelValidator(context);\r\n    }\r\n    \r\n    bool String(Context& context, const Ch* str, SizeType length, bool) const {\r\n        if (!(type_ & (1 << kStringSchemaType))) {\r\n            DisallowedType(context, GetStringString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n\r\n        if (minLength_ != 0 || maxLength_ != SizeType(~0)) {\r\n            SizeType count;\r\n            if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {\r\n                if (count < minLength_) {\r\n                    context.error_handler.TooShort(str, length, minLength_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());\r\n                }\r\n                if (count > maxLength_) {\r\n                    context.error_handler.TooLong(str, length, maxLength_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());\r\n                }\r\n            }\r\n        }\r\n\r\n        if (pattern_ && !IsPatternMatch(pattern_, str, length)) {\r\n            context.error_handler.DoesNotMatch(str, length);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());\r\n        }\r\n\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool StartObject(Context& context) const {\r\n        if (!(type_ & (1 << kObjectSchemaType))) {\r\n            DisallowedType(context, GetObjectString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n\r\n        if (hasDependencies_ || hasRequired_) {\r\n            context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));\r\n            std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);\r\n        }\r\n\r\n        if (patternProperties_) { // pre-allocate schema array\r\n            SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType\r\n            context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));\r\n            context.patternPropertiesSchemaCount = 0;\r\n            std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);\r\n        }\r\n\r\n        return CreateParallelValidator(context);\r\n    }\r\n    \r\n    bool Key(Context& context, const Ch* str, SizeType len, bool) const {\r\n        if (patternProperties_) {\r\n            context.patternPropertiesSchemaCount = 0;\r\n            for (SizeType i = 0; i < patternPropertyCount_; i++)\r\n                if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {\r\n                    context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;\r\n                    context.valueSchema = typeless_;\r\n                }\r\n        }\r\n\r\n        SizeType index;\r\n        if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {\r\n            if (context.patternPropertiesSchemaCount > 0) {\r\n                context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;\r\n                context.valueSchema = typeless_;\r\n                context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;\r\n            }\r\n            else\r\n                context.valueSchema = properties_[index].schema;\r\n\r\n            if (context.propertyExist)\r\n                context.propertyExist[index] = true;\r\n\r\n            return true;\r\n        }\r\n\r\n        if (additionalPropertiesSchema_) {\r\n            if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {\r\n                context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;\r\n                context.valueSchema = typeless_;\r\n                context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;\r\n            }\r\n            else\r\n                context.valueSchema = additionalPropertiesSchema_;\r\n            return true;\r\n        }\r\n        else if (additionalProperties_) {\r\n            context.valueSchema = typeless_;\r\n            return true;\r\n        }\r\n\r\n        if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties\r\n            context.error_handler.DisallowedProperty(str, len);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    bool EndObject(Context& context, SizeType memberCount) const {\r\n        if (hasRequired_) {\r\n            context.error_handler.StartMissingProperties();\r\n            for (SizeType index = 0; index < propertyCount_; index++)\r\n                if (properties_[index].required && !context.propertyExist[index])\r\n                    context.error_handler.AddMissingProperty(properties_[index].name);\r\n            if (context.error_handler.EndMissingProperties())\r\n                RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());\r\n        }\r\n\r\n        if (memberCount < minProperties_) {\r\n            context.error_handler.TooFewProperties(memberCount, minProperties_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());\r\n        }\r\n\r\n        if (memberCount > maxProperties_) {\r\n            context.error_handler.TooManyProperties(memberCount, maxProperties_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());\r\n        }\r\n\r\n        if (hasDependencies_) {\r\n            context.error_handler.StartDependencyErrors();\r\n            for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {\r\n                const Property& source = properties_[sourceIndex];\r\n                if (context.propertyExist[sourceIndex]) {\r\n                    if (source.dependencies) {\r\n                        context.error_handler.StartMissingDependentProperties();\r\n                        for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)\r\n                            if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])\r\n                                context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);\r\n                        context.error_handler.EndMissingDependentProperties(source.name);\r\n                    }\r\n                    else if (source.dependenciesSchema) {\r\n                        ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];\r\n                        if (!dependenciesValidator->IsValid())\r\n                            context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);\r\n                    }\r\n                }\r\n            }\r\n            if (context.error_handler.EndDependencyErrors())\r\n                RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    bool StartArray(Context& context) const {\r\n        if (!(type_ & (1 << kArraySchemaType))) {\r\n            DisallowedType(context, GetArrayString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n\r\n        context.arrayElementIndex = 0;\r\n        context.inArray = true;\r\n\r\n        return CreateParallelValidator(context);\r\n    }\r\n\r\n    bool EndArray(Context& context, SizeType elementCount) const {\r\n        context.inArray = false;\r\n        \r\n        if (elementCount < minItems_) {\r\n            context.error_handler.TooFewItems(elementCount, minItems_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());\r\n        }\r\n        \r\n        if (elementCount > maxItems_) {\r\n            context.error_handler.TooManyItems(elementCount, maxItems_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    // Generate functions for string literal according to Ch\r\n#define RAPIDJSON_STRING_(name, ...) \\\r\n    static const ValueType& Get##name##String() {\\\r\n        static const Ch s[] = { __VA_ARGS__, '\\0' };\\\r\n        static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\\\r\n        return v;\\\r\n    }\r\n\r\n    RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')\r\n    RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')\r\n    RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')\r\n    RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')\r\n    RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')\r\n    RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')\r\n    RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')\r\n    RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')\r\n    RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')\r\n    RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')\r\n    RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')\r\n    RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')\r\n    RAPIDJSON_STRING_(Not, 'n', 'o', 't')\r\n    RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')\r\n    RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')\r\n    RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')\r\n    RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')\r\n    RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')\r\n    RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')\r\n    RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')\r\n    RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')\r\n    RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')\r\n    RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')\r\n    RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')\r\n    RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')\r\n    RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')\r\n    RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')\r\n    RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')\r\n    RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')\r\n    RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')\r\n    RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')\r\n    RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')\r\n    RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')\r\n\r\n#undef RAPIDJSON_STRING_\r\n\r\nprivate:\r\n    enum SchemaValueType {\r\n        kNullSchemaType,\r\n        kBooleanSchemaType,\r\n        kObjectSchemaType,\r\n        kArraySchemaType,\r\n        kStringSchemaType,\r\n        kNumberSchemaType,\r\n        kIntegerSchemaType,\r\n        kTotalSchemaType\r\n    };\r\n\r\n#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX\r\n        typedef internal::GenericRegex<EncodingType, AllocatorType> RegexType;\r\n#elif RAPIDJSON_SCHEMA_USE_STDREGEX\r\n        typedef std::basic_regex<Ch> RegexType;\r\n#else\r\n        typedef char RegexType;\r\n#endif\r\n\r\n    struct SchemaArray {\r\n        SchemaArray() : schemas(), count() {}\r\n        ~SchemaArray() { AllocatorType::Free(schemas); }\r\n        const SchemaType** schemas;\r\n        SizeType begin; // begin index of context.validators\r\n        SizeType count;\r\n    };\r\n\r\n    template <typename V1, typename V2>\r\n    void AddUniqueElement(V1& a, const V2& v) {\r\n        for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)\r\n            if (*itr == v)\r\n                return;\r\n        V1 c(v, *allocator_);\r\n        a.PushBack(c, *allocator_);\r\n    }\r\n\r\n    static const ValueType* GetMember(const ValueType& value, const ValueType& name) {\r\n        typename ValueType::ConstMemberIterator itr = value.FindMember(name);\r\n        return itr != value.MemberEnd() ? &(itr->value) : 0;\r\n    }\r\n\r\n    static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {\r\n        if (const ValueType* v = GetMember(value, name))\r\n            if (v->IsBool())\r\n                out = v->GetBool();\r\n    }\r\n\r\n    static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {\r\n        if (const ValueType* v = GetMember(value, name))\r\n            if (v->IsUint64() && v->GetUint64() <= SizeType(~0))\r\n                out = static_cast<SizeType>(v->GetUint64());\r\n    }\r\n\r\n    void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {\r\n        if (const ValueType* v = GetMember(value, name)) {\r\n            if (v->IsArray() && v->Size() > 0) {\r\n                PointerType q = p.Append(name, allocator_);\r\n                out.count = v->Size();\r\n                out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));\r\n                memset(out.schemas, 0, sizeof(Schema*)* out.count);\r\n                for (SizeType i = 0; i < out.count; i++)\r\n                    schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);\r\n                out.begin = validatorCount_;\r\n                validatorCount_ += out.count;\r\n            }\r\n        }\r\n    }\r\n\r\n#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX\r\n    template <typename ValueType>\r\n    RegexType* CreatePattern(const ValueType& value) {\r\n        if (value.IsString()) {\r\n            RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_);\r\n            if (!r->IsValid()) {\r\n                r->~RegexType();\r\n                AllocatorType::Free(r);\r\n                r = 0;\r\n            }\r\n            return r;\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {\r\n        GenericRegexSearch<RegexType> rs(*pattern);\r\n        return rs.Search(str);\r\n    }\r\n#elif RAPIDJSON_SCHEMA_USE_STDREGEX\r\n    template <typename ValueType>\r\n    RegexType* CreatePattern(const ValueType& value) {\r\n        if (value.IsString())\r\n            try {\r\n                return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);\r\n            }\r\n            catch (const std::regex_error&) {\r\n            }\r\n        return 0;\r\n    }\r\n\r\n    static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {\r\n        std::match_results<const Ch*> r;\r\n        return std::regex_search(str, str + length, r, *pattern);\r\n    }\r\n#else\r\n    template <typename ValueType>\r\n    RegexType* CreatePattern(const ValueType&) { return 0; }\r\n\r\n    static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }\r\n#endif // RAPIDJSON_SCHEMA_USE_STDREGEX\r\n\r\n    void AddType(const ValueType& type) {\r\n        if      (type == GetNullString()   ) type_ |= 1 << kNullSchemaType;\r\n        else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;\r\n        else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;\r\n        else if (type == GetArrayString()  ) type_ |= 1 << kArraySchemaType;\r\n        else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;\r\n        else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;\r\n        else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);\r\n    }\r\n\r\n    bool CreateParallelValidator(Context& context) const {\r\n        if (enum_ || context.arrayUniqueness)\r\n            context.hasher = context.factory.CreateHasher();\r\n\r\n        if (validatorCount_) {\r\n            RAPIDJSON_ASSERT(context.validators == 0);\r\n            context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));\r\n            context.validatorCount = validatorCount_;\r\n\r\n            if (allOf_.schemas)\r\n                CreateSchemaValidators(context, allOf_);\r\n\r\n            if (anyOf_.schemas)\r\n                CreateSchemaValidators(context, anyOf_);\r\n            \r\n            if (oneOf_.schemas)\r\n                CreateSchemaValidators(context, oneOf_);\r\n            \r\n            if (not_)\r\n                context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);\r\n            \r\n            if (hasSchemaDependencies_) {\r\n                for (SizeType i = 0; i < propertyCount_; i++)\r\n                    if (properties_[i].dependenciesSchema)\r\n                        context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);\r\n            }\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {\r\n        for (SizeType i = 0; i < schemas.count; i++)\r\n            context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);\r\n    }\r\n\r\n    // O(n)\r\n    bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {\r\n        SizeType len = name.GetStringLength();\r\n        const Ch* str = name.GetString();\r\n        for (SizeType index = 0; index < propertyCount_; index++)\r\n            if (properties_[index].name.GetStringLength() == len && \r\n                (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))\r\n            {\r\n                *outIndex = index;\r\n                return true;\r\n            }\r\n        return false;\r\n    }\r\n\r\n    bool CheckInt(Context& context, int64_t i) const {\r\n        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {\r\n            DisallowedType(context, GetIntegerString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n\r\n        if (!minimum_.IsNull()) {\r\n            if (minimum_.IsInt64()) {\r\n                if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {\r\n                    context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());\r\n                }\r\n            }\r\n            else if (minimum_.IsUint64()) {\r\n                context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);\r\n                RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()\r\n            }\r\n            else if (!CheckDoubleMinimum(context, static_cast<double>(i)))\r\n                return false;\r\n        }\r\n\r\n        if (!maximum_.IsNull()) {\r\n            if (maximum_.IsInt64()) {\r\n                if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {\r\n                    context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());\r\n                }\r\n            }\r\n            else if (maximum_.IsUint64()) { }\r\n                /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()\r\n            else if (!CheckDoubleMaximum(context, static_cast<double>(i)))\r\n                return false;\r\n        }\r\n\r\n        if (!multipleOf_.IsNull()) {\r\n            if (multipleOf_.IsUint64()) {\r\n                if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {\r\n                    context.error_handler.NotMultipleOf(i, multipleOf_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());\r\n                }\r\n            }\r\n            else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))\r\n                return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    bool CheckUint(Context& context, uint64_t i) const {\r\n        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {\r\n            DisallowedType(context, GetIntegerString());\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());\r\n        }\r\n\r\n        if (!minimum_.IsNull()) {\r\n            if (minimum_.IsUint64()) {\r\n                if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {\r\n                    context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());\r\n                }\r\n            }\r\n            else if (minimum_.IsInt64())\r\n                /* do nothing */; // i >= 0 > minimum.Getint64()\r\n            else if (!CheckDoubleMinimum(context, static_cast<double>(i)))\r\n                return false;\r\n        }\r\n\r\n        if (!maximum_.IsNull()) {\r\n            if (maximum_.IsUint64()) {\r\n                if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {\r\n                    context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());\r\n                }\r\n            }\r\n            else if (maximum_.IsInt64()) {\r\n                context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);\r\n                RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_\r\n            }\r\n            else if (!CheckDoubleMaximum(context, static_cast<double>(i)))\r\n                return false;\r\n        }\r\n\r\n        if (!multipleOf_.IsNull()) {\r\n            if (multipleOf_.IsUint64()) {\r\n                if (i % multipleOf_.GetUint64() != 0) {\r\n                    context.error_handler.NotMultipleOf(i, multipleOf_);\r\n                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());\r\n                }\r\n            }\r\n            else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))\r\n                return false;\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    bool CheckDoubleMinimum(Context& context, double d) const {\r\n        if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {\r\n            context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());\r\n        }\r\n        return true;\r\n    }\r\n\r\n    bool CheckDoubleMaximum(Context& context, double d) const {\r\n        if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {\r\n            context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());\r\n        }\r\n        return true;\r\n    }\r\n\r\n    bool CheckDoubleMultipleOf(Context& context, double d) const {\r\n        double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());\r\n        double q = std::floor(a / b);\r\n        double r = a - q * b;\r\n        if (r > 0.0) {\r\n            context.error_handler.NotMultipleOf(d, multipleOf_);\r\n            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());\r\n        }\r\n        return true;\r\n    }\r\n\r\n    void DisallowedType(Context& context, const ValueType& actualType) const {\r\n        ErrorHandler& eh = context.error_handler;\r\n        eh.StartDisallowedType();\r\n\r\n        if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());\r\n        if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());\r\n        if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());\r\n        if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());\r\n        if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());\r\n\r\n        if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());\r\n        else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());\r\n\r\n        eh.EndDisallowedType(actualType);\r\n    }\r\n\r\n    struct Property {\r\n        Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}\r\n        ~Property() { AllocatorType::Free(dependencies); }\r\n        SValue name;\r\n        const SchemaType* schema;\r\n        const SchemaType* dependenciesSchema;\r\n        SizeType dependenciesValidatorIndex;\r\n        bool* dependencies;\r\n        bool required;\r\n    };\r\n\r\n    struct PatternProperty {\r\n        PatternProperty() : schema(), pattern() {}\r\n        ~PatternProperty() { \r\n            if (pattern) {\r\n                pattern->~RegexType();\r\n                AllocatorType::Free(pattern);\r\n            }\r\n        }\r\n        const SchemaType* schema;\r\n        RegexType* pattern;\r\n    };\r\n\r\n    AllocatorType* allocator_;\r\n    SValue uri_;\r\n    PointerType pointer_;\r\n    const SchemaType* typeless_;\r\n    uint64_t* enum_;\r\n    SizeType enumCount_;\r\n    SchemaArray allOf_;\r\n    SchemaArray anyOf_;\r\n    SchemaArray oneOf_;\r\n    const SchemaType* not_;\r\n    unsigned type_; // bitmask of kSchemaType\r\n    SizeType validatorCount_;\r\n    SizeType notValidatorIndex_;\r\n\r\n    Property* properties_;\r\n    const SchemaType* additionalPropertiesSchema_;\r\n    PatternProperty* patternProperties_;\r\n    SizeType patternPropertyCount_;\r\n    SizeType propertyCount_;\r\n    SizeType minProperties_;\r\n    SizeType maxProperties_;\r\n    bool additionalProperties_;\r\n    bool hasDependencies_;\r\n    bool hasRequired_;\r\n    bool hasSchemaDependencies_;\r\n\r\n    const SchemaType* additionalItemsSchema_;\r\n    const SchemaType* itemsList_;\r\n    const SchemaType** itemsTuple_;\r\n    SizeType itemsTupleCount_;\r\n    SizeType minItems_;\r\n    SizeType maxItems_;\r\n    bool additionalItems_;\r\n    bool uniqueItems_;\r\n\r\n    RegexType* pattern_;\r\n    SizeType minLength_;\r\n    SizeType maxLength_;\r\n\r\n    SValue minimum_;\r\n    SValue maximum_;\r\n    SValue multipleOf_;\r\n    bool exclusiveMinimum_;\r\n    bool exclusiveMaximum_;\r\n};\r\n\r\ntemplate<typename Stack, typename Ch>\r\nstruct TokenHelper {\r\n    RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {\r\n        *documentStack.template Push<Ch>() = '/';\r\n        char buffer[21];\r\n        size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);\r\n        for (size_t i = 0; i < length; i++)\r\n            *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);\r\n    }\r\n};\r\n\r\n// Partial specialized version for char to prevent buffer copying.\r\ntemplate <typename Stack>\r\nstruct TokenHelper<Stack, char> {\r\n    RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {\r\n        if (sizeof(SizeType) == 4) {\r\n            char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint\r\n            *buffer++ = '/';\r\n            const char* end = internal::u32toa(index, buffer);\r\n             documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));\r\n        }\r\n        else {\r\n            char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64\r\n            *buffer++ = '/';\r\n            const char* end = internal::u64toa(index, buffer);\r\n            documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));\r\n        }\r\n    }\r\n};\r\n\r\n} // namespace internal\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// IGenericRemoteSchemaDocumentProvider\r\n\r\ntemplate <typename SchemaDocumentType>\r\nclass IGenericRemoteSchemaDocumentProvider {\r\npublic:\r\n    typedef typename SchemaDocumentType::Ch Ch;\r\n\r\n    virtual ~IGenericRemoteSchemaDocumentProvider() {}\r\n    virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericSchemaDocument\r\n\r\n//! JSON schema document.\r\n/*!\r\n    A JSON schema document is a compiled version of a JSON schema.\r\n    It is basically a tree of internal::Schema.\r\n\r\n    \\note This is an immutable class (i.e. its instance cannot be modified after construction).\r\n    \\tparam ValueT Type of JSON value (e.g. \\c Value ), which also determine the encoding.\r\n    \\tparam Allocator Allocator type for allocating memory of this document.\r\n*/\r\ntemplate <typename ValueT, typename Allocator = CrtAllocator>\r\nclass GenericSchemaDocument {\r\npublic:\r\n    typedef ValueT ValueType;\r\n    typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;\r\n    typedef Allocator AllocatorType;\r\n    typedef typename ValueType::EncodingType EncodingType;\r\n    typedef typename EncodingType::Ch Ch;\r\n    typedef internal::Schema<GenericSchemaDocument> SchemaType;\r\n    typedef GenericPointer<ValueType, Allocator> PointerType;\r\n    typedef GenericValue<EncodingType, Allocator> URIType;\r\n    friend class internal::Schema<GenericSchemaDocument>;\r\n    template <typename, typename, typename>\r\n    friend class GenericSchemaValidator;\r\n\r\n    //! Constructor.\r\n    /*!\r\n        Compile a JSON document into schema document.\r\n\r\n        \\param document A JSON document as source.\r\n        \\param uri The base URI of this schema document for purposes of violation reporting.\r\n        \\param uriLength Length of \\c name, in code points.\r\n        \\param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.\r\n        \\param allocator An optional allocator instance for allocating memory. Can be null.\r\n    */\r\n    explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,\r\n        IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :\r\n        remoteProvider_(remoteProvider),\r\n        allocator_(allocator),\r\n        ownAllocator_(),\r\n        root_(),\r\n        typeless_(),\r\n        schemaMap_(allocator, kInitialSchemaMapSize),\r\n        schemaRef_(allocator, kInitialSchemaRefSize)\r\n    {\r\n        if (!allocator_)\r\n            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();\r\n\r\n        Ch noUri[1] = {0};\r\n        uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);\r\n\r\n        typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));\r\n        new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_);\r\n\r\n        // Generate root schema, it will call CreateSchema() to create sub-schemas,\r\n        // And call AddRefSchema() if there are $ref.\r\n        CreateSchemaRecursive(&root_, PointerType(), document, document);\r\n\r\n        // Resolve $ref\r\n        while (!schemaRef_.Empty()) {\r\n            SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);\r\n            if (const SchemaType* s = GetSchema(refEntry->target)) {\r\n                if (refEntry->schema)\r\n                    *refEntry->schema = s;\r\n\r\n                // Create entry in map if not exist\r\n                if (!GetSchema(refEntry->source)) {\r\n                    new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);\r\n                }\r\n            }\r\n            else if (refEntry->schema)\r\n                *refEntry->schema = typeless_;\r\n\r\n            refEntry->~SchemaRefEntry();\r\n        }\r\n\r\n        RAPIDJSON_ASSERT(root_ != 0);\r\n\r\n        schemaRef_.ShrinkToFit(); // Deallocate all memory for ref\r\n    }\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    //! Move constructor in C++11\r\n    GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :\r\n        remoteProvider_(rhs.remoteProvider_),\r\n        allocator_(rhs.allocator_),\r\n        ownAllocator_(rhs.ownAllocator_),\r\n        root_(rhs.root_),\r\n        typeless_(rhs.typeless_),\r\n        schemaMap_(std::move(rhs.schemaMap_)),\r\n        schemaRef_(std::move(rhs.schemaRef_)),\r\n        uri_(std::move(rhs.uri_))\r\n    {\r\n        rhs.remoteProvider_ = 0;\r\n        rhs.allocator_ = 0;\r\n        rhs.ownAllocator_ = 0;\r\n        rhs.typeless_ = 0;\r\n    }\r\n#endif\r\n\r\n    //! Destructor\r\n    ~GenericSchemaDocument() {\r\n        while (!schemaMap_.Empty())\r\n            schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();\r\n\r\n        if (typeless_) {\r\n            typeless_->~SchemaType();\r\n            Allocator::Free(typeless_);\r\n        }\r\n\r\n        RAPIDJSON_DELETE(ownAllocator_);\r\n    }\r\n\r\n    const URIType& GetURI() const { return uri_; }\r\n\r\n    //! Get the root schema.\r\n    const SchemaType& GetRoot() const { return *root_; }\r\n\r\nprivate:\r\n    //! Prohibit copying\r\n    GenericSchemaDocument(const GenericSchemaDocument&);\r\n    //! Prohibit assignment\r\n    GenericSchemaDocument& operator=(const GenericSchemaDocument&);\r\n\r\n    struct SchemaRefEntry {\r\n        SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}\r\n        PointerType source;\r\n        PointerType target;\r\n        const SchemaType** schema;\r\n    };\r\n\r\n    struct SchemaEntry {\r\n        SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}\r\n        ~SchemaEntry() {\r\n            if (owned) {\r\n                schema->~SchemaType();\r\n                Allocator::Free(schema);\r\n            }\r\n        }\r\n        PointerType pointer;\r\n        SchemaType* schema;\r\n        bool owned;\r\n    };\r\n\r\n    void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {\r\n        if (schema)\r\n            *schema = typeless_;\r\n\r\n        if (v.GetType() == kObjectType) {\r\n            const SchemaType* s = GetSchema(pointer);\r\n            if (!s)\r\n                CreateSchema(schema, pointer, v, document);\r\n\r\n            for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)\r\n                CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);\r\n        }\r\n        else if (v.GetType() == kArrayType)\r\n            for (SizeType i = 0; i < v.Size(); i++)\r\n                CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);\r\n    }\r\n\r\n    void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {\r\n        RAPIDJSON_ASSERT(pointer.IsValid());\r\n        if (v.IsObject()) {\r\n            if (!HandleRefSchema(pointer, schema, v, document)) {\r\n                SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);\r\n                new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);\r\n                if (schema)\r\n                    *schema = s;\r\n            }\r\n        }\r\n    }\r\n\r\n    bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {\r\n        static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\\0' };\r\n        static const ValueType kRefValue(kRefString, 4);\r\n\r\n        typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);\r\n        if (itr == v.MemberEnd())\r\n            return false;\r\n\r\n        if (itr->value.IsString()) {\r\n            SizeType len = itr->value.GetStringLength();\r\n            if (len > 0) {\r\n                const Ch* s = itr->value.GetString();\r\n                SizeType i = 0;\r\n                while (i < len && s[i] != '#') // Find the first #\r\n                    i++;\r\n\r\n                if (i > 0) { // Remote reference, resolve immediately\r\n                    if (remoteProvider_) {\r\n                        if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) {\r\n                            PointerType pointer(&s[i], len - i, allocator_);\r\n                            if (pointer.IsValid()) {\r\n                                if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {\r\n                                    if (schema)\r\n                                        *schema = sc;\r\n                                    new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(source, const_cast<SchemaType*>(sc), false, allocator_);\r\n                                    return true;\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                else if (s[i] == '#') { // Local reference, defer resolution\r\n                    PointerType pointer(&s[i], len - i, allocator_);\r\n                    if (pointer.IsValid()) {\r\n                        if (const ValueType* nv = pointer.Get(document))\r\n                            if (HandleRefSchema(source, schema, *nv, document))\r\n                                return true;\r\n\r\n                        new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);\r\n                        return true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n\r\n    const SchemaType* GetSchema(const PointerType& pointer) const {\r\n        for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)\r\n            if (pointer == target->pointer)\r\n                return target->schema;\r\n        return 0;\r\n    }\r\n\r\n    PointerType GetPointer(const SchemaType* schema) const {\r\n        for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)\r\n            if (schema == target->schema)\r\n                return target->pointer;\r\n        return PointerType();\r\n    }\r\n\r\n    const SchemaType* GetTypeless() const { return typeless_; }\r\n\r\n    static const size_t kInitialSchemaMapSize = 64;\r\n    static const size_t kInitialSchemaRefSize = 64;\r\n\r\n    IRemoteSchemaDocumentProviderType* remoteProvider_;\r\n    Allocator *allocator_;\r\n    Allocator *ownAllocator_;\r\n    const SchemaType* root_;                //!< Root schema.\r\n    SchemaType* typeless_;\r\n    internal::Stack<Allocator> schemaMap_;  // Stores created Pointer -> Schemas\r\n    internal::Stack<Allocator> schemaRef_;  // Stores Pointer from $ref and schema which holds the $ref\r\n    URIType uri_;\r\n};\r\n\r\n//! GenericSchemaDocument using Value type.\r\ntypedef GenericSchemaDocument<Value> SchemaDocument;\r\n//! IGenericRemoteSchemaDocumentProvider using SchemaDocument.\r\ntypedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericSchemaValidator\r\n\r\n//! JSON Schema Validator.\r\n/*!\r\n    A SAX style JSON schema validator.\r\n    It uses a \\c GenericSchemaDocument to validate SAX events.\r\n    It delegates the incoming SAX events to an output handler.\r\n    The default output handler does nothing.\r\n    It can be reused multiple times by calling \\c Reset().\r\n\r\n    \\tparam SchemaDocumentType Type of schema document.\r\n    \\tparam OutputHandler Type of output handler. Default handler does nothing.\r\n    \\tparam StateAllocator Allocator for storing the internal validation states.\r\n*/\r\ntemplate <\r\n    typename SchemaDocumentType,\r\n    typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,\r\n    typename StateAllocator = CrtAllocator>\r\nclass GenericSchemaValidator :\r\n    public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>, \r\n    public internal::ISchemaValidator,\r\n    public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType>\r\n{\r\npublic:\r\n    typedef typename SchemaDocumentType::SchemaType SchemaType;\r\n    typedef typename SchemaDocumentType::PointerType PointerType;\r\n    typedef typename SchemaType::EncodingType EncodingType;\r\n    typedef typename SchemaType::SValue SValue;\r\n    typedef typename EncodingType::Ch Ch;\r\n    typedef GenericStringRef<Ch> StringRefType;\r\n    typedef GenericValue<EncodingType, StateAllocator> ValueType;\r\n\r\n    //! Constructor without output handler.\r\n    /*!\r\n        \\param schemaDocument The schema document to conform to.\r\n        \\param allocator Optional allocator for storing internal validation states.\r\n        \\param schemaStackCapacity Optional initial capacity of schema path stack.\r\n        \\param documentStackCapacity Optional initial capacity of document path stack.\r\n    */\r\n    GenericSchemaValidator(\r\n        const SchemaDocumentType& schemaDocument,\r\n        StateAllocator* allocator = 0, \r\n        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,\r\n        size_t documentStackCapacity = kDefaultDocumentStackCapacity)\r\n        :\r\n        schemaDocument_(&schemaDocument),\r\n        root_(schemaDocument.GetRoot()),\r\n        stateAllocator_(allocator),\r\n        ownStateAllocator_(0),\r\n        schemaStack_(allocator, schemaStackCapacity),\r\n        documentStack_(allocator, documentStackCapacity),\r\n        outputHandler_(0),\r\n        error_(kObjectType),\r\n        currentError_(),\r\n        missingDependents_(),\r\n        valid_(true)\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n        , depth_(0)\r\n#endif\r\n    {\r\n    }\r\n\r\n    //! Constructor with output handler.\r\n    /*!\r\n        \\param schemaDocument The schema document to conform to.\r\n        \\param allocator Optional allocator for storing internal validation states.\r\n        \\param schemaStackCapacity Optional initial capacity of schema path stack.\r\n        \\param documentStackCapacity Optional initial capacity of document path stack.\r\n    */\r\n    GenericSchemaValidator(\r\n        const SchemaDocumentType& schemaDocument,\r\n        OutputHandler& outputHandler,\r\n        StateAllocator* allocator = 0, \r\n        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,\r\n        size_t documentStackCapacity = kDefaultDocumentStackCapacity)\r\n        :\r\n        schemaDocument_(&schemaDocument),\r\n        root_(schemaDocument.GetRoot()),\r\n        stateAllocator_(allocator),\r\n        ownStateAllocator_(0),\r\n        schemaStack_(allocator, schemaStackCapacity),\r\n        documentStack_(allocator, documentStackCapacity),\r\n        outputHandler_(&outputHandler),\r\n        error_(kObjectType),\r\n        currentError_(),\r\n        missingDependents_(),\r\n        valid_(true)\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n        , depth_(0)\r\n#endif\r\n    {\r\n    }\r\n\r\n    //! Destructor.\r\n    ~GenericSchemaValidator() {\r\n        Reset();\r\n        RAPIDJSON_DELETE(ownStateAllocator_);\r\n    }\r\n\r\n    //! Reset the internal states.\r\n    void Reset() {\r\n        while (!schemaStack_.Empty())\r\n            PopSchema();\r\n        documentStack_.Clear();\r\n        error_.SetObject();\r\n        currentError_.SetNull();\r\n        missingDependents_.SetNull();\r\n        valid_ = true;\r\n    }\r\n\r\n    //! Checks whether the current state is valid.\r\n    // Implementation of ISchemaValidator\r\n    virtual bool IsValid() const { return valid_; }\r\n\r\n    //! Gets the error object.\r\n    ValueType& GetError() { return error_; }\r\n    const ValueType& GetError() const { return error_; }\r\n\r\n    //! Gets the JSON pointer pointed to the invalid schema.\r\n    PointerType GetInvalidSchemaPointer() const {\r\n        return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();\r\n    }\r\n\r\n    //! Gets the keyword of invalid schema.\r\n    const Ch* GetInvalidSchemaKeyword() const {\r\n        return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;\r\n    }\r\n\r\n    //! Gets the JSON pointer pointed to the invalid value.\r\n    PointerType GetInvalidDocumentPointer() const {\r\n        if (documentStack_.Empty()) {\r\n            return PointerType();\r\n        }\r\n        else {\r\n            return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));\r\n        }\r\n    }\r\n\r\n    void NotMultipleOf(int64_t actual, const SValue& expected) {\r\n        AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);\r\n    }\r\n    void NotMultipleOf(uint64_t actual, const SValue& expected) {\r\n        AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);\r\n    }\r\n    void NotMultipleOf(double actual, const SValue& expected) {\r\n        AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);\r\n    }\r\n    void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) {\r\n        AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,\r\n            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);\r\n    }\r\n    void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) {\r\n        AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,\r\n            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);\r\n    }\r\n    void AboveMaximum(double actual, const SValue& expected, bool exclusive) {\r\n        AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,\r\n            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);\r\n    }\r\n    void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) {\r\n        AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,\r\n            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);\r\n    }\r\n    void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) {\r\n        AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,\r\n            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);\r\n    }\r\n    void BelowMinimum(double actual, const SValue& expected, bool exclusive) {\r\n        AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,\r\n            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);\r\n    }\r\n\r\n    void TooLong(const Ch* str, SizeType length, SizeType expected) {\r\n        AddNumberError(SchemaType::GetMaxLengthString(),\r\n            ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());\r\n    }\r\n    void TooShort(const Ch* str, SizeType length, SizeType expected) {\r\n        AddNumberError(SchemaType::GetMinLengthString(),\r\n            ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());\r\n    }\r\n    void DoesNotMatch(const Ch* str, SizeType length) {\r\n        currentError_.SetObject();\r\n        currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());\r\n        AddCurrentError(SchemaType::GetPatternString());\r\n    }\r\n\r\n    void DisallowedItem(SizeType index) {\r\n        currentError_.SetObject();\r\n        currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());\r\n        AddCurrentError(SchemaType::GetAdditionalItemsString(), true);\r\n    }\r\n    void TooFewItems(SizeType actualCount, SizeType expectedCount) {\r\n        AddNumberError(SchemaType::GetMinItemsString(),\r\n            ValueType(actualCount).Move(), SValue(expectedCount).Move());\r\n    }\r\n    void TooManyItems(SizeType actualCount, SizeType expectedCount) {\r\n        AddNumberError(SchemaType::GetMaxItemsString(),\r\n            ValueType(actualCount).Move(), SValue(expectedCount).Move());\r\n    }\r\n    void DuplicateItems(SizeType index1, SizeType index2) {\r\n        ValueType duplicates(kArrayType);\r\n        duplicates.PushBack(index1, GetStateAllocator());\r\n        duplicates.PushBack(index2, GetStateAllocator());\r\n        currentError_.SetObject();\r\n        currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());\r\n        AddCurrentError(SchemaType::GetUniqueItemsString(), true);\r\n    }\r\n\r\n    void TooManyProperties(SizeType actualCount, SizeType expectedCount) {\r\n        AddNumberError(SchemaType::GetMaxPropertiesString(),\r\n            ValueType(actualCount).Move(), SValue(expectedCount).Move());\r\n    }\r\n    void TooFewProperties(SizeType actualCount, SizeType expectedCount) {\r\n        AddNumberError(SchemaType::GetMinPropertiesString(),\r\n            ValueType(actualCount).Move(), SValue(expectedCount).Move());\r\n    }\r\n    void StartMissingProperties() {\r\n        currentError_.SetArray();\r\n    }\r\n    void AddMissingProperty(const SValue& name) {\r\n        currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());\r\n    }\r\n    bool EndMissingProperties() {\r\n        if (currentError_.Empty())\r\n            return false;\r\n        ValueType error(kObjectType);\r\n        error.AddMember(GetMissingString(), currentError_, GetStateAllocator());\r\n        currentError_ = error;\r\n        AddCurrentError(SchemaType::GetRequiredString());\r\n        return true;\r\n    }\r\n    void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) {\r\n        for (SizeType i = 0; i < count; ++i)\r\n            MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());\r\n    }\r\n    void DisallowedProperty(const Ch* name, SizeType length) {\r\n        currentError_.SetObject();\r\n        currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());\r\n        AddCurrentError(SchemaType::GetAdditionalPropertiesString(), true);\r\n    }\r\n\r\n    void StartDependencyErrors() {\r\n        currentError_.SetObject();\r\n    }\r\n    void StartMissingDependentProperties() {\r\n        missingDependents_.SetArray();\r\n    }\r\n    void AddMissingDependentProperty(const SValue& targetName) {\r\n        missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());\r\n    }\r\n    void EndMissingDependentProperties(const SValue& sourceName) {\r\n        if (!missingDependents_.Empty())\r\n            currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),\r\n                missingDependents_, GetStateAllocator());\r\n    }\r\n    void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) {\r\n        currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),\r\n            static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());\r\n    }\r\n    bool EndDependencyErrors() {\r\n        if (currentError_.ObjectEmpty())\r\n            return false;\r\n        ValueType error(kObjectType);\r\n        error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());\r\n        currentError_ = error;\r\n        AddCurrentError(SchemaType::GetDependenciesString());\r\n        return true;\r\n    }\r\n\r\n    void DisallowedValue() {\r\n        currentError_.SetObject();\r\n        AddCurrentError(SchemaType::GetEnumString());\r\n    }\r\n    void StartDisallowedType() {\r\n        currentError_.SetArray();\r\n    }\r\n    void AddExpectedType(const typename SchemaType::ValueType& expectedType) {\r\n        currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());\r\n    }\r\n    void EndDisallowedType(const typename SchemaType::ValueType& actualType) {\r\n        ValueType error(kObjectType);\r\n        error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());\r\n        error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());\r\n        currentError_ = error;\r\n        AddCurrentError(SchemaType::GetTypeString());\r\n    }\r\n    void NotAllOf(ISchemaValidator** subvalidators, SizeType count) {\r\n        for (SizeType i = 0; i < count; ++i) {\r\n            MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());\r\n        }\r\n    }\r\n    void NoneOf(ISchemaValidator** subvalidators, SizeType count) {\r\n        AddErrorArray(SchemaType::GetAnyOfString(), subvalidators, count);\r\n    }\r\n    void NotOneOf(ISchemaValidator** subvalidators, SizeType count) {\r\n        AddErrorArray(SchemaType::GetOneOfString(), subvalidators, count);\r\n    }\r\n    void Disallowed() {\r\n        currentError_.SetObject();\r\n        AddCurrentError(SchemaType::GetNotString());\r\n    }\r\n\r\n#define RAPIDJSON_STRING_(name, ...) \\\r\n    static const StringRefType& Get##name##String() {\\\r\n        static const Ch s[] = { __VA_ARGS__, '\\0' };\\\r\n        static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \\\r\n        return v;\\\r\n    }\r\n\r\n    RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')\r\n    RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')\r\n    RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')\r\n    RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')\r\n    RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')\r\n    RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')\r\n    RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')\r\n    RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')\r\n\r\n#undef RAPIDJSON_STRING_\r\n\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \\\r\nRAPIDJSON_MULTILINEMACRO_BEGIN\\\r\n    *documentStack_.template Push<Ch>() = '\\0';\\\r\n    documentStack_.template Pop<Ch>(1);\\\r\n    internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\\\r\nRAPIDJSON_MULTILINEMACRO_END\r\n#else\r\n#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()\r\n#endif\r\n\r\n#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\\\r\n    if (!valid_) return false; \\\r\n    if (!BeginValue() || !CurrentSchema().method arg1) {\\\r\n        RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\\\r\n        return valid_ = false;\\\r\n    }\r\n\r\n#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\\\r\n    for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\\\r\n        if (context->hasher)\\\r\n            static_cast<HasherType*>(context->hasher)->method arg2;\\\r\n        if (context->validators)\\\r\n            for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\\\r\n                static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\\\r\n        if (context->patternPropertiesValidators)\\\r\n            for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\\\r\n                static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\\\r\n    }\r\n\r\n#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\\\r\n    return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2)\r\n\r\n#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \\\r\n    RAPIDJSON_SCHEMA_HANDLE_BEGIN_   (method, arg1);\\\r\n    RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\\\r\n    RAPIDJSON_SCHEMA_HANDLE_END_     (method, arg2)\r\n\r\n    bool Null()             { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null,   (CurrentContext()), ( )); }\r\n    bool Bool(bool b)       { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool,   (CurrentContext(), b), (b)); }\r\n    bool Int(int i)         { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int,    (CurrentContext(), i), (i)); }\r\n    bool Uint(unsigned u)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint,   (CurrentContext(), u), (u)); }\r\n    bool Int64(int64_t i)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64,  (CurrentContext(), i), (i)); }\r\n    bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }\r\n    bool Double(double d)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }\r\n    bool RawNumber(const Ch* str, SizeType length, bool copy)\r\n                                    { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }\r\n    bool String(const Ch* str, SizeType length, bool copy)\r\n                                    { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }\r\n\r\n    bool StartObject() {\r\n        RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));\r\n        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());\r\n        return valid_ = !outputHandler_ || outputHandler_->StartObject();\r\n    }\r\n    \r\n    bool Key(const Ch* str, SizeType len, bool copy) {\r\n        if (!valid_) return false;\r\n        AppendToken(str, len);\r\n        if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;\r\n        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));\r\n        return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);\r\n    }\r\n    \r\n    bool EndObject(SizeType memberCount) { \r\n        if (!valid_) return false;\r\n        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));\r\n        if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;\r\n        RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));\r\n    }\r\n\r\n    bool StartArray() {\r\n        RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));\r\n        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());\r\n        return valid_ = !outputHandler_ || outputHandler_->StartArray();\r\n    }\r\n    \r\n    bool EndArray(SizeType elementCount) {\r\n        if (!valid_) return false;\r\n        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));\r\n        if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;\r\n        RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));\r\n    }\r\n\r\n#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_\r\n#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_\r\n#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_\r\n#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_\r\n\r\n    // Implementation of ISchemaStateFactory<SchemaType>\r\n    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {\r\n        return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(),\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n        depth_ + 1,\r\n#endif\r\n        &GetStateAllocator());\r\n    }\r\n\r\n    virtual void DestroySchemaValidator(ISchemaValidator* validator) {\r\n        GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);\r\n        v->~GenericSchemaValidator();\r\n        StateAllocator::Free(v);\r\n    }\r\n\r\n    virtual void* CreateHasher() {\r\n        return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());\r\n    }\r\n\r\n    virtual uint64_t GetHashCode(void* hasher) {\r\n        return static_cast<HasherType*>(hasher)->GetHashCode();\r\n    }\r\n\r\n    virtual void DestroryHasher(void* hasher) {\r\n        HasherType* h = static_cast<HasherType*>(hasher);\r\n        h->~HasherType();\r\n        StateAllocator::Free(h);\r\n    }\r\n\r\n    virtual void* MallocState(size_t size) {\r\n        return GetStateAllocator().Malloc(size);\r\n    }\r\n\r\n    virtual void FreeState(void* p) {\r\n        StateAllocator::Free(p);\r\n    }\r\n\r\nprivate:\r\n    typedef typename SchemaType::Context Context;\r\n    typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;\r\n    typedef internal::Hasher<EncodingType, StateAllocator> HasherType;\r\n\r\n    GenericSchemaValidator( \r\n        const SchemaDocumentType& schemaDocument,\r\n        const SchemaType& root,\r\n        const char* basePath, size_t basePathSize,\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n        unsigned depth,\r\n#endif\r\n        StateAllocator* allocator = 0,\r\n        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,\r\n        size_t documentStackCapacity = kDefaultDocumentStackCapacity)\r\n        :\r\n        schemaDocument_(&schemaDocument),\r\n        root_(root),\r\n        stateAllocator_(allocator),\r\n        ownStateAllocator_(0),\r\n        schemaStack_(allocator, schemaStackCapacity),\r\n        documentStack_(allocator, documentStackCapacity),\r\n        outputHandler_(0),\r\n        error_(kObjectType),\r\n        currentError_(),\r\n        missingDependents_(),\r\n        valid_(true)\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n        , depth_(depth)\r\n#endif\r\n    {\r\n        if (basePath && basePathSize)\r\n            memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);\r\n    }\r\n\r\n    StateAllocator& GetStateAllocator() {\r\n        if (!stateAllocator_)\r\n            stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)();\r\n        return *stateAllocator_;\r\n    }\r\n\r\n    bool BeginValue() {\r\n        if (schemaStack_.Empty())\r\n            PushSchema(root_);\r\n        else {\r\n            if (CurrentContext().inArray)\r\n                internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);\r\n\r\n            if (!CurrentSchema().BeginValue(CurrentContext()))\r\n                return false;\r\n\r\n            SizeType count = CurrentContext().patternPropertiesSchemaCount;\r\n            const SchemaType** sa = CurrentContext().patternPropertiesSchemas;\r\n            typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;\r\n            bool valueUniqueness = CurrentContext().valueUniqueness;\r\n            RAPIDJSON_ASSERT(CurrentContext().valueSchema);\r\n            PushSchema(*CurrentContext().valueSchema);\r\n\r\n            if (count > 0) {\r\n                CurrentContext().objectPatternValidatorType = patternValidatorType;\r\n                ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;\r\n                SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;\r\n                va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));\r\n                for (SizeType i = 0; i < count; i++)\r\n                    va[validatorCount++] = CreateSchemaValidator(*sa[i]);\r\n            }\r\n\r\n            CurrentContext().arrayUniqueness = valueUniqueness;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    bool EndValue() {\r\n        if (!CurrentSchema().EndValue(CurrentContext()))\r\n            return false;\r\n\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n        GenericStringBuffer<EncodingType> sb;\r\n        schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);\r\n\r\n        *documentStack_.template Push<Ch>() = '\\0';\r\n        documentStack_.template Pop<Ch>(1);\r\n        internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());\r\n#endif\r\n\r\n        uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;\r\n        \r\n        PopSchema();\r\n\r\n        if (!schemaStack_.Empty()) {\r\n            Context& context = CurrentContext();\r\n            if (context.valueUniqueness) {\r\n                HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);\r\n                if (!a)\r\n                    CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);\r\n                for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)\r\n                    if (itr->GetUint64() == h) {\r\n                        DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());\r\n                        RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());\r\n                    }\r\n                a->PushBack(h, GetStateAllocator());\r\n            }\r\n        }\r\n\r\n        // Remove the last token of document pointer\r\n        while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')\r\n            ;\r\n\r\n        return true;\r\n    }\r\n\r\n    void AppendToken(const Ch* str, SizeType len) {\r\n        documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters\r\n        *documentStack_.template PushUnsafe<Ch>() = '/';\r\n        for (SizeType i = 0; i < len; i++) {\r\n            if (str[i] == '~') {\r\n                *documentStack_.template PushUnsafe<Ch>() = '~';\r\n                *documentStack_.template PushUnsafe<Ch>() = '0';\r\n            }\r\n            else if (str[i] == '/') {\r\n                *documentStack_.template PushUnsafe<Ch>() = '~';\r\n                *documentStack_.template PushUnsafe<Ch>() = '1';\r\n            }\r\n            else\r\n                *documentStack_.template PushUnsafe<Ch>() = str[i];\r\n        }\r\n    }\r\n\r\n    RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, *this, &schema); }\r\n    \r\n    RAPIDJSON_FORCEINLINE void PopSchema() {\r\n        Context* c = schemaStack_.template Pop<Context>(1);\r\n        if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {\r\n            a->~HashCodeArray();\r\n            StateAllocator::Free(a);\r\n        }\r\n        c->~Context();\r\n    }\r\n\r\n    void AddErrorLocation(ValueType& result, bool parent) {\r\n        GenericStringBuffer<EncodingType> sb;\r\n        PointerType instancePointer = GetInvalidDocumentPointer();\r\n        ((parent && instancePointer.GetTokenCount() > 0)\r\n            ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)\r\n            : instancePointer).StringifyUriFragment(sb);\r\n        ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),\r\n            GetStateAllocator());\r\n        result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());\r\n        sb.Clear();\r\n        memcpy(sb.Push(CurrentSchema().GetURI().GetStringLength()),\r\n            CurrentSchema().GetURI().GetString(),\r\n            CurrentSchema().GetURI().GetStringLength() * sizeof(Ch));\r\n        GetInvalidSchemaPointer().StringifyUriFragment(sb);\r\n        ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),\r\n            GetStateAllocator());\r\n        result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());\r\n    }\r\n\r\n    void AddError(ValueType& keyword, ValueType& error) {\r\n        typename ValueType::MemberIterator member = error_.FindMember(keyword);\r\n        if (member == error_.MemberEnd())\r\n            error_.AddMember(keyword, error, GetStateAllocator());\r\n        else {\r\n            if (member->value.IsObject()) {\r\n                ValueType errors(kArrayType);\r\n                errors.PushBack(member->value, GetStateAllocator());\r\n                member->value = errors;\r\n            }\r\n            member->value.PushBack(error, GetStateAllocator());\r\n        }\r\n    }\r\n\r\n    void AddCurrentError(const typename SchemaType::ValueType& keyword, bool parent = false) {\r\n        AddErrorLocation(currentError_, parent);\r\n        AddError(ValueType(keyword, GetStateAllocator(), false).Move(), currentError_);\r\n    }\r\n\r\n    void MergeError(ValueType& other) {\r\n        for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) {\r\n            AddError(it->name, it->value);\r\n        }\r\n    }\r\n\r\n    void AddNumberError(const typename SchemaType::ValueType& keyword, ValueType& actual, const SValue& expected,\r\n        const typename SchemaType::ValueType& (*exclusive)() = 0) {\r\n        currentError_.SetObject();\r\n        currentError_.AddMember(GetActualString(), actual, GetStateAllocator());\r\n        currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());\r\n        if (exclusive)\r\n            currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator());\r\n        AddCurrentError(keyword);\r\n    }\r\n\r\n    void AddErrorArray(const typename SchemaType::ValueType& keyword,\r\n        ISchemaValidator** subvalidators, SizeType count) {\r\n        ValueType errors(kArrayType);\r\n        for (SizeType i = 0; i < count; ++i)\r\n            errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());\r\n        currentError_.SetObject();\r\n        currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());\r\n        AddCurrentError(keyword);\r\n    }\r\n\r\n    const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }\r\n    Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }\r\n    const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }\r\n\r\n    static const size_t kDefaultSchemaStackCapacity = 1024;\r\n    static const size_t kDefaultDocumentStackCapacity = 256;\r\n    const SchemaDocumentType* schemaDocument_;\r\n    const SchemaType& root_;\r\n    StateAllocator* stateAllocator_;\r\n    StateAllocator* ownStateAllocator_;\r\n    internal::Stack<StateAllocator> schemaStack_;    //!< stack to store the current path of schema (BaseSchemaType *)\r\n    internal::Stack<StateAllocator> documentStack_;  //!< stack to store the current path of validating document (Ch)\r\n    OutputHandler* outputHandler_;\r\n    ValueType error_;\r\n    ValueType currentError_;\r\n    ValueType missingDependents_;\r\n    bool valid_;\r\n#if RAPIDJSON_SCHEMA_VERBOSE\r\n    unsigned depth_;\r\n#endif\r\n};\r\n\r\ntypedef GenericSchemaValidator<SchemaDocument> SchemaValidator;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// SchemaValidatingReader\r\n\r\n//! A helper class for parsing with validation.\r\n/*!\r\n    This helper class is a functor, designed as a parameter of \\ref GenericDocument::Populate().\r\n\r\n    \\tparam parseFlags Combination of \\ref ParseFlag.\r\n    \\tparam InputStream Type of input stream, implementing Stream concept.\r\n    \\tparam SourceEncoding Encoding of the input stream.\r\n    \\tparam SchemaDocumentType Type of schema document.\r\n    \\tparam StackAllocator Allocator type for stack.\r\n*/\r\ntemplate <\r\n    unsigned parseFlags,\r\n    typename InputStream,\r\n    typename SourceEncoding,\r\n    typename SchemaDocumentType = SchemaDocument,\r\n    typename StackAllocator = CrtAllocator>\r\nclass SchemaValidatingReader {\r\npublic:\r\n    typedef typename SchemaDocumentType::PointerType PointerType;\r\n    typedef typename InputStream::Ch Ch;\r\n    typedef GenericValue<SourceEncoding, StackAllocator> ValueType;\r\n\r\n    //! Constructor\r\n    /*!\r\n        \\param is Input stream.\r\n        \\param sd Schema document.\r\n    */\r\n    SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), error_(kObjectType), isValid_(true) {}\r\n\r\n    template <typename Handler>\r\n    bool operator()(Handler& handler) {\r\n        GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;\r\n        GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);\r\n        parseResult_ = reader.template Parse<parseFlags>(is_, validator);\r\n\r\n        isValid_ = validator.IsValid();\r\n        if (isValid_) {\r\n            invalidSchemaPointer_ = PointerType();\r\n            invalidSchemaKeyword_ = 0;\r\n            invalidDocumentPointer_ = PointerType();\r\n            error_.SetObject();\r\n        }\r\n        else {\r\n            invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();\r\n            invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();\r\n            invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();\r\n            error_.CopyFrom(validator.GetError(), allocator_);\r\n        }\r\n\r\n        return parseResult_;\r\n    }\r\n\r\n    const ParseResult& GetParseResult() const { return parseResult_; }\r\n    bool IsValid() const { return isValid_; }\r\n    const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }\r\n    const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }\r\n    const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }\r\n    const ValueType& GetError() const { return error_; }\r\n\r\nprivate:\r\n    InputStream& is_;\r\n    const SchemaDocumentType& sd_;\r\n\r\n    ParseResult parseResult_;\r\n    PointerType invalidSchemaPointer_;\r\n    const Ch* invalidSchemaKeyword_;\r\n    PointerType invalidDocumentPointer_;\r\n    StackAllocator allocator_;\r\n    ValueType error_;\r\n    bool isValid_;\r\n};\r\n\r\nRAPIDJSON_NAMESPACE_END\r\nRAPIDJSON_DIAG_POP\r\n\r\n#endif // RAPIDJSON_SCHEMA_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/stream.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n//\r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed\r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\r\n// specific language governing permissions and limitations under the License.\r\n\r\n#include \"rapidjson.h\"\r\n\r\n#ifndef RAPIDJSON_STREAM_H_\r\n#define RAPIDJSON_STREAM_H_\r\n\r\n#include \"encodings.h\"\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n//  Stream\r\n\r\n/*! \\class rapidjson::Stream\r\n    \\brief Concept for reading and writing characters.\r\n\r\n    For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().\r\n\r\n    For write-only stream, only need to implement Put() and Flush().\r\n\r\n\\code\r\nconcept Stream {\r\n    typename Ch;    //!< Character type of the stream.\r\n\r\n    //! Read the current character from stream without moving the read cursor.\r\n    Ch Peek() const;\r\n\r\n    //! Read the current character from stream and moving the read cursor to next character.\r\n    Ch Take();\r\n\r\n    //! Get the current read cursor.\r\n    //! \\return Number of characters read from start.\r\n    size_t Tell();\r\n\r\n    //! Begin writing operation at the current read pointer.\r\n    //! \\return The begin writer pointer.\r\n    Ch* PutBegin();\r\n\r\n    //! Write a character.\r\n    void Put(Ch c);\r\n\r\n    //! Flush the buffer.\r\n    void Flush();\r\n\r\n    //! End the writing operation.\r\n    //! \\param begin The begin write pointer returned by PutBegin().\r\n    //! \\return Number of characters written.\r\n    size_t PutEnd(Ch* begin);\r\n}\r\n\\endcode\r\n*/\r\n\r\n//! Provides additional information for stream.\r\n/*!\r\n    By using traits pattern, this type provides a default configuration for stream.\r\n    For custom stream, this type can be specialized for other configuration.\r\n    See TEST(Reader, CustomStringStream) in readertest.cpp for example.\r\n*/\r\ntemplate<typename Stream>\r\nstruct StreamTraits {\r\n    //! Whether to make local copy of stream for optimization during parsing.\r\n    /*!\r\n        By default, for safety, streams do not use local copy optimization.\r\n        Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.\r\n    */\r\n    enum { copyOptimization = 0 };\r\n};\r\n\r\n//! Reserve n characters for writing to a stream.\r\ntemplate<typename Stream>\r\ninline void PutReserve(Stream& stream, size_t count) {\r\n    (void)stream;\r\n    (void)count;\r\n}\r\n\r\n//! Write character to a stream, presuming buffer is reserved.\r\ntemplate<typename Stream>\r\ninline void PutUnsafe(Stream& stream, typename Stream::Ch c) {\r\n    stream.Put(c);\r\n}\r\n\r\n//! Put N copies of a character to a stream.\r\ntemplate<typename Stream, typename Ch>\r\ninline void PutN(Stream& stream, Ch c, size_t n) {\r\n    PutReserve(stream, n);\r\n    for (size_t i = 0; i < n; i++)\r\n        PutUnsafe(stream, c);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// GenericStreamWrapper\r\n\r\n//! A Stream Wrapper\r\n/*! \\tThis string stream is a wrapper for any stream by just forwarding any\r\n    \\treceived message to the origin stream.\r\n    \\note implements Stream concept\r\n*/\r\n\r\n#if defined(_MSC_VER) && _MSC_VER <= 1800\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4702)  // unreachable code\r\nRAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated\r\n#endif\r\n\r\ntemplate <typename InputStream, typename Encoding = UTF8<> >\r\nclass GenericStreamWrapper {\r\npublic:\r\n    typedef typename Encoding::Ch Ch;\r\n    GenericStreamWrapper(InputStream& is): is_(is) {}\r\n\r\n    Ch Peek() const { return is_.Peek(); }\r\n    Ch Take() { return is_.Take(); }\r\n    size_t Tell() { return is_.Tell(); }\r\n    Ch* PutBegin() { return is_.PutBegin(); }\r\n    void Put(Ch ch) { is_.Put(ch); }\r\n    void Flush() { is_.Flush(); }\r\n    size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); }\r\n\r\n    // wrapper for MemoryStream\r\n    const Ch* Peek4() const { return is_.Peek4(); }\r\n\r\n    // wrapper for AutoUTFInputStream\r\n    UTFType GetType() const { return is_.GetType(); }\r\n    bool HasBOM() const { return is_.HasBOM(); }\r\n\r\nprotected:\r\n    InputStream& is_;\r\n};\r\n\r\n#if defined(_MSC_VER) && _MSC_VER <= 1800\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// StringStream\r\n\r\n//! Read-only string stream.\r\n/*! \\note implements Stream concept\r\n*/\r\ntemplate <typename Encoding>\r\nstruct GenericStringStream {\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    GenericStringStream(const Ch *src) : src_(src), head_(src) {}\r\n\r\n    Ch Peek() const { return *src_; }\r\n    Ch Take() { return *src_++; }\r\n    size_t Tell() const { return static_cast<size_t>(src_ - head_); }\r\n\r\n    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }\r\n    void Put(Ch) { RAPIDJSON_ASSERT(false); }\r\n    void Flush() { RAPIDJSON_ASSERT(false); }\r\n    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }\r\n\r\n    const Ch* src_;     //!< Current read position.\r\n    const Ch* head_;    //!< Original head of the string.\r\n};\r\n\r\ntemplate <typename Encoding>\r\nstruct StreamTraits<GenericStringStream<Encoding> > {\r\n    enum { copyOptimization = 1 };\r\n};\r\n\r\n//! String stream with UTF8 encoding.\r\ntypedef GenericStringStream<UTF8<> > StringStream;\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// InsituStringStream\r\n\r\n//! A read-write string stream.\r\n/*! This string stream is particularly designed for in-situ parsing.\r\n    \\note implements Stream concept\r\n*/\r\ntemplate <typename Encoding>\r\nstruct GenericInsituStringStream {\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}\r\n\r\n    // Read\r\n    Ch Peek() { return *src_; }\r\n    Ch Take() { return *src_++; }\r\n    size_t Tell() { return static_cast<size_t>(src_ - head_); }\r\n\r\n    // Write\r\n    void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }\r\n\r\n    Ch* PutBegin() { return dst_ = src_; }\r\n    size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }\r\n    void Flush() {}\r\n\r\n    Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }\r\n    void Pop(size_t count) { dst_ -= count; }\r\n\r\n    Ch* src_;\r\n    Ch* dst_;\r\n    Ch* head_;\r\n};\r\n\r\ntemplate <typename Encoding>\r\nstruct StreamTraits<GenericInsituStringStream<Encoding> > {\r\n    enum { copyOptimization = 1 };\r\n};\r\n\r\n//! Insitu string stream with UTF8 encoding.\r\ntypedef GenericInsituStringStream<UTF8<> > InsituStringStream;\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#endif // RAPIDJSON_STREAM_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/stringbuffer.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_STRINGBUFFER_H_\r\n#define RAPIDJSON_STRINGBUFFER_H_\r\n\r\n#include \"stream.h\"\r\n#include \"internal/stack.h\"\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n#include <utility> // std::move\r\n#endif\r\n\r\n#include \"internal/stack.h\"\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(c++98-compat)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n//! Represents an in-memory output stream.\r\n/*!\r\n    \\tparam Encoding Encoding of the stream.\r\n    \\tparam Allocator type for allocating memory buffer.\r\n    \\note implements Stream concept\r\n*/\r\ntemplate <typename Encoding, typename Allocator = CrtAllocator>\r\nclass GenericStringBuffer {\r\npublic:\r\n    typedef typename Encoding::Ch Ch;\r\n\r\n    GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}\r\n    GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {\r\n        if (&rhs != this)\r\n            stack_ = std::move(rhs.stack_);\r\n        return *this;\r\n    }\r\n#endif\r\n\r\n    void Put(Ch c) { *stack_.template Push<Ch>() = c; }\r\n    void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }\r\n    void Flush() {}\r\n\r\n    void Clear() { stack_.Clear(); }\r\n    void ShrinkToFit() {\r\n        // Push and pop a null terminator. This is safe.\r\n        *stack_.template Push<Ch>() = '\\0';\r\n        stack_.ShrinkToFit();\r\n        stack_.template Pop<Ch>(1);\r\n    }\r\n\r\n    void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }\r\n    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }\r\n    Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }\r\n    void Pop(size_t count) { stack_.template Pop<Ch>(count); }\r\n\r\n    const Ch* GetString() const {\r\n        // Push and pop a null terminator. This is safe.\r\n        *stack_.template Push<Ch>() = '\\0';\r\n        stack_.template Pop<Ch>(1);\r\n\r\n        return stack_.template Bottom<Ch>();\r\n    }\r\n\r\n    //! Get the size of string in bytes in the string buffer.\r\n    size_t GetSize() const { return stack_.GetSize(); }\r\n\r\n    //! Get the length of string in Ch in the string buffer.\r\n    size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }\r\n\r\n    static const size_t kDefaultCapacity = 256;\r\n    mutable internal::Stack<Allocator> stack_;\r\n\r\nprivate:\r\n    // Prohibit copy constructor & assignment operator.\r\n    GenericStringBuffer(const GenericStringBuffer&);\r\n    GenericStringBuffer& operator=(const GenericStringBuffer&);\r\n};\r\n\r\n//! String buffer with UTF8 encoding\r\ntypedef GenericStringBuffer<UTF8<> > StringBuffer;\r\n\r\ntemplate<typename Encoding, typename Allocator>\r\ninline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {\r\n    stream.Reserve(count);\r\n}\r\n\r\ntemplate<typename Encoding, typename Allocator>\r\ninline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {\r\n    stream.PutUnsafe(c);\r\n}\r\n\r\n//! Implement specialized version of PutN() with memset() for better performance.\r\ntemplate<>\r\ninline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {\r\n    std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));\r\n}\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#if defined(__clang__)\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_STRINGBUFFER_H_\r\n"
  },
  {
    "path": "MiniEngine/rapidjson-master/include/rapidjson/writer.h",
    "content": "// Tencent is pleased to support the open source community by making RapidJSON available.\r\n// \r\n// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.\r\n//\r\n// Licensed under the MIT License (the \"License\"); you may not use this file except\r\n// in compliance with the License. You may obtain a copy of the License at\r\n//\r\n// http://opensource.org/licenses/MIT\r\n//\r\n// Unless required by applicable law or agreed to in writing, software distributed \r\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR \r\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the \r\n// specific language governing permissions and limitations under the License.\r\n\r\n#ifndef RAPIDJSON_WRITER_H_\r\n#define RAPIDJSON_WRITER_H_\r\n\r\n#include \"stream.h\"\r\n#include \"internal/meta.h\"\r\n#include \"internal/stack.h\"\r\n#include \"internal/strfunc.h\"\r\n#include \"internal/dtoa.h\"\r\n#include \"internal/itoa.h\"\r\n#include \"stringbuffer.h\"\r\n#include <new>      // placement new\r\n\r\n#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)\r\n#include <intrin.h>\r\n#pragma intrinsic(_BitScanForward)\r\n#endif\r\n#ifdef RAPIDJSON_SSE42\r\n#include <nmmintrin.h>\r\n#elif defined(RAPIDJSON_SSE2)\r\n#include <emmintrin.h>\r\n#elif defined(RAPIDJSON_NEON)\r\n#include <arm_neon.h>\r\n#endif\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(4127) // conditional expression is constant\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_PUSH\r\nRAPIDJSON_DIAG_OFF(padded)\r\nRAPIDJSON_DIAG_OFF(unreachable-code)\r\nRAPIDJSON_DIAG_OFF(c++98-compat)\r\n#endif\r\n\r\nRAPIDJSON_NAMESPACE_BEGIN\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n// WriteFlag\r\n\r\n/*! \\def RAPIDJSON_WRITE_DEFAULT_FLAGS \r\n    \\ingroup RAPIDJSON_CONFIG\r\n    \\brief User-defined kWriteDefaultFlags definition.\r\n\r\n    User can define this as any \\c WriteFlag combinations.\r\n*/\r\n#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS\r\n#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags\r\n#endif\r\n\r\n//! Combination of writeFlags\r\nenum WriteFlag {\r\n    kWriteNoFlags = 0,              //!< No flags are set.\r\n    kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.\r\n    kWriteNanAndInfFlag = 2,        //!< Allow writing of Infinity, -Infinity and NaN.\r\n    kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS  //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS\r\n};\r\n\r\n//! JSON writer\r\n/*! Writer implements the concept Handler.\r\n    It generates JSON text by events to an output os.\r\n\r\n    User may programmatically calls the functions of a writer to generate JSON text.\r\n\r\n    On the other side, a writer can also be passed to objects that generates events, \r\n\r\n    for example Reader::Parse() and Document::Accept().\r\n\r\n    \\tparam OutputStream Type of output stream.\r\n    \\tparam SourceEncoding Encoding of source string.\r\n    \\tparam TargetEncoding Encoding of output stream.\r\n    \\tparam StackAllocator Type of allocator for allocating memory of stack.\r\n    \\note implements Handler concept\r\n*/\r\ntemplate<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>\r\nclass Writer {\r\npublic:\r\n    typedef typename SourceEncoding::Ch Ch;\r\n\r\n    static const int kDefaultMaxDecimalPlaces = 324;\r\n\r\n    //! Constructor\r\n    /*! \\param os Output stream.\r\n        \\param stackAllocator User supplied allocator. If it is null, it will create a private one.\r\n        \\param levelDepth Initial capacity of stack.\r\n    */\r\n    explicit\r\n    Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : \r\n        os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}\r\n\r\n    explicit\r\n    Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :\r\n        os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}\r\n\r\n#if RAPIDJSON_HAS_CXX11_RVALUE_REFS\r\n    Writer(Writer&& rhs) :\r\n        os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {\r\n        rhs.os_ = 0;\r\n    }\r\n#endif\r\n\r\n    //! Reset the writer with a new stream.\r\n    /*!\r\n        This function reset the writer with a new stream and default settings,\r\n        in order to make a Writer object reusable for output multiple JSONs.\r\n\r\n        \\param os New output stream.\r\n        \\code\r\n        Writer<OutputStream> writer(os1);\r\n        writer.StartObject();\r\n        // ...\r\n        writer.EndObject();\r\n\r\n        writer.Reset(os2);\r\n        writer.StartObject();\r\n        // ...\r\n        writer.EndObject();\r\n        \\endcode\r\n    */\r\n    void Reset(OutputStream& os) {\r\n        os_ = &os;\r\n        hasRoot_ = false;\r\n        level_stack_.Clear();\r\n    }\r\n\r\n    //! Checks whether the output is a complete JSON.\r\n    /*!\r\n        A complete JSON has a complete root object or array.\r\n    */\r\n    bool IsComplete() const {\r\n        return hasRoot_ && level_stack_.Empty();\r\n    }\r\n\r\n    int GetMaxDecimalPlaces() const {\r\n        return maxDecimalPlaces_;\r\n    }\r\n\r\n    //! Sets the maximum number of decimal places for double output.\r\n    /*!\r\n        This setting truncates the output with specified number of decimal places.\r\n\r\n        For example, \r\n\r\n        \\code\r\n        writer.SetMaxDecimalPlaces(3);\r\n        writer.StartArray();\r\n        writer.Double(0.12345);                 // \"0.123\"\r\n        writer.Double(0.0001);                  // \"0.0\"\r\n        writer.Double(1.234567890123456e30);    // \"1.234567890123456e30\" (do not truncate significand for positive exponent)\r\n        writer.Double(1.23e-4);                 // \"0.0\"                  (do truncate significand for negative exponent)\r\n        writer.EndArray();\r\n        \\endcode\r\n\r\n        The default setting does not truncate any decimal places. You can restore to this setting by calling\r\n        \\code\r\n        writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);\r\n        \\endcode\r\n    */\r\n    void SetMaxDecimalPlaces(int maxDecimalPlaces) {\r\n        maxDecimalPlaces_ = maxDecimalPlaces;\r\n    }\r\n\r\n    /*!@name Implementation of Handler\r\n        \\see Handler\r\n    */\r\n    //@{\r\n\r\n    bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); }\r\n    bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }\r\n    bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); }\r\n    bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); }\r\n    bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }\r\n    bool Uint64(uint64_t u64)   { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }\r\n\r\n    //! Writes the given \\c double value to the stream\r\n    /*!\r\n        \\param d The value to be written.\r\n        \\return Whether it is succeed.\r\n    */\r\n    bool Double(double d)       { Prefix(kNumberType); return EndValue(WriteDouble(d)); }\r\n\r\n    bool RawNumber(const Ch* str, SizeType length, bool copy = false) {\r\n        RAPIDJSON_ASSERT(str != 0);\r\n        (void)copy;\r\n        Prefix(kNumberType);\r\n        return EndValue(WriteString(str, length));\r\n    }\r\n\r\n    bool String(const Ch* str, SizeType length, bool copy = false) {\r\n        RAPIDJSON_ASSERT(str != 0);\r\n        (void)copy;\r\n        Prefix(kStringType);\r\n        return EndValue(WriteString(str, length));\r\n    }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool String(const std::basic_string<Ch>& str) {\r\n        return String(str.data(), SizeType(str.size()));\r\n    }\r\n#endif\r\n\r\n    bool StartObject() {\r\n        Prefix(kObjectType);\r\n        new (level_stack_.template Push<Level>()) Level(false);\r\n        return WriteStartObject();\r\n    }\r\n\r\n    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }\r\n\r\n#if RAPIDJSON_HAS_STDSTRING\r\n    bool Key(const std::basic_string<Ch>& str)\r\n    {\r\n      return Key(str.data(), SizeType(str.size()));\r\n    }\r\n#endif\r\n\t\r\n    bool EndObject(SizeType memberCount = 0) {\r\n        (void)memberCount;\r\n        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object\r\n        RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object\r\n        RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value\r\n        level_stack_.template Pop<Level>(1);\r\n        return EndValue(WriteEndObject());\r\n    }\r\n\r\n    bool StartArray() {\r\n        Prefix(kArrayType);\r\n        new (level_stack_.template Push<Level>()) Level(true);\r\n        return WriteStartArray();\r\n    }\r\n\r\n    bool EndArray(SizeType elementCount = 0) {\r\n        (void)elementCount;\r\n        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));\r\n        RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);\r\n        level_stack_.template Pop<Level>(1);\r\n        return EndValue(WriteEndArray());\r\n    }\r\n    //@}\r\n\r\n    /*! @name Convenience extensions */\r\n    //@{\r\n\r\n    //! Simpler but slower overload.\r\n    bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }\r\n    bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }\r\n    \r\n    //@}\r\n\r\n    //! Write a raw JSON value.\r\n    /*!\r\n        For user to write a stringified JSON as a value.\r\n\r\n        \\param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.\r\n        \\param length Length of the json.\r\n        \\param type Type of the root of json.\r\n    */\r\n    bool RawValue(const Ch* json, size_t length, Type type) {\r\n        RAPIDJSON_ASSERT(json != 0);\r\n        Prefix(type);\r\n        return EndValue(WriteRawValue(json, length));\r\n    }\r\n\r\n    //! Flush the output stream.\r\n    /*!\r\n        Allows the user to flush the output stream immediately.\r\n     */\r\n    void Flush() {\r\n        os_->Flush();\r\n    }\r\n\r\nprotected:\r\n    //! Information for each nested level\r\n    struct Level {\r\n        Level(bool inArray_) : valueCount(0), inArray(inArray_) {}\r\n        size_t valueCount;  //!< number of values in this level\r\n        bool inArray;       //!< true if in array, otherwise in object\r\n    };\r\n\r\n    static const size_t kDefaultLevelDepth = 32;\r\n\r\n    bool WriteNull()  {\r\n        PutReserve(*os_, 4);\r\n        PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;\r\n    }\r\n\r\n    bool WriteBool(bool b)  {\r\n        if (b) {\r\n            PutReserve(*os_, 4);\r\n            PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');\r\n        }\r\n        else {\r\n            PutReserve(*os_, 5);\r\n            PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');\r\n        }\r\n        return true;\r\n    }\r\n\r\n    bool WriteInt(int i) {\r\n        char buffer[11];\r\n        const char* end = internal::i32toa(i, buffer);\r\n        PutReserve(*os_, static_cast<size_t>(end - buffer));\r\n        for (const char* p = buffer; p != end; ++p)\r\n            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));\r\n        return true;\r\n    }\r\n\r\n    bool WriteUint(unsigned u) {\r\n        char buffer[10];\r\n        const char* end = internal::u32toa(u, buffer);\r\n        PutReserve(*os_, static_cast<size_t>(end - buffer));\r\n        for (const char* p = buffer; p != end; ++p)\r\n            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));\r\n        return true;\r\n    }\r\n\r\n    bool WriteInt64(int64_t i64) {\r\n        char buffer[21];\r\n        const char* end = internal::i64toa(i64, buffer);\r\n        PutReserve(*os_, static_cast<size_t>(end - buffer));\r\n        for (const char* p = buffer; p != end; ++p)\r\n            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));\r\n        return true;\r\n    }\r\n\r\n    bool WriteUint64(uint64_t u64) {\r\n        char buffer[20];\r\n        char* end = internal::u64toa(u64, buffer);\r\n        PutReserve(*os_, static_cast<size_t>(end - buffer));\r\n        for (char* p = buffer; p != end; ++p)\r\n            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));\r\n        return true;\r\n    }\r\n\r\n    bool WriteDouble(double d) {\r\n        if (internal::Double(d).IsNanOrInf()) {\r\n            if (!(writeFlags & kWriteNanAndInfFlag))\r\n                return false;\r\n            if (internal::Double(d).IsNan()) {\r\n                PutReserve(*os_, 3);\r\n                PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');\r\n                return true;\r\n            }\r\n            if (internal::Double(d).Sign()) {\r\n                PutReserve(*os_, 9);\r\n                PutUnsafe(*os_, '-');\r\n            }\r\n            else\r\n                PutReserve(*os_, 8);\r\n            PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');\r\n            PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');\r\n            return true;\r\n        }\r\n\r\n        char buffer[25];\r\n        char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);\r\n        PutReserve(*os_, static_cast<size_t>(end - buffer));\r\n        for (char* p = buffer; p != end; ++p)\r\n            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));\r\n        return true;\r\n    }\r\n\r\n    bool WriteString(const Ch* str, SizeType length)  {\r\n        static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };\r\n        static const char escape[256] = {\r\n#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\n            //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F\r\n            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00\r\n            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10\r\n              0,   0, '\"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20\r\n            Z16, Z16,                                                                       // 30~4F\r\n              0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\\\',   0,   0,   0, // 50\r\n            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF\r\n#undef Z16\r\n        };\r\n\r\n        if (TargetEncoding::supportUnicode)\r\n            PutReserve(*os_, 2 + length * 6); // \"\\uxxxx...\"\r\n        else\r\n            PutReserve(*os_, 2 + length * 12);  // \"\\uxxxx\\uyyyy...\"\r\n\r\n        PutUnsafe(*os_, '\\\"');\r\n        GenericStringStream<SourceEncoding> is(str);\r\n        while (ScanWriteUnescapedString(is, length)) {\r\n            const Ch c = is.Peek();\r\n            if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {\r\n                // Unicode escaping\r\n                unsigned codepoint;\r\n                if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))\r\n                    return false;\r\n                PutUnsafe(*os_, '\\\\');\r\n                PutUnsafe(*os_, 'u');\r\n                if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {\r\n                    PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]);\r\n                }\r\n                else {\r\n                    RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);\r\n                    // Surrogate pair\r\n                    unsigned s = codepoint - 0x010000;\r\n                    unsigned lead = (s >> 10) + 0xD800;\r\n                    unsigned trail = (s & 0x3FF) + 0xDC00;\r\n                    PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(lead      ) & 15]);\r\n                    PutUnsafe(*os_, '\\\\');\r\n                    PutUnsafe(*os_, 'u');\r\n                    PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]);\r\n                    PutUnsafe(*os_, hexDigits[(trail      ) & 15]);                    \r\n                }\r\n            }\r\n            else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {\r\n                is.Take();\r\n                PutUnsafe(*os_, '\\\\');\r\n                PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));\r\n                if (escape[static_cast<unsigned char>(c)] == 'u') {\r\n                    PutUnsafe(*os_, '0');\r\n                    PutUnsafe(*os_, '0');\r\n                    PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);\r\n                    PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);\r\n                }\r\n            }\r\n            else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? \r\n                Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :\r\n                Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))\r\n                return false;\r\n        }\r\n        PutUnsafe(*os_, '\\\"');\r\n        return true;\r\n    }\r\n\r\n    bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {\r\n        return RAPIDJSON_LIKELY(is.Tell() < length);\r\n    }\r\n\r\n    bool WriteStartObject() { os_->Put('{'); return true; }\r\n    bool WriteEndObject()   { os_->Put('}'); return true; }\r\n    bool WriteStartArray()  { os_->Put('['); return true; }\r\n    bool WriteEndArray()    { os_->Put(']'); return true; }\r\n\r\n    bool WriteRawValue(const Ch* json, size_t length) {\r\n        PutReserve(*os_, length);\r\n        GenericStringStream<SourceEncoding> is(json);\r\n        while (RAPIDJSON_LIKELY(is.Tell() < length)) {\r\n            const Ch c = is.Peek();\r\n            RAPIDJSON_ASSERT(c != '\\0');\r\n            if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? \r\n                Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :\r\n                Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))\r\n                return false;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    void Prefix(Type type) {\r\n        (void)type;\r\n        if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root\r\n            Level* level = level_stack_.template Top<Level>();\r\n            if (level->valueCount > 0) {\r\n                if (level->inArray) \r\n                    os_->Put(','); // add comma if it is not the first element in array\r\n                else  // in object\r\n                    os_->Put((level->valueCount % 2 == 0) ? ',' : ':');\r\n            }\r\n            if (!level->inArray && level->valueCount % 2 == 0)\r\n                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name\r\n            level->valueCount++;\r\n        }\r\n        else {\r\n            RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.\r\n            hasRoot_ = true;\r\n        }\r\n    }\r\n\r\n    // Flush the value if it is the top level one.\r\n    bool EndValue(bool ret) {\r\n        if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text\r\n            Flush();\r\n        return ret;\r\n    }\r\n\r\n    OutputStream* os_;\r\n    internal::Stack<StackAllocator> level_stack_;\r\n    int maxDecimalPlaces_;\r\n    bool hasRoot_;\r\n\r\nprivate:\r\n    // Prohibit copy constructor & assignment operator.\r\n    Writer(const Writer&);\r\n    Writer& operator=(const Writer&);\r\n};\r\n\r\n// Full specialization for StringStream to prevent memory copying\r\n\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::WriteInt(int i) {\r\n    char *buffer = os_->Push(11);\r\n    const char* end = internal::i32toa(i, buffer);\r\n    os_->Pop(static_cast<size_t>(11 - (end - buffer)));\r\n    return true;\r\n}\r\n\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::WriteUint(unsigned u) {\r\n    char *buffer = os_->Push(10);\r\n    const char* end = internal::u32toa(u, buffer);\r\n    os_->Pop(static_cast<size_t>(10 - (end - buffer)));\r\n    return true;\r\n}\r\n\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {\r\n    char *buffer = os_->Push(21);\r\n    const char* end = internal::i64toa(i64, buffer);\r\n    os_->Pop(static_cast<size_t>(21 - (end - buffer)));\r\n    return true;\r\n}\r\n\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {\r\n    char *buffer = os_->Push(20);\r\n    const char* end = internal::u64toa(u, buffer);\r\n    os_->Pop(static_cast<size_t>(20 - (end - buffer)));\r\n    return true;\r\n}\r\n\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::WriteDouble(double d) {\r\n    if (internal::Double(d).IsNanOrInf()) {\r\n        // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).\r\n        if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))\r\n            return false;\r\n        if (internal::Double(d).IsNan()) {\r\n            PutReserve(*os_, 3);\r\n            PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');\r\n            return true;\r\n        }\r\n        if (internal::Double(d).Sign()) {\r\n            PutReserve(*os_, 9);\r\n            PutUnsafe(*os_, '-');\r\n        }\r\n        else\r\n            PutReserve(*os_, 8);\r\n        PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');\r\n        PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');\r\n        return true;\r\n    }\r\n    \r\n    char *buffer = os_->Push(25);\r\n    char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);\r\n    os_->Pop(static_cast<size_t>(25 - (end - buffer)));\r\n    return true;\r\n}\r\n\r\n#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {\r\n    if (length < 16)\r\n        return RAPIDJSON_LIKELY(is.Tell() < length);\r\n\r\n    if (!RAPIDJSON_LIKELY(is.Tell() < length))\r\n        return false;\r\n\r\n    const char* p = is.src_;\r\n    const char* end = is.head_ + length;\r\n    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n    const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));\r\n    if (nextAligned > end)\r\n        return true;\r\n\r\n    while (p != nextAligned)\r\n        if (*p < 0x20 || *p == '\\\"' || *p == '\\\\') {\r\n            is.src_ = p;\r\n            return RAPIDJSON_LIKELY(is.Tell() < length);\r\n        }\r\n        else\r\n            os_->PutUnsafe(*p++);\r\n\r\n    // The rest of string using SIMD\r\n    static const char dquote[16] = { '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"', '\\\"' };\r\n    static const char bslash[16] = { '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\', '\\\\' };\r\n    static const char space[16]  = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };\r\n    const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));\r\n    const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));\r\n    const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));\r\n\r\n    for (; p != endAligned; p += 16) {\r\n        const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));\r\n        const __m128i t1 = _mm_cmpeq_epi8(s, dq);\r\n        const __m128i t2 = _mm_cmpeq_epi8(s, bs);\r\n        const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F\r\n        const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);\r\n        unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));\r\n        if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped\r\n            SizeType len;\r\n#ifdef _MSC_VER         // Find the index of first escaped\r\n            unsigned long offset;\r\n            _BitScanForward(&offset, r);\r\n            len = offset;\r\n#else\r\n            len = static_cast<SizeType>(__builtin_ffs(r) - 1);\r\n#endif\r\n            char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));\r\n            for (size_t i = 0; i < len; i++)\r\n                q[i] = p[i];\r\n\r\n            p += len;\r\n            break;\r\n        }\r\n        _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);\r\n    }\r\n\r\n    is.src_ = p;\r\n    return RAPIDJSON_LIKELY(is.Tell() < length);\r\n}\r\n#elif defined(RAPIDJSON_NEON)\r\ntemplate<>\r\ninline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {\r\n    if (length < 16)\r\n        return RAPIDJSON_LIKELY(is.Tell() < length);\r\n\r\n    if (!RAPIDJSON_LIKELY(is.Tell() < length))\r\n        return false;\r\n\r\n    const char* p = is.src_;\r\n    const char* end = is.head_ + length;\r\n    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));\r\n    const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));\r\n    if (nextAligned > end)\r\n        return true;\r\n\r\n    while (p != nextAligned)\r\n        if (*p < 0x20 || *p == '\\\"' || *p == '\\\\') {\r\n            is.src_ = p;\r\n            return RAPIDJSON_LIKELY(is.Tell() < length);\r\n        }\r\n        else\r\n            os_->PutUnsafe(*p++);\r\n\r\n    // The rest of string using SIMD\r\n    const uint8x16_t s0 = vmovq_n_u8('\"');\r\n    const uint8x16_t s1 = vmovq_n_u8('\\\\');\r\n    const uint8x16_t s2 = vmovq_n_u8('\\b');\r\n    const uint8x16_t s3 = vmovq_n_u8(32);\r\n\r\n    for (; p != endAligned; p += 16) {\r\n        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));\r\n        uint8x16_t x = vceqq_u8(s, s0);\r\n        x = vorrq_u8(x, vceqq_u8(s, s1));\r\n        x = vorrq_u8(x, vceqq_u8(s, s2));\r\n        x = vorrq_u8(x, vcltq_u8(s, s3));\r\n\r\n        x = vrev64q_u8(x);                     // Rev in 64\r\n        uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0);   // extract\r\n        uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1);  // extract\r\n\r\n        SizeType len = 0;\r\n        bool escaped = false;\r\n        if (low == 0) {\r\n            if (high != 0) {\r\n                unsigned lz = (unsigned)__builtin_clzll(high);\r\n                len = 8 + (lz >> 3);\r\n                escaped = true;\r\n            }\r\n        } else {\r\n            unsigned lz = (unsigned)__builtin_clzll(low);\r\n            len = lz >> 3;\r\n            escaped = true;\r\n        }\r\n        if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped\r\n            char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));\r\n            for (size_t i = 0; i < len; i++)\r\n                q[i] = p[i];\r\n\r\n            p += len;\r\n            break;\r\n        }\r\n        vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);\r\n    }\r\n\r\n    is.src_ = p;\r\n    return RAPIDJSON_LIKELY(is.Tell() < length);\r\n}\r\n#endif // RAPIDJSON_NEON\r\n\r\nRAPIDJSON_NAMESPACE_END\r\n\r\n#ifdef _MSC_VER\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#ifdef __clang__\r\nRAPIDJSON_DIAG_POP\r\n#endif\r\n\r\n#endif // RAPIDJSON_RAPIDJSON_H_\r\n"
  },
  {
    "path": "MiniEngine/readme.md",
    "content": "# MiniEngine by Team Minigraph at Microsoft\n\n## Getting started:\n* Open ModelViewer/ModelViewer_VS14.sln\n* Select configuration: Debug (full validation), Profile (instrumented), Release\n* Select platform\n* Build and run\n\n## Controls:\n* forward/backward/strafe: left thumbstick or WASD (FPS controls)\n* up/down: triggers or E/Q\n* yaw/pitch: right thumbstick or mouse\n* toggle slow movement: click left thumbstick or lshift\n* open debug menu: back button or backspace\n* navigate debug menu: dpad or arrow keys\n* toggle debug menu item: A button or return\n* adjust debug menu value: dpad left/right or left/right arrow keys\n"
  },
  {
    "path": "MiniEngine/zlib-1.2.11/zconf.h",
    "content": "/* zconf.h -- configuration of the zlib compression library\r\n * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler\r\n * For conditions of distribution and use, see copyright notice in zlib.h\r\n */\r\n\r\n/* @(#) $Id$ */\r\n\r\n#ifndef ZCONF_H\r\n#define ZCONF_H\r\n\r\n/*\r\n * If you *really* need a unique prefix for all types and library functions,\r\n * compile with -DZ_PREFIX. The \"standard\" zlib should be compiled without it.\r\n * Even better than compiling with -DZ_PREFIX would be to use configure to set\r\n * this permanently in zconf.h using \"./configure --zprefix\".\r\n */\r\n#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */\r\n#  define Z_PREFIX_SET\r\n\r\n/* all linked symbols and init macros */\r\n#  define _dist_code            z__dist_code\r\n#  define _length_code          z__length_code\r\n#  define _tr_align             z__tr_align\r\n#  define _tr_flush_bits        z__tr_flush_bits\r\n#  define _tr_flush_block       z__tr_flush_block\r\n#  define _tr_init              z__tr_init\r\n#  define _tr_stored_block      z__tr_stored_block\r\n#  define _tr_tally             z__tr_tally\r\n#  define adler32               z_adler32\r\n#  define adler32_combine       z_adler32_combine\r\n#  define adler32_combine64     z_adler32_combine64\r\n#  define adler32_z             z_adler32_z\r\n#  ifndef Z_SOLO\r\n#    define compress              z_compress\r\n#    define compress2             z_compress2\r\n#    define compressBound         z_compressBound\r\n#  endif\r\n#  define crc32                 z_crc32\r\n#  define crc32_combine         z_crc32_combine\r\n#  define crc32_combine64       z_crc32_combine64\r\n#  define crc32_z               z_crc32_z\r\n#  define deflate               z_deflate\r\n#  define deflateBound          z_deflateBound\r\n#  define deflateCopy           z_deflateCopy\r\n#  define deflateEnd            z_deflateEnd\r\n#  define deflateGetDictionary  z_deflateGetDictionary\r\n#  define deflateInit           z_deflateInit\r\n#  define deflateInit2          z_deflateInit2\r\n#  define deflateInit2_         z_deflateInit2_\r\n#  define deflateInit_          z_deflateInit_\r\n#  define deflateParams         z_deflateParams\r\n#  define deflatePending        z_deflatePending\r\n#  define deflatePrime          z_deflatePrime\r\n#  define deflateReset          z_deflateReset\r\n#  define deflateResetKeep      z_deflateResetKeep\r\n#  define deflateSetDictionary  z_deflateSetDictionary\r\n#  define deflateSetHeader      z_deflateSetHeader\r\n#  define deflateTune           z_deflateTune\r\n#  define deflate_copyright     z_deflate_copyright\r\n#  define get_crc_table         z_get_crc_table\r\n#  ifndef Z_SOLO\r\n#    define gz_error              z_gz_error\r\n#    define gz_intmax             z_gz_intmax\r\n#    define gz_strwinerror        z_gz_strwinerror\r\n#    define gzbuffer              z_gzbuffer\r\n#    define gzclearerr            z_gzclearerr\r\n#    define gzclose               z_gzclose\r\n#    define gzclose_r             z_gzclose_r\r\n#    define gzclose_w             z_gzclose_w\r\n#    define gzdirect              z_gzdirect\r\n#    define gzdopen               z_gzdopen\r\n#    define gzeof                 z_gzeof\r\n#    define gzerror               z_gzerror\r\n#    define gzflush               z_gzflush\r\n#    define gzfread               z_gzfread\r\n#    define gzfwrite              z_gzfwrite\r\n#    define gzgetc                z_gzgetc\r\n#    define gzgetc_               z_gzgetc_\r\n#    define gzgets                z_gzgets\r\n#    define gzoffset              z_gzoffset\r\n#    define gzoffset64            z_gzoffset64\r\n#    define gzopen                z_gzopen\r\n#    define gzopen64              z_gzopen64\r\n#    ifdef _WIN32\r\n#      define gzopen_w              z_gzopen_w\r\n#    endif\r\n#    define gzprintf              z_gzprintf\r\n#    define gzputc                z_gzputc\r\n#    define gzputs                z_gzputs\r\n#    define gzread                z_gzread\r\n#    define gzrewind              z_gzrewind\r\n#    define gzseek                z_gzseek\r\n#    define gzseek64              z_gzseek64\r\n#    define gzsetparams           z_gzsetparams\r\n#    define gztell                z_gztell\r\n#    define gztell64              z_gztell64\r\n#    define gzungetc              z_gzungetc\r\n#    define gzvprintf             z_gzvprintf\r\n#    define gzwrite               z_gzwrite\r\n#  endif\r\n#  define inflate               z_inflate\r\n#  define inflateBack           z_inflateBack\r\n#  define inflateBackEnd        z_inflateBackEnd\r\n#  define inflateBackInit       z_inflateBackInit\r\n#  define inflateBackInit_      z_inflateBackInit_\r\n#  define inflateCodesUsed      z_inflateCodesUsed\r\n#  define inflateCopy           z_inflateCopy\r\n#  define inflateEnd            z_inflateEnd\r\n#  define inflateGetDictionary  z_inflateGetDictionary\r\n#  define inflateGetHeader      z_inflateGetHeader\r\n#  define inflateInit           z_inflateInit\r\n#  define inflateInit2          z_inflateInit2\r\n#  define inflateInit2_         z_inflateInit2_\r\n#  define inflateInit_          z_inflateInit_\r\n#  define inflateMark           z_inflateMark\r\n#  define inflatePrime          z_inflatePrime\r\n#  define inflateReset          z_inflateReset\r\n#  define inflateReset2         z_inflateReset2\r\n#  define inflateResetKeep      z_inflateResetKeep\r\n#  define inflateSetDictionary  z_inflateSetDictionary\r\n#  define inflateSync           z_inflateSync\r\n#  define inflateSyncPoint      z_inflateSyncPoint\r\n#  define inflateUndermine      z_inflateUndermine\r\n#  define inflateValidate       z_inflateValidate\r\n#  define inflate_copyright     z_inflate_copyright\r\n#  define inflate_fast          z_inflate_fast\r\n#  define inflate_table         z_inflate_table\r\n#  ifndef Z_SOLO\r\n#    define uncompress            z_uncompress\r\n#    define uncompress2           z_uncompress2\r\n#  endif\r\n#  define zError                z_zError\r\n#  ifndef Z_SOLO\r\n#    define zcalloc               z_zcalloc\r\n#    define zcfree                z_zcfree\r\n#  endif\r\n#  define zlibCompileFlags      z_zlibCompileFlags\r\n#  define zlibVersion           z_zlibVersion\r\n\r\n/* all zlib typedefs in zlib.h and zconf.h */\r\n#  define Byte                  z_Byte\r\n#  define Bytef                 z_Bytef\r\n#  define alloc_func            z_alloc_func\r\n#  define charf                 z_charf\r\n#  define free_func             z_free_func\r\n#  ifndef Z_SOLO\r\n#    define gzFile                z_gzFile\r\n#  endif\r\n#  define gz_header             z_gz_header\r\n#  define gz_headerp            z_gz_headerp\r\n#  define in_func               z_in_func\r\n#  define intf                  z_intf\r\n#  define out_func              z_out_func\r\n#  define uInt                  z_uInt\r\n#  define uIntf                 z_uIntf\r\n#  define uLong                 z_uLong\r\n#  define uLongf                z_uLongf\r\n#  define voidp                 z_voidp\r\n#  define voidpc                z_voidpc\r\n#  define voidpf                z_voidpf\r\n\r\n/* all zlib structs in zlib.h and zconf.h */\r\n#  define gz_header_s           z_gz_header_s\r\n#  define internal_state        z_internal_state\r\n\r\n#endif\r\n\r\n#if defined(__MSDOS__) && !defined(MSDOS)\r\n#  define MSDOS\r\n#endif\r\n#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)\r\n#  define OS2\r\n#endif\r\n#if defined(_WINDOWS) && !defined(WINDOWS)\r\n#  define WINDOWS\r\n#endif\r\n#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)\r\n#  ifndef WIN32\r\n#    define WIN32\r\n#  endif\r\n#endif\r\n#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)\r\n#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)\r\n#    ifndef SYS16BIT\r\n#      define SYS16BIT\r\n#    endif\r\n#  endif\r\n#endif\r\n\r\n/*\r\n * Compile with -DMAXSEG_64K if the alloc function cannot allocate more\r\n * than 64k bytes at a time (needed on systems with 16-bit int).\r\n */\r\n#ifdef SYS16BIT\r\n#  define MAXSEG_64K\r\n#endif\r\n#ifdef MSDOS\r\n#  define UNALIGNED_OK\r\n#endif\r\n\r\n#ifdef __STDC_VERSION__\r\n#  ifndef STDC\r\n#    define STDC\r\n#  endif\r\n#  if __STDC_VERSION__ >= 199901L\r\n#    ifndef STDC99\r\n#      define STDC99\r\n#    endif\r\n#  endif\r\n#endif\r\n#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))\r\n#  define STDC\r\n#endif\r\n#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))\r\n#  define STDC\r\n#endif\r\n#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))\r\n#  define STDC\r\n#endif\r\n#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))\r\n#  define STDC\r\n#endif\r\n\r\n#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */\r\n#  define STDC\r\n#endif\r\n\r\n#ifndef STDC\r\n#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */\r\n#    define const       /* note: need a more gentle solution here */\r\n#  endif\r\n#endif\r\n\r\n#if defined(ZLIB_CONST) && !defined(z_const)\r\n#  define z_const const\r\n#else\r\n#  define z_const\r\n#endif\r\n\r\n#ifdef Z_SOLO\r\n   typedef unsigned long z_size_t;\r\n#else\r\n#  define z_longlong long long\r\n#  if defined(NO_SIZE_T)\r\n     typedef unsigned NO_SIZE_T z_size_t;\r\n#  elif defined(STDC)\r\n#    include <stddef.h>\r\n     typedef size_t z_size_t;\r\n#  else\r\n     typedef unsigned long z_size_t;\r\n#  endif\r\n#  undef z_longlong\r\n#endif\r\n\r\n/* Maximum value for memLevel in deflateInit2 */\r\n#ifndef MAX_MEM_LEVEL\r\n#  ifdef MAXSEG_64K\r\n#    define MAX_MEM_LEVEL 8\r\n#  else\r\n#    define MAX_MEM_LEVEL 9\r\n#  endif\r\n#endif\r\n\r\n/* Maximum value for windowBits in deflateInit2 and inflateInit2.\r\n * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files\r\n * created by gzip. (Files created by minigzip can still be extracted by\r\n * gzip.)\r\n */\r\n#ifndef MAX_WBITS\r\n#  define MAX_WBITS   15 /* 32K LZ77 window */\r\n#endif\r\n\r\n/* The memory requirements for deflate are (in bytes):\r\n            (1 << (windowBits+2)) +  (1 << (memLevel+9))\r\n that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)\r\n plus a few kilobytes for small objects. For example, if you want to reduce\r\n the default memory requirements from 256K to 128K, compile with\r\n     make CFLAGS=\"-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7\"\r\n Of course this will generally degrade compression (there's no free lunch).\r\n\r\n   The memory requirements for inflate are (in bytes) 1 << windowBits\r\n that is, 32K for windowBits=15 (default value) plus about 7 kilobytes\r\n for small objects.\r\n*/\r\n\r\n                        /* Type declarations */\r\n\r\n#ifndef OF /* function prototypes */\r\n#  ifdef STDC\r\n#    define OF(args)  args\r\n#  else\r\n#    define OF(args)  ()\r\n#  endif\r\n#endif\r\n\r\n#ifndef Z_ARG /* function prototypes for stdarg */\r\n#  if defined(STDC) || defined(Z_HAVE_STDARG_H)\r\n#    define Z_ARG(args)  args\r\n#  else\r\n#    define Z_ARG(args)  ()\r\n#  endif\r\n#endif\r\n\r\n/* The following definitions for FAR are needed only for MSDOS mixed\r\n * model programming (small or medium model with some far allocations).\r\n * This was tested only with MSC; for other MSDOS compilers you may have\r\n * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,\r\n * just define FAR to be empty.\r\n */\r\n#ifdef SYS16BIT\r\n#  if defined(M_I86SM) || defined(M_I86MM)\r\n     /* MSC small or medium model */\r\n#    define SMALL_MEDIUM\r\n#    ifdef _MSC_VER\r\n#      define FAR _far\r\n#    else\r\n#      define FAR far\r\n#    endif\r\n#  endif\r\n#  if (defined(__SMALL__) || defined(__MEDIUM__))\r\n     /* Turbo C small or medium model */\r\n#    define SMALL_MEDIUM\r\n#    ifdef __BORLANDC__\r\n#      define FAR _far\r\n#    else\r\n#      define FAR far\r\n#    endif\r\n#  endif\r\n#endif\r\n\r\n#if defined(WINDOWS) || defined(WIN32)\r\n   /* If building or using zlib as a DLL, define ZLIB_DLL.\r\n    * This is not mandatory, but it offers a little performance increase.\r\n    */\r\n#  ifdef ZLIB_DLL\r\n#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))\r\n#      ifdef ZLIB_INTERNAL\r\n#        define ZEXTERN extern __declspec(dllexport)\r\n#      else\r\n#        define ZEXTERN extern __declspec(dllimport)\r\n#      endif\r\n#    endif\r\n#  endif  /* ZLIB_DLL */\r\n   /* If building or using zlib with the WINAPI/WINAPIV calling convention,\r\n    * define ZLIB_WINAPI.\r\n    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.\r\n    */\r\n#  ifdef ZLIB_WINAPI\r\n#    ifdef FAR\r\n#      undef FAR\r\n#    endif\r\n#    include <windows.h>\r\n     /* No need for _export, use ZLIB.DEF instead. */\r\n     /* For complete Windows compatibility, use WINAPI, not __stdcall. */\r\n#    define ZEXPORT WINAPI\r\n#    ifdef WIN32\r\n#      define ZEXPORTVA WINAPIV\r\n#    else\r\n#      define ZEXPORTVA FAR CDECL\r\n#    endif\r\n#  endif\r\n#endif\r\n\r\n#if defined (__BEOS__)\r\n#  ifdef ZLIB_DLL\r\n#    ifdef ZLIB_INTERNAL\r\n#      define ZEXPORT   __declspec(dllexport)\r\n#      define ZEXPORTVA __declspec(dllexport)\r\n#    else\r\n#      define ZEXPORT   __declspec(dllimport)\r\n#      define ZEXPORTVA __declspec(dllimport)\r\n#    endif\r\n#  endif\r\n#endif\r\n\r\n#ifndef ZEXTERN\r\n#  define ZEXTERN extern\r\n#endif\r\n#ifndef ZEXPORT\r\n#  define ZEXPORT\r\n#endif\r\n#ifndef ZEXPORTVA\r\n#  define ZEXPORTVA\r\n#endif\r\n\r\n#ifndef FAR\r\n#  define FAR\r\n#endif\r\n\r\n#if !defined(__MACTYPES__)\r\ntypedef unsigned char  Byte;  /* 8 bits */\r\n#endif\r\ntypedef unsigned int   uInt;  /* 16 bits or more */\r\ntypedef unsigned long  uLong; /* 32 bits or more */\r\n\r\n#ifdef SMALL_MEDIUM\r\n   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */\r\n#  define Bytef Byte FAR\r\n#else\r\n   typedef Byte  FAR Bytef;\r\n#endif\r\ntypedef char  FAR charf;\r\ntypedef int   FAR intf;\r\ntypedef uInt  FAR uIntf;\r\ntypedef uLong FAR uLongf;\r\n\r\n#ifdef STDC\r\n   typedef void const *voidpc;\r\n   typedef void FAR   *voidpf;\r\n   typedef void       *voidp;\r\n#else\r\n   typedef Byte const *voidpc;\r\n   typedef Byte FAR   *voidpf;\r\n   typedef Byte       *voidp;\r\n#endif\r\n\r\n#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)\r\n#  include <limits.h>\r\n#  if (UINT_MAX == 0xffffffffUL)\r\n#    define Z_U4 unsigned\r\n#  elif (ULONG_MAX == 0xffffffffUL)\r\n#    define Z_U4 unsigned long\r\n#  elif (USHRT_MAX == 0xffffffffUL)\r\n#    define Z_U4 unsigned short\r\n#  endif\r\n#endif\r\n\r\n#ifdef Z_U4\r\n   typedef Z_U4 z_crc_t;\r\n#else\r\n   typedef unsigned long z_crc_t;\r\n#endif\r\n\r\n#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */\r\n#  define Z_HAVE_UNISTD_H\r\n#endif\r\n\r\n#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */\r\n#  define Z_HAVE_STDARG_H\r\n#endif\r\n\r\n#ifdef STDC\r\n#  ifndef Z_SOLO\r\n#    include <sys/types.h>      /* for off_t */\r\n#  endif\r\n#endif\r\n\r\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\r\n#  ifndef Z_SOLO\r\n#    include <stdarg.h>         /* for va_list */\r\n#  endif\r\n#endif\r\n\r\n#ifdef _WIN32\r\n#  ifndef Z_SOLO\r\n#    include <stddef.h>         /* for wchar_t */\r\n#  endif\r\n#endif\r\n\r\n/* a little trick to accommodate both \"#define _LARGEFILE64_SOURCE\" and\r\n * \"#define _LARGEFILE64_SOURCE 1\" as requesting 64-bit operations, (even\r\n * though the former does not conform to the LFS document), but considering\r\n * both \"#undef _LARGEFILE64_SOURCE\" and \"#define _LARGEFILE64_SOURCE 0\" as\r\n * equivalently requesting no 64-bit operations\r\n */\r\n#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1\r\n#  undef _LARGEFILE64_SOURCE\r\n#endif\r\n\r\n#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)\r\n#  define Z_HAVE_UNISTD_H\r\n#endif\r\n#ifndef Z_SOLO\r\n#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)\r\n#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */\r\n#    ifdef VMS\r\n#      include <unixio.h>       /* for off_t */\r\n#    endif\r\n#    ifndef z_off_t\r\n#      define z_off_t off_t\r\n#    endif\r\n#  endif\r\n#endif\r\n\r\n#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0\r\n#  define Z_LFS64\r\n#endif\r\n\r\n#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)\r\n#  define Z_LARGE64\r\n#endif\r\n\r\n#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)\r\n#  define Z_WANT64\r\n#endif\r\n\r\n#if !defined(SEEK_SET) && !defined(Z_SOLO)\r\n#  define SEEK_SET        0       /* Seek from beginning of file.  */\r\n#  define SEEK_CUR        1       /* Seek from current position.  */\r\n#  define SEEK_END        2       /* Set file pointer to EOF plus \"offset\" */\r\n#endif\r\n\r\n#ifndef z_off_t\r\n#  define z_off_t long\r\n#endif\r\n\r\n#if !defined(_WIN32) && defined(Z_LARGE64)\r\n#  define z_off64_t off64_t\r\n#else\r\n#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)\r\n#    define z_off64_t __int64\r\n#  else\r\n#    define z_off64_t z_off_t\r\n#  endif\r\n#endif\r\n\r\n/* MVS linker does not support external names larger than 8 bytes */\r\n#if defined(__MVS__)\r\n  #pragma map(deflateInit_,\"DEIN\")\r\n  #pragma map(deflateInit2_,\"DEIN2\")\r\n  #pragma map(deflateEnd,\"DEEND\")\r\n  #pragma map(deflateBound,\"DEBND\")\r\n  #pragma map(inflateInit_,\"ININ\")\r\n  #pragma map(inflateInit2_,\"ININ2\")\r\n  #pragma map(inflateEnd,\"INEND\")\r\n  #pragma map(inflateSync,\"INSY\")\r\n  #pragma map(inflateSetDictionary,\"INSEDI\")\r\n  #pragma map(compressBound,\"CMBND\")\r\n  #pragma map(inflate_table,\"INTABL\")\r\n  #pragma map(inflate_fast,\"INFA\")\r\n  #pragma map(inflate_copyright,\"INCOPY\")\r\n#endif\r\n\r\n#endif /* ZCONF_H */\r\n"
  },
  {
    "path": "MiniEngine/zlib-1.2.11/zlib.h",
    "content": "/* zlib.h -- interface of the 'zlib' general purpose compression library\r\n  version 1.2.11, January 15th, 2017\r\n\r\n  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler\r\n\r\n  This software is provided 'as-is', without any express or implied\r\n  warranty.  In no event will the authors be held liable for any damages\r\n  arising from the use of this software.\r\n\r\n  Permission is granted to anyone to use this software for any purpose,\r\n  including commercial applications, and to alter it and redistribute it\r\n  freely, subject to the following restrictions:\r\n\r\n  1. The origin of this software must not be misrepresented; you must not\r\n     claim that you wrote the original software. If you use this software\r\n     in a product, an acknowledgment in the product documentation would be\r\n     appreciated but is not required.\r\n  2. Altered source versions must be plainly marked as such, and must not be\r\n     misrepresented as being the original software.\r\n  3. This notice may not be removed or altered from any source distribution.\r\n\r\n  Jean-loup Gailly        Mark Adler\r\n  jloup@gzip.org          madler@alumni.caltech.edu\r\n\r\n\r\n  The data format used by the zlib library is described by RFCs (Request for\r\n  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950\r\n  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).\r\n*/\r\n\r\n#ifndef ZLIB_H\r\n#define ZLIB_H\r\n\r\n#include \"zconf.h\"\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n#define ZLIB_VERSION \"1.2.11\"\r\n#define ZLIB_VERNUM 0x12b0\r\n#define ZLIB_VER_MAJOR 1\r\n#define ZLIB_VER_MINOR 2\r\n#define ZLIB_VER_REVISION 11\r\n#define ZLIB_VER_SUBREVISION 0\r\n\r\n/*\r\n    The 'zlib' compression library provides in-memory compression and\r\n  decompression functions, including integrity checks of the uncompressed data.\r\n  This version of the library supports only one compression method (deflation)\r\n  but other algorithms will be added later and will have the same stream\r\n  interface.\r\n\r\n    Compression can be done in a single step if the buffers are large enough,\r\n  or can be done by repeated calls of the compression function.  In the latter\r\n  case, the application must provide more input and/or consume the output\r\n  (providing more output space) before each call.\r\n\r\n    The compressed data format used by default by the in-memory functions is\r\n  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped\r\n  around a deflate stream, which is itself documented in RFC 1951.\r\n\r\n    The library also supports reading and writing files in gzip (.gz) format\r\n  with an interface similar to that of stdio using the functions that start\r\n  with \"gz\".  The gzip format is different from the zlib format.  gzip is a\r\n  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.\r\n\r\n    This library can optionally read and write gzip and raw deflate streams in\r\n  memory as well.\r\n\r\n    The zlib format was designed to be compact and fast for use in memory\r\n  and on communications channels.  The gzip format was designed for single-\r\n  file compression on file systems, has a larger header than zlib to maintain\r\n  directory information, and uses a different, slower check method than zlib.\r\n\r\n    The library does not install any signal handler.  The decoder checks\r\n  the consistency of the compressed data, so the library should never crash\r\n  even in the case of corrupted input.\r\n*/\r\n\r\ntypedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));\r\ntypedef void   (*free_func)  OF((voidpf opaque, voidpf address));\r\n\r\nstruct internal_state;\r\n\r\ntypedef struct z_stream_s {\r\n    z_const Bytef *next_in;     /* next input byte */\r\n    uInt     avail_in;  /* number of bytes available at next_in */\r\n    uLong    total_in;  /* total number of input bytes read so far */\r\n\r\n    Bytef    *next_out; /* next output byte will go here */\r\n    uInt     avail_out; /* remaining free space at next_out */\r\n    uLong    total_out; /* total number of bytes output so far */\r\n\r\n    z_const char *msg;  /* last error message, NULL if no error */\r\n    struct internal_state FAR *state; /* not visible by applications */\r\n\r\n    alloc_func zalloc;  /* used to allocate the internal state */\r\n    free_func  zfree;   /* used to free the internal state */\r\n    voidpf     opaque;  /* private data object passed to zalloc and zfree */\r\n\r\n    int     data_type;  /* best guess about the data type: binary or text\r\n                           for deflate, or the decoding state for inflate */\r\n    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */\r\n    uLong   reserved;   /* reserved for future use */\r\n} z_stream;\r\n\r\ntypedef z_stream FAR *z_streamp;\r\n\r\n/*\r\n     gzip header information passed to and from zlib routines.  See RFC 1952\r\n  for more details on the meanings of these fields.\r\n*/\r\ntypedef struct gz_header_s {\r\n    int     text;       /* true if compressed data believed to be text */\r\n    uLong   time;       /* modification time */\r\n    int     xflags;     /* extra flags (not used when writing a gzip file) */\r\n    int     os;         /* operating system */\r\n    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */\r\n    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */\r\n    uInt    extra_max;  /* space at extra (only when reading header) */\r\n    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */\r\n    uInt    name_max;   /* space at name (only when reading header) */\r\n    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */\r\n    uInt    comm_max;   /* space at comment (only when reading header) */\r\n    int     hcrc;       /* true if there was or will be a header crc */\r\n    int     done;       /* true when done reading gzip header (not used\r\n                           when writing a gzip file) */\r\n} gz_header;\r\n\r\ntypedef gz_header FAR *gz_headerp;\r\n\r\n/*\r\n     The application must update next_in and avail_in when avail_in has dropped\r\n   to zero.  It must update next_out and avail_out when avail_out has dropped\r\n   to zero.  The application must initialize zalloc, zfree and opaque before\r\n   calling the init function.  All other fields are set by the compression\r\n   library and must not be updated by the application.\r\n\r\n     The opaque value provided by the application will be passed as the first\r\n   parameter for calls of zalloc and zfree.  This can be useful for custom\r\n   memory management.  The compression library attaches no meaning to the\r\n   opaque value.\r\n\r\n     zalloc must return Z_NULL if there is not enough memory for the object.\r\n   If zlib is used in a multi-threaded application, zalloc and zfree must be\r\n   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are\r\n   Z_NULL on entry to the initialization function, they are set to internal\r\n   routines that use the standard library functions malloc() and free().\r\n\r\n     On 16-bit systems, the functions zalloc and zfree must be able to allocate\r\n   exactly 65536 bytes, but will not be required to allocate more than this if\r\n   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers\r\n   returned by zalloc for objects of exactly 65536 bytes *must* have their\r\n   offset normalized to zero.  The default allocation function provided by this\r\n   library ensures this (see zutil.c).  To reduce memory requirements and avoid\r\n   any allocation of 64K objects, at the expense of compression ratio, compile\r\n   the library with -DMAX_WBITS=14 (see zconf.h).\r\n\r\n     The fields total_in and total_out can be used for statistics or progress\r\n   reports.  After compression, total_in holds the total size of the\r\n   uncompressed data and may be saved for use by the decompressor (particularly\r\n   if the decompressor wants to decompress everything in a single step).\r\n*/\r\n\r\n                        /* constants */\r\n\r\n#define Z_NO_FLUSH      0\r\n#define Z_PARTIAL_FLUSH 1\r\n#define Z_SYNC_FLUSH    2\r\n#define Z_FULL_FLUSH    3\r\n#define Z_FINISH        4\r\n#define Z_BLOCK         5\r\n#define Z_TREES         6\r\n/* Allowed flush values; see deflate() and inflate() below for details */\r\n\r\n#define Z_OK            0\r\n#define Z_STREAM_END    1\r\n#define Z_NEED_DICT     2\r\n#define Z_ERRNO        (-1)\r\n#define Z_STREAM_ERROR (-2)\r\n#define Z_DATA_ERROR   (-3)\r\n#define Z_MEM_ERROR    (-4)\r\n#define Z_BUF_ERROR    (-5)\r\n#define Z_VERSION_ERROR (-6)\r\n/* Return codes for the compression/decompression functions. Negative values\r\n * are errors, positive values are used for special but normal events.\r\n */\r\n\r\n#define Z_NO_COMPRESSION         0\r\n#define Z_BEST_SPEED             1\r\n#define Z_BEST_COMPRESSION       9\r\n#define Z_DEFAULT_COMPRESSION  (-1)\r\n/* compression levels */\r\n\r\n#define Z_FILTERED            1\r\n#define Z_HUFFMAN_ONLY        2\r\n#define Z_RLE                 3\r\n#define Z_FIXED               4\r\n#define Z_DEFAULT_STRATEGY    0\r\n/* compression strategy; see deflateInit2() below for details */\r\n\r\n#define Z_BINARY   0\r\n#define Z_TEXT     1\r\n#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */\r\n#define Z_UNKNOWN  2\r\n/* Possible values of the data_type field for deflate() */\r\n\r\n#define Z_DEFLATED   8\r\n/* The deflate compression method (the only one supported in this version) */\r\n\r\n#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */\r\n\r\n#define zlib_version zlibVersion()\r\n/* for compatibility with versions < 1.0.2 */\r\n\r\n\r\n                        /* basic functions */\r\n\r\nZEXTERN const char * ZEXPORT zlibVersion OF((void));\r\n/* The application can compare zlibVersion and ZLIB_VERSION for consistency.\r\n   If the first character differs, the library code actually used is not\r\n   compatible with the zlib.h header file used by the application.  This check\r\n   is automatically made by deflateInit and inflateInit.\r\n */\r\n\r\n/*\r\nZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));\r\n\r\n     Initializes the internal stream state for compression.  The fields\r\n   zalloc, zfree and opaque must be initialized before by the caller.  If\r\n   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default\r\n   allocation functions.\r\n\r\n     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:\r\n   1 gives best speed, 9 gives best compression, 0 gives no compression at all\r\n   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION\r\n   requests a default compromise between speed and compression (currently\r\n   equivalent to level 6).\r\n\r\n     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\r\n   memory, Z_STREAM_ERROR if level is not a valid compression level, or\r\n   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible\r\n   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null\r\n   if there is no error message.  deflateInit does not perform any compression:\r\n   this will be done by deflate().\r\n*/\r\n\r\n\r\nZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));\r\n/*\r\n    deflate compresses as much data as possible, and stops when the input\r\n  buffer becomes empty or the output buffer becomes full.  It may introduce\r\n  some output latency (reading input without producing any output) except when\r\n  forced to flush.\r\n\r\n    The detailed semantics are as follows.  deflate performs one or both of the\r\n  following actions:\r\n\r\n  - Compress more input starting at next_in and update next_in and avail_in\r\n    accordingly.  If not all input can be processed (because there is not\r\n    enough room in the output buffer), next_in and avail_in are updated and\r\n    processing will resume at this point for the next call of deflate().\r\n\r\n  - Generate more output starting at next_out and update next_out and avail_out\r\n    accordingly.  This action is forced if the parameter flush is non zero.\r\n    Forcing flush frequently degrades the compression ratio, so this parameter\r\n    should be set only when necessary.  Some output may be provided even if\r\n    flush is zero.\r\n\r\n    Before the call of deflate(), the application should ensure that at least\r\n  one of the actions is possible, by providing more input and/or consuming more\r\n  output, and updating avail_in or avail_out accordingly; avail_out should\r\n  never be zero before the call.  The application can consume the compressed\r\n  output when it wants, for example when the output buffer is full (avail_out\r\n  == 0), or after each call of deflate().  If deflate returns Z_OK and with\r\n  zero avail_out, it must be called again after making room in the output\r\n  buffer because there might be more output pending. See deflatePending(),\r\n  which can be used if desired to determine whether or not there is more ouput\r\n  in that case.\r\n\r\n    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to\r\n  decide how much data to accumulate before producing output, in order to\r\n  maximize compression.\r\n\r\n    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is\r\n  flushed to the output buffer and the output is aligned on a byte boundary, so\r\n  that the decompressor can get all input data available so far.  (In\r\n  particular avail_in is zero after the call if enough output space has been\r\n  provided before the call.) Flushing may degrade compression for some\r\n  compression algorithms and so it should be used only when necessary.  This\r\n  completes the current deflate block and follows it with an empty stored block\r\n  that is three bits plus filler bits to the next byte, followed by four bytes\r\n  (00 00 ff ff).\r\n\r\n    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the\r\n  output buffer, but the output is not aligned to a byte boundary.  All of the\r\n  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.\r\n  This completes the current deflate block and follows it with an empty fixed\r\n  codes block that is 10 bits long.  This assures that enough bytes are output\r\n  in order for the decompressor to finish the block before the empty fixed\r\n  codes block.\r\n\r\n    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as\r\n  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to\r\n  seven bits of the current block are held to be written as the next byte after\r\n  the next deflate block is completed.  In this case, the decompressor may not\r\n  be provided enough bits at this point in order to complete decompression of\r\n  the data provided so far to the compressor.  It may need to wait for the next\r\n  block to be emitted.  This is for advanced applications that need to control\r\n  the emission of deflate blocks.\r\n\r\n    If flush is set to Z_FULL_FLUSH, all output is flushed as with\r\n  Z_SYNC_FLUSH, and the compression state is reset so that decompression can\r\n  restart from this point if previous compressed data has been damaged or if\r\n  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade\r\n  compression.\r\n\r\n    If deflate returns with avail_out == 0, this function must be called again\r\n  with the same value of the flush parameter and more output space (updated\r\n  avail_out), until the flush is complete (deflate returns with non-zero\r\n  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that\r\n  avail_out is greater than six to avoid repeated flush markers due to\r\n  avail_out == 0 on return.\r\n\r\n    If the parameter flush is set to Z_FINISH, pending input is processed,\r\n  pending output is flushed and deflate returns with Z_STREAM_END if there was\r\n  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this\r\n  function must be called again with Z_FINISH and more output space (updated\r\n  avail_out) but no more input data, until it returns with Z_STREAM_END or an\r\n  error.  After deflate has returned Z_STREAM_END, the only possible operations\r\n  on the stream are deflateReset or deflateEnd.\r\n\r\n    Z_FINISH can be used in the first deflate call after deflateInit if all the\r\n  compression is to be done in a single step.  In order to complete in one\r\n  call, avail_out must be at least the value returned by deflateBound (see\r\n  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough\r\n  output space is provided, deflate will not return Z_STREAM_END, and it must\r\n  be called again as described above.\r\n\r\n    deflate() sets strm->adler to the Adler-32 checksum of all input read\r\n  so far (that is, total_in bytes).  If a gzip stream is being generated, then\r\n  strm->adler will be the CRC-32 checksum of the input read so far.  (See\r\n  deflateInit2 below.)\r\n\r\n    deflate() may update strm->data_type if it can make a good guess about\r\n  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is\r\n  considered binary.  This field is only for information purposes and does not\r\n  affect the compression algorithm in any manner.\r\n\r\n    deflate() returns Z_OK if some progress has been made (more input\r\n  processed or more output produced), Z_STREAM_END if all input has been\r\n  consumed and all output has been produced (only when flush is set to\r\n  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example\r\n  if next_in or next_out was Z_NULL or the state was inadvertently written over\r\n  by the application), or Z_BUF_ERROR if no progress is possible (for example\r\n  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and\r\n  deflate() can be called again with more input and more output space to\r\n  continue compressing.\r\n*/\r\n\r\n\r\nZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));\r\n/*\r\n     All dynamically allocated data structures for this stream are freed.\r\n   This function discards any unprocessed input and does not flush any pending\r\n   output.\r\n\r\n     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the\r\n   stream state was inconsistent, Z_DATA_ERROR if the stream was freed\r\n   prematurely (some input or output was discarded).  In the error case, msg\r\n   may be set but then points to a static string (which must not be\r\n   deallocated).\r\n*/\r\n\r\n\r\n/*\r\nZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));\r\n\r\n     Initializes the internal stream state for decompression.  The fields\r\n   next_in, avail_in, zalloc, zfree and opaque must be initialized before by\r\n   the caller.  In the current version of inflate, the provided input is not\r\n   read or consumed.  The allocation of a sliding window will be deferred to\r\n   the first call of inflate (if the decompression does not complete on the\r\n   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates\r\n   them to use default allocation functions.\r\n\r\n     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\r\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\r\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\r\n   invalid, such as a null pointer to the structure.  msg is set to null if\r\n   there is no error message.  inflateInit does not perform any decompression.\r\n   Actual decompression will be done by inflate().  So next_in, and avail_in,\r\n   next_out, and avail_out are unused and unchanged.  The current\r\n   implementation of inflateInit() does not process any header information --\r\n   that is deferred until inflate() is called.\r\n*/\r\n\r\n\r\nZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));\r\n/*\r\n    inflate decompresses as much data as possible, and stops when the input\r\n  buffer becomes empty or the output buffer becomes full.  It may introduce\r\n  some output latency (reading input without producing any output) except when\r\n  forced to flush.\r\n\r\n  The detailed semantics are as follows.  inflate performs one or both of the\r\n  following actions:\r\n\r\n  - Decompress more input starting at next_in and update next_in and avail_in\r\n    accordingly.  If not all input can be processed (because there is not\r\n    enough room in the output buffer), then next_in and avail_in are updated\r\n    accordingly, and processing will resume at this point for the next call of\r\n    inflate().\r\n\r\n  - Generate more output starting at next_out and update next_out and avail_out\r\n    accordingly.  inflate() provides as much output as possible, until there is\r\n    no more input data or no more space in the output buffer (see below about\r\n    the flush parameter).\r\n\r\n    Before the call of inflate(), the application should ensure that at least\r\n  one of the actions is possible, by providing more input and/or consuming more\r\n  output, and updating the next_* and avail_* values accordingly.  If the\r\n  caller of inflate() does not provide both available input and available\r\n  output space, it is possible that there will be no progress made.  The\r\n  application can consume the uncompressed output when it wants, for example\r\n  when the output buffer is full (avail_out == 0), or after each call of\r\n  inflate().  If inflate returns Z_OK and with zero avail_out, it must be\r\n  called again after making room in the output buffer because there might be\r\n  more output pending.\r\n\r\n    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,\r\n  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much\r\n  output as possible to the output buffer.  Z_BLOCK requests that inflate()\r\n  stop if and when it gets to the next deflate block boundary.  When decoding\r\n  the zlib or gzip format, this will cause inflate() to return immediately\r\n  after the header and before the first block.  When doing a raw inflate,\r\n  inflate() will go ahead and process the first block, and will return when it\r\n  gets to the end of that block, or when it runs out of data.\r\n\r\n    The Z_BLOCK option assists in appending to or combining deflate streams.\r\n  To assist in this, on return inflate() always sets strm->data_type to the\r\n  number of unused bits in the last byte taken from strm->next_in, plus 64 if\r\n  inflate() is currently decoding the last block in the deflate stream, plus\r\n  128 if inflate() returned immediately after decoding an end-of-block code or\r\n  decoding the complete header up to just before the first byte of the deflate\r\n  stream.  The end-of-block will not be indicated until all of the uncompressed\r\n  data from that block has been written to strm->next_out.  The number of\r\n  unused bits may in general be greater than seven, except when bit 7 of\r\n  data_type is set, in which case the number of unused bits will be less than\r\n  eight.  data_type is set as noted here every time inflate() returns for all\r\n  flush options, and so can be used to determine the amount of currently\r\n  consumed input in bits.\r\n\r\n    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the\r\n  end of each deflate block header is reached, before any actual data in that\r\n  block is decoded.  This allows the caller to determine the length of the\r\n  deflate block header for later use in random access within a deflate block.\r\n  256 is added to the value of strm->data_type when inflate() returns\r\n  immediately after reaching the end of the deflate block header.\r\n\r\n    inflate() should normally be called until it returns Z_STREAM_END or an\r\n  error.  However if all decompression is to be performed in a single step (a\r\n  single call of inflate), the parameter flush should be set to Z_FINISH.  In\r\n  this case all pending input is processed and all pending output is flushed;\r\n  avail_out must be large enough to hold all of the uncompressed data for the\r\n  operation to complete.  (The size of the uncompressed data may have been\r\n  saved by the compressor for this purpose.)  The use of Z_FINISH is not\r\n  required to perform an inflation in one step.  However it may be used to\r\n  inform inflate that a faster approach can be used for the single inflate()\r\n  call.  Z_FINISH also informs inflate to not maintain a sliding window if the\r\n  stream completes, which reduces inflate's memory footprint.  If the stream\r\n  does not complete, either because not all of the stream is provided or not\r\n  enough output space is provided, then a sliding window will be allocated and\r\n  inflate() can be called again to continue the operation as if Z_NO_FLUSH had\r\n  been used.\r\n\r\n     In this implementation, inflate() always flushes as much output as\r\n  possible to the output buffer, and always uses the faster approach on the\r\n  first call.  So the effects of the flush parameter in this implementation are\r\n  on the return value of inflate() as noted below, when inflate() returns early\r\n  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of\r\n  memory for a sliding window when Z_FINISH is used.\r\n\r\n     If a preset dictionary is needed after this call (see inflateSetDictionary\r\n  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary\r\n  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets\r\n  strm->adler to the Adler-32 checksum of all output produced so far (that is,\r\n  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described\r\n  below.  At the end of the stream, inflate() checks that its computed Adler-32\r\n  checksum is equal to that saved by the compressor and returns Z_STREAM_END\r\n  only if the checksum is correct.\r\n\r\n    inflate() can decompress and check either zlib-wrapped or gzip-wrapped\r\n  deflate data.  The header type is detected automatically, if requested when\r\n  initializing with inflateInit2().  Any information contained in the gzip\r\n  header is not retained unless inflateGetHeader() is used.  When processing\r\n  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output\r\n  produced so far.  The CRC-32 is checked against the gzip trailer, as is the\r\n  uncompressed length, modulo 2^32.\r\n\r\n    inflate() returns Z_OK if some progress has been made (more input processed\r\n  or more output produced), Z_STREAM_END if the end of the compressed data has\r\n  been reached and all uncompressed output has been produced, Z_NEED_DICT if a\r\n  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was\r\n  corrupted (input stream not conforming to the zlib format or incorrect check\r\n  value, in which case strm->msg points to a string with a more specific\r\n  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example\r\n  next_in or next_out was Z_NULL, or the state was inadvertently written over\r\n  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR\r\n  if no progress was possible or if there was not enough room in the output\r\n  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and\r\n  inflate() can be called again with more input and more output space to\r\n  continue decompressing.  If Z_DATA_ERROR is returned, the application may\r\n  then call inflateSync() to look for a good compression block if a partial\r\n  recovery of the data is to be attempted.\r\n*/\r\n\r\n\r\nZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));\r\n/*\r\n     All dynamically allocated data structures for this stream are freed.\r\n   This function discards any unprocessed input and does not flush any pending\r\n   output.\r\n\r\n     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state\r\n   was inconsistent.\r\n*/\r\n\r\n\r\n                        /* Advanced functions */\r\n\r\n/*\r\n    The following functions are needed only in some special applications.\r\n*/\r\n\r\n/*\r\nZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,\r\n                                     int  level,\r\n                                     int  method,\r\n                                     int  windowBits,\r\n                                     int  memLevel,\r\n                                     int  strategy));\r\n\r\n     This is another version of deflateInit with more compression options.  The\r\n   fields next_in, zalloc, zfree and opaque must be initialized before by the\r\n   caller.\r\n\r\n     The method parameter is the compression method.  It must be Z_DEFLATED in\r\n   this version of the library.\r\n\r\n     The windowBits parameter is the base two logarithm of the window size\r\n   (the size of the history buffer).  It should be in the range 8..15 for this\r\n   version of the library.  Larger values of this parameter result in better\r\n   compression at the expense of memory usage.  The default value is 15 if\r\n   deflateInit is used instead.\r\n\r\n     For the current implementation of deflate(), a windowBits value of 8 (a\r\n   window size of 256 bytes) is not supported.  As a result, a request for 8\r\n   will result in 9 (a 512-byte window).  In that case, providing 8 to\r\n   inflateInit2() will result in an error when the zlib header with 9 is\r\n   checked against the initialization of inflate().  The remedy is to not use 8\r\n   with deflateInit2() with this initialization, or at least in that case use 9\r\n   with inflateInit2().\r\n\r\n     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits\r\n   determines the window size.  deflate() will then generate raw deflate data\r\n   with no zlib header or trailer, and will not compute a check value.\r\n\r\n     windowBits can also be greater than 15 for optional gzip encoding.  Add\r\n   16 to windowBits to write a simple gzip header and trailer around the\r\n   compressed data instead of a zlib wrapper.  The gzip header will have no\r\n   file name, no extra data, no comment, no modification time (set to zero), no\r\n   header crc, and the operating system will be set to the appropriate value,\r\n   if the operating system was determined at compile time.  If a gzip stream is\r\n   being written, strm->adler is a CRC-32 instead of an Adler-32.\r\n\r\n     For raw deflate or gzip encoding, a request for a 256-byte window is\r\n   rejected as invalid, since only the zlib header provides a means of\r\n   transmitting the window size to the decompressor.\r\n\r\n     The memLevel parameter specifies how much memory should be allocated\r\n   for the internal compression state.  memLevel=1 uses minimum memory but is\r\n   slow and reduces compression ratio; memLevel=9 uses maximum memory for\r\n   optimal speed.  The default value is 8.  See zconf.h for total memory usage\r\n   as a function of windowBits and memLevel.\r\n\r\n     The strategy parameter is used to tune the compression algorithm.  Use the\r\n   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a\r\n   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no\r\n   string match), or Z_RLE to limit match distances to one (run-length\r\n   encoding).  Filtered data consists mostly of small values with a somewhat\r\n   random distribution.  In this case, the compression algorithm is tuned to\r\n   compress them better.  The effect of Z_FILTERED is to force more Huffman\r\n   coding and less string matching; it is somewhat intermediate between\r\n   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as\r\n   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The\r\n   strategy parameter only affects the compression ratio but not the\r\n   correctness of the compressed output even if it is not set appropriately.\r\n   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler\r\n   decoder for special applications.\r\n\r\n     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\r\n   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid\r\n   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is\r\n   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is\r\n   set to null if there is no error message.  deflateInit2 does not perform any\r\n   compression: this will be done by deflate().\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,\r\n                                             const Bytef *dictionary,\r\n                                             uInt  dictLength));\r\n/*\r\n     Initializes the compression dictionary from the given byte sequence\r\n   without producing any compressed output.  When using the zlib format, this\r\n   function must be called immediately after deflateInit, deflateInit2 or\r\n   deflateReset, and before any call of deflate.  When doing raw deflate, this\r\n   function must be called either before any call of deflate, or immediately\r\n   after the completion of a deflate block, i.e. after all input has been\r\n   consumed and all output has been delivered when using any of the flush\r\n   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The\r\n   compressor and decompressor must use exactly the same dictionary (see\r\n   inflateSetDictionary).\r\n\r\n     The dictionary should consist of strings (byte sequences) that are likely\r\n   to be encountered later in the data to be compressed, with the most commonly\r\n   used strings preferably put towards the end of the dictionary.  Using a\r\n   dictionary is most useful when the data to be compressed is short and can be\r\n   predicted with good accuracy; the data can then be compressed better than\r\n   with the default empty dictionary.\r\n\r\n     Depending on the size of the compression data structures selected by\r\n   deflateInit or deflateInit2, a part of the dictionary may in effect be\r\n   discarded, for example if the dictionary is larger than the window size\r\n   provided in deflateInit or deflateInit2.  Thus the strings most likely to be\r\n   useful should be put at the end of the dictionary, not at the front.  In\r\n   addition, the current implementation of deflate will use at most the window\r\n   size minus 262 bytes of the provided dictionary.\r\n\r\n     Upon return of this function, strm->adler is set to the Adler-32 value\r\n   of the dictionary; the decompressor may later use this value to determine\r\n   which dictionary has been used by the compressor.  (The Adler-32 value\r\n   applies to the whole dictionary even if only a subset of the dictionary is\r\n   actually used by the compressor.) If a raw deflate was requested, then the\r\n   Adler-32 value is not computed and strm->adler is not set.\r\n\r\n     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a\r\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\r\n   inconsistent (for example if deflate has already been called for this stream\r\n   or if not at a block boundary for raw deflate).  deflateSetDictionary does\r\n   not perform any compression: this will be done by deflate().\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,\r\n                                             Bytef *dictionary,\r\n                                             uInt  *dictLength));\r\n/*\r\n     Returns the sliding dictionary being maintained by deflate.  dictLength is\r\n   set to the number of bytes in the dictionary, and that many bytes are copied\r\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\r\n   always enough.  If deflateGetDictionary() is called with dictionary equal to\r\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\r\n   Similary, if dictLength is Z_NULL, then it is not set.\r\n\r\n     deflateGetDictionary() may return a length less than the window size, even\r\n   when more than the window size in input has been provided. It may return up\r\n   to 258 bytes less in that case, due to how zlib's implementation of deflate\r\n   manages the sliding window and lookahead for matches, where matches can be\r\n   up to 258 bytes long. If the application needs the last window-size bytes of\r\n   input, then that would need to be saved by the application outside of zlib.\r\n\r\n     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\r\n   stream state is inconsistent.\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,\r\n                                    z_streamp source));\r\n/*\r\n     Sets the destination stream as a complete copy of the source stream.\r\n\r\n     This function can be useful when several compression strategies will be\r\n   tried, for example when there are several ways of pre-processing the input\r\n   data with a filter.  The streams that will be discarded should then be freed\r\n   by calling deflateEnd.  Note that deflateCopy duplicates the internal\r\n   compression state which can be quite large, so this strategy is slow and can\r\n   consume lots of memory.\r\n\r\n     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\r\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\r\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\r\n   destination.\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));\r\n/*\r\n     This function is equivalent to deflateEnd followed by deflateInit, but\r\n   does not free and reallocate the internal compression state.  The stream\r\n   will leave the compression level and any other attributes that may have been\r\n   set unchanged.\r\n\r\n     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,\r\n                                      int level,\r\n                                      int strategy));\r\n/*\r\n     Dynamically update the compression level and compression strategy.  The\r\n   interpretation of level and strategy is as in deflateInit2().  This can be\r\n   used to switch between compression and straight copy of the input data, or\r\n   to switch to a different kind of input data requiring a different strategy.\r\n   If the compression approach (which is a function of the level) or the\r\n   strategy is changed, and if any input has been consumed in a previous\r\n   deflate() call, then the input available so far is compressed with the old\r\n   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches\r\n   for the compression levels 0, 1..3, and 4..9 respectively.  The new level\r\n   and strategy will take effect at the next call of deflate().\r\n\r\n     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does\r\n   not have enough output space to complete, then the parameter change will not\r\n   take effect.  In this case, deflateParams() can be called again with the\r\n   same parameters and more output space to try again.\r\n\r\n     In order to assure a change in the parameters on the first try, the\r\n   deflate stream should be flushed using deflate() with Z_BLOCK or other flush\r\n   request until strm.avail_out is not zero, before calling deflateParams().\r\n   Then no more input data should be provided before the deflateParams() call.\r\n   If this is done, the old level and strategy will be applied to the data\r\n   compressed before deflateParams(), and the new level and strategy will be\r\n   applied to the the data compressed after deflateParams().\r\n\r\n     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream\r\n   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if\r\n   there was not enough output space to complete the compression of the\r\n   available input data before a change in the strategy or approach.  Note that\r\n   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return\r\n   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be\r\n   retried with more output space.\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,\r\n                                    int good_length,\r\n                                    int max_lazy,\r\n                                    int nice_length,\r\n                                    int max_chain));\r\n/*\r\n     Fine tune deflate's internal compression parameters.  This should only be\r\n   used by someone who understands the algorithm used by zlib's deflate for\r\n   searching for the best matching string, and even then only by the most\r\n   fanatic optimizer trying to squeeze out the last compressed bit for their\r\n   specific input data.  Read the deflate.c source code for the meaning of the\r\n   max_lazy, good_length, nice_length, and max_chain parameters.\r\n\r\n     deflateTune() can be called after deflateInit() or deflateInit2(), and\r\n   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.\r\n */\r\n\r\nZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,\r\n                                       uLong sourceLen));\r\n/*\r\n     deflateBound() returns an upper bound on the compressed size after\r\n   deflation of sourceLen bytes.  It must be called after deflateInit() or\r\n   deflateInit2(), and after deflateSetHeader(), if used.  This would be used\r\n   to allocate an output buffer for deflation in a single pass, and so would be\r\n   called before deflate().  If that first deflate() call is provided the\r\n   sourceLen input bytes, an output buffer allocated to the size returned by\r\n   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed\r\n   to return Z_STREAM_END.  Note that it is possible for the compressed size to\r\n   be larger than the value returned by deflateBound() if flush options other\r\n   than Z_FINISH or Z_NO_FLUSH are used.\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,\r\n                                       unsigned *pending,\r\n                                       int *bits));\r\n/*\r\n     deflatePending() returns the number of bytes and bits of output that have\r\n   been generated, but not yet provided in the available output.  The bytes not\r\n   provided would be due to the available output space having being consumed.\r\n   The number of bits of output not provided are between 0 and 7, where they\r\n   await more bits to join them in order to fill out a full byte.  If pending\r\n   or bits are Z_NULL, then those values are not set.\r\n\r\n     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent.\r\n */\r\n\r\nZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,\r\n                                     int bits,\r\n                                     int value));\r\n/*\r\n     deflatePrime() inserts bits in the deflate output stream.  The intent\r\n   is that this function is used to start off the deflate output with the bits\r\n   leftover from a previous deflate stream when appending to it.  As such, this\r\n   function can only be used for raw deflate, and must be used before the first\r\n   deflate() call after a deflateInit2() or deflateReset().  bits must be less\r\n   than or equal to 16, and that many of the least significant bits of value\r\n   will be inserted in the output.\r\n\r\n     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough\r\n   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the\r\n   source stream state was inconsistent.\r\n*/\r\n\r\nZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,\r\n                                         gz_headerp head));\r\n/*\r\n     deflateSetHeader() provides gzip header information for when a gzip\r\n   stream is requested by deflateInit2().  deflateSetHeader() may be called\r\n   after deflateInit2() or deflateReset() and before the first call of\r\n   deflate().  The text, time, os, extra field, name, and comment information\r\n   in the provided gz_header structure are written to the gzip header (xflag is\r\n   ignored -- the extra flags are set according to the compression level).  The\r\n   caller must assure that, if not Z_NULL, name and comment are terminated with\r\n   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are\r\n   available there.  If hcrc is true, a gzip header crc is included.  Note that\r\n   the current versions of the command-line version of gzip (up through version\r\n   1.3.x) do not support header crc's, and will report that it is a \"multi-part\r\n   gzip file\" and give up.\r\n\r\n     If deflateSetHeader is not used, the default gzip header has text false,\r\n   the time set to zero, and os set to 255, with no extra, name, or comment\r\n   fields.  The gzip header is returned to the default state by deflateReset().\r\n\r\n     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent.\r\n*/\r\n\r\n/*\r\nZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,\r\n                                     int  windowBits));\r\n\r\n     This is another version of inflateInit with an extra parameter.  The\r\n   fields next_in, avail_in, zalloc, zfree and opaque must be initialized\r\n   before by the caller.\r\n\r\n     The windowBits parameter is the base two logarithm of the maximum window\r\n   size (the size of the history buffer).  It should be in the range 8..15 for\r\n   this version of the library.  The default value is 15 if inflateInit is used\r\n   instead.  windowBits must be greater than or equal to the windowBits value\r\n   provided to deflateInit2() while compressing, or it must be equal to 15 if\r\n   deflateInit2() was not used.  If a compressed stream with a larger window\r\n   size is given as input, inflate() will return with the error code\r\n   Z_DATA_ERROR instead of trying to allocate a larger window.\r\n\r\n     windowBits can also be zero to request that inflate use the window size in\r\n   the zlib header of the compressed stream.\r\n\r\n     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits\r\n   determines the window size.  inflate() will then process raw deflate data,\r\n   not looking for a zlib or gzip header, not generating a check value, and not\r\n   looking for any check values for comparison at the end of the stream.  This\r\n   is for use with other formats that use the deflate compressed data format\r\n   such as zip.  Those formats provide their own check values.  If a custom\r\n   format is developed using the raw deflate format for compressed data, it is\r\n   recommended that a check value such as an Adler-32 or a CRC-32 be applied to\r\n   the uncompressed data as is done in the zlib, gzip, and zip formats.  For\r\n   most applications, the zlib format should be used as is.  Note that comments\r\n   above on the use in deflateInit2() applies to the magnitude of windowBits.\r\n\r\n     windowBits can also be greater than 15 for optional gzip decoding.  Add\r\n   32 to windowBits to enable zlib and gzip decoding with automatic header\r\n   detection, or add 16 to decode only the gzip format (the zlib format will\r\n   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a\r\n   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see\r\n   below), inflate() will not automatically decode concatenated gzip streams.\r\n   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state\r\n   would need to be reset to continue decoding a subsequent gzip stream.\r\n\r\n     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\r\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\r\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\r\n   invalid, such as a null pointer to the structure.  msg is set to null if\r\n   there is no error message.  inflateInit2 does not perform any decompression\r\n   apart from possibly reading the zlib header if present: actual decompression\r\n   will be done by inflate().  (So next_in and avail_in may be modified, but\r\n   next_out and avail_out are unused and unchanged.) The current implementation\r\n   of inflateInit2() does not process any header information -- that is\r\n   deferred until inflate() is called.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,\r\n                                             const Bytef *dictionary,\r\n                                             uInt  dictLength));\r\n/*\r\n     Initializes the decompression dictionary from the given uncompressed byte\r\n   sequence.  This function must be called immediately after a call of inflate,\r\n   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor\r\n   can be determined from the Adler-32 value returned by that call of inflate.\r\n   The compressor and decompressor must use exactly the same dictionary (see\r\n   deflateSetDictionary).  For raw inflate, this function can be called at any\r\n   time to set the dictionary.  If the provided dictionary is smaller than the\r\n   window and there is already data in the window, then the provided dictionary\r\n   will amend what's there.  The application must insure that the dictionary\r\n   that was used for compression is provided.\r\n\r\n     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a\r\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\r\n   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the\r\n   expected one (incorrect Adler-32 value).  inflateSetDictionary does not\r\n   perform any decompression: this will be done by subsequent calls of\r\n   inflate().\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,\r\n                                             Bytef *dictionary,\r\n                                             uInt  *dictLength));\r\n/*\r\n     Returns the sliding dictionary being maintained by inflate.  dictLength is\r\n   set to the number of bytes in the dictionary, and that many bytes are copied\r\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\r\n   always enough.  If inflateGetDictionary() is called with dictionary equal to\r\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\r\n   Similary, if dictLength is Z_NULL, then it is not set.\r\n\r\n     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\r\n   stream state is inconsistent.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));\r\n/*\r\n     Skips invalid compressed data until a possible full flush point (see above\r\n   for the description of deflate with Z_FULL_FLUSH) can be found, or until all\r\n   available input is skipped.  No output is provided.\r\n\r\n     inflateSync searches for a 00 00 FF FF pattern in the compressed data.\r\n   All full flush points have this pattern, but not all occurrences of this\r\n   pattern are full flush points.\r\n\r\n     inflateSync returns Z_OK if a possible full flush point has been found,\r\n   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point\r\n   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.\r\n   In the success case, the application may save the current current value of\r\n   total_in which indicates where valid compressed data was found.  In the\r\n   error case, the application may repeatedly call inflateSync, providing more\r\n   input each time, until success or end of the input data.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,\r\n                                    z_streamp source));\r\n/*\r\n     Sets the destination stream as a complete copy of the source stream.\r\n\r\n     This function can be useful when randomly accessing a large stream.  The\r\n   first pass through the stream can periodically record the inflate state,\r\n   allowing restarting inflate at those points when randomly accessing the\r\n   stream.\r\n\r\n     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\r\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\r\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\r\n   destination.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));\r\n/*\r\n     This function is equivalent to inflateEnd followed by inflateInit,\r\n   but does not free and reallocate the internal decompression state.  The\r\n   stream will keep attributes that may have been set by inflateInit2.\r\n\r\n     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,\r\n                                      int windowBits));\r\n/*\r\n     This function is the same as inflateReset, but it also permits changing\r\n   the wrap and window size requests.  The windowBits parameter is interpreted\r\n   the same as it is for inflateInit2.  If the window size is changed, then the\r\n   memory allocated for the window is freed, and the window will be reallocated\r\n   by inflate() if needed.\r\n\r\n     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent (such as zalloc or state being Z_NULL), or if\r\n   the windowBits parameter is invalid.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,\r\n                                     int bits,\r\n                                     int value));\r\n/*\r\n     This function inserts bits in the inflate input stream.  The intent is\r\n   that this function is used to start inflating at a bit position in the\r\n   middle of a byte.  The provided bits will be used before any bytes are used\r\n   from next_in.  This function should only be used with raw inflate, and\r\n   should be used before the first inflate() call after inflateInit2() or\r\n   inflateReset().  bits must be less than or equal to 16, and that many of the\r\n   least significant bits of value will be inserted in the input.\r\n\r\n     If bits is negative, then the input stream bit buffer is emptied.  Then\r\n   inflatePrime() can be called again to put bits in the buffer.  This is used\r\n   to clear out bits leftover after feeding inflate a block description prior\r\n   to feeding inflate codes.\r\n\r\n     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent.\r\n*/\r\n\r\nZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));\r\n/*\r\n     This function returns two values, one in the lower 16 bits of the return\r\n   value, and the other in the remaining upper bits, obtained by shifting the\r\n   return value down 16 bits.  If the upper value is -1 and the lower value is\r\n   zero, then inflate() is currently decoding information outside of a block.\r\n   If the upper value is -1 and the lower value is non-zero, then inflate is in\r\n   the middle of a stored block, with the lower value equaling the number of\r\n   bytes from the input remaining to copy.  If the upper value is not -1, then\r\n   it is the number of bits back from the current bit position in the input of\r\n   the code (literal or length/distance pair) currently being processed.  In\r\n   that case the lower value is the number of bytes already emitted for that\r\n   code.\r\n\r\n     A code is being processed if inflate is waiting for more input to complete\r\n   decoding of the code, or if it has completed decoding but is waiting for\r\n   more output space to write the literal or match data.\r\n\r\n     inflateMark() is used to mark locations in the input data for random\r\n   access, which may be at bit positions, and to note those cases where the\r\n   output of a code may span boundaries of random access blocks.  The current\r\n   location in the input stream can be determined from avail_in and data_type\r\n   as noted in the description for the Z_BLOCK flush parameter for inflate.\r\n\r\n     inflateMark returns the value noted above, or -65536 if the provided\r\n   source stream state was inconsistent.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,\r\n                                         gz_headerp head));\r\n/*\r\n     inflateGetHeader() requests that gzip header information be stored in the\r\n   provided gz_header structure.  inflateGetHeader() may be called after\r\n   inflateInit2() or inflateReset(), and before the first call of inflate().\r\n   As inflate() processes the gzip stream, head->done is zero until the header\r\n   is completed, at which time head->done is set to one.  If a zlib stream is\r\n   being decoded, then head->done is set to -1 to indicate that there will be\r\n   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be\r\n   used to force inflate() to return immediately after header processing is\r\n   complete and before any actual data is decompressed.\r\n\r\n     The text, time, xflags, and os fields are filled in with the gzip header\r\n   contents.  hcrc is set to true if there is a header CRC.  (The header CRC\r\n   was valid if done is set to one.) If extra is not Z_NULL, then extra_max\r\n   contains the maximum number of bytes to write to extra.  Once done is true,\r\n   extra_len contains the actual extra field length, and extra contains the\r\n   extra field, or that field truncated if extra_max is less than extra_len.\r\n   If name is not Z_NULL, then up to name_max characters are written there,\r\n   terminated with a zero unless the length is greater than name_max.  If\r\n   comment is not Z_NULL, then up to comm_max characters are written there,\r\n   terminated with a zero unless the length is greater than comm_max.  When any\r\n   of extra, name, or comment are not Z_NULL and the respective field is not\r\n   present in the header, then that field is set to Z_NULL to signal its\r\n   absence.  This allows the use of deflateSetHeader() with the returned\r\n   structure to duplicate the header.  However if those fields are set to\r\n   allocated memory, then the application will need to save those pointers\r\n   elsewhere so that they can be eventually freed.\r\n\r\n     If inflateGetHeader is not used, then the header information is simply\r\n   discarded.  The header is always checked for validity, including the header\r\n   CRC if present.  inflateReset() will reset the process to discard the header\r\n   information.  The application would need to call inflateGetHeader() again to\r\n   retrieve the header from the next gzip stream.\r\n\r\n     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\r\n   stream state was inconsistent.\r\n*/\r\n\r\n/*\r\nZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,\r\n                                        unsigned char FAR *window));\r\n\r\n     Initialize the internal stream state for decompression using inflateBack()\r\n   calls.  The fields zalloc, zfree and opaque in strm must be initialized\r\n   before the call.  If zalloc and zfree are Z_NULL, then the default library-\r\n   derived memory allocation routines are used.  windowBits is the base two\r\n   logarithm of the window size, in the range 8..15.  window is a caller\r\n   supplied buffer of that size.  Except for special applications where it is\r\n   assured that deflate was used with small window sizes, windowBits must be 15\r\n   and a 32K byte window must be supplied to be able to decompress general\r\n   deflate streams.\r\n\r\n     See inflateBack() for the usage of these routines.\r\n\r\n     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of\r\n   the parameters are invalid, Z_MEM_ERROR if the internal state could not be\r\n   allocated, or Z_VERSION_ERROR if the version of the library does not match\r\n   the version of the header file.\r\n*/\r\n\r\ntypedef unsigned (*in_func) OF((void FAR *,\r\n                                z_const unsigned char FAR * FAR *));\r\ntypedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));\r\n\r\nZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,\r\n                                    in_func in, void FAR *in_desc,\r\n                                    out_func out, void FAR *out_desc));\r\n/*\r\n     inflateBack() does a raw inflate with a single call using a call-back\r\n   interface for input and output.  This is potentially more efficient than\r\n   inflate() for file i/o applications, in that it avoids copying between the\r\n   output and the sliding window by simply making the window itself the output\r\n   buffer.  inflate() can be faster on modern CPUs when used with large\r\n   buffers.  inflateBack() trusts the application to not change the output\r\n   buffer passed by the output function, at least until inflateBack() returns.\r\n\r\n     inflateBackInit() must be called first to allocate the internal state\r\n   and to initialize the state with the user-provided window buffer.\r\n   inflateBack() may then be used multiple times to inflate a complete, raw\r\n   deflate stream with each call.  inflateBackEnd() is then called to free the\r\n   allocated state.\r\n\r\n     A raw deflate stream is one with no zlib or gzip header or trailer.\r\n   This routine would normally be used in a utility that reads zip or gzip\r\n   files and writes out uncompressed files.  The utility would decode the\r\n   header and process the trailer on its own, hence this routine expects only\r\n   the raw deflate stream to decompress.  This is different from the default\r\n   behavior of inflate(), which expects a zlib header and trailer around the\r\n   deflate stream.\r\n\r\n     inflateBack() uses two subroutines supplied by the caller that are then\r\n   called by inflateBack() for input and output.  inflateBack() calls those\r\n   routines until it reads a complete deflate stream and writes out all of the\r\n   uncompressed data, or until it encounters an error.  The function's\r\n   parameters and return types are defined above in the in_func and out_func\r\n   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the\r\n   number of bytes of provided input, and a pointer to that input in buf.  If\r\n   there is no input available, in() must return zero -- buf is ignored in that\r\n   case -- and inflateBack() will return a buffer error.  inflateBack() will\r\n   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].\r\n   out() should return zero on success, or non-zero on failure.  If out()\r\n   returns non-zero, inflateBack() will return with an error.  Neither in() nor\r\n   out() are permitted to change the contents of the window provided to\r\n   inflateBackInit(), which is also the buffer that out() uses to write from.\r\n   The length written by out() will be at most the window size.  Any non-zero\r\n   amount of input may be provided by in().\r\n\r\n     For convenience, inflateBack() can be provided input on the first call by\r\n   setting strm->next_in and strm->avail_in.  If that input is exhausted, then\r\n   in() will be called.  Therefore strm->next_in must be initialized before\r\n   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called\r\n   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in\r\n   must also be initialized, and then if strm->avail_in is not zero, input will\r\n   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].\r\n\r\n     The in_desc and out_desc parameters of inflateBack() is passed as the\r\n   first parameter of in() and out() respectively when they are called.  These\r\n   descriptors can be optionally used to pass any information that the caller-\r\n   supplied in() and out() functions need to do their job.\r\n\r\n     On return, inflateBack() will set strm->next_in and strm->avail_in to\r\n   pass back any unused input that was provided by the last in() call.  The\r\n   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR\r\n   if in() or out() returned an error, Z_DATA_ERROR if there was a format error\r\n   in the deflate stream (in which case strm->msg is set to indicate the nature\r\n   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.\r\n   In the case of Z_BUF_ERROR, an input or output error can be distinguished\r\n   using strm->next_in which will be Z_NULL only if in() returned an error.  If\r\n   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning\r\n   non-zero.  (in() will always be called before out(), so strm->next_in is\r\n   assured to be defined if out() returns non-zero.)  Note that inflateBack()\r\n   cannot return Z_OK.\r\n*/\r\n\r\nZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));\r\n/*\r\n     All memory allocated by inflateBackInit() is freed.\r\n\r\n     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream\r\n   state was inconsistent.\r\n*/\r\n\r\nZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));\r\n/* Return flags indicating compile-time options.\r\n\r\n    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:\r\n     1.0: size of uInt\r\n     3.2: size of uLong\r\n     5.4: size of voidpf (pointer)\r\n     7.6: size of z_off_t\r\n\r\n    Compiler, assembler, and debug options:\r\n     8: ZLIB_DEBUG\r\n     9: ASMV or ASMINF -- use ASM code\r\n     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention\r\n     11: 0 (reserved)\r\n\r\n    One-time table building (smaller code, but not thread-safe if true):\r\n     12: BUILDFIXED -- build static block decoding tables when needed\r\n     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed\r\n     14,15: 0 (reserved)\r\n\r\n    Library content (indicates missing functionality):\r\n     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking\r\n                          deflate code when not needed)\r\n     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect\r\n                    and decode gzip streams (to avoid linking crc code)\r\n     18-19: 0 (reserved)\r\n\r\n    Operation variations (changes in library functionality):\r\n     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate\r\n     21: FASTEST -- deflate algorithm with only one, lowest compression level\r\n     22,23: 0 (reserved)\r\n\r\n    The sprintf variant used by gzprintf (zero is best):\r\n     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format\r\n     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!\r\n     26: 0 = returns value, 1 = void -- 1 means inferred string length returned\r\n\r\n    Remainder:\r\n     27-31: 0 (reserved)\r\n */\r\n\r\n#ifndef Z_SOLO\r\n\r\n                        /* utility functions */\r\n\r\n/*\r\n     The following utility functions are implemented on top of the basic\r\n   stream-oriented functions.  To simplify the interface, some default options\r\n   are assumed (compression level and memory usage, standard memory allocation\r\n   functions).  The source code of these utility functions can be modified if\r\n   you need special options.\r\n*/\r\n\r\nZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,\r\n                                 const Bytef *source, uLong sourceLen));\r\n/*\r\n     Compresses the source buffer into the destination buffer.  sourceLen is\r\n   the byte length of the source buffer.  Upon entry, destLen is the total size\r\n   of the destination buffer, which must be at least the value returned by\r\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\r\n   compressed data.  compress() is equivalent to compress2() with a level\r\n   parameter of Z_DEFAULT_COMPRESSION.\r\n\r\n     compress returns Z_OK if success, Z_MEM_ERROR if there was not\r\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\r\n   buffer.\r\n*/\r\n\r\nZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,\r\n                                  const Bytef *source, uLong sourceLen,\r\n                                  int level));\r\n/*\r\n     Compresses the source buffer into the destination buffer.  The level\r\n   parameter has the same meaning as in deflateInit.  sourceLen is the byte\r\n   length of the source buffer.  Upon entry, destLen is the total size of the\r\n   destination buffer, which must be at least the value returned by\r\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\r\n   compressed data.\r\n\r\n     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\r\n   memory, Z_BUF_ERROR if there was not enough room in the output buffer,\r\n   Z_STREAM_ERROR if the level parameter is invalid.\r\n*/\r\n\r\nZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));\r\n/*\r\n     compressBound() returns an upper bound on the compressed size after\r\n   compress() or compress2() on sourceLen bytes.  It would be used before a\r\n   compress() or compress2() call to allocate the destination buffer.\r\n*/\r\n\r\nZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,\r\n                                   const Bytef *source, uLong sourceLen));\r\n/*\r\n     Decompresses the source buffer into the destination buffer.  sourceLen is\r\n   the byte length of the source buffer.  Upon entry, destLen is the total size\r\n   of the destination buffer, which must be large enough to hold the entire\r\n   uncompressed data.  (The size of the uncompressed data must have been saved\r\n   previously by the compressor and transmitted to the decompressor by some\r\n   mechanism outside the scope of this compression library.) Upon exit, destLen\r\n   is the actual size of the uncompressed data.\r\n\r\n     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not\r\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\r\n   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In\r\n   the case where there is not enough room, uncompress() will fill the output\r\n   buffer with the uncompressed data up to that point.\r\n*/\r\n\r\nZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,\r\n                                    const Bytef *source, uLong *sourceLen));\r\n/*\r\n     Same as uncompress, except that sourceLen is a pointer, where the\r\n   length of the source is *sourceLen.  On return, *sourceLen is the number of\r\n   source bytes consumed.\r\n*/\r\n\r\n                        /* gzip file access functions */\r\n\r\n/*\r\n     This library supports reading and writing files in gzip (.gz) format with\r\n   an interface similar to that of stdio, using the functions that start with\r\n   \"gz\".  The gzip format is different from the zlib format.  gzip is a gzip\r\n   wrapper, documented in RFC 1952, wrapped around a deflate stream.\r\n*/\r\n\r\ntypedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */\r\n\r\n/*\r\nZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));\r\n\r\n     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as\r\n   in fopen (\"rb\" or \"wb\") but can also include a compression level (\"wb9\") or\r\n   a strategy: 'f' for filtered data as in \"wb6f\", 'h' for Huffman-only\r\n   compression as in \"wb1h\", 'R' for run-length encoding as in \"wb1R\", or 'F'\r\n   for fixed code compression as in \"wb9F\".  (See the description of\r\n   deflateInit2 for more information about the strategy parameter.)  'T' will\r\n   request transparent writing or appending with no compression and not using\r\n   the gzip format.\r\n\r\n     \"a\" can be used instead of \"w\" to request that the gzip stream that will\r\n   be written be appended to the file.  \"+\" will result in an error, since\r\n   reading and writing to the same gzip file is not supported.  The addition of\r\n   \"x\" when writing will create the file exclusively, which fails if the file\r\n   already exists.  On systems that support it, the addition of \"e\" when\r\n   reading or writing will set the flag to close the file on an execve() call.\r\n\r\n     These functions, as well as gzip, will read and decode a sequence of gzip\r\n   streams in a file.  The append function of gzopen() can be used to create\r\n   such a file.  (Also see gzflush() for another way to do this.)  When\r\n   appending, gzopen does not test whether the file begins with a gzip stream,\r\n   nor does it look for the end of the gzip streams to begin appending.  gzopen\r\n   will simply append a gzip stream to the existing file.\r\n\r\n     gzopen can be used to read a file which is not in gzip format; in this\r\n   case gzread will directly read from the file without decompression.  When\r\n   reading, this will be detected automatically by looking for the magic two-\r\n   byte gzip header.\r\n\r\n     gzopen returns NULL if the file could not be opened, if there was\r\n   insufficient memory to allocate the gzFile state, or if an invalid mode was\r\n   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).\r\n   errno can be checked to determine if the reason gzopen failed was that the\r\n   file could not be opened.\r\n*/\r\n\r\nZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));\r\n/*\r\n     gzdopen associates a gzFile with the file descriptor fd.  File descriptors\r\n   are obtained from calls like open, dup, creat, pipe or fileno (if the file\r\n   has been previously opened with fopen).  The mode parameter is as in gzopen.\r\n\r\n     The next call of gzclose on the returned gzFile will also close the file\r\n   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor\r\n   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,\r\n   mode);.  The duplicated descriptor should be saved to avoid a leak, since\r\n   gzdopen does not close fd if it fails.  If you are using fileno() to get the\r\n   file descriptor from a FILE *, then you will have to use dup() to avoid\r\n   double-close()ing the file descriptor.  Both gzclose() and fclose() will\r\n   close the associated file descriptor, so they need to have different file\r\n   descriptors.\r\n\r\n     gzdopen returns NULL if there was insufficient memory to allocate the\r\n   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not\r\n   provided, or '+' was provided), or if fd is -1.  The file descriptor is not\r\n   used until the next gz* read, write, seek, or close operation, so gzdopen\r\n   will not detect if fd is invalid (unless fd is -1).\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));\r\n/*\r\n     Set the internal buffer size used by this library's functions.  The\r\n   default buffer size is 8192 bytes.  This function must be called after\r\n   gzopen() or gzdopen(), and before any other calls that read or write the\r\n   file.  The buffer memory allocation is always deferred to the first read or\r\n   write.  Three times that size in buffer space is allocated.  A larger buffer\r\n   size of, for example, 64K or 128K bytes will noticeably increase the speed\r\n   of decompression (reading).\r\n\r\n     The new buffer size also affects the maximum length for gzprintf().\r\n\r\n     gzbuffer() returns 0 on success, or -1 on failure, such as being called\r\n   too late.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));\r\n/*\r\n     Dynamically update the compression level or strategy.  See the description\r\n   of deflateInit2 for the meaning of these parameters.  Previously provided\r\n   data is flushed before the parameter change.\r\n\r\n     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not\r\n   opened for writing, Z_ERRNO if there is an error writing the flushed data,\r\n   or Z_MEM_ERROR if there is a memory allocation error.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));\r\n/*\r\n     Reads the given number of uncompressed bytes from the compressed file.  If\r\n   the input file is not in gzip format, gzread copies the given number of\r\n   bytes into the buffer directly from the file.\r\n\r\n     After reaching the end of a gzip stream in the input, gzread will continue\r\n   to read, looking for another gzip stream.  Any number of gzip streams may be\r\n   concatenated in the input file, and will all be decompressed by gzread().\r\n   If something other than a gzip stream is encountered after a gzip stream,\r\n   that remaining trailing garbage is ignored (and no error is returned).\r\n\r\n     gzread can be used to read a gzip file that is being concurrently written.\r\n   Upon reaching the end of the input, gzread will return with the available\r\n   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then\r\n   gzclearerr can be used to clear the end of file indicator in order to permit\r\n   gzread to be tried again.  Z_OK indicates that a gzip stream was completed\r\n   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the\r\n   middle of a gzip stream.  Note that gzread does not return -1 in the event\r\n   of an incomplete gzip stream.  This error is deferred until gzclose(), which\r\n   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip\r\n   stream.  Alternatively, gzerror can be used before gzclose to detect this\r\n   case.\r\n\r\n     gzread returns the number of uncompressed bytes actually read, less than\r\n   len for end of file, or -1 for error.  If len is too large to fit in an int,\r\n   then nothing is read, -1 is returned, and the error state is set to\r\n   Z_STREAM_ERROR.\r\n*/\r\n\r\nZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,\r\n                                     gzFile file));\r\n/*\r\n     Read up to nitems items of size size from file to buf, otherwise operating\r\n   as gzread() does.  This duplicates the interface of stdio's fread(), with\r\n   size_t request and return types.  If the library defines size_t, then\r\n   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned\r\n   integer type that can contain a pointer.\r\n\r\n     gzfread() returns the number of full items read of size size, or zero if\r\n   the end of the file was reached and a full item could not be read, or if\r\n   there was an error.  gzerror() must be consulted if zero is returned in\r\n   order to determine if there was an error.  If the multiplication of size and\r\n   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing\r\n   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.\r\n\r\n     In the event that the end of file is reached and only a partial item is\r\n   available at the end, i.e. the remaining uncompressed data length is not a\r\n   multiple of size, then the final partial item is nevetheless read into buf\r\n   and the end-of-file flag is set.  The length of the partial item read is not\r\n   provided, but could be inferred from the result of gztell().  This behavior\r\n   is the same as the behavior of fread() implementations in common libraries,\r\n   but it prevents the direct use of gzfread() to read a concurrently written\r\n   file, reseting and retrying on end-of-file, when size is not 1.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzwrite OF((gzFile file,\r\n                                voidpc buf, unsigned len));\r\n/*\r\n     Writes the given number of uncompressed bytes into the compressed file.\r\n   gzwrite returns the number of uncompressed bytes written or 0 in case of\r\n   error.\r\n*/\r\n\r\nZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,\r\n                                      z_size_t nitems, gzFile file));\r\n/*\r\n     gzfwrite() writes nitems items of size size from buf to file, duplicating\r\n   the interface of stdio's fwrite(), with size_t request and return types.  If\r\n   the library defines size_t, then z_size_t is identical to size_t.  If not,\r\n   then z_size_t is an unsigned integer type that can contain a pointer.\r\n\r\n     gzfwrite() returns the number of full items written of size size, or zero\r\n   if there was an error.  If the multiplication of size and nitems overflows,\r\n   i.e. the product does not fit in a z_size_t, then nothing is written, zero\r\n   is returned, and the error state is set to Z_STREAM_ERROR.\r\n*/\r\n\r\nZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));\r\n/*\r\n     Converts, formats, and writes the arguments to the compressed file under\r\n   control of the format string, as in fprintf.  gzprintf returns the number of\r\n   uncompressed bytes actually written, or a negative zlib error code in case\r\n   of error.  The number of uncompressed bytes written is limited to 8191, or\r\n   one less than the buffer size given to gzbuffer().  The caller should assure\r\n   that this limit is not exceeded.  If it is exceeded, then gzprintf() will\r\n   return an error (0) with nothing written.  In this case, there may also be a\r\n   buffer overflow with unpredictable consequences, which is possible only if\r\n   zlib was compiled with the insecure functions sprintf() or vsprintf()\r\n   because the secure snprintf() or vsnprintf() functions were not available.\r\n   This can be determined using zlibCompileFlags().\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));\r\n/*\r\n     Writes the given null-terminated string to the compressed file, excluding\r\n   the terminating null character.\r\n\r\n     gzputs returns the number of characters written, or -1 in case of error.\r\n*/\r\n\r\nZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));\r\n/*\r\n     Reads bytes from the compressed file until len-1 characters are read, or a\r\n   newline character is read and transferred to buf, or an end-of-file\r\n   condition is encountered.  If any characters are read or if len == 1, the\r\n   string is terminated with a null character.  If no characters are read due\r\n   to an end-of-file or len < 1, then the buffer is left untouched.\r\n\r\n     gzgets returns buf which is a null-terminated string, or it returns NULL\r\n   for end-of-file or in case of error.  If there was an error, the contents at\r\n   buf are indeterminate.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));\r\n/*\r\n     Writes c, converted to an unsigned char, into the compressed file.  gzputc\r\n   returns the value that was written, or -1 in case of error.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzgetc OF((gzFile file));\r\n/*\r\n     Reads one byte from the compressed file.  gzgetc returns this byte or -1\r\n   in case of end of file or error.  This is implemented as a macro for speed.\r\n   As such, it does not do all of the checking the other functions do.  I.e.\r\n   it does not check to see if file is NULL, nor whether the structure file\r\n   points to has been clobbered or not.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));\r\n/*\r\n     Push one character back onto the stream to be read as the first character\r\n   on the next read.  At least one character of push-back is allowed.\r\n   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will\r\n   fail if c is -1, and may fail if a character has been pushed but not read\r\n   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the\r\n   output buffer size of pushed characters is allowed.  (See gzbuffer above.)\r\n   The pushed character will be discarded if the stream is repositioned with\r\n   gzseek() or gzrewind().\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));\r\n/*\r\n     Flushes all pending output into the compressed file.  The parameter flush\r\n   is as in the deflate() function.  The return value is the zlib error number\r\n   (see function gzerror below).  gzflush is only permitted when writing.\r\n\r\n     If the flush parameter is Z_FINISH, the remaining data is written and the\r\n   gzip stream is completed in the output.  If gzwrite() is called again, a new\r\n   gzip stream will be started in the output.  gzread() is able to read such\r\n   concatenated gzip streams.\r\n\r\n     gzflush should be called only when strictly necessary because it will\r\n   degrade compression if called too often.\r\n*/\r\n\r\n/*\r\nZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,\r\n                                   z_off_t offset, int whence));\r\n\r\n     Sets the starting position for the next gzread or gzwrite on the given\r\n   compressed file.  The offset represents a number of bytes in the\r\n   uncompressed data stream.  The whence parameter is defined as in lseek(2);\r\n   the value SEEK_END is not supported.\r\n\r\n     If the file is opened for reading, this function is emulated but can be\r\n   extremely slow.  If the file is opened for writing, only forward seeks are\r\n   supported; gzseek then compresses a sequence of zeroes up to the new\r\n   starting position.\r\n\r\n     gzseek returns the resulting offset location as measured in bytes from\r\n   the beginning of the uncompressed stream, or -1 in case of error, in\r\n   particular if the file is opened for writing and the new starting position\r\n   would be before the current position.\r\n*/\r\n\r\nZEXTERN int ZEXPORT    gzrewind OF((gzFile file));\r\n/*\r\n     Rewinds the given file. This function is supported only for reading.\r\n\r\n     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)\r\n*/\r\n\r\n/*\r\nZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));\r\n\r\n     Returns the starting position for the next gzread or gzwrite on the given\r\n   compressed file.  This position represents a number of bytes in the\r\n   uncompressed data stream, and is zero when starting, even if appending or\r\n   reading a gzip stream from the middle of a file using gzdopen().\r\n\r\n     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)\r\n*/\r\n\r\n/*\r\nZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));\r\n\r\n     Returns the current offset in the file being read or written.  This offset\r\n   includes the count of bytes that precede the gzip stream, for example when\r\n   appending or when using gzdopen() for reading.  When reading, the offset\r\n   does not include as yet unused buffered input.  This information can be used\r\n   for a progress indicator.  On error, gzoffset() returns -1.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzeof OF((gzFile file));\r\n/*\r\n     Returns true (1) if the end-of-file indicator has been set while reading,\r\n   false (0) otherwise.  Note that the end-of-file indicator is set only if the\r\n   read tried to go past the end of the input, but came up short.  Therefore,\r\n   just like feof(), gzeof() may return false even if there is no more data to\r\n   read, in the event that the last read request was for the exact number of\r\n   bytes remaining in the input file.  This will happen if the input file size\r\n   is an exact multiple of the buffer size.\r\n\r\n     If gzeof() returns true, then the read functions will return no more data,\r\n   unless the end-of-file indicator is reset by gzclearerr() and the input file\r\n   has grown since the previous end of file was detected.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzdirect OF((gzFile file));\r\n/*\r\n     Returns true (1) if file is being copied directly while reading, or false\r\n   (0) if file is a gzip stream being decompressed.\r\n\r\n     If the input file is empty, gzdirect() will return true, since the input\r\n   does not contain a gzip stream.\r\n\r\n     If gzdirect() is used immediately after gzopen() or gzdopen() it will\r\n   cause buffers to be allocated to allow reading the file to determine if it\r\n   is a gzip file.  Therefore if gzbuffer() is used, it should be called before\r\n   gzdirect().\r\n\r\n     When writing, gzdirect() returns true (1) if transparent writing was\r\n   requested (\"wT\" for the gzopen() mode), or false (0) otherwise.  (Note:\r\n   gzdirect() is not needed when writing.  Transparent writing must be\r\n   explicitly requested, so the application already knows the answer.  When\r\n   linking statically, using gzdirect() will include all of the zlib code for\r\n   gzip file reading and decompression, which may not be desired.)\r\n*/\r\n\r\nZEXTERN int ZEXPORT    gzclose OF((gzFile file));\r\n/*\r\n     Flushes all pending output if necessary, closes the compressed file and\r\n   deallocates the (de)compression state.  Note that once file is closed, you\r\n   cannot call gzerror with file, since its structures have been deallocated.\r\n   gzclose must not be called more than once on the same file, just as free\r\n   must not be called more than once on the same allocation.\r\n\r\n     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a\r\n   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the\r\n   last read ended in the middle of a gzip stream, or Z_OK on success.\r\n*/\r\n\r\nZEXTERN int ZEXPORT gzclose_r OF((gzFile file));\r\nZEXTERN int ZEXPORT gzclose_w OF((gzFile file));\r\n/*\r\n     Same as gzclose(), but gzclose_r() is only for use when reading, and\r\n   gzclose_w() is only for use when writing or appending.  The advantage to\r\n   using these instead of gzclose() is that they avoid linking in zlib\r\n   compression or decompression code that is not used when only reading or only\r\n   writing respectively.  If gzclose() is used, then both compression and\r\n   decompression code will be included the application when linking to a static\r\n   zlib library.\r\n*/\r\n\r\nZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));\r\n/*\r\n     Returns the error message for the last error which occurred on the given\r\n   compressed file.  errnum is set to zlib error number.  If an error occurred\r\n   in the file system and not in the compression library, errnum is set to\r\n   Z_ERRNO and the application may consult errno to get the exact error code.\r\n\r\n     The application must not modify the returned string.  Future calls to\r\n   this function may invalidate the previously returned string.  If file is\r\n   closed, then the string previously returned by gzerror will no longer be\r\n   available.\r\n\r\n     gzerror() should be used to distinguish errors from end-of-file for those\r\n   functions above that do not distinguish those cases in their return values.\r\n*/\r\n\r\nZEXTERN void ZEXPORT gzclearerr OF((gzFile file));\r\n/*\r\n     Clears the error and end-of-file flags for file.  This is analogous to the\r\n   clearerr() function in stdio.  This is useful for continuing to read a gzip\r\n   file that is being written concurrently.\r\n*/\r\n\r\n#endif /* !Z_SOLO */\r\n\r\n                        /* checksum functions */\r\n\r\n/*\r\n     These functions are not related to compression but are exported\r\n   anyway because they might be useful in applications using the compression\r\n   library.\r\n*/\r\n\r\nZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));\r\n/*\r\n     Update a running Adler-32 checksum with the bytes buf[0..len-1] and\r\n   return the updated checksum.  If buf is Z_NULL, this function returns the\r\n   required initial value for the checksum.\r\n\r\n     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed\r\n   much faster.\r\n\r\n   Usage example:\r\n\r\n     uLong adler = adler32(0L, Z_NULL, 0);\r\n\r\n     while (read_buffer(buffer, length) != EOF) {\r\n       adler = adler32(adler, buffer, length);\r\n     }\r\n     if (adler != original_adler) error();\r\n*/\r\n\r\nZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,\r\n                                    z_size_t len));\r\n/*\r\n     Same as adler32(), but with a size_t length.\r\n*/\r\n\r\n/*\r\nZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,\r\n                                          z_off_t len2));\r\n\r\n     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1\r\n   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for\r\n   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of\r\n   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note\r\n   that the z_off_t type (like off_t) is a signed integer.  If len2 is\r\n   negative, the result has no meaning or utility.\r\n*/\r\n\r\nZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));\r\n/*\r\n     Update a running CRC-32 with the bytes buf[0..len-1] and return the\r\n   updated CRC-32.  If buf is Z_NULL, this function returns the required\r\n   initial value for the crc.  Pre- and post-conditioning (one's complement) is\r\n   performed within this function so it shouldn't be done by the application.\r\n\r\n   Usage example:\r\n\r\n     uLong crc = crc32(0L, Z_NULL, 0);\r\n\r\n     while (read_buffer(buffer, length) != EOF) {\r\n       crc = crc32(crc, buffer, length);\r\n     }\r\n     if (crc != original_crc) error();\r\n*/\r\n\r\nZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,\r\n                                  z_size_t len));\r\n/*\r\n     Same as crc32(), but with a size_t length.\r\n*/\r\n\r\n/*\r\nZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));\r\n\r\n     Combine two CRC-32 check values into one.  For two sequences of bytes,\r\n   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were\r\n   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32\r\n   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and\r\n   len2.\r\n*/\r\n\r\n\r\n                        /* various hacks, don't look :) */\r\n\r\n/* deflateInit and inflateInit are macros to allow checking the zlib version\r\n * and the compiler's view of z_stream:\r\n */\r\nZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,\r\n                                     const char *version, int stream_size));\r\nZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,\r\n                                     const char *version, int stream_size));\r\nZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,\r\n                                      int windowBits, int memLevel,\r\n                                      int strategy, const char *version,\r\n                                      int stream_size));\r\nZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,\r\n                                      const char *version, int stream_size));\r\nZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,\r\n                                         unsigned char FAR *window,\r\n                                         const char *version,\r\n                                         int stream_size));\r\n#ifdef Z_PREFIX_SET\r\n#  define z_deflateInit(strm, level) \\\r\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\r\n#  define z_inflateInit(strm) \\\r\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\r\n#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\r\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\r\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\r\n#  define z_inflateInit2(strm, windowBits) \\\r\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\r\n                        (int)sizeof(z_stream))\r\n#  define z_inflateBackInit(strm, windowBits, window) \\\r\n          inflateBackInit_((strm), (windowBits), (window), \\\r\n                           ZLIB_VERSION, (int)sizeof(z_stream))\r\n#else\r\n#  define deflateInit(strm, level) \\\r\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\r\n#  define inflateInit(strm) \\\r\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\r\n#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\r\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\r\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\r\n#  define inflateInit2(strm, windowBits) \\\r\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\r\n                        (int)sizeof(z_stream))\r\n#  define inflateBackInit(strm, windowBits, window) \\\r\n          inflateBackInit_((strm), (windowBits), (window), \\\r\n                           ZLIB_VERSION, (int)sizeof(z_stream))\r\n#endif\r\n\r\n#ifndef Z_SOLO\r\n\r\n/* gzgetc() macro and its supporting function and exposed data structure.  Note\r\n * that the real internal state is much larger than the exposed structure.\r\n * This abbreviated structure exposes just enough for the gzgetc() macro.  The\r\n * user should not mess with these exposed elements, since their names or\r\n * behavior could change in the future, perhaps even capriciously.  They can\r\n * only be used by the gzgetc() macro.  You have been warned.\r\n */\r\nstruct gzFile_s {\r\n    unsigned have;\r\n    unsigned char *next;\r\n    z_off64_t pos;\r\n};\r\nZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */\r\n#ifdef Z_PREFIX_SET\r\n#  undef z_gzgetc\r\n#  define z_gzgetc(g) \\\r\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\r\n#else\r\n#  define gzgetc(g) \\\r\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\r\n#endif\r\n\r\n/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or\r\n * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if\r\n * both are true, the application gets the *64 functions, and the regular\r\n * functions are changed to 64 bits) -- in case these are set on systems\r\n * without large file support, _LFS64_LARGEFILE must also be true\r\n */\r\n#ifdef Z_LARGE64\r\n   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\r\n   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));\r\n   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));\r\n   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));\r\n   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));\r\n   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));\r\n#endif\r\n\r\n#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)\r\n#  ifdef Z_PREFIX_SET\r\n#    define z_gzopen z_gzopen64\r\n#    define z_gzseek z_gzseek64\r\n#    define z_gztell z_gztell64\r\n#    define z_gzoffset z_gzoffset64\r\n#    define z_adler32_combine z_adler32_combine64\r\n#    define z_crc32_combine z_crc32_combine64\r\n#  else\r\n#    define gzopen gzopen64\r\n#    define gzseek gzseek64\r\n#    define gztell gztell64\r\n#    define gzoffset gzoffset64\r\n#    define adler32_combine adler32_combine64\r\n#    define crc32_combine crc32_combine64\r\n#  endif\r\n#  ifndef Z_LARGE64\r\n     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\r\n     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));\r\n     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));\r\n     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));\r\n     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));\r\n     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));\r\n#  endif\r\n#else\r\n   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));\r\n   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));\r\n   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));\r\n   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));\r\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\r\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\r\n#endif\r\n\r\n#else /* Z_SOLO */\r\n\r\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\r\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\r\n\r\n#endif /* !Z_SOLO */\r\n\r\n/* undocumented functions */\r\nZEXTERN const char   * ZEXPORT zError           OF((int));\r\nZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));\r\nZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));\r\nZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));\r\nZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));\r\nZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));\r\nZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));\r\nZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));\r\n#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)\r\nZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,\r\n                                            const char *mode));\r\n#endif\r\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\r\n#  ifndef Z_SOLO\r\nZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,\r\n                                                  const char *format,\r\n                                                  va_list va));\r\n#  endif\r\n#endif\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif /* ZLIB_H */\r\n"
  },
  {
    "path": "README.md",
    "content": "# DISCONTINUATION OF PROJECT #\nThis project will no longer be maintained by Intel.\nIntel has ceased development and contributions including, but not limited to, maintenance, bug fixes, new releases, or updates, to this project.\nIntel no longer accepts patches to this project.\n# Checkerboard Rendering (CBR) and Dynamic Resolution Rendering (DRR) Sample in DX12 MiniEngine\nThis repository is based on a snapshot of Microsoft's repository.\n\n## Sample Overview\n*The tested IDE is Visual Studio 2017.*\n\nThis repository contains a straight forward integration of CBR and DRR into the DX12 MiniEngine.  An indepth explanation of CBR and the algorithms presented here can be found in the corresponding white paper: https://software.intel.com/en-us/articles/checkerboard-rendering-for-real-time-upscaling-on-intel-integrated-graphics-v-12\n\nThe sample is designed to \"build and run\".  Simply clone (or download) this repository, build the MiniEngine\\ModelViewer\\ModelViewer_VS17.sln solution and run.  CBR is enabled by default, it (along with multiple other post processes) can be enabled or disabled by pressing the 'backspace' key to bring up the toggle menu.\n\n### CBR\nThe CBR options in the toggle menu are as follows:\n* **Enable**: Enable or disable CBR.\n* **Check Shading Occlusion**: During movement which spans multiple pixels per frame: If enabled; Attempt to retrieve the correct shading information from frame N-1's pixels.  If disabled; Always assume the shading is occluded and extract the shading color from frame N.\n* **Show Derived Motion**: For each pixel which had motion derived from the depth buffer, render it as red in the color buffer.\n* **Show Missing Pixels**: For each pixel which our algorithm determined the shading information was missing, render it as red in the color buffer.\n* **Show Occluded Pixels**: For each pixel which our algorithm determined the shading information was occluded by movement, render it as hot-pink in the color buffer.\n* **Show Pixel Motion**: For each pixel which our algorithm determined motion vectors must be used to fetch the shading information from frame N-1, render it as green in the color buffer.\n* **Depth Tolerance**: The depth tolerance (linear from near clip to far clip) used by our algorithm to determine if the shading information is occluded.\n\n### DRR\nThe DRR options in the toggle menu are as follows:\n* **Enable**: Enable or disable DRR.\n* **Desired Frame Rate**: The target frame rate for the DRR algorithm.\n* **Force Scale**: Force DRR to run at the scale specified by Min Scale.\n* **Min Scale**: The low end limit to DRR's resolution scaling.\n* **Resolution Increments**: The increments DRR will use when scaling resolutions.\n* **_Advanced/Frame Rate Delta Resolution**: The amount of 'delta' (or headroom) to allow in the frame rate before switching resolutions.\n* **_Advanced/Frame Rate Low Pass K**: The K filtering value used when accumulating the latest frame time.\n* **_Advanced/Rate of Change**: The rate at which DRR's internal scale changes.\n* **_Internal/Frame Rate**: The frame rate DRR is tracking, this is filtered by the value specified with 'Frame Rate Low Pass K'.\n* **_Internal/Scale**: DRR's internal scale, once this passes the 'Resolution Increment' threshold the resolution will change. \n\n\n\n### Files\nThe core of CBR and DRR exists in two files:\n\n#### ModelViewer.cpp\nModified version of the original ModelViewer.cpp in the MiniEngine.  This file is responsible for jittering the viewport and setting the correct render states.  To find the CBR specific code do a search for \"CBR\", to find the DRR specific code do a search for \"DRR\".\n\n#### CheckerboardColorResolveCS.cs\nThis file is the CBR reconstruction shader, the crux of the CBR algorithm, it constructs a full resolution image from frames N-1 and N.\n\n\n\n# DirectX-Graphics-Samples\nThis repo contains the DirectX Graphics samples that demonstrate how to build graphics intensive applications for Windows 10. We also have a YouTube channel! Visit us here: https://www.youtube.com/MicrosoftDirectX12andGraphicsEducation\n\n## API Samples\nIn the Samples directory, you will find samples that attempt to break off specific features and specific usage scenarios into bite sized chunks. For example, the ExecuteIndirect sample will show you just enough about execute indirect to get started with that feature without diving too deep into multiengine whereas the nBodyGravity sample will delve into multiengine without touching on the execute indirect feature etc. By doing this, we hope to make it easier to get started with DirectX 12.\n\n## Visual Studio Templates\nIn the Templates directory you will find copies of the projects that are available for creation in Visual Studio's \"New Project\" wizard.\n\n## MiniEngine: A DirectX 12 Engine Starter Kit\nIn addition to the samples, we are announcing the first DirectX 12 preview release of the MiniEngine.\n\nIt came from a desire to quickly dive into graphics and performance experiments.  We knew we would need some basic building blocks whenever starting a new 3D app, and we had already written these things at countless previous gigs.  We got tired of reinventing the wheel, so we established our own core library of helper classes and platform abstractions.  We wanted to be able to create a new app by writing just the Init(), Update(), and Render() functions and leveraging as much reusable code as possible.  Today our core library has been redesigned for DirectX 12 and aims to serve as an example of efficient API usage.  It is obviously not exhaustive of what a game engine needs, but it can serve as the cornerstone of something new.  You can also borrow whatever useful code you find.\n\n### Some features of MiniEngine\n* High-quality anti-aliased text rendering\n* Real-time CPU and GPU profiling\n* User-controlled variables\n* Game controller, mouse, and keyboard input\n* A friendly DirectXMath wrapper\n* Perspective camera supporting traditional and reversed Z matrices\n* Asynchronous DDS texture loading and ZLib decompression\n* Large library of shaders\n* Easy shader embedding via a compile-to-header system\n* Easy render target, depth target, and unordered access view creation\n* A thread-safe GPU command context system (WIP)\n* Easy-to-use dynamic constant buffers and descriptor tables\n\n## Requirements\n* Windows 10\n* [Visual Studio 2017](https://www.visualstudio.com/) with the [Windows 10 Creator Update SDK](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk)\n\n## Contributing\nWe're always looking for your help to fix bugs and improve the samples.  File those pull requests and we'll be happy to take a look.\n\nFind more information on DirectX 12 on our blog: http://blogs.msdn.com/b/directx/\n\nTroubleshooting information for this repository can be found in the site [Wiki](https://github.com/Microsoft/DirectX-Graphics-Samples/wiki).\n\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.\n"
  },
  {
    "path": "Sponza/MySequence/perfreport.csv",
    "content": "Copy texture to memory, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.693088, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.693504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.694144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.69232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \nPost Effects, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000512, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000288, 0.000256, 0.000288, 0.000288, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.002784, 0.00064, 0.00064, 0.00064, 0.00064, 0.000608, 0.00064, 0.000608, 0.000608, 0.00064, 0.00064, 0.00064, 0.00064, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000288, 0.000256, 0.000288, 0.000512, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000288, 0.000256, 0.000256, 0.000768, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000256, 0.000288, 0.000256, 0.000288, \nPresent, 0.170976, 0.17296, 0.181472, 0.184256, 0.183776, 0.191072, 0.197952, 0.18496, 0.183744, 0.178816, 0.184576, 0.180704, 0.182272, 0.179392, 0.199712, 0.170656, 0.18064, 0.182368, 0.17376, 0.179264, 0.180448, 0.2024, 0.182272, 0.18432, 0.183904, 0.179584, 0.182592, 0.181472, 0.180928, 0.173216, 0.181408, 0.180896, 0.182016, 0.179104, 0.184832, 0.179072, 0.177216, 0.178592, 0.172576, 0.162944, 0.176352, 0.179008, 0.182016, 0.176416, 0.188992, 0.182656, 0.18, 0.180768, 0.18064, 0.180032, 0.186112, 0.1968, 0.205952, 0.180864, 0.176832, 0.1808, 0.180992, 0.17424, 0.184288, 0.190336, 0.18672, 0.180608, 0.18176, 0.181472, 0.203872, 0.18144, 0.180896, 0.177696, 0.17616, 0.179136, 0.2016, 0.19696, 0.180512, 0.18192, 0.17696, 0.182176, 0.184128, 0.18288, 0.182752, 0.184736, 0.175648, 0.175776, 0.177632, 0.186752, 0.16976, 0.170592, 0.173088, 0.311488, 0.175712, 0.161056, 0.265344, 0.163904, 0.168736, 0.174848, 0.179296, 0.181152, 0.17248, 0.181728, 0.18512, 0.187872, 0.187264, 0.184544, 0.180576, 0.18144, 0.173856, 0.202624, 0.181664, 0.183168, 0.188288, 0.182016, 0.182592, 0.304352, 0.188448, 0.188928, 0.178528, 0.179744, 0.192768, 0.192544, 0.182752, 0.176192, 0.17664, 0.180608, 0.182016, 0.12736, 0.145504, 0.173472, 0.15776, 0.157312, 0.158048, 0.162336, 0.1608, 0.1632, 0.164672, 0.166656, 0.188896, 0.178592, 0.168928, 0.178688, 0.180768, 0.185152, 0.199712, 0.199744, 0.17968, 0.178912, 0.18048, 0.172064, 0.178464, 0.183232, 0.178656, 0.179968, 0.16544, 0.178848, 0.181792, 0.176736, 0.180608, 0.179296, 0.180096, 0.176832, 0.180448, 0.175936, 0.179776, 0.180544, 0.17648, 0.173376, 0.178432, 0.179744, 0.200288, 0.180448, 0.214048, 0.165824, 0.2872, 0.165376, 0.181696, 0.164448, 0.289344, 0.154656, 0.16448, 0.167488, 0.33968, 0.344896, 0.16432, 0.164352, 0.760096, 0.770368, 0.79072, 0.920768, 0.772096, 2.07245, 2.02752, 2.07034, 2.07002, 2.08426, 2.10573, 2.01856, 0.530144, 0.18032, 0.1728, 0.1736, 0.172192, 0.182304, 0.276768, 0.165056, 0.180096, 0.178048, 0.180928, 0.17776, 0.185216, 0.167136, 0.163136, 0.172288, 0.183072, 0.182176, 0.179072, 0.211008, 0.181312, 0.176992, 0.17904, 0.178592, 0.181088, 0.19696, 0.19552, 0.215008, 0.185824, 0.178464, 0.177696, 0.173952, 0.180864, 0.181088, 0.176576, 0.183488, 0.194048, 0.187808, 0.184832, 0.188288, 0.188352, 0.256512, 0.40112, 0.170752, 0.156416, 0.191904, 0.209888, 0.187488, 0.196224, 0.165248, 0.129248, 0.17312, 0.162464, 0.16736, 0.167872, 0.1608, 0.178304, 0.162048, 0.165472, 0.163808, 0.168768, 0.17456, 0.19616, 0.179232, 0.190208, 0.173408, 0.175328, 0.198688, 0.177728, 0.176864, 0.184384, 0.205184, 0.18064, 0.186144, 0.184544, 0.181664, 0.176128, 0.177408, 0.17904, 0.176992, 0.19808, 0.1768, 0.173632, 0.177536, 0.175808, 0.176608, 0.177472, 0.176672, 0.177824, 0.176992, 0.1944, 0.176064, 0.178976, 0.17488, 0.179552, 0.176416, 0.179936, 0.1752, 0.186464, 0.182144, 0.175904, 0.173248, 0.21664, 0.157312, 0.177824, 0.159328, 0.187008, 0.176192, 0.34976, 0.129472, 0.127488, 0.156, 0.165792, 0.158944, 0.161248, 0.159264, 0.158784, 0.163136, 0.232416, 0.17152, 0.175392, 0.179264, 0.175552, 0.185248, 0.196064, 0.180992, 0.15808, 0.158944, 0.172256, 0.153568, 0.17184, 0.16496, 0.163232, 0.163424, 0.162784, 0.16144, 0.166304, 0.129312, \nRender UI, 0.005888, 0.00576, 0.005728, 0.005888, 0.005888, 0.007168, 0.006528, 0.005728, 0.005888, 0.00576, 0.005568, 0.005568, 0.005568, 0.006048, 0.005888, 0.00576, 0.005888, 0.005728, 0.005728, 0.005888, 0.005888, 0.00592, 0.006048, 0.00624, 0.005728, 0.005568, 0.005888, 0.005408, 0.005248, 0.005728, 0.00576, 0.005248, 0.006208, 0.005888, 0.00592, 0.006048, 0.005888, 0.005728, 0.005088, 0.005728, 0.005568, 0.005888, 0.00592, 0.005888, 0.005728, 0.006048, 0.005728, 0.00576, 0.006048, 0.00608, 0.00608, 0.005888, 0.005888, 0.005568, 0.005728, 0.00592, 0.005728, 0.005728, 0.00592, 0.005728, 0.005728, 0.00592, 0.005728, 0.006208, 0.00592, 0.005728, 0.006368, 0.006208, 0.005888, 0.00576, 0.006048, 0.005888, 0.00528, 0.005888, 0.005888, 0.005728, 0.006048, 0.00592, 0.005216, 0.006048, 0.005728, 0.005888, 0.00592, 0.005728, 0.005728, 0.006688, 0.007168, 0.006208, 0.00576, 0.0056, 0.005728, 0.005888, 0.00608, 0.005888, 0.0072, 0.00704, 0.006528, 0.006048, 0.00592, 0.006048, 0.00608, 0.005728, 0.006688, 0.006688, 0.00592, 0.00576, 0.005728, 0.005728, 0.005888, 0.00592, 0.00608, 0.00592, 0.00592, 0.005888, 0.0056, 0.00592, 0.00576, 0.005728, 0.00592, 0.005888, 0.005728, 0.007168, 0.007808, 0.00656, 0.005728, 0.005632, 0.00592, 0.005728, 0.005728, 0.00608, 0.00608, 0.005568, 0.005888, 0.005888, 0.005728, 0.005888, 0.005888, 0.005888, 0.00592, 0.005888, 0.005728, 0.005536, 0.005728, 0.00576, 0.005888, 0.00592, 0.006048, 0.00576, 0.005728, 0.005248, 0.005888, 0.005888, 0.005888, 0.005728, 0.00592, 0.005888, 0.005728, 0.00592, 0.005888, 0.006048, 0.006048, 0.00624, 0.00592, 0.0056, 0.005888, 0.00592, 0.00592, 0.00608, 0.005728, 0.00512, 0.005728, 0.005888, 0.005728, 0.006688, 0.00608, 0.00576, 0.006848, 0.0064, 0.006048, 0.00576, 0.006688, 0.007008, 0.024832, 0.02032, 0.020704, 0.020736, 0.019936, 0.016608, 0.017344, 0.01664, 0.01696, 0.017056, 0.017312, 0.01664, 0.01664, 0.005248, 0.005568, 0.0056, 0.0056, 0.006208, 0.005888, 0.006208, 0.005888, 0.00544, 0.00576, 0.0056, 0.005888, 0.005728, 0.005888, 0.00576, 0.00592, 0.005888, 0.005888, 0.005888, 0.005248, 0.005728, 0.005728, 0.006208, 0.005696, 0.005248, 0.005568, 0.00576, 0.005728, 0.005728, 0.00576, 0.005888, 0.005728, 0.005728, 0.005408, 0.005888, 0.006048, 0.005888, 0.005568, 0.008768, 0.006368, 0.006528, 0.007968, 0.007008, 0.00592, 0.005728, 0.005728, 0.007712, 0.007808, 0.006432, 0.005792, 0.00544, 0.005568, 0.00592, 0.00592, 0.0056, 0.00576, 0.00592, 0.006048, 0.00624, 0.005728, 0.005888, 0.0056, 0.005248, 0.005728, 0.005888, 0.005728, 0.005728, 0.006048, 0.00592, 0.00576, 0.00512, 0.005888, 0.006048, 0.005888, 0.005728, 0.005888, 0.006048, 0.005568, 0.005856, 0.005248, 0.005568, 0.005568, 0.005728, 0.00576, 0.005728, 0.005888, 0.005568, 0.005408, 0.005568, 0.005728, 0.005728, 0.005728, 0.005888, 0.005568, 0.005728, 0.00592, 0.005728, 0.005888, 0.005568, 0.0056, 0.005568, 0.005728, 0.005728, 0.005728, 0.005568, 0.00576, 0.007168, 0.007808, 0.006304, 0.005792, 0.005728, 0.005568, 0.0056, 0.005888, 0.005408, 0.00576, 0.005728, 0.005888, 0.005728, 0.005728, 0.005728, 0.00576, 0.005888, 0.00576, 0.005728, 0.005728, 0.006368, 0.005728, 0.006208, 0.00592, 0.00624, 0.005728, 0.005568, 0.005888, 0.00576, 0.005728, 0.005568, \nScene Render, 2.73686, 2.14877, 3.32886, 2.66797, 3.1937, 2.75626, 3.21178, 2.68166, 3.20672, 2.66637, 3.20339, 2.65222, 3.19075, 2.68419, 3.20538, 2.66317, 3.20906, 2.64806, 3.19539, 2.64573, 3.1896, 2.67574, 3.21254, 2.6544, 3.21427, 2.67165, 3.18899, 2.66176, 3.21146, 2.69456, 3.18941, 2.65478, 3.21331, 2.68736, 3.19418, 2.66698, 3.2128, 2.6505, 3.19946, 2.65693, 3.18886, 2.71126, 3.18762, 2.67117, 3.20467, 2.65184, 3.20554, 2.65203, 3.23066, 2.68717, 3.21066, 2.64352, 3.2049, 2.66931, 3.1952, 2.66288, 3.21846, 2.66061, 3.19472, 2.66016, 3.20842, 2.67885, 3.21296, 2.65706, 3.18576, 2.65408, 3.21283, 2.64864, 3.21821, 2.67981, 3.21293, 2.66803, 3.21258, 2.67459, 3.2217, 2.65773, 3.20067, 2.6399, 3.21126, 2.6696, 3.20294, 2.65923, 3.15203, 2.65674, 3.09523, 2.35325, 3.26448, 2.83798, 3.28989, 2.74029, 3.22842, 2.67296, 3.21286, 2.66762, 3.25168, 2.72275, 3.23606, 2.67955, 3.22845, 2.69139, 3.21792, 2.67434, 3.2257, 2.70195, 3.24998, 2.70886, 3.21696, 2.67846, 3.20989, 2.68035, 3.22118, 2.67696, 3.25907, 2.70368, 3.22931, 2.7128, 3.21008, 2.67232, 3.23635, 2.67264, 3.22528, 2.69882, 3.21699, 2.71747, 2.97114, 2.50973, 3.28102, 2.76659, 3.33632, 2.70979, 3.25094, 2.72541, 3.27098, 2.8392, 3.22816, 2.70515, 3.28717, 2.65194, 3.28358, 2.63555, 3.14883, 2.58982, 3.09587, 2.60858, 3.10714, 2.55722, 3.03606, 2.56618, 3.18806, 2.5336, 3.14954, 2.50886, 3.11126, 2.49379, 3.11658, 2.53139, 2.93347, 2.4761, 2.88838, 2.40243, 2.80342, 2.34397, 2.76691, 2.35254, 2.77219, 2.3255, 2.7375, 2.33939, 2.70954, 2.31146, 2.6801, 2.29792, 2.68285, 2.28992, 2.60445, 2.01642, 2.70861, 2.34362, 2.59546, 2.24842, 2.52368, 2.17274, 2.47603, 10.5131, 12.4086, 11.6584, 11.4261, 10.4232, 11.1511, 10.3049, 11.0181, 10.2657, 10.8606, 10.1164, 10.6983, 2.07507, 2.30058, 2.03402, 2.26243, 2.03126, 2.26528, 2.01971, 2.20538, 1.99136, 2.17408, 1.99869, 2.14576, 1.98774, 2.15722, 1.98733, 2.09984, 1.93955, 2.04893, 1.92032, 2.01846, 1.89149, 1.98243, 1.86602, 1.94016, 1.84762, 1.91795, 1.84746, 1.90269, 1.82342, 1.87786, 1.80374, 1.84282, 1.79293, 1.82202, 1.76339, 1.78736, 1.74634, 1.77661, 1.55469, 1.77984, 1.7593, 1.79827, 1.77757, 1.77706, 1.75402, 1.76854, 1.75542, 1.74538, 1.52525, 1.51619, 1.52445, 1.71827, 1.72134, 1.71536, 1.71277, 1.70989, 1.70739, 1.70218, 1.70576, 1.69222, 1.7007, 1.68912, 1.70074, 1.69645, 1.70381, 1.70509, 1.71782, 1.70413, 1.74781, 1.69949, 1.73542, 1.75098, 1.76714, 1.7641, 1.78118, 1.76979, 1.78096, 1.77626, 1.78867, 1.77632, 1.83219, 1.79091, 1.79414, 1.79194, 1.81002, 1.80998, 1.8239, 1.81645, 1.83075, 1.82243, 1.83338, 1.82749, 1.8377, 1.83616, 1.84669, 1.84822, 1.85789, 1.91229, 1.8713, 1.87597, 1.89088, 1.89968, 1.89808, 1.92854, 1.90864, 1.9519, 1.9536, 2.01053, 1.77734, 1.81712, 1.79363, 2.08992, 2.06013, 2.11002, 2.04259, 2.11565, 2.02474, 2.14992, 2.03504, 2.14909, 2.04787, 2.19085, 2.10483, 2.2705, 2.1431, 2.31066, 2.16947, 2.31485, 2.20838, 2.36573, 2.25155, 2.35168, 2.2376, 2.36723, 2.23648, 2.42259, 2.27002, \n"
  },
  {
    "path": "Sponza/animation.json",
    "content": "{\n    \"StartTime\": 0.0,\n    \"EndTime\": 10.0,\n    \"CameraAnimation\": {\n        \"interpolation\": 2,\n        \"tension\": 0.5,\n        \"keyframes\": [\n            {\n                \"time\": 0.0,\n                \"value\": {\n                    \"pos\": [\n                        1274.3001708984376,\n                        204.8365020751953,\n                        -13.321953773498536\n                    ],\n                    \"up\": [\n                        -0.0509587824344635,\n                        0.9986894130706787,\n                        -0.004793293308466673\n                    ],\n                    \"forward\": [\n                        -0.9943004250526428,\n                        -0.05118371546268463,\n                        -0.09352605044841767\n                    ]\n                }\n            },\n            {\n                \"time\": 2.453000068664551,\n                \"value\": {\n                    \"pos\": [\n                        -1038.1590576171876,\n                        164.1266326904297,\n                        -41.85654830932617\n                    ],\n                    \"up\": [\n                        -0.03669549152255058,\n                        0.999324381351471,\n                        -0.0020565949380397798\n                    ],\n                    \"forward\": [\n                        -0.9977586269378662,\n                        -0.03675307705998421,\n                        -0.05591927468776703\n                    ]\n                }\n            },\n            {\n                \"time\": 6.26300048828125,\n                \"value\": {\n                    \"pos\": [\n                        2154.620361328125,\n                        1585.082763671875,\n                        24.798633575439454\n                    ],\n                    \"up\": [\n                        -0.2810738682746887,\n                        0.9596209526062012,\n                        -0.011188925243914128\n                    ],\n                    \"forward\": [\n                        -0.9588615298271179,\n                        -0.2812964916229248,\n                        -0.038170140236616138\n                    ]\n                }\n            },\n            {\n                \"time\": 10.719000816345215,\n                \"value\": {\n                    \"pos\": [\n                        2128.524169921875,\n                        112.29964447021485,\n                        25.076427459716798\n                    ],\n                    \"up\": [\n                        0.05357148125767708,\n                        0.9985640645027161,\n                        0.00039571369416080415\n                    ],\n                    \"forward\": [\n                        -0.9985367059707642,\n                        0.05357293784618378,\n                        -0.007375838700681925\n                    ]\n                }\n            }\n        ]\n    },\n    \"Subtitles\": {\n        \"keyframes\": [\n            {\n                \"time\": 0.0,\n                \"value\": \"\"\n            },\n            {\n                \"time\": 2.0,\n                \"value\": \"This is a demo camera animation\"\n            },\n            {\n                \"time\": 5.0,\n                \"value\": \"\"\n            },\n            {\n                \"time\": 11.0,\n                \"value\": \"Wow, you can also animate the sun direction!\"\n            },\n            {\n                \"time\": 15.0,\n                \"value\": \"And some booleans, like visualizations, too\"\n            }\n        ]\n    },\n    \"AnimatedVars\": [\n        {\n            \"Name\": \"ShowWaveTileCounts\",\n            \"Type\": 2,\n            \"Animation\": {\n                \"interpolation\": 0,\n                \"tension\": 0.5,\n                \"keyframes\": []\n            }\n        },\n        {\n            \"Name\": \"SunOrientation\",\n            \"Type\": 0,\n            \"Animation\": {\n                \"interpolation\": 2,\n                \"tension\": 0.5,\n                \"keyframes\": [\n                    {\n                        \"time\": 0.0,\n                        \"value\": -0.5\n                    }\n                ]\n            }\n        }\n    ]\n}"
  },
  {
    "path": "Sponza/default.anim",
    "content": "{\n    \"StartTime\": 0.0,\n    \"EndTime\": 12.0,\n    \"CameraAnimation\": {\n        \"interpolation\": 2,\n        \"tension\": 0.5,\n        \"keyframes\": [\n            {\n                \"time\": 0.0,\n                \"value\": {\n                    \"pos\": [\n                        1300.39013671875,\n                        615.7099609375,\n                        -516.9178466796875\n                    ],\n                    \"up\": [\n                        -0.09393462538719177,\n                        0.9943204522132874,\n                        0.05003299564123154\n                    ],\n                    \"forward\": [\n                        -0.8775953650474548,\n                        -0.10642844438552857,\n                        0.4674391746520996\n                    ]\n                }\n            },\n            {\n                \"time\": 2.0,\n                \"value\": {\n                    \"pos\": [\n                        1122.1114501953125,\n                        582.8412475585938,\n                        564.4061889648438\n                    ],\n                    \"up\": [\n                        -0.036188289523124698,\n                        0.9983628988265991,\n                        -0.04429496079683304\n                    ],\n                    \"forward\": [\n                        -0.6316463947296143,\n                        -0.057198215276002887,\n                        -0.7731438279151917\n                    ]\n                }\n            },\n            {\n                \"time\": 3.0,\n                \"value\": {\n                    \"pos\": [\n                        555.3658447265625,\n                        565.3318481445313,\n                        535.7691650390625\n                    ],\n                    \"up\": [\n                        -0.009369914419949055,\n                        0.9973298907279968,\n                        -0.07242655754089356\n                    ],\n                    \"forward\": [\n                        -0.12795941531658173,\n                        -0.07303013652563095,\n                        -0.9890870451927185\n                    ]\n                }\n            },\n            {\n                \"time\": 5.0,\n                \"value\": {\n                    \"pos\": [\n                        192.6989288330078,\n                        578.7852783203125,\n                        610.9442749023438\n                    ],\n                    \"up\": [\n                        0.00570015050470829,\n                        0.9954999685287476,\n                        -0.09459082037210465\n                    ],\n                    \"forward\": [\n                        0.059881340712308887,\n                        -0.0947624146938324,\n                        -0.9936974048614502\n                    ]\n                }\n            },\n            {\n                \"time\": 7.0,\n                \"value\": {\n                    \"pos\": [\n                        188.64305114746095,\n                        612.1615600585938,\n                        186.7040557861328\n                    ],\n                    \"up\": [\n                        0.3280718922615051,\n                        0.7031778693199158,\n                        -0.6308009624481201\n                    ],\n                    \"forward\": [\n                        0.324456125497818,\n                        -0.7110140323638916,\n                        -0.6238487362861633\n                    ]\n                }\n            },\n            {\n                \"time\": 9.0,\n                \"value\": {\n                    \"pos\": [\n                        654.0864868164063,\n                        291.3877258300781,\n                        83.40959167480469\n                    ],\n                    \"up\": [\n                        0.10797914862632752,\n                        0.9020001292228699,\n                        -0.4180147647857666\n                    ],\n                    \"forward\": [\n                        0.2255944460630417,\n                        -0.4317358434200287,\n                        -0.8733334541320801\n                    ]\n                }\n            },\n            {\n                \"time\": 12.0,\n                \"value\": {\n                    \"pos\": [\n                        1092.0758056640625,\n                        188.9507598876953,\n                        9.3355712890625\n                    ],\n                    \"up\": [\n                        0.01885099709033966,\n                        0.9998204708099365,\n                        0.0019444607896730304\n                    ],\n                    \"forward\": [\n                        -0.9945436120033264,\n                        0.018951015546917917,\n                        -0.10258614271879196\n                    ]\n                }\n            }\n        ]\n    }\n}"
  },
  {
    "path": "Sponza/sponza.scn",
    "content": "{\n\t\"ModelPath\" : \"sponza.h3d\",\n\t\"Animation\" : \"animation.json\"\n}"
  },
  {
    "path": "TechniqueDemos/.gitignore",
    "content": "# ignore non-code directories and files\n.vs/\nx64/\n*.ipch\n*.sdf\n*.opensdf\n*.user\n*.VC.db\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/readme.md",
    "content": "# Memory Management Sample\nThis is an advanced sample designed to demonstrate new memory management techniques in DirectX 12 and the new WDDMv2 driver model. DirectX 12 requires developers to explicitly manage their memory residency to ensure they do not use more than their fair share of memory on the system, in order to give other applications the ability to run in parallel.\n\nBy using tiled resources and DirectX 12's new resource model, the sample demonstrates how the user can map individual mip levels to different heaps, allowing them to manage residency at a sub-resource granularity. Applications can use this to stay within the kernel provided video memory budget, while also streaming mipmaps asynchronously with rendering operations.\n\n## Controls and Features\n### (M)ipmap overlays\nPress the 'm' key to toggle mipmap overlays. The overlays on the images show which mipmaps are loaded and displayed. Each image is given an overlay and an outline. The overlay color displays the current mip level needed to render the image at full quality for the current zoom level. The outline, by contrast, shows the mip level which is currently resident by the background streaming thread.\n\nThe colors table used for mipmaps are in \"rainbow order\" - that is, mip 0=Red, 1=Orange, 2=Yellow, etc. \n\n### (S)tatistics overlays\nPress the 's' key to toggle statistics overlays. The statistics overlays show some useful information for visualizing the state of the application, including a memory graph, CPU timing numbers, framerate, and glitch count. \n\nThe memory graph shows both the application's current usage (yellow) as well as the current budget for that process (red line). A well-behaved application is defined as one whose current usage always remains under the budget (or tries its best to do so).\n\nUnder memory pressure, some applications will simply be unable to stay under the budget due to a combination of a highly constrained budget and a minimum footprint required by the application. Consuming more memory than your process budget allows can subject your process to throttling by the graphics kernel. The exact behavior when going over budget depends on a number of factors, such as whether or not a non-local video memory budget exists, and the priority of your application (e.g. DWM and foreground applications are prioritized over background applications). \n\n### Budget overrides (+/-)\nPress the '+' and '-' keys to adjust the budget in 128 MB chunks. Zero, which is the default value, means to use the kernel provided budget value.\n\nAlthough the memory graph in the statistics overlay is useful for visualizing the current state of the application, it can be hard to determine if the application is behaving correctly if the budget never changes. The graphics kernel will periodically issue new budgets to the process over time based on total system-wide memory pressure, but there is currently no way to control the budget assigned to the process from user mode. This sample simulates this behavior by clamping the value returned by the graphics kernel to a maximum value, allowing the application to behave under the impression that its memory budget is more restricted than it really is. The application can use this override to stress trimming and prefetching behaviors.\n\n### Camera Management (d/c)\nThe sample uses the user's camera as a means to determine what should be trimmed or prefetched. For example, images closer to the camera are prioritized higher than images further away. Under normal conditions, this is quite difficult to visualize - after all, how can you see the paging engine prefetching textures nearby (but outside of) the camera view, if you cannot actually see outside of the camera?\n\nTo solve this issue, the sample provided two cameras which can be controlled independently. These two cameras decouple the memory management algorithms from the rendering.\n\nPress the 'd' key to detach the cameras, and the 'c' key to toggle which camera is controlled by the mouse. The primary camera will always control rendering, but if detached, the secondary camera will control the residency management.\n\nThe detached camera is shown as hollow red rectangle. The hollow center is the camera view - i.e. what the user would see, if looking through that camera. The red region outside of that is the camera's prefetching region. This region is used to determine which nearby images need to be loaded. The nearby mipmaps are prefetched in this fashion to prevent texture popping caused by casual camera movement. The sample also attempts to load one mipmap higher than the current visible mipmap in the center view.\n\nThe exact decision on how to prefetch and trim is up to the application, but the sample uses the following priority scheme:\n\n1. Page in all visible mipmaps  (i.e. mipmaps needed for rendering at the current camera zoom)\n2. Page in one mipmap higher for visible mipmaps, and the currently visible mipmap levels for nearby images (e.g. those in the red region)\n3. Round-robin all images and load one more mipmap until all images load mipmap 0 or we are at our budget.\n\nPriorities 1 and 2 are designed to ensure the highest quality rendering for images the user is expected to see, while priority 3 is designed purely to prefetch as much as possible. In our sample, it was determined that mipmaps loaded during priority 3 did not have a strict ordering requirement, and the chosen mipmap may correspond to seemingly random images from the perspective of the debug camera, due to the round-robin approach.\n\n### Toggle (v)-sync\nPress the 'v' key to toggle v-sync on and off.\n\n### Toggle (f)ullscreen mode\nPress the 'f' key to toggle between fullscreen and windowed modes.\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Camera.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n#include \"Camera.h\"\r\n\r\nCamera::Camera() :\r\n\tm_position(),\r\n\tm_zoom(),\r\n\tm_projectionRect()\r\n{\r\n}\r\n\r\nvoid Camera::Initialize(PointF position, float zoom)\r\n{\r\n\tm_projectionRect.Left = -640.0f;\r\n\tm_projectionRect.Right = 640.0f;\r\n\tm_projectionRect.Top = -360.0f;\r\n\tm_projectionRect.Bottom = 360.0f;\r\n\r\n\tm_position = position;\r\n\tm_zoom = zoom;\r\n}\r\n\r\nXMMATRIX Camera::GetViewProjectionMatrix() const\r\n{\r\n\tXMMATRIX Projection = XMMatrixOrthographicOffCenterLH(\r\n\t\tm_projectionRect.Left / m_zoom,\r\n\t\tm_projectionRect.Right / m_zoom,\r\n\t\tm_projectionRect.Bottom / m_zoom,\r\n\t\tm_projectionRect.Top / m_zoom,\r\n\t\t0.1f,\r\n\t\t10.0f);\r\n\r\n\tXMVECTOR Eye = XMVectorSet(m_position.X, m_position.Y, -1.0f, 0.0f);\r\n\tXMVECTOR LookAt = XMVectorSet(m_position.X, m_position.Y, 0.0f, 0.0f);\r\n\tXMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);\r\n\r\n\tXMMATRIX View = XMMatrixLookAtLH(Eye, LookAt, Up);\r\n\r\n\treturn View * Projection;\r\n}\r\n\r\nRectF Camera::GenerateViewportBounds() const\r\n{\r\n\tRectF ViewportBounds = m_projectionRect;\r\n\tViewportBounds.Left = ViewportBounds.Left / m_zoom + m_position.X;\r\n\tViewportBounds.Right = ViewportBounds.Right / m_zoom + m_position.X;\r\n\tViewportBounds.Top = ViewportBounds.Top / m_zoom + m_position.Y;\r\n\tViewportBounds.Bottom = ViewportBounds.Bottom / m_zoom + m_position.Y;\r\n\r\n\treturn ViewportBounds;\r\n}\r\n\r\nvoid Camera::OnMouseMove(PointF delta)\r\n{\r\n\tm_position.X -= delta.X / m_zoom;\r\n\tm_position.Y -= delta.Y / m_zoom;\r\n}\r\n\r\nvoid Camera::OnMouseWheel(short delta)\r\n{\r\n\tif (abs(delta) >= WHEEL_DELTA)\r\n\t{\r\n\t\tfloat newZoom = m_zoom;\r\n\t\tfloat deltaZoom = 1.0f - ((float)abs(delta) / WHEEL_DELTA / 10.0f);\r\n\r\n\t\tif (delta < 0)\r\n\t\t{\r\n\t\t\tnewZoom *= deltaZoom;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnewZoom /= deltaZoom;\r\n\t\t}\r\n\r\n\t\tif (newZoom < 0.1f)\r\n\t\t{\r\n\t\t\tnewZoom = 0.1f;\r\n\t\t}\r\n\t\tif (newZoom > 100.0f)\r\n\t\t{\r\n\t\t\tnewZoom = 100.0f;\r\n\t\t}\r\n\r\n\t\tm_zoom = newZoom;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Camera.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\nusing namespace DirectX;\r\n\r\nclass Camera\r\n{\r\npublic:\r\n\tCamera();\r\n\tvoid Initialize(PointF position, float zoom);\r\n\r\n\tinline void SetOrthographicProjection(const RectF& Rect)\r\n\t{\r\n\t\tm_projectionRect = Rect;\r\n\t}\r\n\r\n\tinline float GetZoom() const\r\n\t{\r\n\t\treturn m_zoom;\r\n\t}\r\n\r\n\tXMMATRIX GetViewProjectionMatrix() const;\r\n\tRectF GenerateViewportBounds() const;\r\n\r\n\tvoid OnMouseMove(PointF delta);\r\n\tvoid OnMouseWheel(short delta);\r\n\r\nprivate:\r\n\tPointF m_position;\r\n\tfloat m_zoom;\r\n\tRectF m_projectionRect;\r\n\r\n\tbool m_mouseDown;\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Color.hlsl",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\ncbuffer Projection : register(b0)\r\n{\r\n\tfloat4x4 GProjectionMatrix;\r\n};\r\n\r\nstruct PSInput\r\n{\r\n\tfloat4 Position : SV_POSITION;\r\n\tfloat4 Color : COLOR;\r\n};\r\n\r\nPSInput VShader(float3 Position : POSITION, float4 Color : COLOR)\r\n{\r\n\tPSInput Output;\r\n\r\n\tOutput.Position = float4(Position, 1.0f);\r\n\tOutput.Position = mul(GProjectionMatrix, Output.Position);\r\n\tOutput.Color = Color;\r\n\r\n\treturn Output;\r\n}\r\n\r\nfloat4 PShader(PSInput Input) : SV_TARGET\r\n{\r\n\treturn Input.Color;\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Context.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\nContext::Context(DX12Framework* pFramework) :\r\n\tm_pFramework(pFramework)\r\n{\r\n\tInitializeListHead(&m_ActiveFrameListHead);\r\n\tInitializeListHead(&m_FreeFrameListHead);\r\n}\r\n\r\nContext::~Context()\r\n{\r\n}\r\n\r\nHRESULT Context::CreateDeviceDependentState(D3D12_COMMAND_LIST_TYPE Type)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tID3D12Device* pDevice = m_pFramework->GetDevice();\r\n\r\n\tD3D12_COMMAND_QUEUE_DESC Desc = {};\r\n\tDesc.Type = Type;\r\n\tDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;\r\n\tDesc.NodeMask = 0;\r\n\tDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;\r\n\r\n\thr = pDevice->CreateCommandQueue(&Desc, IID_PPV_ARGS(&m_pCommandQueue));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create command queue with Type=%d, hr=0x%.8x\", Type, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pFenceObject));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create fence object, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tm_hFlushEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\tif (m_hFlushEvent == nullptr)\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create paging flush event, Error=0x%.8x\", GetLastError());\r\n\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid Context::DestroyDeviceDependentState()\r\n{\r\n\tassert(m_pCurrentFrame == nullptr);\r\n\tassert(m_ActiveFrames == 0);\r\n\r\n\tSafeRelease(m_pFenceObject);\r\n\tSafeRelease(m_pCommandQueue);\r\n\r\n\tif (m_hFlushEvent)\r\n\t{\r\n\t\tCloseHandle(m_hFlushEvent);\r\n\t}\r\n\r\n\tassert(IsListEmpty(&m_FreeFrameListHead));\r\n}\r\n\r\nvoid Context::WaitForFence(UINT64 Fence)\r\n{\r\n\tUINT64 CompletedFence = m_pFenceObject->GetCompletedValue();\r\n\tif (CompletedFence >= Fence)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tHANDLE hWaitHandle = TlsGetValue(m_pFramework->GetThreadContextWaitHandleIndex());\r\n\tm_pFenceObject->SetEventOnCompletion(Fence, hWaitHandle);\r\n\r\n\tWaitForSingleObject(hWaitHandle, INFINITE);\r\n}\r\n\r\nvoid Context::Flush()\r\n{\r\n\tWaitForAllFrames();\r\n}\r\n\r\nvoid Context::RetireFrameInternal(Frame* pFrame)\r\n{\r\n\t// Retire resources.\r\n\r\n\tRemoveEntryList(pFrame);\r\n\tInsertHeadList(&m_FreeFrameListHead, pFrame);\r\n\r\n\tassert(m_ActiveFrames > 0);\r\n\t--m_ActiveFrames;\r\n\r\n\tHRESULT hr = pFrame->pCommandAllocator->Reset();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Resetting the command allocator failed, hr=0x%.8x\", hr);\r\n\t}\r\n\r\n\tRetireFrame(pFrame);\r\n\r\n\tm_LastCompletedFence = pFrame->CompletionFence;\r\n}\r\n\r\nvoid Context::Begin()\r\n{\r\n\tassert(m_pCurrentFrame == nullptr);\r\n\r\n\tif (IsListEmpty(&m_FreeFrameListHead))\r\n\t{\r\n\t\tWaitForSingleFrame();\r\n\t}\r\n\r\n\tassert(!IsListEmpty(&m_FreeFrameListHead));\r\n\r\n\tLIST_ENTRY* pFrameEntry = RemoveHeadList(&m_FreeFrameListHead);\r\n\tm_pCurrentFrame = static_cast<Frame*>(pFrameEntry);\r\n\t++m_CurrentFence;\r\n\tm_pCurrentFrame->CompletionFence = m_CurrentFence;\r\n\r\n\tHRESULT hr = m_pCurrentFrame->pCommandList->Reset(m_pCurrentFrame->pCommandAllocator, nullptr);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_CRITICAL_ERROR(\"Failed to reset command list, hr=0x%.8x\", hr);\r\n\t}\r\n}\r\n\r\nHRESULT Context::Execute()\r\n{\r\n\tHRESULT hr;\r\n\r\n\thr = m_pCurrentFrame->pCommandList->Close();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to close command list, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tID3D12CommandList* ppCommandLists[] = { m_pCurrentFrame->pCommandList };\r\n\tm_pCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid Context::End()\r\n{\r\n\tassert(m_pCurrentFrame != nullptr);\r\n\r\n\t//\r\n\t// Signal can return an error during device removed, but we will hide this error from the caller\r\n\t// and instead handle any resulting errors during Present calls.\r\n\t//\r\n\tm_pCommandQueue->Signal(m_pFenceObject, m_CurrentFence);\r\n\r\n\tInsertTailList(&m_ActiveFrameListHead, m_pCurrentFrame);\r\n\r\n\t++m_ActiveFrames;\r\n\r\n\tm_pCurrentFrame = nullptr;\r\n}\r\n\r\nvoid Context::WaitForSingleFrame()\r\n{\r\n\tif (!IsListEmpty(&m_ActiveFrameListHead))\r\n\t{\r\n\t\tFrame* pFrame = static_cast<Frame*>(m_ActiveFrameListHead.Flink);\r\n\t\tWaitForFence(pFrame->CompletionFence);\r\n\r\n\t\tRetireFrameInternal(pFrame);\r\n\t}\r\n}\r\n\r\nvoid Context::WaitForAllFrames()\r\n{\r\n\tif (!IsListEmpty(&m_ActiveFrameListHead))\r\n\t{\r\n\t\tFrame* pLastFrame = static_cast<Frame*>(m_ActiveFrameListHead.Blink);\r\n\t\tWaitForFence(pLastFrame->CompletionFence);\r\n\r\n\t\tLIST_ENTRY* pFrameEntry = m_ActiveFrameListHead.Flink;\r\n\t\twhile (pFrameEntry != &m_ActiveFrameListHead)\r\n\t\t{\r\n\t\t\tFrame* pFrame = static_cast<Frame*>(pFrameEntry);\r\n\t\t\tpFrameEntry = pFrameEntry->Flink;\r\n\r\n\t\t\tRetireFrameInternal(pFrame);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nHRESULT Context::InitializeFrame(Frame* pFrame, D3D12_COMMAND_LIST_TYPE Type)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tInsertTailList(&m_FreeFrameListHead, pFrame);\r\n\r\n\thr = m_pFramework->GetDevice()->CreateCommandAllocator(Type, IID_PPV_ARGS(&pFrame->pCommandAllocator));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create command allocator with Type=%d, hr=0x%.8x\", Type, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_pFramework->GetDevice()->CreateCommandList(0, Type, pFrame->pCommandAllocator, nullptr, IID_PPV_ARGS(&pFrame->pCommandList));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create command list with Type=%d, hr=0x%.8x\", Type, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tpFrame->pCommandList->Close();\r\n\r\n\treturn S_OK;\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Context.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// A Frame object stores information about each iteration of the pipeline.\r\n// For rendering, this would correspond 1:1 with a real rendering frame (i.e. from\r\n// one Present() call to the next).\r\n// For paging, a frame corresponds to each unique paging operation.\r\n// Each frame belongs to a Context object (defined below), and operations are queued\r\n// on that Context's D3D12 command queue. At the end of each frame, the frame's\r\n// completion fence is signaled on the command queue, allowing us to monitor\r\n// completion of GPU work for that frame.\r\n//\r\nstruct Frame : LIST_ENTRY\r\n{\r\n\tID3D12CommandAllocator* pCommandAllocator;\r\n\tID3D12GraphicsCommandList* pCommandList;\r\n\tUINT64 CompletionFence;\r\n};\r\n\r\n//\r\n// A context is used to abstract GPU scheduling state. Each context contains a command\r\n// queue, a fence object used to signal and track GPU work, and a list of frames that\r\n// can be running in parallel.\r\n// The Context object is subclassed into a RenderContext and PagingContext, which create\r\n// unique queue types and perform unique operations.\r\n//\r\nclass Context\r\n{\r\nprotected:\r\n\tDX12Framework* m_pFramework;\r\n\r\n\t// List entry head storing a list of all actively running frames. All actively running\r\n\t// frames are assumed to be running on the GPU until they are retired.\r\n\tLIST_ENTRY m_ActiveFrameListHead;\r\n\r\n\t// List entry head storing a list of free frame objects which can be reused.\r\n\tLIST_ENTRY m_FreeFrameListHead;\r\n\r\n\t// The current fence for this command queue. This fence value is incremented once per frame.\r\n\tUINT64 m_CurrentFence = 0;\r\n\r\n\t// Stores the fence of the most recently completed and retired frame. It can safely be\r\n\t// assumed that any fence value lower than this is referring to work that has completed\r\n\t// on the GPU, and is safe to reuse.\r\n\tUINT64 m_LastCompletedFence = 0;\r\n\r\n\t// The frame currently being recorded by the context. This value is null outside of\r\n\t// calls to Begin() and End().\r\n\tFrame* m_pCurrentFrame = nullptr;\r\n\r\n\t// The D3D12 command queue object to which all work is submitted.\r\n\tID3D12CommandQueue* m_pCommandQueue = nullptr;\r\n\r\n\t// The D3D12 fence object used track progress on the command queue.\r\n\tID3D12Fence* m_pFenceObject = nullptr;\r\n\r\n\t// A handle (allocated per thread with TLS) allowing a thread to safely wait on this context.\r\n\tHANDLE m_hFlushEvent = nullptr;\r\n\r\n\t// The number of active frames in flight that are accessing the GPU.\r\n\tUINT32 m_ActiveFrames = 0;\r\n\r\nprotected:\r\n\tHRESULT InitializeFrame(Frame* pFrame, D3D12_COMMAND_LIST_TYPE Type);\r\n\tvirtual void RetireFrame(Frame* /*pFrame*/) { }\r\n\r\nprivate:\r\n\tvoid RetireFrameInternal(Frame* pFrame);\r\n\r\npublic:\r\n\tContext(DX12Framework* pFramework);\r\n\t~Context();\r\n\r\n\tHRESULT CreateDeviceDependentState(D3D12_COMMAND_LIST_TYPE Type);\r\n\tvoid DestroyDeviceDependentState();\r\n\r\n\tvoid Begin();\r\n\tHRESULT Execute();\r\n\tvoid End();\r\n\r\n\tvoid WaitForFence(UINT64 Fence);\r\n\tvoid WaitForSingleFrame();\r\n\tvoid WaitForAllFrames();\r\n\r\n\tvoid Flush();\r\n\r\n\tinline ID3D12CommandQueue* GetCommandQueue()\r\n\t{\r\n\t\treturn m_pCommandQueue;\r\n\t}\r\n\r\n\tinline UINT32 GetActiveFrameCount() const\r\n\t{\r\n\t\treturn m_ActiveFrames;\r\n\t}\r\n\r\n\tinline UINT64 GetLastCompletedFence() const\r\n\t{\r\n\t\treturn m_LastCompletedFence;\r\n\t}\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/D3D12MemoryManagement.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\n//\r\n// The size and padding between images rendered on screen.\r\n//\r\n#define RENDER_TILE_SIZE 256\r\n#define RENDER_TILE_PADDING 8\r\n\r\n//\r\n// The number of rows of images to display at any one time.\r\n//\r\n#define NUM_ROWS 4\r\n\r\n//\r\n// Constants defining the size and formatting of the memory graph shown in the top-right corner.\r\n//\r\n#define GRAPH_PADDING 16.0f\r\n#define GRAPH_WIDTH 512.0f\r\n#define GRAPH_HEIGHT 96.0f\r\n#define GRAPH_HEIGHT_RATIO 90\r\n#define GRAPH_WIDTH_PER_SEGMENT (GRAPH_WIDTH / GRAPH_SEGMENTS)\r\n#define GRAPH_NOTCH_COUNT 4\r\n\r\n//\r\n// The default distance from the camera (unscaled) to prioritize prefetched mipmaps.\r\n//\r\n#define PREFETCH_DISTANCE 600.0f\r\n\r\n//\r\n// Helper function to calculate an average for a numbe rof statistic points.\r\n//\r\nstatic float AverageStatistics(float* pStats, UINT StatCount)\r\n{\r\n\tfloat Total = 0.0f;\r\n\tfor (UINT i = 0; i < StatCount; ++i)\r\n\t{\r\n\t\tTotal += pStats[i];\r\n\t}\r\n\treturn Total / StatCount;\r\n}\r\n\r\n//\r\n// Initializes the specified image object to reference the input resource,\r\n// and calculates the image bounds based on its image index. The image bounds\r\n// are then cached and used for visibility and rendering calculations.\r\n//\r\nvoid InitializeImage(Image* pImage, Resource* pResource, UINT32 ImageIndex)\r\n{\r\n\tUINT32 TileWidth = RENDER_TILE_SIZE;\r\n\tUINT32 TileHeight = RENDER_TILE_SIZE;\r\n\r\n\tUINT32 Row = ImageIndex % NUM_ROWS;\r\n\tUINT32 Col = ImageIndex / NUM_ROWS;\r\n\r\n\tUINT32 HeightOffset = ((NUM_ROWS - 1) * RENDER_TILE_SIZE + (NUM_ROWS - 1) * RENDER_TILE_PADDING) / 2;\r\n\r\n\tD3D12_RESOURCE_DESC Desc = pResource->pDeviceState->pD3DResource->GetDesc();\r\n\tfloat ScaleX = 1.0f;\r\n\tfloat ScaleY = 1.0f;\r\n\tif (Desc.Width < 256)\r\n\t{\r\n\t\tScaleX = Desc.Width / 256.0f;\r\n\t}\r\n\tif (Desc.Height < 256)\r\n\t{\r\n\t\tScaleY = Desc.Height / 256.0f;\r\n\t}\r\n\r\n\tif (Desc.Width > Desc.Height)\r\n\t{\r\n\t\tScaleY *= (float)Desc.Height / Desc.Width;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tScaleX *= (float)Desc.Width / Desc.Height;\r\n\t}\r\n\r\n\tfloat X = Col * ((float)TileWidth + RENDER_TILE_PADDING);\r\n\tfloat Y = Row * ((float)TileHeight + RENDER_TILE_PADDING) - HeightOffset;\r\n\tfloat Width = TileWidth * ScaleX;\r\n\tfloat Height = TileHeight * ScaleY;\r\n\r\n\tfloat HalfWidth = Width / 2;\r\n\tfloat HalfHeight = Height / 2;\r\n\r\n\tRectF DestRect =\r\n\t{\r\n\t\tX - HalfWidth,\r\n\t\tY - HalfHeight,\r\n\t\tX + HalfWidth,\r\n\t\tY + HalfHeight\r\n\t};\r\n\r\n\tpImage->pResource = pResource;\r\n\tpImage->Bounds = DestRect;\r\n}\r\n\r\nD3D12MemoryManagement::D3D12MemoryManagement()\r\n{\r\n\tm_ViewportCamera.Initialize(PointF{ 600.0f, 0.0f }, 0.6f);\r\n\tSetSceneCamera(&m_ViewportCamera);\r\n\r\n\tm_DebugCamera = m_ViewportCamera;\r\n\tm_pCapturedCamera = &m_ViewportCamera;\r\n\tm_pSceneCamera = &m_ViewportCamera;\r\n\tZeroMemory(m_GraphPoints, sizeof(m_GraphPoints));\r\n#if(_DEBUG)\r\n\tm_bRenderStats = true;\r\n\tm_bDrawMipColors = true;\r\n#endif\r\n}\r\n\r\nD3D12MemoryManagement::~D3D12MemoryManagement()\r\n{\r\n}\r\n\r\nHRESULT D3D12MemoryManagement::CreateDeviceDependentState()\r\n{\r\n\t//\r\n\t// D2D brushes must be created when the device is recreated.\r\n\t//\r\n\tHRESULT hr;\r\n\thr = m_pD2DContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &m_pTextBrush);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create solid color brush for text, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nHRESULT D3D12MemoryManagement::CreateDeviceIndependentState()\r\n{\r\n\tHRESULT hr;\r\n\r\n\t//\r\n\t// Text formats are not dependent on a graphics device, so they can be created\r\n\t// once and saved.\r\n\t//\r\n\thr = m_pDWriteFactory->CreateTextFormat(\r\n\t\tL\"Verdana\",\r\n\t\tnullptr,\r\n\t\tDWRITE_FONT_WEIGHT_NORMAL,\r\n\t\tDWRITE_FONT_STYLE_NORMAL,\r\n\t\tDWRITE_FONT_STRETCH_NORMAL,\r\n\t\t11.0f,\r\n\t\tL\"en-us\",\r\n\t\t&m_pTextFormat);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create text format, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tm_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING);\r\n\tm_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid D3D12MemoryManagement::DestroyDeviceDependentState()\r\n{\r\n\tSafeRelease(m_pTextBrush);\r\n}\r\n\r\nvoid D3D12MemoryManagement::DestroyDeviceIndependentState()\r\n{\r\n\tSafeRelease(m_pTextFormat);\r\n}\r\n\r\n//\r\n// LoadAssets goes through the texture asset directory and attempts to load all files\r\n// as images for the application to stream in. Texture assets are located in\r\n// Assets\\Textures, relative to the sample binary.\r\n//\r\nHRESULT D3D12MemoryManagement::LoadAssets()\r\n{\r\n\tWCHAR FileName[MAX_PATH];\r\n\tGetWorkingDir(FileName, MAX_PATH);\r\n\r\n\twcscat_s(FileName, L\"Assets\\\\Textures\\\\*\");\r\n\tWCHAR* pEnd = FileName + wcslen(FileName) - 1;\r\n\r\n\tWIN32_FIND_DATA ffd;\r\n\tHANDLE hFind = FindFirstFile(FileName, &ffd);\r\n\r\n\tif (INVALID_HANDLE_VALUE == hFind)\r\n\t{\r\n\t\t//\r\n\t\t// Does the directory not exist?\r\n\t\t//\r\n\t\tLOG_ERROR(\"Failed to load texture assets\");\r\n\t\treturn E_FAIL;\r\n\t}\r\n\r\n\tUINT ImageIndex = 0;\r\n\r\n\tdo\r\n\t{\r\n\t\tif (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// Ignore directories.\r\n\t\t\t//\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// Try to create the resource from the file. This may not be a valid image file,\r\n\t\t\t// and if this is the case, we will fail to create the resource, and continue\r\n\t\t\t// with the next file.\r\n\t\t\t//\r\n\t\t\t*pEnd = L'\\0';\r\n\t\t\twcscat_s(FileName, ffd.cFileName);\r\n\r\n\t\t\tResource* pResource = nullptr;\r\n\r\n\t\t\tHRESULT hr = CreateResource(FileName, &pResource);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tImage Img;\r\n\t\t\tInitializeImage(&Img, pResource, ImageIndex);\r\n\t\t\tm_Images.push_back(Img);\r\n\r\n\t\t\t++ImageIndex;\r\n\t\t}\r\n\t} while (FindNextFile(hFind, &ffd) != 0);\r\n\r\n\tFindClose(hFind);\r\n\r\n\tfor (UINT GeneratedImage = 0; GeneratedImage < MAX_GENERATED_IMAGES; ++GeneratedImage)\r\n\t{\r\n\t\tResource* pResource = nullptr;\r\n\t\tHRESULT hr = CreateResource(L\"\", &pResource);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Unable to generate image %d\", GeneratedImage);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tImage Img;\r\n\t\tInitializeImage(&Img, pResource, ImageIndex);\r\n\t\tm_Images.push_back(Img);\r\n\r\n\t\t++ImageIndex;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nbool D3D12MemoryManagement::HandleMessage(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)\r\n{\r\n\tbool bHandled = DX12Framework::HandleMessage(hwnd, Message, wParam, lParam);\r\n\tif (bHandled)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tswitch (Message)\r\n\t{\r\n\tcase WM_MOUSEWHEEL:\r\n\t\t{\r\n\t\t\t// Use mouse wheel to apply camera zoom.\r\n\t\t\tm_pCapturedCamera->OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam));\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\tcase WM_LBUTTONDOWN:\r\n\t\t{\r\n\t\t\t// Use left mouse button and movement for panning.\r\n\t\t\tm_MouseX = (int)LOWORD(lParam);\r\n\t\t\tm_MouseY = (int)HIWORD(lParam);\r\n\t\t\tm_bMouseDown = true;\r\n\r\n\t\t\tSetCapture(m_Hwnd);\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\tcase WM_LBUTTONUP:\r\n\t\t{\r\n\t\t\tm_bMouseDown = false;\r\n\t\t\tReleaseCapture();\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\tcase WM_MOUSEMOVE:\r\n\t\t{\r\n\t\t\tif (m_bMouseDown)\r\n\t\t\t{\r\n\t\t\t\tint xPos = (int)(short)LOWORD(lParam);\r\n\t\t\t\tint yPos = (int)(short)HIWORD(lParam);\r\n\r\n\t\t\t\tfloat DeltaScrollX = (float)(xPos - m_MouseX);\r\n\t\t\t\tfloat DeltaScrollY = (float)(yPos - m_MouseY);\r\n\r\n\t\t\t\tif (m_pCapturedCamera == &m_ViewportCamera)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pCapturedCamera->OnMouseMove(PointF{ DeltaScrollX, DeltaScrollY });\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Move the debug camera relative to the viewport camera's coordinate space.\r\n\t\t\t\t\t//\r\n\t\t\t\t\tfloat zoom = m_pCapturedCamera->GetZoom() / m_ViewportCamera.GetZoom();\r\n\t\t\t\t\tm_pCapturedCamera->OnMouseMove(PointF{ -DeltaScrollX * zoom, -DeltaScrollY * zoom });\r\n\t\t\t\t}\r\n\r\n\t\t\t\tm_MouseX = xPos;\r\n\t\t\t\tm_MouseY = yPos;\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t//\r\n\t// On window resize, adjust the camera perspective to match the new window size.\r\n\t//\r\n\tcase WM_SIZE:\r\n\t\t{\r\n\t\t\tRectF NewProjection =\r\n\t\t\t{\r\n\t\t\t\t-m_WindowWidth / 2.0f,\r\n\t\t\t\t-m_WindowHeight / 2.0f,\r\n\t\t\t\tm_WindowWidth / 2.0f,\r\n\t\t\t\tm_WindowHeight / 2.0f,\r\n\t\t\t};\r\n\t\t\tm_pCapturedCamera->SetOrthographicProjection(NewProjection);\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\tcase WM_KEYDOWN:\r\n\t\t{\r\n\t\t\tif (wParam == GetVirtualKeyFromCharacter('s')) // Toggle 's'tats.\r\n\t\t\t{\r\n\t\t\t\tm_bRenderStats = !m_bRenderStats;\r\n\t\t\t}\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('m')) // View 'm'ip coloring.\r\n\t\t\t{\r\n\t\t\t\tm_bDrawMipColors = !m_bDrawMipColors;\r\n\t\t\t}\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('v')) // Toggle 'v'sync.\r\n\t\t\t{\r\n\t\t\t\tm_bPresentOnVsync = !m_bPresentOnVsync;\r\n\t\t\t}\r\n\t#if(_DEBUG)\r\n\t\t\t//\r\n\t\t\t// In debug builds, allow simulated device removed errors for testing purposes.\r\n\t\t\t//\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('r')) // Simulate 'r'emove device.\r\n\t\t\t{\r\n\t\t\t\tm_SimulatedRenderResult = DXGI_ERROR_DEVICE_REMOVED;\r\n\t\t\t\tif (m_NewAdapterIndex == 0xFFFFFFFF)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_NewAdapterIndex = 0;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Toggle adapters 0 and 1.\r\n\t\t\t\t\tm_NewAdapterIndex = !m_NewAdapterIndex;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('e')) //  Simulate remove device without adapter toggle.\r\n\t\t\t{\r\n\t\t\t\tm_SimulatedRenderResult = DXGI_ERROR_DEVICE_REMOVED;\r\n\t\t\t}\r\n\t#endif\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('c')) // Toggle 'c'amera.\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Toggle captured viewport - switched which viewport the mouse controls.\r\n\t\t\t\t//\r\n\t\t\t\tif (m_pCapturedCamera == &m_ViewportCamera)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pCapturedCamera = &m_DebugCamera;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pCapturedCamera = &m_ViewportCamera;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('d')) // 'D'etach camera.\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Toggle scene viewport - switches which camera is used as the scene camera\r\n\t\t\t\t// which determines prefetching and display behavior.\r\n\t\t\t\t//\r\n\t\t\t\tif (m_pSceneCamera == &m_ViewportCamera)\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pSceneCamera = &m_DebugCamera;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pSceneCamera = &m_ViewportCamera;\r\n\t\t\t\t\tm_pCapturedCamera = &m_ViewportCamera;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (wParam == GetVirtualKeyFromCharacter('f')) // Toggle 'f'ullscreen mode.\r\n\t\t\t{\r\n\t\t\t\tHRESULT hr = S_OK;\r\n\t\t\t\tif (m_bFullscreen)\r\n\t\t\t\t{\r\n\t\t\t\t\tSetWindowLongPtr(m_Hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);\r\n\t\t\t\t\tSetWindowPos(\r\n\t\t\t\t\t\tm_Hwnd,\r\n\t\t\t\t\t\tnullptr,\r\n\t\t\t\t\t\tm_WindowRect.left,\r\n\t\t\t\t\t\tm_WindowRect.top,\r\n\t\t\t\t\t\tm_WindowRect.right - m_WindowRect.left,\r\n\t\t\t\t\t\tm_WindowRect.bottom - m_WindowRect.top,\r\n\t\t\t\t\t\t0);\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tIDXGIOutput* pDXGIOutput;\r\n\t\t\t\t\thr = m_pDXGISwapChain->GetContainingOutput(&pDXGIOutput);\r\n\t\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tDXGI_OUTPUT_DESC Desc;\r\n\t\t\t\t\t\tpDXGIOutput->GetDesc(&Desc);\r\n\r\n\t\t\t\t\t\tGetWindowRect(m_Hwnd, &m_WindowRect);\r\n\t\t\t\t\t\tSetWindowLongPtr(m_Hwnd, GWL_STYLE, WS_POPUP);\r\n\t\t\t\t\t\tSetWindowPos(\r\n\t\t\t\t\t\t\tm_Hwnd,\r\n\t\t\t\t\t\t\tHWND_TOP,\r\n\t\t\t\t\t\t\tDesc.DesktopCoordinates.left,\r\n\t\t\t\t\t\t\tDesc.DesktopCoordinates.top,\r\n\t\t\t\t\t\t\tDesc.DesktopCoordinates.right - Desc.DesktopCoordinates.left,\r\n\t\t\t\t\t\t\tDesc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top,\r\n\t\t\t\t\t\t\tSWP_FRAMECHANGED | SWP_SHOWWINDOW);\r\n\r\n\t\t\t\t\t\tpDXGIOutput->Release();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (SUCCEEDED(hr))\r\n\t\t\t\t{\r\n\t\t\t\t\tShowWindow(m_Hwnd, SW_SHOWNORMAL);\r\n\t\t\t\t\tm_bFullscreen = !m_bFullscreen;\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t\t//\r\n\t\t\t// Budget overrides in debug builds.\r\n\t\t\t//\r\n\t\t\telse if (wParam == VK_OEM_PLUS || wParam == VK_ADD) // '+' - Increase budget.\r\n\t\t\t{\r\n\t\t\t\tUINT64 CurrentOverride = GetLocalBudgetOverride();\r\n\t\t\t\tCurrentOverride += _128MB;\r\n\t\t\t\tSetLocalBudgetOverride(CurrentOverride);\r\n\t\t\t}\r\n\t\t\telse if (wParam == VK_OEM_MINUS || wParam == VK_SUBTRACT) // '-' - Decrease budget.\r\n\t\t\t{\r\n\t\t\t\tUINT64 CurrentOverride = GetLocalBudgetOverride();\r\n\t\t\t\tif (CurrentOverride > _128MB)\r\n\t\t\t\t{\r\n\t\t\t\t\tCurrentOverride -= _128MB;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tCurrentOverride = 0;\r\n\t\t\t\t}\r\n\t\t\t\tSetLocalBudgetOverride(CurrentOverride);\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid D3D12MemoryManagement::CalculateImagePagingData(const RectF* pViewportBounds, const Image* pImage, UINT8* pVisibleMip, UINT8* pPrefetchMip)\r\n{\r\n\tfloat ImageScale = (pImage->Bounds.Right - pImage->Bounds.Left) * m_pSceneCamera->GetZoom();\r\n\tUINT8 RequiredMip = (UINT8)CalculateRequiredMipLevel(pImage->pResource, ImageScale);\r\n\r\n\t//\r\n\t// Determine if the resource is visible, or nearby, and if so, calculate the visible\r\n\t// or prefetchable mipmap index for this resource. This is used to determine the\r\n\t// priority which the paging thread will stream in the resources. Visible mipmaps\r\n\t// have a higher priority than prefetched ones, and prefetched mipmaps are higher\r\n\t// priority than all others.\r\n\t//\r\n\tfloat ScaledPrefetchDistance = PREFETCH_DISTANCE / m_pSceneCamera->GetZoom();\r\n\tbool IsVisible = RectIntersects(*pViewportBounds, pImage->Bounds);\r\n\tbool IsNearlyVisible = RectNearlyIntersects(*pViewportBounds, pImage->Bounds, ScaledPrefetchDistance);\r\n\r\n\tUINT8 VisibleMip;\r\n\tUINT8 PrefetchMip;\r\n\r\n\tif (IsVisible)\r\n\t{\r\n\t\tVisibleMip = RequiredMip;\r\n\t\tPrefetchMip = IncreaseMipQuality(RequiredMip, 1);\r\n\t}\r\n\telse if (IsNearlyVisible)\r\n\t{\r\n\t\tVisibleMip = UNDEFINED_MIPMAP_INDEX;\r\n\t\tPrefetchMip = RequiredMip;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tVisibleMip = UNDEFINED_MIPMAP_INDEX;\r\n\t\tPrefetchMip = UNDEFINED_MIPMAP_INDEX;\r\n\t}\r\n\r\n\t*pVisibleMip = VisibleMip;\r\n\t*pPrefetchMip = PrefetchMip;\r\n}\r\n\r\nHRESULT D3D12MemoryManagement::RenderScene(const RectF& ViewportBounds)\r\n{\r\n\tRectF SceneBounds = m_pSceneCamera->GenerateViewportBounds();\r\n\r\n\tfor (auto& Img : m_Images)\r\n\t{\r\n\t\tResource* pResource = Img.pResource;\r\n\r\n\t\t//\r\n\t\t// Get image visibility and prefetching information.\r\n\t\t//\r\n\t\tUINT8 VisibleMip;\r\n\t\tUINT8 PrefetchMip;\r\n\t\tCalculateImagePagingData(&SceneBounds, &Img, &VisibleMip, &PrefetchMip);\r\n\r\n\t\t//\r\n\t\t// If the visibility or prefetch values have changed, notify the paging thread\r\n\t\t// so it can update this resource's priority.\r\n\t\t//\r\n\t\tif (pResource->VisibleMip != VisibleMip || pResource->PrefetchMip != PrefetchMip)\r\n\t\t{\r\n\t\t\tpResource->VisibleMip = VisibleMip;\r\n\t\t\tpResource->PrefetchMip = PrefetchMip;\r\n\t\t\tNotifyPagingWork(pResource);\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// Although visibility information is calculated above using the scene camera, for debug\r\n\t\t// purposes, we may want to render with another camera. We will calculate the real\r\n\t\t// image visibility for rendering purposes using the viewport bounds instead of the scene\r\n\t\t// bounds.\r\n\t\t//\r\n\t\tbool IsVisible = RectIntersects(Img.Bounds, ViewportBounds);\r\n\t\tif (IsVisible)\r\n\t\t{\r\n\t\t\tstatic const ColorF DefaultColor = { 1, 1, 1, 1 };\r\n\r\n\t\t\tFillRectangle(&Img.Bounds, &DefaultColor, pResource);\r\n\r\n\t\t\tif (m_bDrawMipColors)\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Render overlay and border around images to indicate both the visible\r\n\t\t\t\t// mipmap, and the mipmap that is resident. This shows the difference\r\n\t\t\t\t// between the requested and actual mipmap.\r\n\t\t\t\t//\r\n\t\t\t\tstatic const ColorF MipColors[MAX_MIP_COUNT] =\r\n\t\t\t\t{\r\n\t\t\t\t\t{ 1.0f, 0.0f, 0.0f, 0.5f }, // Red\r\n\t\t\t\t\t{ 1.0f, 0.5f, 0.0f, 0.5f }, // Orange\r\n\t\t\t\t\t{ 1.0f, 1.0f, 0.0f, 0.5f }, // Yellow\r\n\t\t\t\t\t{ 0.0f, 1.0f, 0.0f, 0.5f }, // Green\r\n\t\t\t\t\t{ 0.0f, 1.0f, 1.0f, 0.5f }, // Aqua\r\n\t\t\t\t\t{ 0.0f, 0.5f, 0.5f, 0.5f }, // LightBlue\r\n\t\t\t\t\t{ 0.0f, 0.0f, 1.0f, 0.5f }, // Blue\r\n\t\t\t\t\t{ 0.5f, 0.0f, 1.0f, 0.5f }, // Purple\r\n\t\t\t\t\t{ 1.0f, 0.0f, 1.0f, 0.5f }, // Magenta\r\n\t\t\t\t\t{ 0.6f, 0.3f, 0.0f, 0.5f }, // Brown\r\n\t\t\t\t\t{ 0.4f, 0.4f, 0.0f, 0.5f }, // Gold\r\n\t\t\t\t\t{ 1.0f, 1.0f, 1.0f, 0.5f }, // White\r\n\t\t\t\t\t{ 0.7f, 0.7f, 0.7f, 0.5f }, // LightGray\r\n\t\t\t\t\t{ 0.3f, 0.3f, 0.3f, 0.5f }, // DarkGray\r\n\t\t\t\t\t{ 0.0f, 0.0f, 0.0f, 0.5f }, // Black\r\n\t\t\t\t};\r\n\r\n\t\t\t\tVisibleMip = pResource->VisibleMip;\r\n\t\t\t\tconst ColorF* pVisibleColor = &MipColors[VisibleMip];\r\n\r\n\t\t\t\tFillRectangle(&Img.Bounds, pVisibleColor);\r\n\r\n\t\t\t\tUINT8 ResidentMip = pResource->MostDetailedMipResident;\r\n\t\t\t\tconst ColorF* pResidentColor = &MipColors[ResidentMip];\r\n\r\n\t\t\t\tDrawRectangle(&Img.Bounds, 2.0f, pResidentColor);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Render debug viewport.\r\n\t//\r\n\t{\r\n\t\tColorF ViewportColor = { 1.0f, 0.0f, 0.0f, 0.25f };\r\n\t\tColorF ViewportColorNoPrefetch = { 1.0f, 0.0f, 0.0f, 1.0f };\r\n\r\n\t\tconst ColorF* pColor = &ViewportColorNoPrefetch;\r\n\t\tfloat Thickness = 2 / m_ViewportCamera.GetZoom();\r\n\r\n\t\tfloat ScaledPrefetchDistance = PREFETCH_DISTANCE / m_pSceneCamera->GetZoom();\r\n\t\tThickness = ScaledPrefetchDistance;\r\n\t\tpColor = &ViewportColor;\r\n\r\n\t\tDrawRectangle(&SceneBounds, Thickness, pColor);\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\n//\r\n// Renders the user interface using D2D on top of our D3D12 content.\r\n//\r\nHRESULT D3D12MemoryManagement::RenderUI()\r\n{\r\n\tHRESULT hr = S_OK;\r\n\r\n\tUINT FrameIndex = m_pDXGISwapChain->GetCurrentBackBufferIndex();\r\n\r\n\t//\r\n\t// Acquire the wrapped back buffer object. When we release the wrapped object, it will\r\n\t// be placed in a presentable state, and we can call Present directly.\r\n\t//\r\n\tm_p11On12Device->AcquireWrappedResources(&m_pWrappedBackBuffers[FrameIndex], 1);\r\n\r\n\tm_pD2DContext->SetTarget(m_pD2DRenderTargets[FrameIndex]);\r\n\tm_pD2DContext->BeginDraw();\r\n\tm_pD2DContext->SetTransform(D2D1::Matrix3x2F::Identity());\r\n\r\n\tif (m_bRenderStats)\r\n\t{\r\n\t\t//\r\n\t\t// Render statistical information, such as the framerate, memory budget graph,\r\n\t\t// and glitch count.\r\n\t\t//\r\n\t\tm_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING);\r\n\t\tm_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);\r\n\t\tRenderMemoryGraph();\r\n\r\n\t\t//\r\n\t\t// Frame statistics (FPS, CPU time, etc).\r\n\t\t//\r\n\t\t{\r\n\t\t\tD2D1_RECT_F TextRect;\r\n\r\n\t\t\tTextRect.left = 8;\r\n\t\t\tTextRect.top = 8;\r\n\t\t\tTextRect.right = 256;\r\n\t\t\tTextRect.bottom = 256;\r\n\r\n\t\t\tfloat StatTimeBetweenFrames = AverageStatistics(m_StatTimeBetweenFrames, STATISTIC_COUNT);\r\n\t\t\tfloat StatRenderScene = AverageStatistics(m_StatRenderScene, STATISTIC_COUNT);\r\n\t\t\tfloat StatRenderUI = AverageStatistics(m_StatRenderUI, STATISTIC_COUNT);\r\n\r\n\t\t\tm_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);\r\n\t\t\tm_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);\r\n\t\t\twchar_t FPSString[128];\r\n\t\t\tswprintf_s(\r\n\t\t\t\tFPSString,\r\n\t\t\t\t_TRUNCATE,\r\n\t\t\t\tL\"FPS: %d (%.2fms)\\n\"\r\n\t\t\t\tL\"Glitch Count: %d\\n\"\r\n\t\t\t\tL\"\\n\"\r\n\t\t\t\tL\"RenderScene: %.2f ms\\n\"\r\n\t\t\t\tL\"RenderUI: %.2f ms\",\r\n\t\t\t\t(UINT)(1.0f / StatTimeBetweenFrames),\r\n\t\t\t\tStatTimeBetweenFrames * 1000.0f,\r\n\t\t\t\tGetGlitchCount(),\r\n\t\t\t\tStatRenderScene * 1000.0f,\r\n\t\t\t\tStatRenderUI * 1000.0f);\r\n\r\n\t\t\tm_pD2DContext->DrawTextW(\r\n\t\t\t\tFPSString,\r\n\t\t\t\t(UINT)wcslen(FPSString),\r\n\t\t\t\tm_pTextFormat,\r\n\t\t\t\t&TextRect,\r\n\t\t\t\tm_pTextBrush);\r\n\t\t}\r\n\t}\r\n\r\n\thr = m_pD2DContext->EndDraw();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"D2D EndDraw failed, hr=0x%.8x\", hr);\r\n\t}\r\n\r\n\t//\r\n\t// Unreference the render target after rendering completes.\r\n\t//\r\n\tm_pD2DContext->SetTarget(nullptr);\r\n\r\n\tm_p11On12Device->ReleaseWrappedResources(&m_pWrappedBackBuffers[FrameIndex], 1);\r\n\r\n\t//\r\n\t// Flush D2D based content on the D3D11On12 device to synchronize with D3D12 content.\r\n\t//\r\n\tm_p11Context->Flush();\r\n\r\n\treturn hr;\r\n}\r\n\r\nvoid D3D12MemoryManagement::RenderMemoryGraph()\r\n{\r\n\tstatic const D2D1_COLOR_F BackgroundColor = { 0.1f, 0.1f, 0.1f, 0.85f };\r\n\tstatic const D2D1_COLOR_F BorderColor = { 0.75f, 0.75f, 0.75f, 0.75f };\r\n\tstatic const D2D1_COLOR_F NotchColor = { 0.75f, 0.75f, 0.75f, 0.4f };\r\n\tstatic const D2D1_COLOR_F UsageColor = { 0.5f, 0.5f, 0.0f, 0.75f };\r\n\tstatic const D2D1_COLOR_F CurrentUsageColor = { 0.8f, 0.8f, 0.0f, 1.0f };\r\n\tstatic const D2D1_COLOR_F CurrentBudgetColor = { 0.8f, 0.0f, 0.0f, 1.0f };\r\n\r\n\tHRESULT hr;\r\n\r\n\tDXGI_QUERY_VIDEO_MEMORY_INFO LocalInfo = GetLocalVideoMemoryInfo();\r\n\r\n\tUINT64 Tick = GetTickCount64();\r\n\tif (Tick - m_LastGraphTick > 1000 / GRAPH_SEGMENTS * 10)\r\n\t{\r\n\t\t// Record data point.\r\n\t\tm_GraphPoints[m_CurrentGraphPoint % NUM_GRAPH_POINTS] = LocalInfo.CurrentUsage;\r\n\t\t++m_CurrentGraphPoint;\r\n\t\tm_LastGraphTick = Tick;\r\n\t}\r\n\r\n\t//\r\n\t// Get largest sample in point set for an upper bound.\r\n\t//\r\n\tUINT64 LargestSeenValue = 0;\r\n\tfor (UINT i = 0; i < NUM_GRAPH_POINTS; ++i)\r\n\t{\r\n\t\tif (m_GraphPoints[i] > LargestSeenValue)\r\n\t\t{\r\n\t\t\tLargestSeenValue = m_GraphPoints[i];\r\n\t\t}\r\n\t}\r\n\tif (LargestSeenValue == 0)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t//\r\n\t// Calculate graph scale values.\r\n\t//\r\n\tUINT LargestSeenValueMB = (UINT)(LargestSeenValue / 1024 / 1024);\r\n\r\n\t//\r\n\t// Graph is scaled by powers of 2 scaled by 100, e.g. 100, 200, 400, 800, ...\r\n\t// Use the power of two value to scale the graph accordingly.\r\n\t//\r\n\tDWORD ScaleIndex;\r\n\tDWORD Result = BitScanReverse(&ScaleIndex, LargestSeenValueMB / 100);\r\n\tif (Result == 0)\r\n\t{\r\n\t\tScaleIndex = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t++ScaleIndex;\r\n\t}\r\n\r\n\t//\r\n\t// Graph only goes up GRAPH_HEIGHT_RATIO % to the top to leave a little bit of room\r\n\t// at the top of the graph. Purely aesthetics.\r\n\t//\r\n\tUINT GraphSizeMB = (1 << ScaleIndex) * 100;\r\n\tfloat GraphHeightPadded = GRAPH_HEIGHT * GRAPH_HEIGHT_RATIO / 100;\r\n\tfloat GraphPaddingTop = GRAPH_HEIGHT - GraphHeightPadded;\r\n\r\n\t//\r\n\t// Calculate the graph rectangle bounds.\r\n\t//\r\n\tRectF GraphDest;\r\n\r\n\tGraphDest.Right = m_WindowWidth - GRAPH_PADDING;\r\n\tGraphDest.Left = GraphDest.Right - GRAPH_WIDTH;\r\n\tGraphDest.Top = GRAPH_PADDING;\r\n\tGraphDest.Bottom = GraphDest.Top + GRAPH_HEIGHT;\r\n\r\n\t//\r\n\t// Try to create the brush and path geometry for the graph. If either fails, we cannot render the graph.\r\n\t//\r\n\tComPtr<ID2D1SolidColorBrush> pBrush;\r\n\tComPtr<ID2D1PathGeometry> pPathGeometry;\r\n\r\n\thr = m_pD2DContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &pBrush);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create solid color brush for rendering UI, hr=0x.8x\", hr);\r\n\t\treturn;\r\n\t}\r\n\r\n\thr = GenerateMemoryGraphGeometry(GraphDest, GraphSizeMB, &pPathGeometry);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to generate path geometry for memory graph, hr=0x.8x\", hr);\r\n\t\treturn;\r\n\t}\r\n\r\n\t//\r\n\t// Render memory graph border and background.\r\n\t//\r\n\t{\r\n\t\tpBrush->SetColor(BackgroundColor);\r\n\t\tm_pD2DContext->FillRectangle((D2D1_RECT_F&)GraphDest, pBrush.Get());\r\n\r\n\t\tpBrush->SetColor(BorderColor);\r\n\t\tm_pD2DContext->DrawRectangle((D2D1_RECT_F&)GraphDest, pBrush.Get(), 2);\r\n\t}\r\n\r\n\t//\r\n\t// Render the path geometry for the graph.\r\n\t//\r\n\t{\r\n\t\tpBrush->SetColor(UsageColor);\r\n\t\tm_pD2DContext->FillGeometry(pPathGeometry.Get(), pBrush.Get());\r\n\t}\r\n\r\n\t//\r\n\t// Render the notches on the graph for reference values.\r\n\t//\r\n\t{\r\n\t\tpBrush->SetColor(NotchColor);\r\n\t\tUINT SizePerNotch = GraphSizeMB / GRAPH_NOTCH_COUNT;\r\n\r\n\t\tfor (int i = 0; i < GRAPH_NOTCH_COUNT + 1; ++i)\r\n\t\t{\r\n\t\t\twchar_t Text[32];\r\n\t\t\tswprintf_s(Text, _TRUNCATE, L\"%dMB\", SizePerNotch * i);\r\n\r\n\t\t\tD2D1_RECT_F TextRect;\r\n\r\n\t\t\tTextRect.left = GraphDest.Left - 100;\r\n\t\t\tTextRect.top = GraphDest.Top + GraphPaddingTop + (GRAPH_NOTCH_COUNT - i) * (GraphHeightPadded / GRAPH_NOTCH_COUNT) - 10;\r\n\t\t\tTextRect.right = GraphDest.Left - 5;\r\n\t\t\tTextRect.bottom = TextRect.top + 20;\r\n\r\n\t\t\tm_pD2DContext->DrawTextW(\r\n\t\t\t\tText,\r\n\t\t\t\t(UINT)wcslen(Text),\r\n\t\t\t\tm_pTextFormat,\r\n\t\t\t\t&TextRect,\r\n\t\t\t\tm_pTextBrush);\r\n\r\n\t\t\t//\r\n\t\t\t// Label 0MB, but do not draw the line.\r\n\t\t\t//\r\n\t\t\tif (i > 0)\r\n\t\t\t{\r\n\t\t\t\tD2D1_POINT_2F Point0 = { GraphDest.Left, TextRect.top + 10 };\r\n\t\t\t\tD2D1_POINT_2F Point1 = { GraphDest.Right, TextRect.top + 10 };\r\n\t\t\t\tm_pD2DContext->DrawLine(Point0, Point1, pBrush.Get(), 1);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Draw current usage/budget line and value.\r\n\t//\r\n\t{\r\n\t\t//\r\n\t\t// Usage\r\n\t\t//\r\n\t\t{\r\n\t\t\tpBrush->SetColor(CurrentUsageColor);\r\n\t\t\tfloat Top = GraphDest.Bottom - (LocalInfo.CurrentUsage / 1024 / 1024) / (float)GraphSizeMB * GraphHeightPadded;\r\n\r\n\t\t\tD2D1_POINT_2F Point0 = { GraphDest.Left, Top };\r\n\t\t\tD2D1_POINT_2F Point1 = { GraphDest.Right, Top };\r\n\t\t\tm_pD2DContext->DrawLine(Point0, Point1, pBrush.Get(), 1);\r\n\r\n\t\t\twchar_t Text[32];\r\n\t\t\tswprintf_s(Text, L\"%dMB\", (UINT)(LocalInfo.CurrentUsage / 1024 / 1024));\r\n\r\n\t\t\tD2D1_RECT_F TextRect;\r\n\r\n\t\t\tTextRect.left = Point0.x;\r\n\t\t\tTextRect.top = Top;\r\n\t\t\tTextRect.right = Point1.x - 5;\r\n\t\t\tTextRect.bottom = Top + 10;\r\n\r\n\t\t\tm_pD2DContext->DrawTextW(\r\n\t\t\t\tText,\r\n\t\t\t\t(UINT)wcslen(Text),\r\n\t\t\t\tm_pTextFormat,\r\n\t\t\t\t&TextRect,\r\n\t\t\t\tm_pTextBrush);\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// Budget\r\n\t\t//\r\n\t\t{\r\n\t\t\tpBrush->SetColor(CurrentBudgetColor);\r\n\t\t\tfloat Top = max(GraphDest.Bottom - (LocalInfo.Budget / 1024 / 1024) / (float)GraphSizeMB * GraphHeightPadded, GraphDest.Top);\r\n\r\n\t\t\tD2D1_POINT_2F Point0 = { GraphDest.Left, Top };\r\n\t\t\tD2D1_POINT_2F Point1 = { GraphDest.Right, Top };\r\n\t\t\tm_pD2DContext->DrawLine(Point0, Point1, pBrush.Get(), 1);\r\n\r\n\t\t\twchar_t Text[32];\r\n\t\t\tswprintf_s(Text, L\"%dMB\", (UINT)(LocalInfo.Budget / 1024 / 1024));\r\n\r\n\t\t\tD2D1_RECT_F TextRect;\r\n\r\n\t\t\tTextRect.left = Point0.x;\r\n\t\t\tTextRect.top = Top - 10;\r\n\t\t\tTextRect.right = Point1.x - 5;\r\n\t\t\tTextRect.bottom = Top;\r\n\r\n\t\t\tm_pD2DContext->DrawTextW(\r\n\t\t\t\tText,\r\n\t\t\t\t(UINT)wcslen(Text),\r\n\t\t\t\tm_pTextFormat,\r\n\t\t\t\t&TextRect,\r\n\t\t\t\tm_pTextBrush);\r\n\t\t}\r\n\r\n\t}\r\n}\r\n\r\n//\r\n// Generates new graph geometry, which may change every frame.\r\n//\r\nHRESULT D3D12MemoryManagement::GenerateMemoryGraphGeometry(const RectF& Bounds, UINT GraphSizeMB, ID2D1PathGeometry** ppPathGeometry)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tID2D1PathGeometry* pPathGeometry = nullptr;\r\n\tID2D1GeometrySink* pGeometrySink = nullptr;\r\n\r\n\thr = m_pD2DFactory->CreatePathGeometry(&pPathGeometry);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create path geometry, hr=0x%.8x\");\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\thr = pPathGeometry->Open(&pGeometrySink);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to open path geometry sink, hr=0x%.8x\");\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\t{\r\n\t\tfloat GraphHeightPadded = GRAPH_HEIGHT * GRAPH_HEIGHT_RATIO / 100;\r\n\t\tfloat XStep = GRAPH_WIDTH / GRAPH_SEGMENTS;\r\n\r\n\t\tD2D1_POINT_2F Point;\r\n\t\tPoint.x = Bounds.Left;\r\n\t\tPoint.y = Bounds.Bottom;\r\n\r\n\t\tpGeometrySink->BeginFigure(Point, D2D1_FIGURE_BEGIN_FILLED);\r\n\r\n\t\tfor (UINT i = 0; i < NUM_GRAPH_POINTS; ++i)\r\n\t\t{\r\n\t\t\tUINT32 GraphPoint = (i + m_CurrentGraphPoint) % NUM_GRAPH_POINTS;\r\n\r\n\t\t\tPoint.y = Bounds.Bottom - (m_GraphPoints[GraphPoint] / 1024 / 1024) / (float)GraphSizeMB * GraphHeightPadded;\r\n\t\t\tpGeometrySink->AddLine(Point);\r\n\t\t\tPoint.x += XStep;\r\n\t\t}\r\n\r\n\t\tPoint.x = Bounds.Right;\r\n\t\tPoint.y = Bounds.Bottom;\r\n\t\tpGeometrySink->AddLine(Point);\r\n\r\n\t\tpGeometrySink->EndFigure(D2D1_FIGURE_END_CLOSED);\r\n\t}\r\n\r\n\thr = pGeometrySink->Close();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to close path geometry sink, hr=0x%.8x\", hr);\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\tpGeometrySink->Release();\r\n\t*ppPathGeometry = pPathGeometry;\r\n\r\n\treturn S_OK;\r\n\r\ncleanup:\r\n\tSafeRelease(pGeometrySink);\r\n\tSafeRelease(pPathGeometry);\r\n\r\n\treturn hr;\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/D3D12MemoryManagement.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// The number of segments in the graph, representing the update frequency. The number\r\n// of graph points should be one greater than the number of segments, accounting for\r\n// the fact that each segment has two sides.\r\n//\r\n// e.g. 'GRAPH_SEGMENTS' represents the number of gaps, where 'NUM_GRAPH_POINTS'\r\n// represents the number of pipes (edges) of the segments, with shared edges combined:\r\n//\r\n//     1       2       3       4       5       6       7       8\r\n// 1       2       3       4       5       6       7       8       9\r\n// |       |       |       |       |       |       |       |       |\r\n// |       |       |       |       |       |       |       |       |\r\n//\r\n#define GRAPH_SEGMENTS 64\r\n#define NUM_GRAPH_POINTS (GRAPH_SEGMENTS + 1)\r\n\r\n//\r\n// Houses the resource information and the visual bounds for each loaded asset.\r\n//\r\nstruct Image\r\n{\r\n\tRectF Bounds;\r\n\tResource* pResource;\r\n};\r\n\r\nclass D3D12MemoryManagement : public DX12Framework\r\n{\r\nprivate:\r\n\tstd::vector<Image> m_Images;\r\n\r\n\tCamera m_ViewportCamera;\r\n\tCamera m_DebugCamera;\r\n\tCamera* m_pCapturedCamera;\r\n\tCamera* m_pSceneCamera;\r\n\r\n\tint m_MouseX = 0;\r\n\tint m_MouseY = 0;\r\n\tbool m_bMouseDown = false;\r\n\r\n\tUINT64 m_LastGraphTick = 0;\r\n\tbool m_bRenderStats = false;\r\n\tUINT32 m_CurrentGraphPoint = 0;\r\n\tUINT64 m_GraphPoints[NUM_GRAPH_POINTS];\r\n\r\n\tbool m_bDrawMipColors = false;\r\n\tbool m_bSimulateDeviceRemoved = false;\r\n\tbool m_bFullscreen = false;\r\n\tRECT m_WindowRect;\r\n\r\n\t//\r\n\t// D2D UI rendering\r\n\t//\r\n\tID2D1SolidColorBrush* m_pTextBrush = nullptr;\r\n\tIDWriteTextFormat* m_pTextFormat = nullptr;\r\n\r\nprotected:\r\n\tvirtual HRESULT CreateDeviceIndependentState() override;\r\n\tvirtual HRESULT CreateDeviceDependentState() override;\r\n\tvirtual void DestroyDeviceIndependentState() override;\r\n\tvirtual void DestroyDeviceDependentState() override;\r\n\r\n\tvirtual HRESULT LoadAssets();\r\n\tvirtual HRESULT RenderScene(const RectF& ViewportBounds);\r\n\tvirtual HRESULT RenderUI();\r\n\tvirtual bool HandleMessage(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);\r\n\r\n\tHRESULT GenerateMemoryGraphGeometry(const RectF& Bounds, UINT GraphSizeMB, ID2D1PathGeometry** ppPathGeometry);\r\n\tvoid RenderMemoryGraph();\r\n\r\n\tvoid CalculateImagePagingData(\r\n\t\tconst RectF* pViewportBounds,\r\n\t\tconst Image* pImage,\r\n\t\tUINT8* pVisibleMip,\r\n\t\tUINT8* pPrefetchMip);\r\n\r\npublic:\r\n\tD3D12MemoryManagement();\r\n\tvirtual ~D3D12MemoryManagement();\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/D3D12MemoryManagement.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 14\r\nVisualStudioVersion = 14.0.23107.0\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"D3D12MemoryManagement\", \"D3D12MemoryManagement.vcxproj\", \"{DB40D747-0C18-47BA-A8E8-316562316632}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tRelease|x64 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{DB40D747-0C18-47BA-A8E8-316562316632}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{DB40D747-0C18-47BA-A8E8-316562316632}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{DB40D747-0C18-47BA-A8E8-316562316632}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{DB40D747-0C18-47BA-A8E8-316562316632}.Release|x64.Build.0 = Release|x64\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/D3D12MemoryManagement.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{DB40D747-0C18-47BA-A8E8-316562316632}</ProjectGuid>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <RootNamespace>D3D12MemoryManagement</RootNamespace>\r\n    <ProjectName>D3D12MemoryManagement</ProjectName>\r\n    <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v140</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v140</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <CompileAsWinRT>false</CompileAsWinRT>\r\n      <MinimalRebuild>true</MinimalRebuild>\r\n      <AdditionalUsingDirectories>\r\n      </AdditionalUsingDirectories>\r\n      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <WarningLevel>Level3</WarningLevel>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <AdditionalDependencies>d3d12.lib;d3d11.lib;dxgi.lib;d3dcompiler.lib;windowscodecs.lib;d2d1.lib;dwrite.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <DelayLoadDLLs>d3d12.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Manifest>\r\n      <EnableDpiAwareness>false</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n      <WarningLevel>Level3</WarningLevel>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>d3d12.lib;d3d11.lib;dxgi.lib;d3dcompiler.lib;windowscodecs.lib;d2d1.lib;dwrite.lib;%(AdditionalDependencies)</AdditionalDependencies>\r\n      <DelayLoadDLLs>d3d12.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Manifest>\r\n      <EnableDpiAwareness>false</EnableDpiAwareness>\r\n    </Manifest>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <CustomBuild Include=\"TileGrid.dds\">\r\n      <DeploymentContent>true</DeploymentContent>\r\n      <FileType>Document</FileType>\r\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">copy %(Identity) \"$(OutDir)Assets\\Textures\" &gt; NUL</Command>\r\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">$(OutDir)Assets\\Textures\\%(Identity)</Outputs>\r\n      <TreatOutputAsContent Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</TreatOutputAsContent>\r\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">copy %(Identity) \"$(OutDir)Assets\\Textures\" &gt; NUL</Command>\r\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">$(OutDir)Assets\\Textures\\%(Identity)</Outputs>\r\n      <TreatOutputAsContent Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</TreatOutputAsContent>\r\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Copying TileGrid.dds to output location</Message>\r\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Copying TileGrid.dds to output location</Message>\r\n    </CustomBuild>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <CustomBuild Include=\"Color.hlsl\">\r\n      <DeploymentContent>true</DeploymentContent>\r\n      <FileType>Document</FileType>\r\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">copy %(Identity) \"$(OutDir)Assets\\Shaders\" &gt; NUL</Command>\r\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">$(OutDir)Assets\\Shaders\\%(Identity)</Outputs>\r\n      <TreatOutputAsContent Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</TreatOutputAsContent>\r\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">copy %(Identity) \"$(OutDir)Assets\\Shaders\" &gt; NUL</Command>\r\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">$(OutDir)Assets\\Shaders\\%(Identity)</Outputs>\r\n      <TreatOutputAsContent Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</TreatOutputAsContent>\r\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Copying Color.hlsl to output location</Message>\r\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Copying Color.hlsl to output location</Message>\r\n    </CustomBuild>\r\n    <CustomBuild Include=\"Texture.hlsl\">\r\n      <DeploymentContent>true</DeploymentContent>\r\n      <FileType>Document</FileType>\r\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">copy %(Identity) \"$(OutDir)Assets\\Shaders\" &gt; NUL</Command>\r\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">$(OutDir)Assets\\Shaders\\%(Identity)</Outputs>\r\n      <TreatOutputAsContent Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</TreatOutputAsContent>\r\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">copy %(Identity) \"$(OutDir)Assets\\Shaders\" &gt; NUL</Command>\r\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">$(OutDir)Assets\\Shaders\\%(Identity)</Outputs>\r\n      <TreatOutputAsContent Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</TreatOutputAsContent>\r\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Copying Texture.hlsl to output location</Message>\r\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Copying Texture.hlsl to output location</Message>\r\n    </CustomBuild>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"Camera.h\" />\r\n    <ClInclude Include=\"Context.h\" />\r\n    <ClInclude Include=\"d3dx12.h\" />\r\n    <ClInclude Include=\"Framework.h\" />\r\n    <ClInclude Include=\"List.h\" />\r\n    <ClInclude Include=\"Log.h\" />\r\n    <ClInclude Include=\"Paging.h\" />\r\n    <ClInclude Include=\"Render.h\" />\r\n    <ClInclude Include=\"Resource.h\" />\r\n    <ClInclude Include=\"Shader.h\" />\r\n    <ClInclude Include=\"stdafx.h\" />\r\n    <ClInclude Include=\"D3D12MemoryManagement.h\" />\r\n    <ClInclude Include=\"Util.h\" />\r\n    <ClInclude Include=\"Versioning.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"Camera.cpp\" />\r\n    <ClCompile Include=\"Context.cpp\" />\r\n    <ClCompile Include=\"Framework.cpp\" />\r\n    <ClCompile Include=\"Log.cpp\" />\r\n    <ClCompile Include=\"main.cpp\" />\r\n    <ClCompile Include=\"Paging.cpp\" />\r\n    <ClCompile Include=\"Render.cpp\" />\r\n    <ClCompile Include=\"Shader.cpp\" />\r\n    <ClCompile Include=\"stdafx.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3D12MemoryManagement.cpp\" />\r\n    <ClCompile Include=\"Util.cpp\" />\r\n    <ClCompile Include=\"Versioning.cpp\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/D3D12MemoryManagement.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Header Files\">\r\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Resource Files\">\r\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Source Files\\Framework\">\r\n      <UniqueIdentifier>{e24b3882-c027-4166-84f6-218f4a5e93b6}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Header Files\\Framework\">\r\n      <UniqueIdentifier>{3d1ea446-5bea-44d8-8dda-7f9ab9f73f7a}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Assets\">\r\n      <UniqueIdentifier>{fa267806-56ad-4689-bda3-3c62af81e99e}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Assets\\Shaders\">\r\n      <UniqueIdentifier>{215b78f9-f560-4ecf-b44a-dbd780399529}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"Assets\\Textures\">\r\n      <UniqueIdentifier>{1764783a-70d5-486f-b955-610c251444cb}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"stdafx.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Camera.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Context.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Framework.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Paging.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Render.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Shader.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Util.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Versioning.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Log.cpp\">\r\n      <Filter>Source Files\\Framework</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3D12MemoryManagement.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"main.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"Camera.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Context.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Framework.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"List.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Paging.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Render.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Resource.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Shader.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Util.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Versioning.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Log.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"D3D12MemoryManagement.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"d3dx12.h\">\r\n      <Filter>Header Files\\Framework</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"stdafx.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <CustomBuild Include=\"Color.hlsl\">\r\n      <Filter>Assets\\Shaders</Filter>\r\n    </CustomBuild>\r\n    <CustomBuild Include=\"Texture.hlsl\">\r\n      <Filter>Assets\\Shaders</Filter>\r\n    </CustomBuild>\r\n    <CustomBuild Include=\"TileGrid.dds\">\r\n      <Filter>Assets\\Textures</Filter>\r\n    </CustomBuild>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Framework.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\n#define DEFAULT_CLIENT_WIDTH 1280\r\n#define DEFAULT_CLIENT_HEIGHT 720\r\n\r\n#define WINDOW_CLASS L\"MemorySampleApp\"\r\n\r\n#define SWAPCHAIN_BACK_BUFFER_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM\r\n\r\n//\r\n// Maximum size of a single paging operation. Mipmaps greater than 32MB in size will be\r\n// broken up into multiple transfers.\r\n//\r\n#define MAX_TRANSFER_SIZE _32MB\r\n\r\nLRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)\r\n{\r\n\tDX12Framework* pApplication = (DX12Framework*)GetWindowLongPtr(hwnd, GWLP_USERDATA);\r\n\tif (pApplication->HandleMessage(hwnd, Message, wParam, lParam))\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn DefWindowProc(hwnd, Message, wParam, lParam);\r\n}\r\n\r\nLRESULT CALLBACK WndProcPreCreate(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)\r\n{\r\n\tif (Message == WM_CREATE)\r\n\t{\r\n\t\t//\r\n\t\t// On creation, assign our user data (DX12Framework*) to the hwnd, and point\r\n\t\t// to the new WndProc used to handle those messages.\r\n\t\t//\r\n\t\tCREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;\r\n\r\n\t\tSetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pCreate->lpCreateParams);\r\n\t\tSetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc);\r\n\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn DefWindowProc(hwnd, Message, wParam, lParam);\r\n}\r\n\r\nDX12Framework::DX12Framework() :\r\n\tm_RenderContext(this),\r\n\tm_PagingContext(this)\r\n{\r\n\tInitializeListHead(&m_ResourceListHead);\r\n\tInitializeListHead(&m_DynamicBufferListHead);\r\n\tInitializeListHead(&m_DynamicDescriptorHeapListHead);\r\n\tInitializeListHead(&m_UnreferencedResourceListHead);\r\n\tInitializeListHead(&m_UncommittedListHead);\r\n\tfor (int i = 0; i < MAX_MIP_COUNT; ++i)\r\n\t{\r\n\t\tInitializeListHead(&m_CommitmentListHeads[i]);\r\n\t}\r\n\r\n\tZeroMemory(m_StatTimeBetweenFrames, sizeof(m_StatTimeBetweenFrames));\r\n\tZeroMemory(m_StatRenderScene, sizeof(m_StatRenderScene));\r\n\tZeroMemory(m_StatRenderUI, sizeof(m_StatRenderUI));\r\n\tZeroMemory(m_pRenderTargets, sizeof(m_pRenderTargets));\r\n\tZeroMemory(m_pWrappedBackBuffers, sizeof(m_pRenderTargets));\r\n\tZeroMemory(m_pD2DRenderTargets, sizeof(m_pRenderTargets));\r\n}\r\n\r\nDX12Framework::~DX12Framework()\r\n{\r\n}\r\n\r\nHRESULT DX12Framework::Init()\r\n{\r\n\tHRESULT hr;\r\n\r\n\thr = CreateDeviceIndependentStateInternal();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create device independent state\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = CreateDeviceDependentStateInternal();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create device dependent state\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = LoadAssets();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to load sample app assets\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\n//\r\n// Creates all device independent state. This includes any resource or object which\r\n// can persist across a D3D12 device removal.\r\n//\r\nHRESULT DX12Framework::CreateDeviceIndependentStateInternal()\r\n{\r\n\tHRESULT hr;\r\n\tUINT dxgiFactoryFlags = 0;\r\n\r\n#if(_DEBUG)\r\n\t{\r\n\t\t//\r\n\t\t// Try to enable the debug layer if it's present on the system. It should\r\n\t\t// be enabled before creating the device.\r\n\t\t// Install the 'Graphics Tools' optional feature in Settings to enable\r\n\t\t// the SDK layers.\r\n\t\t//\r\n\t\tbool bDebugLayerEnabled = false;\r\n\r\n\t\tID3D12Debug* pDebugController;\r\n\t\tif (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pDebugController))))\r\n\t\t{\r\n\t\t\tpDebugController->EnableDebugLayer();\r\n\t\t\tpDebugController->Release();\r\n\r\n\t\t\tbDebugLayerEnabled = true;\r\n\t\t\tdxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;\r\n\t\t}\r\n\r\n\t\twprintf(L\"\\nDebug layer is %senabled\\n\\n\", bDebugLayerEnabled ? L\"\" : L\"NOT \");\r\n\t}\r\n#endif\r\n\r\n\thr = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&m_pDXGIFactory));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create DXGI Factory, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// QPC information for framerate tracking.\r\n\t//\r\n\tQueryPerformanceFrequency(&m_PerformanceFrequency);\r\n\tQueryPerformanceCounter(&m_LastFrameCounter);\r\n\r\n\t//\r\n\t// Initialize WIC.\r\n\t//\r\n\thr = CoInitialize(nullptr);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"CoInitialize failed, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pWICFactory));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create IWICFactory instance, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Use TLS to create a waitable event object which can be used to wait on any context.\r\n\t//\r\n\tm_ThreadContextWaitHandleIndex = TlsAlloc();\r\n\tif (m_ThreadContextWaitHandleIndex == TLS_OUT_OF_INDEXES)\r\n\t{\r\n\t\tLOG_ERROR(\"Error allocating TLS index for wait handle, Error=0x%.8x\", GetLastError());\r\n\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\tHANDLE hFlushEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\tif (!hFlushEvent)\r\n\t{\r\n\t\tLOG_ERROR(\"Error creating thread flush event, Error=0x%.8x\", GetLastError());\r\n\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\tTlsSetValue(m_ThreadContextWaitHandleIndex, (void*)hFlushEvent);\r\n\r\n\t//\r\n\t// Create window class and the window itself.\r\n\t//\r\n\tstatic const DWORD WindowStyle = WS_OVERLAPPEDWINDOW;\r\n\r\n\tHINSTANCE hInstance = GetModuleHandle(nullptr);\r\n\r\n\tWNDCLASSEX windowClass = {};\r\n\twindowClass.cbSize = sizeof(WNDCLASSEX);\r\n\twindowClass.style = CS_HREDRAW | CS_VREDRAW;\r\n\twindowClass.lpfnWndProc = WndProcPreCreate;\r\n\twindowClass.hInstance = hInstance;\r\n\twindowClass.hCursor = LoadCursor(nullptr, IDC_ARROW);\r\n\twindowClass.lpszClassName = WINDOW_CLASS;\r\n\tif (RegisterClassEx(&windowClass) == FALSE)\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to register window class, Error=0x%.8x\", GetLastError());\r\n\t\tHRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\t//\r\n\t// Adjust window rectangle to ensure we create a window whose client area is the requested size.\r\n\t//\r\n\tRECT WindowRect = { 0, 0, DEFAULT_CLIENT_WIDTH, DEFAULT_CLIENT_HEIGHT };\r\n\tAdjustWindowRect(&WindowRect, WindowStyle, FALSE);\r\n\r\n\tm_Hwnd = CreateWindow(\r\n\t\tWINDOW_CLASS,\r\n\t\tL\"D3D12 Memory Sample\",\r\n\t\tWindowStyle,\r\n\t\t300,\r\n\t\t300,\r\n\t\tWindowRect.right - WindowRect.left,\r\n\t\tWindowRect.bottom - WindowRect.top,\r\n\t\tnullptr,\r\n\t\tnullptr,\r\n\t\thInstance,\r\n\t\tthis);\r\n\tif (!m_Hwnd)\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create window, Error=0x%.8x\", GetLastError());\r\n\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\tm_WindowWidth = DEFAULT_CLIENT_WIDTH;\r\n\tm_WindowHeight = DEFAULT_CLIENT_HEIGHT;\r\n\r\n\t//\r\n\t// Initialize D2D and DWrite device independent interfaces.\r\n\t//\r\n\thr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(m_pDWriteFactory), (IUnknown**)&m_pDWriteFactory);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create DWrite factory, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_PPV_ARGS(&m_pD2DFactory));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create D2D factory, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = CreateDeviceIndependentState();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\treturn hr;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::DestroyResource(Resource* pResource)\r\n{\r\n\tRemoveEntryList(&pResource->ListEntry);\r\n\r\n\tSafeRelease(pResource->pDecoder);\r\n#if(_DEBUG)\r\n\tfree((void*)pResource->pFileName);\r\n#endif\r\n\tassert(pResource->pDeviceState == nullptr);\r\n\r\n\tDestroyResourceDeviceState(pResource);\r\n\tRemoveEntryList(&pResource->CommittedListEntry);\r\n\tdelete pResource;\r\n}\r\n\r\nvoid DX12Framework::DestroyResourceDeviceState(Resource* pResource)\r\n{\r\n\tResourceDeviceState* pDeviceState = pResource->pDeviceState;\r\n\r\n\tif (pDeviceState)\r\n\t{\r\n\t\tSafeRelease(pDeviceState->pD3DResource);\r\n\r\n\t\tfor (UINT i = 0; i < pDeviceState->NumHeaps; ++i)\r\n\t\t{\r\n\t\t\tSafeRelease(pDeviceState->Mips[0].ppHeaps[i]);\r\n\t\t}\r\n\t\tdelete[] pDeviceState->Mips[0].ppHeaps;\r\n\t\tfree(pDeviceState);\r\n\t\tpResource->pDeviceState = nullptr;\r\n\t}\r\n\r\n\tRemoveResourceCommitment(pResource);\r\n\tif (pResource->PrioritizationEntry.Flink != nullptr)\r\n\t{\r\n\t\tRemoveEntryList(&pResource->PrioritizationEntry);\r\n\t\tpResource->PrioritizationEntry.Flink = nullptr;\r\n\t}\r\n}\r\n\r\nvoid DX12Framework::DestroyDeviceIndependentStateInternal()\r\n{\r\n\tDestroyDeviceIndependentState();\r\n\r\n\tLIST_ENTRY* pResourceEntry = m_ResourceListHead.Flink;\r\n\twhile (pResourceEntry != &m_ResourceListHead)\r\n\t{\r\n\t\tResource* pResource = CONTAINING_RECORD(pResourceEntry, Resource, ListEntry);\r\n\t\tpResourceEntry = pResourceEntry->Flink;\r\n\r\n\t\tDestroyResource(pResource);\r\n\t}\r\n\r\n\tHANDLE hFlushEvent = TlsGetValue(m_ThreadContextWaitHandleIndex);\r\n\tif (hFlushEvent)\r\n\t{\r\n\t\tCloseHandle(hFlushEvent);\r\n\t\thFlushEvent = nullptr;\r\n\t}\r\n\r\n\tSafeRelease(m_pDXGIFactory);\r\n\tSafeRelease(m_pWICFactory);\r\n\tSafeRelease(m_pD2DFactory);\r\n\tSafeRelease(m_pDWriteFactory);\r\n\r\n\tCoUninitialize();\r\n}\r\n\r\nHRESULT DX12Framework::CreateDeviceDependentStateInternal()\r\n{\r\n\tHRESULT hr;\r\n\r\n\t{\r\n\t\t//\r\n\t\t// Have the user select the desired graphics adapter.\r\n\t\t//\r\n\t\tIDXGIAdapter* pTempAdapter;\r\n\t\tUINT AdapterOrdinal = 0;\r\n\r\n\t\tprintf(\"Available Adapters:\\n\");\r\n\t\twhile (m_pDXGIFactory->EnumAdapters(AdapterOrdinal, &pTempAdapter) != DXGI_ERROR_NOT_FOUND)\r\n\t\t{\r\n\t\t\tDXGI_ADAPTER_DESC Desc;\r\n\t\t\tpTempAdapter->GetDesc(&Desc);\r\n\r\n\t\t\tprintf(\"  [%d] %ls\\n\", AdapterOrdinal, Desc.Description);\r\n\r\n\t\t\tpTempAdapter->Release();\r\n\t\t\t++AdapterOrdinal;\r\n\t\t}\r\n\r\n\t\tfor (;;)\r\n\t\t{\r\n\t\t\tprintf(\"\\nSelect Adapter: \");\r\n\r\n\t\t\tAdapterOrdinal = m_NewAdapterIndex;\r\n\t\t\tif (AdapterOrdinal == 0xFFFFFFFF)\r\n\t\t\t{\r\n\t\t\t\tif (scanf_s(\"%d\", &AdapterOrdinal) == 0)\r\n\t\t\t\t{\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// If the user did not specify valid input, just use adapter 0.\r\n\t\t\t\t\t//\r\n\t\t\t\t\tAdapterOrdinal = 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\thr = m_pDXGIFactory->EnumAdapters(AdapterOrdinal, &pTempAdapter);\r\n\t\t\tif (hr == DXGI_ERROR_NOT_FOUND)\r\n\t\t\t{\r\n\t\t\t\tLOG_WARNING(\"Invalid adapter ordinal\");\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\thr = pTempAdapter->QueryInterface(&m_pDXGIAdapter);\r\n\t\t\tpTempAdapter->Release();\r\n\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to query IDXGIAdapter3 interface from selected adapter.\");\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Obtain the default video memory information for the local and non-local segment groups.\r\n\t//\r\n\thr = m_pDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &m_LocalVideoMemoryInfo);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to query initial video memory info for local segment group\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_pDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &m_NonLocalVideoMemoryInfo);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to query initial video memory info for non-local segment group\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = D3D12CreateDevice(m_pDXGIAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pDevice));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create D3D12 device, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n#if _DEBUG\r\n\tID3D12InfoQueue* pInfoQueue = nullptr;\r\n\tif (SUCCEEDED(m_pDevice->QueryInterface(IID_PPV_ARGS(&pInfoQueue))))\r\n\t{\r\n\t\t// Suppress whole categories of messages.\r\n\t\t//D3D12_MESSAGE_CATEGORY Categories[] = {};\r\n\r\n\t\t// Suppress messages based on their severity level.\r\n\t\tD3D12_MESSAGE_SEVERITY Severities[] =\r\n\t\t{\r\n\t\t\tD3D12_MESSAGE_SEVERITY_INFO\r\n\t\t};\r\n\r\n\t\t// Suppress individual messages by their ID.\r\n\t\tD3D12_MESSAGE_ID DenyIds[] =\r\n\t\t{\r\n\t\t\t// The 11On12 implementation does not use optimized clearing yet.\r\n\t\t\tD3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE\r\n\t\t};\r\n\r\n\t\tD3D12_INFO_QUEUE_FILTER NewFilter = {};\r\n\t\t//NewFilter.DenyList.NumCategories = _countof(Categories);\r\n\t\t//NewFilter.DenyList.pCategoryList = Categories;\r\n\t\tNewFilter.DenyList.NumSeverities = _countof(Severities);\r\n\t\tNewFilter.DenyList.pSeverityList = Severities;\r\n\t\tNewFilter.DenyList.NumIDs = _countof(DenyIds);\r\n\t\tNewFilter.DenyList.pIDList = DenyIds;\r\n\r\n\t\tpInfoQueue->PushStorageFilter(&NewFilter);\r\n\t\tpInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);\r\n\t\tpInfoQueue->Release();\r\n\t}\r\n#endif\r\n\r\n\t//\r\n\t// Cache the descriptor sizes.\r\n\t//\r\n\tm_DescriptorInfo.RtvDescriptorSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\r\n\tm_DescriptorInfo.SamplerDescriptorSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);\r\n\tm_DescriptorInfo.SrvUavCbvDescriptorSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\r\n\r\n\thr = QueryCaps();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to query device caps\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_RenderContext.CreateDeviceDependentState(SWAPCHAIN_BUFFER_COUNT);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize render context\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_PagingContext.CreateDeviceDependentState();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize paging context\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_TextureShader.CreateDeviceDependentState(m_pDevice, L\"Assets\\\\Shaders\\\\Texture.hlsl\");\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize texture shader\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_ColorShader.CreateDeviceDependentState(m_pDevice, L\"Assets\\\\Shaders\\\\Color.hlsl\");\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize color shader\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Create a basic Flip-Discard swapchain.\r\n\t//\r\n\tDXGI_SWAP_CHAIN_DESC1 SwapChainDesc = {};\r\n\tSwapChainDesc.BufferCount = SWAPCHAIN_BUFFER_COUNT;\r\n\tSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;\r\n\tSwapChainDesc.SampleDesc.Count = 1;\r\n\tSwapChainDesc.Format = SWAPCHAIN_BACK_BUFFER_FORMAT;\r\n\tSwapChainDesc.Height = m_WindowHeight;\r\n\tSwapChainDesc.Scaling = DXGI_SCALING_NONE;\r\n\tSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;\r\n\tSwapChainDesc.Width = m_WindowWidth;\r\n\tSwapChainDesc.Flags = 0;\r\n\r\n\t//\r\n\t// The swap chain is created as an IDXGISwapChain1 interface, but we then query\r\n\t// the IDXGISwapchain3 interface from it.\r\n\t//\r\n\tIDXGISwapChain1* pSwapChain;\r\n\thr = m_pDXGIFactory->CreateSwapChainForHwnd(m_RenderContext.GetCommandQueue(), m_Hwnd, &SwapChainDesc, nullptr, nullptr, &pSwapChain);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create swap chain for hwnd, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = pSwapChain->QueryInterface(&m_pDXGISwapChain);\r\n\tpSwapChain->Release();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to query IDXGISwapChain3 interface, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Create RTV heap for render target.\r\n\t//\r\n\t{\r\n\t\tD3D12_DESCRIPTOR_HEAP_DESC HeapDesc = {};\r\n\r\n\t\tHeapDesc.NumDescriptors = SWAPCHAIN_BUFFER_COUNT;\r\n\t\tHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;\r\n\t\tHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;\r\n\t\thr = m_pDevice->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&m_pRtvHeap));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create RTV descriptor heap, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// If enabled, create the shared staging resource used for transfers.\r\n\t//\r\n\tif (m_bUseSharedStagingSurface)\r\n\t{\r\n\t\thr = m_pDevice->CreateCommittedResource(\r\n\t\t\t&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),\r\n\t\t\tD3D12_HEAP_FLAG_NONE,\r\n\t\t\t&CD3DX12_RESOURCE_DESC::Buffer(MAX_TRANSFER_SIZE),\r\n\t\t\tD3D12_RESOURCE_STATE_GENERIC_READ,\r\n\t\t\tnullptr,\r\n\t\t\tIID_PPV_ARGS(&m_pStagingSurface));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create staging upload buffer, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tCD3DX12_RANGE readRange(0, 0);\r\n\t\thr = m_pStagingSurface->Map(0, &readRange, &m_pStagingSurfaceData);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to map upload buffer data, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Create 11On12 state to enable D2D rendering on D3D12.\r\n\t//\r\n\tIUnknown* pRenderCommandQueue = m_RenderContext.GetCommandQueue();\r\n\thr = D3D11On12CreateDevice(m_pDevice, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, &pRenderCommandQueue, 1, 0, &m_p11Device, &m_p11Context, nullptr);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create D3D11On12 device, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_p11Device->QueryInterface(&m_p11On12Device);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to query 11On12 device interface, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Create D2D/DWrite components.\r\n\t//\r\n\t{\r\n\t\tD2D1_DEVICE_CONTEXT_OPTIONS DeviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE;\r\n\t\tIDXGIDevice* pDxgiDevice;\r\n\t\thr = m_p11On12Device->QueryInterface(&pDxgiDevice);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to query IDXGIDevice interface, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\thr = m_pD2DFactory->CreateDevice(pDxgiDevice, &m_pD2DDevice);\r\n\t\tpDxgiDevice->Release();\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create D2D device, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\thr = m_pD2DDevice->CreateDeviceContext(DeviceOptions, &m_pD2DContext);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create D2D context, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Create the resources to enable D2D to access the swap chain.\r\n\t//\r\n\thr = CreateSwapChainResources();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create swap chain resources\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Initialize our paging worker thread. The worker thread will be used for streaming\r\n\t// resource mipmaps asynchronously from the rendering thread.\r\n\t//\r\n\ttry\r\n\t{\r\n\t\tm_pWorkerThread = new PagingWorkerThread(this);\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to allocate paging worker thread instance\");\r\n\t\treturn E_OUTOFMEMORY;\r\n\t}\r\n\r\n\thr = m_pWorkerThread->Init();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize paging worker thread\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// If we are reinitializing from a device removed state, the application may have\r\n\t// resources already which need to be reinitialized. Do this now.\r\n\t//\r\n\t{\r\n\t\tLIST_ENTRY* pResourceEntry = m_ResourceListHead.Flink;\r\n\t\twhile (pResourceEntry != &m_ResourceListHead)\r\n\t\t{\r\n\t\t\tResource* pResource = CONTAINING_RECORD(pResourceEntry, Resource, ListEntry);\r\n\t\t\tpResourceEntry = pResourceEntry->Flink;\r\n\r\n\t\t\tUINT NumMips;\r\n\t\t\tUINT Width;\r\n\t\t\tUINT Height;\r\n\t\t\tDXGI_FORMAT Format;\r\n\r\n\t\t\thr = GetResourceInformation(pResource->pDecoder, NumMips, Format, Width, Height);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to get resource information, hr=0x%.8x\", hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = CreateResourceDeviceState(pResource, NumMips, Format, Width, Height);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\thr = CreateDeviceDependentState();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\treturn hr;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::DestroyDeviceDependentStateInternal()\r\n{\r\n\tDestroyDeviceDependentState();\r\n\r\n\tif (m_pWorkerThread)\r\n\t{\r\n\t\tdelete m_pWorkerThread;\r\n\t\tm_pWorkerThread = nullptr;\r\n\t}\r\n\r\n\tm_RenderContext.DestroyDeviceDependentState();\r\n\tm_PagingContext.DestroyDeviceDependentState();\r\n\r\n\tm_TextureShader.DestroyDeviceDependentState();\r\n\tm_ColorShader.DestroyDeviceDependentState();\r\n\r\n\t{\r\n\t\tLIST_ENTRY* pResourceEntry = m_ResourceListHead.Flink;\r\n\t\twhile (pResourceEntry != &m_ResourceListHead)\r\n\t\t{\r\n\t\t\tResource* pResource = CONTAINING_RECORD(pResourceEntry, Resource, ListEntry);\r\n\t\t\tpResourceEntry = pResourceEntry->Flink;\r\n\r\n\t\t\tDestroyResourceDeviceState(pResource);\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tLIST_ENTRY* pVersionedBufferEntry = m_DynamicBufferListHead.Flink;\r\n\t\twhile (pVersionedBufferEntry != &m_DynamicBufferListHead)\r\n\t\t{\r\n\t\t\tBuffer* pVersionedBuffer = static_cast<Buffer*>(pVersionedBufferEntry);\r\n\t\t\tpVersionedBufferEntry = pVersionedBufferEntry->Flink;\r\n\t\t\tFreeVersionedBuffer(pVersionedBuffer);\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tLIST_ENTRY* pVersionedDescriptorHeapEntry = m_DynamicDescriptorHeapListHead.Flink;\r\n\t\twhile (pVersionedDescriptorHeapEntry != &m_DynamicDescriptorHeapListHead)\r\n\t\t{\r\n\t\t\tDescriptorHeap* pVersionedDescriptorHeap = static_cast<DescriptorHeap*>(pVersionedDescriptorHeapEntry);\r\n\t\t\tpVersionedDescriptorHeapEntry = pVersionedDescriptorHeapEntry->Flink;\r\n\t\t\tFreeVersionedDescriptorHeap(pVersionedDescriptorHeap);\r\n\t\t}\r\n\t}\r\n\r\n\tSafeRelease(m_pDXGIAdapter);\r\n\tSafeRelease(m_pDevice);\r\n\tSafeRelease(m_pDXGISwapChain);\r\n\tSafeRelease(m_pRtvHeap);\r\n\tSafeRelease(m_pStagingSurface);\r\n\r\n\tSafeRelease(m_p11Device);\r\n\tSafeRelease(m_p11On12Device);\r\n\tSafeRelease(m_pD2DDevice);\r\n\tSafeRelease(m_pD2DContext);\r\n\r\n\tfor (int i = 0; i < SWAPCHAIN_BUFFER_COUNT; ++i)\r\n\t{\r\n\t\tSafeRelease(m_pRenderTargets[i]);\r\n\t\tSafeRelease(m_pWrappedBackBuffers[i]);\r\n\t\tSafeRelease(m_pD2DRenderTargets[i]);\r\n\t}\r\n\r\n\tif (m_p11Context)\r\n\t{\r\n\t\tm_p11Context->ClearState();\r\n\t\tm_p11Context->Flush();\r\n\t\tSafeRelease(m_p11Context);\r\n\t}\r\n}\r\n\r\nHRESULT DX12Framework::CreateSwapChainResources()\r\n{\r\n\tHRESULT hr;\r\n\r\n\tfloat dpiX;\r\n\tfloat dpiY;\r\n\tm_pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);\r\n\tD2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(\r\n\t\tD2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,\r\n\t\tD2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),\r\n\t\tdpiX,\r\n\t\tdpiY);\r\n\r\n\t//\r\n\t// For each buffer in the swapchain, we need to create a wrapped resource, and create\r\n\t// a D2D render target object to enable D2D rendering for the UI.\r\n\t//\r\n\tULONG Ref;\r\n\tfor (UINT n = 0; n < SWAPCHAIN_BUFFER_COUNT; n++)\r\n\t{\r\n\t\thr = m_pDXGISwapChain->GetBuffer(n, IID_PPV_ARGS(&m_pRenderTargets[n]));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to get swap chain back buffer for frame index %d, hr=0x%.8x\", n, hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tCD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_pRtvHeap->GetCPUDescriptorHandleForHeapStart(), n, m_DescriptorInfo.RtvDescriptorSize);\r\n\t\tm_pDevice->CreateRenderTargetView(m_pRenderTargets[n], nullptr, handle);\r\n\r\n\t\tD3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };\r\n\t\thr = m_p11On12Device->CreateWrappedResource(\r\n\t\t\tm_pRenderTargets[n],\r\n\t\t\t&d3d11Flags,\r\n\t\t\tD3D12_RESOURCE_STATE_RENDER_TARGET,\r\n\t\t\tD3D12_RESOURCE_STATE_PRESENT,\r\n\t\t\tIID_PPV_ARGS(&m_pWrappedBackBuffers[n]));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed create 11On12 wrapped resource for render target %d, hr=0x%.8x\", n, hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tIDXGISurface* pSurface;\r\n\t\thr = m_pWrappedBackBuffers[n]->QueryInterface(&pSurface);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to query IDXGISurface from wrapped back buffer, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\thr = m_pD2DContext->CreateBitmapFromDxgiSurface(pSurface, &bitmapProperties, &m_pD2DRenderTargets[n]);\r\n\t\tRef = pSurface->Release();\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create D2D bitmap from back buffer surface, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::DestroySwapChainResources()\r\n{\r\n\tfor (int i = 0; i < SWAPCHAIN_BUFFER_COUNT; ++i)\r\n\t{\r\n\t\tSafeRelease(m_pRenderTargets[i]);\r\n\t\tSafeRelease(m_pD2DRenderTargets[i]);\r\n\t\tSafeRelease(m_pWrappedBackBuffers[i]);\r\n\t}\r\n\r\n\t//\r\n\t// Must flush the 11 queue to ensure that the wrapped resources are destroyed prior to calling\r\n\t// ResizeBuffers, or it will fail because the objects are still live.\r\n\t//\r\n\tm_p11Context->Flush();\r\n\tm_RenderContext.Flush();\r\n}\r\n\r\nHRESULT DX12Framework::InitDynamicBuffer(DynamicBuffer* pBuffer)\r\n{\r\n\tHRESULT hr;\r\n\tBuffer* pNewBuffer;\r\n\r\n\thr = AllocateVersionedBuffer(&pNewBuffer);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to allocate buffer for dynamic buffer 0x%p, hr=0x%.8x\", pBuffer, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tpBuffer->m_pBuffer = pNewBuffer;\r\n\tpBuffer->m_pCurrentAddress = pNewBuffer->pBaseAddress;\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::DestroyDynamicBuffer(DynamicBuffer* pBuffer)\r\n{\r\n\tFreeVersionedBuffer(pBuffer->m_pBuffer);\r\n}\r\n\r\nvoid DX12Framework::FreeVersionedBuffer(Buffer* pBuffer)\r\n{\r\n\tSafeRelease(pBuffer->pBuffer);\r\n\tSafeDelete(pBuffer);\r\n}\r\n\r\nHRESULT DX12Framework::InitDynamicDescriptorHeap(DynamicDescriptorHeap* pHeap)\r\n{\r\n\tHRESULT hr;\r\n\tDescriptorHeap* pNewHeap;\r\n\r\n\thr = AllocateVersionedDescriptorHeap(&pNewHeap);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to allocate heap for dynamic heap 0x%p, hr=0x%.8x\", pHeap, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tpHeap->m_pHeap = pNewHeap;\r\n\tpHeap->m_CurrentHandleIndex = 0;\r\n\tpHeap->m_DescriptorSize = m_DescriptorInfo.SrvUavCbvDescriptorSize;\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::DestroyDynamicDescriptorHeap(DynamicDescriptorHeap* pHeap)\r\n{\r\n\tFreeVersionedDescriptorHeap(pHeap->m_pHeap);\r\n}\r\n\r\nvoid DX12Framework::FreeVersionedDescriptorHeap(DescriptorHeap* pHeap)\r\n{\r\n\tSafeRelease(pHeap->pHeap);\r\n\tSafeDelete(pHeap);\r\n}\r\n\r\nHRESULT DX12Framework::Run()\r\n{\r\n\tHRESULT hr;\r\n\r\n\thr = Init();\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize framework, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tShowWindow(m_Hwnd, SW_SHOWNORMAL);\r\n\r\n\tMSG Msg;\r\n\tfor (;;)\r\n\t{\r\n\t\t//\r\n\t\t// Process any pending window messages.\r\n\t\t//\r\n\t\twhile (PeekMessage(&Msg, 0, 0, 0, PM_REMOVE))\r\n\t\t{\r\n\t\t\tTranslateMessage(&Msg);\r\n\t\t\tDispatchMessage(&Msg);\r\n\r\n\t\t\tif (Msg.message == WM_QUIT)\r\n\t\t\t{\r\n\t\t\t\tgoto exit;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// Render a frame.\r\n\t\t//\r\n\t\thr = RenderInternal();\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failure returned from render (likely device removed), hr=0x%.8x\", hr);\r\n\t\t\tm_RenderContext.Flush();\r\n\t\t\thr = RecreateDeviceDependentState();\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Unable to recover from failure, hr=0x%.8x\", hr);\r\n\t\t\t\tabort();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\nexit:\r\n\tDestroyDeviceDependentStateInternal();\r\n\tDestroyDeviceIndependentStateInternal();\r\n\r\n#ifdef _DEBUG\r\n\tIDXGIDebug1* pDebug = nullptr;\r\n\tif (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug))))\r\n\t{\r\n\t\tpDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY);\r\n\t\tpDebug->Release();\r\n\t}\r\n#endif\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nHRESULT DX12Framework::QueryCaps()\r\n{\r\n\tHRESULT hr;\r\n\r\n\thr = m_pDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &m_Options, sizeof(m_Options));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to acquire D3D12 options for ID3D12Device 0x%p, hr=0x%.8x\", m_pDevice, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\thr = m_pDevice->CheckFeatureSupport(D3D12_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT, &m_GpuVaSupport, sizeof(m_GpuVaSupport));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to acquire GPU virtual address support for ID3D12Device 0x%p, hr=0x%.8x\", m_pDevice, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tD3D12_FEATURE_DATA_FEATURE_LEVELS FeatureLevels = {};\r\n\tD3D_FEATURE_LEVEL FeatureLevelsList[] = {\r\n\t\tD3D_FEATURE_LEVEL_11_0,\r\n\t\tD3D_FEATURE_LEVEL_11_1,\r\n\t\tD3D_FEATURE_LEVEL_12_0,\r\n\t\tD3D_FEATURE_LEVEL_12_1,\r\n\t};\r\n\tFeatureLevels.NumFeatureLevels = ARRAYSIZE(FeatureLevelsList);\r\n\tFeatureLevels.pFeatureLevelsRequested = FeatureLevelsList;\r\n\r\n\thr = m_pDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &FeatureLevels, sizeof(FeatureLevels));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to acquire feature level support for ID3D12Device 0x%p, hr=0x%.8x\", m_pDevice, hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tprintf(\"\\n\");\r\n\tprintf(\"--- Device details --------------------\\n\");\r\n\tprintf(\"  GPU Virtual Address Info:\\n\");\r\n\tprintf(\"    Max Process Size:      %I64d GB\\n\", (1ULL << m_GpuVaSupport.MaxGPUVirtualAddressBitsPerProcess) / 1024 / 1024 / 1024);\r\n\tprintf(\"    Max Resource Size:     %I64d GB\\n\", (1ULL << m_GpuVaSupport.MaxGPUVirtualAddressBitsPerResource) / 1024 / 1024 / 1024);\r\n\tprintf(\"  Feature Level Info:\\n\");\r\n\tprintf(\"    Max Feature Level:     %s\\n\", GetFeatureLevelName(FeatureLevels.MaxSupportedFeatureLevel));\r\n\tprintf(\"  Additional Info:\\n\");\r\n\tprintf(\"    Resource Binding Tier: Tier %d\\n\", m_Options.ResourceBindingTier);\r\n\tprintf(\"    Resource Heap Tier:    Tier %d\\n\", m_Options.ResourceHeapTier);\r\n\tprintf(\"    Tiled Resource Tier:   Tier %d\\n\", m_Options.TiledResourcesTier);\r\n\tprintf(\"\\n\");\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nHRESULT DX12Framework::UpdateVideoMemoryInfo()\r\n{\r\n\tHRESULT hr;\r\n\r\n\tDXGI_QUERY_VIDEO_MEMORY_INFO NewLocal;\r\n\tDXGI_QUERY_VIDEO_MEMORY_INFO NewNonLocal;\r\n\r\n\t//\r\n\t// QueryVideoMemoryInfo obtains up to date budgeting information from the graphics\r\n\t// kernel about video memory usage, budget, and reservation. This sample does not\r\n\t// use the reservation mechanics, but instead focuses on the proper techniques used\r\n\t// to manage the application's video memory usage and stay under budget through\r\n\t// trimming behavior.\r\n\t//\r\n\r\n\t//\r\n\t// Each call to QueryVideoMemoryInfo takes a memory segment group. Applications\r\n\t// should design their video memory usage around the local memory group budget,\r\n\t// and the non-local budget can usually be safely ignored. Non-local memory refers\r\n\t// to memory that is not located near the GPU, and as a result is typically much\r\n\t// slower than the local mmeory. On a discrete video card, the local and non-local\r\n\t// memory groups would represent VRAM and system memory, respectively. Accessing\r\n\t// system memory via PCI-e is far slower than accessing VRAM directly on-board,\r\n\t// and should typically be avoided in high performance graphics. Although some\r\n\t// small or low bandwidth allocations can effectively be placed here, it is not\r\n\t// recommended for normal texture memory. The local memory group always refers to\r\n\t// the fastest and most ideal placement for texture data.\r\n\t//\r\n\thr = m_pDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &NewLocal);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to update non-local video memory info. If the process budget has been lowered, trimming will not be done, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Per the above comment, obtaining the non-local memory info is not strictly\r\n\t// required, and can typically be ignored completely. In some cases, such as on\r\n\t// integrated GPUs, non-local memory does not even exist, and QueryVideoMemoryInfo\r\n\t// will return all zero data. Non-local memory's best usage is often for a fallback\r\n\t// under high memory pressure in order to make forward progress on the system.\r\n\t//\r\n\thr = m_pDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &NewNonLocal);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to update local video memory info. If the process budget has been lowered, trimming will not be done, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tif (m_LocalBudgetOverride != 0)\r\n\t{\r\n\t\tNewLocal.Budget = m_LocalBudgetOverride;\r\n\t}\r\n\r\n\tm_LocalVideoMemoryInfo = NewLocal;\r\n\tm_NonLocalVideoMemoryInfo = NewNonLocal;\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nHRESULT DX12Framework::GetResourceInformation(IWICBitmapDecoder* pDecoder, UINT& NumMips, DXGI_FORMAT& Format, UINT& Width, UINT& Height)\r\n{\r\n\tHRESULT hr;\r\n\tIWICDdsDecoder* pDdsDecoder = nullptr;\r\n\tWICDdsParameters DdsParameters;\r\n\r\n\tif (pDecoder)\r\n\t{\r\n\t\thr = pDecoder->QueryInterface(IID_PPV_ARGS(&pDdsDecoder));\r\n\r\n\t\tif (pDdsDecoder)\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// This is a DDS file. WIC can provide us direct access to the file information\r\n\t\t\t// which it already has stored internally.\r\n\t\t\t//\r\n\t\t\thr = pDdsDecoder->GetParameters(&DdsParameters);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to get DDS parameters from decoder, hr=0x%.8x\", hr);\r\n\t\t\t\tgoto cleanup;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// This is a non-DDS file, which does not directly expose the same information\r\n\t\t\t// as the DDS decoder, but can be obtained from the first frame in the image.\r\n\t\t\t//\r\n\t\t\tComPtr<IWICBitmapFrameDecode> pFrame;\r\n\t\t\thr = pDecoder->GetFrame(0, &pFrame);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to get frame info from decoder, hr=0x%.8x\", hr);\r\n\t\t\t\tgoto cleanup;\r\n\t\t\t}\r\n\r\n\t\t\tBitmapFrameInfo BitmapFrameInfo;\r\n\t\t\thr = GetBitmapFrameInfo(pFrame.Get(), &BitmapFrameInfo);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// May have failed to convert the pixel format into a supported DXGI format.\r\n\t\t\t\t//\r\n\t\t\t\tLOG_ERROR(\"Failed to get bitmap frame information, hr=0x%.8x\", hr);\r\n\t\t\t\tgoto cleanup;\r\n\t\t\t}\r\n\r\n\t\t\tDdsParameters.DxgiFormat = BitmapFrameInfo.DxgiFormat;\r\n\t\t\tDdsParameters.MipLevels = 1;\r\n\t\t\tDdsParameters.Width = BitmapFrameInfo.WidthInBlocks;\r\n\t\t\tDdsParameters.Height = BitmapFrameInfo.HeightInBlocks;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//\r\n\t\t// If no decoder is specified, we will generate an image for it.\r\n\t\t// The data will be loaded on demand as mips are fetched.\r\n\t\t//\r\n\t\tDdsParameters.MipLevels = 13;\r\n\t\tDdsParameters.DxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM;\r\n\t\tDdsParameters.Width = 1 << (DdsParameters.MipLevels - 1);\r\n\t\tDdsParameters.Height = 1 << (DdsParameters.MipLevels - 1);\r\n\t}\r\n\r\n\t//\r\n\t// Check format support for tiled resources.\r\n\t//\r\n\tD3D12_FEATURE_DATA_FORMAT_SUPPORT FormatSupport;\r\n\tFormatSupport.Format = DdsParameters.DxgiFormat;\r\n\thr = m_pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &FormatSupport, sizeof(FormatSupport));\r\n\tif (FAILED(hr) || (FormatSupport.Support2 & D3D12_FORMAT_SUPPORT2_TILED) == 0)\r\n\t{\r\n\t\tLOG_ERROR(\"CheckFeatureSupport failed, or unsupported DXGI format (%d)\", DdsParameters.DxgiFormat);\r\n\t\thr = E_FAIL;\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\tNumMips = DdsParameters.MipLevels;\r\n\tFormat = DdsParameters.DxgiFormat;\r\n\tWidth = DdsParameters.Width;\r\n\tHeight = DdsParameters.Height;\r\n\r\n\treturn S_OK;\r\n\r\ncleanup:\r\n\tSafeRelease(pDdsDecoder);\r\n\r\n\treturn hr;\r\n}\r\n\r\nHRESULT DX12Framework::CreateResource(LPCWSTR pFileName, Resource** ppResource)\r\n{\r\n\tHRESULT hr;\r\n\r\n\t//\r\n\t// Create a new resource object to track the state.\r\n\t//\r\n\tResource* pResource = nullptr;\r\n\ttry\r\n\t{\r\n\t\tpResource = new Resource();\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\tLOG_ERROR(\"Out of memory allocating device independent resource data\");\r\n\t\treturn E_OUTOFMEMORY;\r\n\t}\r\n\r\n\tZeroMemory(pResource, sizeof(Resource));\r\n\r\n\tIWICBitmapDecoder* pDecoder = nullptr;\r\n\tstatic UINT GeneratedImageIndex = 0;\r\n\r\n\tif (pFileName && *pFileName)\r\n\t{\r\n\t\t//\r\n\t\t// Open a WIC decoder to the specified file. We will use the WIC decoder\r\n\t\t// to open access to various mipmaps and copy the pixel data on demand.\r\n\t\t//\r\n\t\thr = m_pWICFactory->CreateDecoderFromFilename(\r\n\t\t\tpFileName,\r\n\t\t\tnullptr,\r\n\t\t\tGENERIC_READ,\r\n\t\t\tWICDecodeMetadataCacheOnDemand,\r\n\t\t\t&pDecoder);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to open frame decoder from file (Not image file?), hr=0x%.8x\", hr);\r\n\t\t\tgoto cleanup;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//\r\n\t\t// This resource will be generated and does not need a decoder.\r\n\t\t//\r\n\t\tpResource->GeneratedImageIndex = GeneratedImageIndex++;\r\n\t}\r\n\r\n\tUINT NumMips;\r\n\tDXGI_FORMAT Format;\r\n\tUINT Width;\r\n\tUINT Height;\r\n\r\n\thr = GetResourceInformation(pDecoder, NumMips, Format, Width, Height);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to get resource information, hr=0x%.8x\", hr);\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\t//\r\n\t// Creates the device dependent resource data for the current D3D12 device.\r\n\t//\r\n\thr = CreateResourceDeviceState(pResource, NumMips, Format, Width, Height);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create resource device state\");\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\t//\r\n\t// Complete resource construction.\r\n\t//\r\n#if(_DEBUG)\r\n\tpResource->pFileName = _wcsdup(pFileName);\r\n#endif\r\n\r\n\tInitializeCriticalSection(&pResource->ReferenceLock);\r\n\r\n\tpResource->pDecoder = pDecoder;\r\n\tInsertTailList(&m_ResourceListHead, &pResource->ListEntry);\r\n\tInsertTailList(&m_UncommittedListHead, &pResource->CommittedListEntry);\r\n\r\n\tassert(pResource->pDeviceState != nullptr);\r\n\r\n\t*ppResource = pResource;\r\n\r\n\treturn S_OK;\r\n\r\ncleanup:\r\n\tSafeDelete(pResource);\r\n\tSafeRelease(pDecoder);\r\n\r\n\treturn hr;\r\n}\r\n\r\nHRESULT DX12Framework::CreateResourceDeviceState(Resource* pResource, UINT NumMips, DXGI_FORMAT Format, UINT Width, UINT Height)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tID3D12Resource* pTiledResource = nullptr;\r\n\tID3D12Heap** ppHeaps = nullptr;\r\n\tResourceDeviceState* pDeviceState = nullptr;\r\n\r\n\t//\r\n\t// Create a new reserved resource which we will map to heaps at a later time.\r\n\t// A reserved resource only consists of a virtual address, which is commonly\r\n\t// plentiful and cheap on most hardware. On some hardware, virtual address space\r\n\t// is limited, and the application may have to write additional code to recreate\r\n\t// resources with fewer mipmaps to reduce address space pressure. This sample\r\n\t// is written to assume that the application is being run on hardware with large\r\n\t// virtual address spaces.\r\n\t// By default, D3D12's TIER1 support for virtual addressing supports a 40-bit\r\n\t// virtual address space, which is equal to 1 terabyte.\r\n\t//\r\n\tD3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(\r\n\t\tFormat,\r\n\t\tWidth,\r\n\t\tHeight,\r\n\t\t1,\r\n\t\t(UINT16)NumMips,\r\n\t\t1,\r\n\t\t0,\r\n\t\tD3D12_RESOURCE_FLAG_NONE,\r\n\t\tD3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE);\r\n\r\n\thr = m_pDevice->CreateReservedResource(&resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&pTiledResource));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\r\n\t\t\t\"Failed to create new resource. DxgiFormat=%d, Width=%d, Height=%d, MipLevels=%d, hr=0x%.8x\",\r\n\t\t\tFormat,\r\n\t\t\tWidth,\r\n\t\t\tHeight,\r\n\t\t\tNumMips,\r\n\t\t\thr);\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\t//\r\n\t// The application cannot determine tile information of a resource on its own. The\r\n\t// driver or device may have restrictions or limitations about how mipmaps are packed\r\n\t// into the tiles. Fortunately, D3D exposes a function which allows the driver to\r\n\t// inform us of the size information for each subresource (mipmap) of the resource.\r\n\t// This includes the dimensions (width, height, depth) of the subresource in tiles, as\r\n\t// well as the mip packing information, such as how many tiles are required to store\r\n\t// packed mipmaps (which is sometimes more than 1).\r\n\t//\r\n\tUINT NumTiles;\r\n\tD3D12_PACKED_MIP_INFO PackedMipInfo;\r\n\tD3D12_SUBRESOURCE_TILING SubresourceTiling[MAX_MIP_COUNT];\r\n\tUINT NumResourceTilings = MAX_MIP_COUNT;\r\n\tm_pDevice->GetResourceTiling(pTiledResource, &NumTiles, &PackedMipInfo, nullptr, &NumResourceTilings, 0, SubresourceTiling);\r\n\r\n\t//\r\n\t// Save off the number of packed and non-packed (standard) mipmaps.\r\n\t// Because packed mipmaps share the same tiles, and thus, the same physical heap memory,\r\n\t// we only need to create a single resource mip tracking structure for all packed mipmaps.\r\n\t//\r\n\tsize_t NumberOfStandardMipIndices = PackedMipInfo.NumStandardMips;\r\n\tsize_t NumberOfPackedMipHeapIndices = 0;\r\n\tif (PackedMipInfo.NumPackedMips > 0)\r\n\t{\r\n\t\tNumberOfPackedMipHeapIndices = 1;\r\n\t}\r\n\r\n\t//\r\n\t// Calculate the size of the resource's device state, and the mipmap data we'll need.\r\n\t//\r\n\tsize_t SizeOfResource = sizeof(ResourceDeviceState) - sizeof(ResourceMip);\r\n\tsize_t NumberOfMipIndices = NumberOfStandardMipIndices + NumberOfPackedMipHeapIndices;\r\n\tsize_t SizeOfResourceMipIndices = NumberOfMipIndices * sizeof(ResourceMip);\r\n\r\n\tpDeviceState = (ResourceDeviceState*)malloc(SizeOfResource + SizeOfResourceMipIndices);\r\n\tif (pDeviceState == nullptr)\r\n\t{\r\n\t\tLOG_ERROR(\"Low memory: Could not allocate resource structure\");\r\n\t\thr = E_OUTOFMEMORY;\r\n\t\tgoto cleanup;\r\n\t}\r\n\tZeroMemory(pDeviceState, SizeOfResource + SizeOfResourceMipIndices);\r\n\r\n\t//\r\n\t// For each mip heap, calculate the number of D3D12 heaps that will back the resource,\r\n\t// and allocate this data up front. Note that we are not creating the actual D3D12\r\n\t// heap here (this is done lazily when we load the image data). We will also\r\n\t// initialize mipmap specific tracking information.\r\n\t//\r\n\tUINT CurrentHeapCount = 0;\r\n\tfor (size_t i = 0; i < NumberOfMipIndices; ++i)\r\n\t{\r\n\t\tMipDescription* pDesc = &pDeviceState->Mips[i].Desc;\r\n\r\n\t\tNumTiles = PackedMipInfo.NumTilesForPackedMips;\r\n\t\tif (SubresourceTiling[i].StartTileIndexInOverallResource == 0xFFFFFFFF)\r\n\t\t{\r\n\t\t\tpDesc->WidthInTiles = 0;\r\n\t\t\tpDesc->HeightInTiles = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tUINT WidthInTiles = SubresourceTiling[i].WidthInTiles;\r\n\t\t\tUINT HeightInTiles = SubresourceTiling[i].HeightInTiles;\r\n\r\n\t\t\tpDesc->WidthInTiles = WidthInTiles;\r\n\t\t\tpDesc->HeightInTiles = HeightInTiles;\r\n\r\n\t\t\tNumTiles = WidthInTiles * HeightInTiles;\r\n\t\t}\r\n\t\tpDesc->HeapStartIndex = CurrentHeapCount;\r\n\r\n\t\t//\r\n\t\t// Even if a resource does not fill in a full 16MB heap, it is OK, because\r\n\t\t// we are counting the number of 16MB or less heaps in the resource. Thus\r\n\t\t// even 64KB rounded up will be 1, which is the correct value.\r\n\t\t//\r\n\t\tUINT MipSize = NumTiles * TILE_SIZE;\r\n\t\tUINT NumHeapsInMip = (MipSize + MAX_HEAP_SIZE - 1) / MAX_HEAP_SIZE;\r\n\r\n\t\tCurrentHeapCount += NumHeapsInMip;\r\n\t\tpDeviceState->Mips[i].ReferenceFence = 0;\r\n\t}\r\n\r\n\t//\r\n\t// Allocate heap list for entire texture. Each mip is broken into chunks of\r\n\t// at most MAX_HEAP_SIZE (Currently 16MB)\r\n\t//\r\n\ttry\r\n\t{\r\n\t\tppHeaps = new ID3D12Heap*[CurrentHeapCount];\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\tLOG_ERROR(\"Out of memory allocating D3D12 heap array\");\r\n\t\thr = E_OUTOFMEMORY;\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\t//\r\n\t// Initialize the rest of the resource to various default values.\r\n\t//\r\n\tZeroMemory(ppHeaps, sizeof(*ppHeaps) * CurrentHeapCount);\r\n\tfor (size_t i = 0; i < NumberOfMipIndices; ++i)\r\n\t{\r\n\t\tpDeviceState->Mips[i].ppHeaps = ppHeaps + pDeviceState->Mips[i].Desc.HeapStartIndex;\r\n\t}\r\n\r\n\tpDeviceState->pD3DResource = pTiledResource;\r\n\tpDeviceState->NumHeaps = CurrentHeapCount;\r\n\r\n\tpResource->PackedMipTileCount = PackedMipInfo.NumTilesForPackedMips;\r\n\tpResource->NumStandardMips = PackedMipInfo.NumStandardMips;\r\n\tpResource->NumPackedMips = PackedMipInfo.NumPackedMips;\r\n\tpResource->MostDetailedMipResident = PackedMipInfo.NumStandardMips + PackedMipInfo.NumPackedMips;\r\n\tpResource->pDeviceState = pDeviceState;\r\n\r\n\t//\r\n\t// By default, the resource should not be visible or prefetched, so we will\r\n\t// initialize these values to UNDEFINED_MIPMAP_INDEX, which is not a valid\r\n\t// mipmap index.\r\n\t//\r\n\tpResource->VisibleMip = UNDEFINED_MIPMAP_INDEX;\r\n\tpResource->PrefetchMip = UNDEFINED_MIPMAP_INDEX;\r\n\r\n\t//\r\n\t// By default, there are no restrictions on which mipmaps may be used for rendering.\r\n\t//\r\n\tpResource->MipRestriction = 0;\r\n\r\n\tpResource->TrimLimit = ERTP_None;\r\n\tpResource->bIgnoreBudget = false;\r\n\r\n\tpResource->PagingEntry.Flink = nullptr;\r\n\r\n\t//\r\n\t// Notify the paging thread of this resource so it can be prioritized. Although\r\n\t// not visible, we will still attempt to page in the packed mipmaps.\r\n\t//\r\n\tNotifyPagingWork(pResource);\r\n\r\n\treturn S_OK;\r\n\r\ncleanup:\r\n\tif (ppHeaps)\r\n\t{\r\n\t\tdelete[] ppHeaps;\r\n\t}\r\n\tSafeRelease(pTiledResource);\r\n\r\n\tif (pDeviceState)\r\n\t{\r\n\t\tfree(pDeviceState);\r\n\t}\r\n\r\n\treturn hr;\r\n}\r\n\r\nHRESULT DX12Framework::GetDdsFrameInfo(IWICDdsFrameDecode* pFrame, BitmapFrameInfo* pFormatInfo)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tWICDdsFormatInfo FormatInfo;\r\n\thr = pFrame->GetFormatInfo(&FormatInfo);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to get format info from DDS frame, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tUINT WidthInBlocks;\r\n\tUINT HeightInBlocks;\r\n\thr = pFrame->GetSizeInBlocks(&WidthInBlocks, &HeightInBlocks);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to get DDS frame size, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tpFormatInfo->BlockWidth = FormatInfo.BlockWidth;\r\n\tpFormatInfo->BlockHeight = FormatInfo.BlockHeight;\r\n\tpFormatInfo->DxgiFormat = FormatInfo.DxgiFormat;\r\n\r\n\tpFormatInfo->WidthInBlocks = WidthInBlocks;\r\n\tpFormatInfo->HeightInBlocks = HeightInBlocks;\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nHRESULT DX12Framework::GetBitmapFrameInfo(IWICBitmapFrameDecode* pFrame, BitmapFrameInfo* pFormatInfo)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tUINT WidthInBlocks;\r\n\tUINT HeightInBlocks;\r\n\thr = pFrame->GetSize(&WidthInBlocks, &HeightInBlocks);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to get bitmap size, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tWICPixelFormatGUID SourcePixelFormat;\r\n\thr = pFrame->GetPixelFormat(&SourcePixelFormat);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to get bitmap pixel format, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tDXGI_FORMAT DxgiFormat;\r\n\r\n\t//\r\n\t// Find the closest pixel format which we can convert the image source data into\r\n\t// for our resource.\r\n\t//\r\n\tGUID TargetPixelFormat;\r\n\tif (!GetTargetPixelFormat(&SourcePixelFormat, &TargetPixelFormat))\r\n\t{\r\n\t\tLOG_ERROR(\r\n\t\t\t\"No target pixel format found for source format, GUID=0x%x, 0x%x, 0x%x, 0x%x\",\r\n\t\t\tSourcePixelFormat.Data1,\r\n\t\t\tSourcePixelFormat.Data2,\r\n\t\t\tSourcePixelFormat.Data3,\r\n\t\t\tSourcePixelFormat.Data4);\r\n\t}\r\n\r\n\t//\r\n\t// Then find the closest matching DXGI format to that target pixel format.\r\n\t//\r\n\tDxgiFormat = GetDXGIFormatFromPixelFormat(&TargetPixelFormat);\r\n\tif (DxgiFormat == DXGI_FORMAT_UNKNOWN)\r\n\t{\r\n\t\tLOG_ERROR(\"No valid DXGI_FORMAT conversion for pixel format, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tpFormatInfo->BlockWidth = 1;\r\n\tpFormatInfo->BlockHeight = 1;\r\n\tpFormatInfo->DxgiFormat = DxgiFormat;\r\n\tpFormatInfo->SourcePixelFormat = SourcePixelFormat;\r\n\tpFormatInfo->TargetPixelFormat = TargetPixelFormat;\r\n\r\n\tpFormatInfo->WidthInBlocks = WidthInBlocks;\r\n\tpFormatInfo->HeightInBlocks = HeightInBlocks;\r\n\r\n\treturn S_OK;\r\n}\r\n\r\n//\r\n// LoadMip is in charge of creating resource data. If necessary, LoadMip will create the\r\n// heaps (physical memory) for the mipmap, update the virtual address mappings, and copy\r\n// the pixel data from the WIC image source.\r\n//\r\nHRESULT DX12Framework::LoadMip(Resource* pResource, UINT32 Mip)\r\n{\r\n\tHRESULT hr;\r\n\r\n\tLOG_MESSAGE(\"Loading mip %d\", Mip);\r\n\r\n\tUINT32 MipHeap = Mip;\r\n\r\n\tUINT NumMips = GetResourceMipCount(pResource);\r\n\tif (Mip >= NumMips)\r\n\t{\r\n\t\tLOG_WARNING(\"Trying to load mip %d for pResource 0x%p, but the image file only contains %d mip levels\", Mip, pResource, NumMips);\r\n\t\treturn S_FALSE;\r\n\t}\r\n\r\n\tBitmapFrameInfo MipFrameInfo = {};\r\n\r\n\tComPtr<IWICDdsDecoder> pDdsDecoder;\r\n\tComPtr<IWICBitmapFrameDecode> pBitmapFrame;\r\n\tComPtr<IWICDdsFrameDecode> pDdsFrame;\r\n\tComPtr<IWICBitmapSource> pSourceBitmap;\r\n\r\n\t//\r\n\t// Different behavior is performed depending on whether this is a generated image,\r\n\t// DDS file, or other image format, since it may contain block compressed pixel data.\r\n\t//\r\n\tif (pResource->pDecoder)\r\n\t{\r\n\t\thr = pResource->pDecoder->QueryInterface(IID_PPV_ARGS(&pDdsDecoder));\r\n\t\tif (SUCCEEDED(hr))\r\n\t\t{\r\n\t\t\thr = pDdsDecoder->GetFrame(0, Mip, 0, &pBitmapFrame);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to load decode frame for Resource 0x%p, mip %d, hr=0x%.8x\", pResource, Mip, hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = pBitmapFrame.As(&pDdsFrame);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to query DDS frame for mip %d, hr=0x%.8x\", Mip, hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = GetDdsFrameInfo(pDdsFrame.Get(), &MipFrameInfo);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to load frame information for mip %d, hr=0x%.8x\", Mip, hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thr = pResource->pDecoder->GetFrame(0, &pBitmapFrame);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to decode bitmap for Resource 0x%p, mip %d, hr=0x%.8x\", pResource, Mip, hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = GetBitmapFrameInfo(pBitmapFrame.Get(), &MipFrameInfo);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to load bitmap information for mip %d, hr=0x%.8x\", Mip, hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\t\t\t// Non-DDS images may need a pixel converter to convert between the source and\r\n\t\t\t// target pixel formats.\r\n\t\t\t//\r\n\t\t\tComPtr<IWICFormatConverter> pConverter;\r\n\t\t\thr = m_pWICFactory->CreateFormatConverter(&pConverter);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to create pixel format converter, hr=0x%.8x\", hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = pConverter->Initialize(\r\n\t\t\t\tpBitmapFrame.Get(),\r\n\t\t\t\tMipFrameInfo.TargetPixelFormat,\r\n\t\t\t\tWICBitmapDitherTypeNone,\r\n\t\t\t\tnullptr,\r\n\t\t\t\t0.0f,\r\n\t\t\t\tWICBitmapPaletteTypeCustom);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to initialize pixel format converter, hr=0x%.8x\", hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tpSourceBitmap = pConverter;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tD3D12_RESOURCE_DESC resourceDesc = pResource->pDeviceState->pD3DResource->GetDesc();\r\n\t\tMipFrameInfo.BlockWidth = 1;\r\n\t\tMipFrameInfo.BlockHeight = 1;\r\n\t\tMipFrameInfo.DxgiFormat = resourceDesc.Format;\r\n\r\n\t\tMipFrameInfo.WidthInBlocks = (UINT)(resourceDesc.Width) >> Mip;\r\n\t\tMipFrameInfo.HeightInBlocks = resourceDesc.Height >> Mip;\r\n\t}\r\n\r\n\tUINT NumTiles;\r\n\tUINT WidthInTiles;\r\n\r\n\t//\r\n\t// Mip maps beyond NumStandardMips are packed, and so the entire set of mipmaps\r\n\t// under it is packed into a single heap.\r\n\t//\r\n\tif (MipHeap >= pResource->PackedMipHeapIndex)\r\n\t{\r\n\t\tMipHeap = pResource->PackedMipHeapIndex;\r\n\t\tWidthInTiles = pResource->PackedMipTileCount;\r\n\t\tNumTiles = pResource->PackedMipTileCount;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tWidthInTiles = pResource->pDeviceState->Mips[MipHeap].Desc.WidthInTiles;\r\n\t\tNumTiles = WidthInTiles * pResource->pDeviceState->Mips[MipHeap].Desc.HeightInTiles;\r\n\t}\r\n\r\n\t//\r\n\t// Round up the number of heaps needed for this mip.\r\n\t//\r\n\tUINT NumHeapsInMip = ((NumTiles * TILE_SIZE) + MAX_HEAP_SIZE - 1) / MAX_HEAP_SIZE;\r\n\r\n\t//\r\n\t// Although we have a fixed heap count that is already calculated, we still calculate\r\n\t// the required size so we don't allocate more space than necessary. We do not want\r\n\t// to create 16MB heaps for mipmaps that are much smaller, or mipmaps which only\r\n\t// excced multiples of 16MB by a small amount (e.g. 33MB == 3 heaps == 16+16+1)\r\n\t//\r\n\tUINT64 RemainingSize = NumTiles * TILE_SIZE;\r\n\tID3D12Heap** ppHeaps = pResource->pDeviceState->Mips[MipHeap].ppHeaps;\r\n\tfor (UINT i = 0; i < NumHeapsInMip; ++i)\r\n\t{\r\n\t\tID3D12Heap* pHeap = ppHeaps[i];\r\n\t\tif (pHeap == nullptr)\r\n\t\t{\r\n\t\t\tD3D12_HEAP_DESC heapDesc = {};\r\n\r\n\t\t\theapDesc.SizeInBytes = min(RemainingSize, MAX_HEAP_SIZE);\r\n\t\t\theapDesc.Alignment = 0;\r\n\t\t\theapDesc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT;\r\n\t\t\theapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n\t\t\theapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n\r\n\t\t\t//\r\n\t\t\t// Tier 1 heaps have restrictions on the type of information that can be stored in\r\n\t\t\t// a heap. To accommodate this, we will retsrict the content to only shader resources.\r\n\t\t\t// The heap cannot store textures that are used as render targets, depth-stencil\r\n\t\t\t// output, or buffers. But this is okay, since we do not use these heaps for those\r\n\t\t\t// purposes.\r\n\t\t\t//\r\n\t\t\theapDesc.Flags = D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_BUFFERS;\r\n\r\n\t\t\thr = m_pDevice->CreateHeap(&heapDesc, IID_PPV_ARGS(&pHeap));\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to create D3D12 heap, hr=0x%.8x\", hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tppHeaps[i] = pHeap;\r\n\t\t\tRemainingSize -= heapDesc.SizeInBytes;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Calculate the required size of the upload buffer for transferring the contents\r\n\t// to the new heaps.\r\n\t//\r\n\tUINT64 UploadBufferSize = GetRequiredIntermediateSize(pResource->pDeviceState->pD3DResource, Mip, 1);\r\n\r\n\tID3D12Resource* pUploadSurface;\r\n\tvoid* pUploadData;\r\n\r\n\t//\r\n\t// If we are using a shared staging surface, we don't have to create a new upload\r\n\t// resource for each transfer. This feature is currently experimental, and disabled\r\n\t// by default.\r\n\t//\r\n\tComPtr<ID3D12Resource> pUploadBuffer;\r\n\tif (m_bUseSharedStagingSurface)\r\n\t{\r\n\t\tpUploadSurface = m_pStagingSurface;\r\n\t\tpUploadData = m_pStagingSurfaceData;\r\n\t}\r\n\telse\r\n\t{\r\n\t\thr = m_pDevice->CreateCommittedResource(\r\n\t\t\t&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),\r\n\t\t\tD3D12_HEAP_FLAG_NONE,\r\n\t\t\t&CD3DX12_RESOURCE_DESC::Buffer(UploadBufferSize),\r\n\t\t\tD3D12_RESOURCE_STATE_GENERIC_READ,\r\n\t\t\tnullptr,\r\n\t\t\tIID_PPV_ARGS(&pUploadBuffer));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create upload buffer, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tCD3DX12_RANGE readRange(0, 0);\r\n\t\thr = pUploadBuffer->Map(0, &readRange, &pUploadData);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to map upload buffer, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tpUploadSurface = pUploadBuffer.Get();\r\n\t}\r\n\r\n\t//\r\n\t// Map the reserved resource (e.g. the virtual address we created with the resource)\r\n\t// to the heaps that back them. Page table updates for tiled resources can be costly,\r\n\t// so we will split up the mapping into one heap at a time (16MB of updates per call).\r\n\t//\r\n\t{\r\n\t\tstatic const UINT MaxTilesPerUpdate = MAX_HEAP_SIZE / TILE_SIZE;\r\n\r\n\t\tUINT32 NumTilesRemaining = NumTiles;\r\n\r\n\t\twhile (NumTilesRemaining)\r\n\t\t{\r\n\t\t\tUINT TilesInUpdate = min(MaxTilesPerUpdate, NumTilesRemaining);\r\n\r\n\t\t\tUINT32 TileOffset = NumTiles - NumTilesRemaining;\r\n\r\n\t\t\tD3D12_TILED_RESOURCE_COORDINATE Coordinates = {};\r\n\t\t\tCoordinates.Subresource = Mip;\r\n\t\t\tCoordinates.X = TileOffset % WidthInTiles;\r\n\t\t\tCoordinates.Y = TileOffset / WidthInTiles;\r\n\r\n\t\t\tD3D12_TILE_REGION_SIZE RegionSize = {};\r\n\t\t\tRegionSize.NumTiles = TilesInUpdate;\r\n\r\n\t\t\tD3D12_TILE_RANGE_FLAGS RangeFlags = D3D12_TILE_RANGE_FLAG_NONE;\r\n\t\t\tUINT RangeOffset = 0;\r\n\t\t\tUINT RangeCount = TilesInUpdate;\r\n\t\t\tm_PagingContext.GetCommandQueue()->UpdateTileMappings(\r\n\t\t\t\tpResource->pDeviceState->pD3DResource,\r\n\t\t\t\t1,\r\n\t\t\t\t&Coordinates,\r\n\t\t\t\t&RegionSize,\r\n\t\t\t\t*ppHeaps,\r\n\t\t\t\t1,\r\n\t\t\t\t&RangeFlags,\r\n\t\t\t\t&RangeOffset,\r\n\t\t\t\t&RangeCount,\r\n\t\t\t\tD3D12_TILE_MAPPING_FLAG_NO_HAZARD);\r\n\r\n\t\t\tNumTilesRemaining -= TilesInUpdate;\r\n\t\t\t++ppHeaps;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Copy the pixel data into the staging resource, and then transfer it to the\r\n\t// reserved resource via CopyTextureRegion.\r\n\t//\r\n\tD3D12_PLACED_SUBRESOURCE_FOOTPRINT Layout;\r\n\r\n\tUINT NumRows;\r\n\tUINT64 RowSizeInBytes;\r\n\tUINT64 TotalBytes;\r\n\tD3D12_RESOURCE_DESC Desc = pResource->pDeviceState->pD3DResource->GetDesc();\r\n\tm_pDevice->GetCopyableFootprints(&Desc, Mip, 1, 0, &Layout, &NumRows, &RowSizeInBytes, &TotalBytes);\r\n\tUINT64 RemainingBytes = TotalBytes;\r\n\r\n\tUINT32 CurrentRow = 0;\r\n\r\n\twhile (RemainingBytes > 0)\r\n\t{\r\n\t\tUINT32 MaxTransferHeightInBlocks;\r\n\r\n\t\t//\r\n\t\t// Begin a paging frame. Each paging operation (i.e. a copy/transfer) must be contained\r\n\t\t// within a paging frame so we can track and synchronize the operation on the context.\r\n\t\t//\r\n\t\tm_PagingContext.Begin();\r\n\r\n\t\tUINT64 BytesInTransfer;\r\n\t\tif (m_bUseSharedStagingSurface)\r\n\t\t{\r\n\t\t\tMaxTransferHeightInBlocks = static_cast<UINT32>(MAX_TRANSFER_SIZE / Layout.Footprint.RowPitch);\r\n\t\t\tBytesInTransfer = min(MAX_TRANSFER_SIZE, RemainingBytes);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tMaxTransferHeightInBlocks = NumRows;\r\n\t\t\tBytesInTransfer = RemainingBytes;\r\n\t\t}\r\n\r\n\t\tUINT32 TransferHeightInBlocks = static_cast<UINT32>((BytesInTransfer + Layout.Footprint.RowPitch - 1) / Layout.Footprint.RowPitch);\r\n\t\tTransferHeightInBlocks = min(TransferHeightInBlocks, MaxTransferHeightInBlocks);\r\n\r\n\t\tUINT32 TransferHeightInRows = TransferHeightInBlocks * MipFrameInfo.BlockHeight;\r\n\r\n\t\tWICRect SourceRect;\r\n\t\tSourceRect.X = 0;\r\n\t\tSourceRect.Y = CurrentRow / MipFrameInfo.BlockHeight;\r\n\t\tSourceRect.Width = MipFrameInfo.WidthInBlocks;\r\n\t\tSourceRect.Height = TransferHeightInBlocks;\r\n\r\n\t\t//\r\n\t\t// The copy differs slightly based on whether or not this is a DDS file with block compressed data.\r\n\t\t//\r\n\t\tif (pDdsFrame)\r\n\t\t{\r\n\t\t\thr = pDdsFrame->CopyBlocks(&SourceRect, Layout.Footprint.RowPitch, Layout.Footprint.RowPitch * TransferHeightInBlocks, ((BYTE*)pUploadData));\r\n\t\t}\r\n\t\telse if (pSourceBitmap.Get())\r\n\t\t{\r\n\t\t\thr = pSourceBitmap->CopyPixels(&SourceRect, Layout.Footprint.RowPitch, Layout.Footprint.RowPitch * TransferHeightInBlocks, ((BYTE*)pUploadData));\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thr = GenerateMip(pResource->GeneratedImageIndex, &SourceRect, Layout.Footprint.RowPitch, Layout.Footprint.RowPitch * TransferHeightInBlocks, (UINT*)pUploadData);\r\n\t\t}\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to copy frame data to upload staging buffer, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// Copy the texture region on the copy command queue.\r\n\t\t//\r\n\t\tFrame* pPagingFrame = m_PagingContext.GetCurrentFrame();\r\n\r\n\t\tD3D12_BOX SrcBox =\r\n\t\t{\r\n\t\t\t0,                      // UINT left;\r\n\t\t\t0,                      // UINT top;\r\n\t\t\t0,                      // UINT front;\r\n\t\t\tMipFrameInfo.WidthInBlocks * MipFrameInfo.BlockWidth, // UINT right;\r\n\t\t\tTransferHeightInRows,   // UINT bottom;\r\n\t\t\t1,                      // UINT back;\r\n\t\t};\r\n\r\n\t\tCD3DX12_TEXTURE_COPY_LOCATION Dst(pResource->pDeviceState->pD3DResource, Mip);\r\n\t\tCD3DX12_TEXTURE_COPY_LOCATION Src(pUploadSurface, Layout);\r\n\t\tSrc.PlacedFootprint.Footprint.Height = TransferHeightInRows;\r\n\t\tSrc.PlacedFootprint.Offset = 0;\r\n\t\tpPagingFrame->pCommandList->CopyTextureRegion(&Dst, 0, CurrentRow, 0, &Src, &SrcBox);\r\n\r\n\t\t//\r\n\t\t// Synchronize on this transfer. An application may extend this implementation\r\n\t\t// to support multiple operations at a time (by allowing multiple paging frames\r\n\t\t// to run concurrently). However, in the interest of simplifying the concepts\r\n\t\t// in the sample, it was opted to serialize paging operations to make things\r\n\t\t// easier to understand.\r\n\t\t//\r\n\t\thr = m_PagingContext.Execute();\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failed to transfer content for resource 0x%p, mip %d. hr=0x%.8x\", pResource, Mip, hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tm_PagingContext.End();\r\n\t\tm_PagingContext.Flush();\r\n\r\n\t\tCurrentRow += TransferHeightInRows;\r\n\t\tRemainingBytes -= BytesInTransfer;\r\n\t}\r\n\r\n\tpResource->MostDetailedMipResident = Mip;\r\n\r\n\tAddResourceCommitment(pResource);\r\n\r\n\treturn S_OK;\r\n}\r\n\r\n_Use_decl_annotations_\r\nHRESULT DX12Framework::GenerateMip(UINT ImageIndex, WICRect* pRect, UINT RowPitch, UINT BufferSizeInBytes, UINT* pBuffer)\r\n{\r\n\tconst UINT RowWidth = RowPitch >> 2;\r\n\tconst UINT BufferSize = BufferSizeInBytes >> 2;\r\n\tconst UINT CellWidth = max(pRect->Width >> 3, 1);\t\t// The width of a cell in the checkboard texture.\r\n\tconst UINT CellHeight = max(pRect->Height >> 3, 1);\t\t// The height of a cell in the checkerboard texture.\r\n\tconst BYTE Gray = 0x88;\r\n\tconst UINT Color = GetGeneratedImageColor(ImageIndex);\r\n\r\n\tif (RowWidth * pRect->Height > BufferSize)\r\n\t{\r\n\t\tLOG_ERROR(\"Buffer is too small for this mip\");\r\n\t\treturn E_INVALIDARG;\r\n\t}\r\n\r\n\tfor (int y = 0; y < pRect->Height; y++)\r\n\t{\r\n\t\tUINT Index = y * RowWidth;\r\n\t\tfor (int x = 0; x < pRect->Width; x++)\r\n\t\t{\r\n\t\t\tUINT i = x / CellWidth;\r\n\t\t\tUINT j = y / CellHeight;\r\n\r\n\t\t\tif (i % 2 == j % 2)\r\n\t\t\t{\r\n\t\t\t\tpBuffer[Index++] = Color;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// A subtle gradient from the top left corner to the bottom right.\r\n\t\t\t\tBYTE Shade = BYTE((i + j) << 3) + Gray;\r\n\t\t\t\tpBuffer[Index++] = 0xff << 24 | Shade << 16 | Shade << 8 | Shade;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\n//\r\n//-------------------------------------------------------------------------------------------------\r\n// The following few functions are helper functions for simplified rendering operations.\r\n// It should be noted that the emphasis of this sample was not to maximize rendeirng\r\n// efficiency, but instead demonstrate memory management behavior. As a result, the\r\n// rendering algorithms used in this application were designed around simplicity, and\r\n// are not intended to be examples of optimized algorithms for rendering using the\r\n// D3D12 API.\r\n//-------------------------------------------------------------------------------------------------\r\n//\r\nvoid DX12Framework::DrawRectangle(const RectF* pDest, float Stroke, const ColorF* pColor)\r\n{\r\n\tRectF Temp;\r\n\r\n\t// Left/Right frame.\r\n\tTemp.Top = pDest->Top - Stroke;\r\n\tTemp.Bottom = pDest->Bottom + Stroke;\r\n\r\n\tTemp.Left = pDest->Left - Stroke;\r\n\tTemp.Right = pDest->Left;\r\n\tFillRectangle(&Temp, pColor);\r\n\r\n\tTemp.Left = pDest->Right;\r\n\tTemp.Right = pDest->Right + Stroke;\r\n\tFillRectangle(&Temp, pColor);\r\n\r\n\t// Top/Bottom frame.\r\n\tTemp.Left = pDest->Left;\r\n\tTemp.Right = pDest->Right;\r\n\r\n\tTemp.Top = pDest->Top - Stroke;\r\n\tTemp.Bottom = pDest->Top;\r\n\tFillRectangle(&Temp, pColor);\r\n\r\n\tTemp.Top = pDest->Bottom;\r\n\tTemp.Bottom = pDest->Bottom + Stroke;\r\n\tFillRectangle(&Temp, pColor);\r\n}\r\n\r\nvoid DX12Framework::FillRectangle(const RectF* pDest, const ColorF* pColor)\r\n{\r\n\tRenderFrame* pCurrentFrame = m_RenderContext.GetCurrentFrame();\r\n\tID3D12GraphicsCommandList* pCommandList = pCurrentFrame->pCommandList;\r\n\r\n\t//\r\n\t// Set the color shader to render solid colored rectangles.\r\n\t//\r\n\tSetShader(pCurrentFrame, &m_ColorShader);\r\n\r\n\ttypedef ColorShader::VertexFormat VertexType;\r\n\r\n\tVertexType Vertices[] =\r\n\t{\r\n\t\t{ { pDest->Left,  pDest->Top,    1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Top Left\r\n\t\t{ { pDest->Right, pDest->Bottom, 1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Bottom Right\r\n\t\t{ { pDest->Left,  pDest->Bottom, 1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Bottom Left\r\n\r\n\t\t{ { pDest->Right, pDest->Bottom, 1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Bottom Right\r\n\t\t{ { pDest->Left,  pDest->Top,    1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Top Left\r\n\t\t{ { pDest->Right, pDest->Top,    1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Top Right\r\n\t};\r\n\r\n\tVertexType* pVertices;\r\n\tUINT32 Offset;\r\n\tHRESULT hrVertexBuffer = pCurrentFrame->VertexBuffer.Allocate(sizeof(VertexType), 6, (void**)&pVertices, &Offset);\r\n\r\n\tif (hrVertexBuffer == E_OUTOFMEMORY)\r\n\t{\r\n\t\t//\r\n\t\t// If we ran out of space in our vertex buffer, we need to rename it in order to allocate\r\n\t\t// more vertices. Rename operations are guaranteed to succeed. Although in most cases\r\n\t\t// the system will have enough memory to simply allocate a new buffer, we are\r\n\t\t// capable of simply flushing the pipeline until the last frame was referenced,\r\n\t\t// allowing us to reuse the current buffer.\r\n\t\t//\r\n\t\tRenameDynamicBuffer(&pCurrentFrame->VertexBuffer);\r\n\t\tResetShader(pCurrentFrame);\r\n\t\thrVertexBuffer = pCurrentFrame->VertexBuffer.Allocate(sizeof(VertexType), 6, (void**)&pVertices, &Offset);\r\n\t\tassert(SUCCEEDED(hrVertexBuffer));\r\n\t}\r\n\r\n\t//\r\n\t// Copy vertices.\r\n\t//\r\n\tmemcpy(pVertices, Vertices, sizeof(Vertices));\r\n\r\n\tpCommandList->DrawInstanced(6, 1, Offset / sizeof(VertexType), 0);\r\n}\r\n\r\nvoid DX12Framework::FillRectangle(const RectF* pDest, const ColorF* pColor, Resource* pResource)\r\n{\r\n\tRenderFrame* pCurrentFrame = m_RenderContext.GetCurrentFrame();\r\n\tID3D12GraphicsCommandList* pCommandList = pCurrentFrame->pCommandList;\r\n\r\n\t//\r\n\t// Texture has not been loaded, use default gray.\r\n\t//\r\n\tif (pResource->MostDetailedMipResident == GetResourceMipCount(pResource))\r\n\t{\r\n\t\tstatic const ColorF FillColor = { .5f, .5f, .5f, 1.0f };\r\n\t\tFillRectangle(pDest, &FillColor);\r\n\t\treturn;\r\n\t}\r\n\r\n\t//\r\n\t// Reference the provided allocation, marking it with a rendering fence, which\r\n\t// we will use to track the visibility of the mipmap, so we can know when we\r\n\t// are allowed to trim it, if necessary.\r\n\t//\r\n\tUINT Mip = ReferenceResource(pResource, pCurrentFrame, pResource->VisibleMip);\r\n\tSetShader(pCurrentFrame, &m_TextureShader);\r\n\r\n\ttypedef TextureShader::VertexFormat VertexType;\r\n\r\n\tVertexType Vertices[] =\r\n\t{\r\n\t\t{ { pDest->Left,  pDest->Top,    1.0f }, { 0.0f, 0.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Top Left\r\n\t\t{ { pDest->Right, pDest->Bottom, 1.0f }, { 1.0f, 1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Bottom Right\r\n\t\t{ { pDest->Left,  pDest->Bottom, 1.0f }, { 0.0f, 1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Bottom Left\r\n\r\n\t\t{ { pDest->Right, pDest->Bottom, 1.0f }, { 1.0f, 1.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Bottom Right\r\n\t\t{ { pDest->Left,  pDest->Top,    1.0f }, { 0.0f, 0.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Top Left\r\n\t\t{ { pDest->Right, pDest->Top,    1.0f }, { 1.0f, 0.0f }, { pColor->R, pColor->G, pColor->B, pColor->A } }, // Top Right\r\n\t};\r\n\r\n\tVertexType* pVertices;\r\n\tUINT32 Offset;\r\n\tHRESULT hrVertexBuffer = pCurrentFrame->VertexBuffer.Allocate(sizeof(VertexType), 6, (void**)&pVertices, &Offset);\r\n\r\n\tD3D12_GPU_DESCRIPTOR_HANDLE GpuHandle;\r\n\tD3D12_CPU_DESCRIPTOR_HANDLE CpuHandle;\r\n\tHRESULT hrSrvDescriptor = pCurrentFrame->SrvCbvHeap.Allocate(1, &GpuHandle, &CpuHandle);\r\n\r\n\tif (hrVertexBuffer == E_OUTOFMEMORY)\r\n\t{\r\n\t\t//\r\n\t\t// If we ran out of space in our vertex buffer, we need to rename it in order to allocate\r\n\t\t// more vertices. Rename operations are guaranteed to succeed. Although in most cases\r\n\t\t// the system will have enough memory to simply allocate a new buffer, we are\r\n\t\t// capable of simply flushing the pipeline until the last frame was referenced,\r\n\t\t// allowing us to reuse the current buffer.\r\n\t\t//\r\n\t\tRenameDynamicBuffer(&pCurrentFrame->VertexBuffer);\r\n\t\tResetShader(pCurrentFrame);\r\n\t\thrVertexBuffer = pCurrentFrame->VertexBuffer.Allocate(sizeof(VertexType), 6, (void**)&pVertices, &Offset);\r\n\t\tassert(SUCCEEDED(hrVertexBuffer));\r\n\t}\r\n\r\n\tif (hrSrvDescriptor == E_OUTOFMEMORY)\r\n\t{\r\n\t\t//\r\n\t\t// The same concept applies to descriptor heaps as buffers. We can guarantee\r\n\t\t// a successful rename operation and make forward progress at all times.\r\n\t\t//\r\n\t\tRenameDynamicDescriptorHeap(&pCurrentFrame->SrvCbvHeap);\r\n\t\tResetShader(pCurrentFrame);\r\n\t\thrSrvDescriptor = pCurrentFrame->SrvCbvHeap.Allocate(1, &GpuHandle, &CpuHandle);\r\n\t\tassert(SUCCEEDED(hrSrvDescriptor));\r\n\t}\r\n\r\n\t//\r\n\t// Copy vertices.\r\n\t//\r\n\tmemcpy(pVertices, Vertices, sizeof(Vertices));\r\n\r\n\t//\r\n\t// Assign SRV.\r\n\t//\r\n\t{\r\n\t\tD3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = {};\r\n\r\n\t\tSrvDesc.Texture2D.MostDetailedMip = Mip;\r\n\t\tSrvDesc.Texture2D.MipLevels = GetResourceMipCount(pResource) - SrvDesc.Texture2D.MostDetailedMip;\r\n\r\n\t\tD3D12_RESOURCE_DESC Desc = pResource->pDeviceState->pD3DResource->GetDesc();\r\n\r\n\t\tSrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\r\n\t\tSrvDesc.Format = Desc.Format;\r\n\t\tSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;\r\n\r\n\t\tm_pDevice->CreateShaderResourceView(pResource->pDeviceState->pD3DResource, &SrvDesc, CpuHandle);\r\n\t}\r\n\r\n\tpCommandList->SetGraphicsRootDescriptorTable(1, GpuHandle);\r\n\tpCommandList->DrawInstanced(6, 1, Offset / sizeof(VertexType), 0);\r\n}\r\n\r\nHRESULT DX12Framework::RecreateDeviceDependentState()\r\n{\r\n\tDestroyDeviceDependentStateInternal();\r\n\r\n\treturn CreateDeviceDependentStateInternal();\r\n}\r\n\r\nbool DX12Framework::HandleMessage(HWND /*hwnd*/, UINT Message, WPARAM wParam, LPARAM lParam)\r\n{\r\n\tswitch (Message)\r\n\t{\r\n\tcase WM_DESTROY:\r\n\t{\r\n\t\tPostQuitMessage(0);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tcase WM_GETMINMAXINFO:\r\n\t{\r\n\t\t//\r\n\t\t// Enforce a minimum window size of 800x480, but no upper bound.\r\n\t\t//\r\n\t\tMINMAXINFO* pMinMaxInfo = (MINMAXINFO*)lParam;\r\n\t\tpMinMaxInfo->ptMinTrackSize.x = 800;\r\n\t\tpMinMaxInfo->ptMinTrackSize.y = 480;\r\n\t\tpMinMaxInfo->ptMaxTrackSize.x = LONG_MAX;\r\n\t\tpMinMaxInfo->ptMaxTrackSize.y = LONG_MAX;\r\n\t\treturn true;\r\n\t}\r\n\r\n\tcase WM_SIZE:\r\n\t{\r\n\t\tif (wParam != SIZE_MINIMIZED)\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// Do not resize swapchain and camera projection on minimize.\r\n\t\t\t//\r\n\t\t\tOnSizeChanged();\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nHRESULT DX12Framework::OnSizeChanged()\r\n{\r\n\tRECT ClientRect;\r\n\tGetClientRect(m_Hwnd, &ClientRect);\r\n\r\n\tLONG NewWidth = ClientRect.right - ClientRect.left;\r\n\tLONG NewHeight = ClientRect.bottom - ClientRect.top;\r\n\r\n\t//\r\n\t// If the window size changed, resize our swapchain and recreate swapchain resources.\r\n\t//\r\n\tif (NewWidth != m_WindowWidth || NewHeight != m_WindowHeight)\r\n\t{\r\n\t\tm_WindowHeight = NewHeight;\r\n\t\tm_WindowWidth = NewWidth;\r\n\r\n\t\tDestroySwapChainResources();\r\n\r\n\t\tHRESULT hr = m_pDXGISwapChain->ResizeBuffers(SWAPCHAIN_BUFFER_COUNT, NewWidth, NewHeight, SWAPCHAIN_BACK_BUFFER_FORMAT, 0);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failed to resize back buffer, hr=0x.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\thr = CreateSwapChainResources();\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failed to recreate swap chain resources! hr=0x.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::PrepareRendering()\r\n{\r\n\t//\r\n\t// Reset the shader.\r\n\t//\r\n\tm_pCurrentShader = nullptr;\r\n}\r\n\r\nvoid DX12Framework::PrepareFrame(RenderFrame* pFrame, const Camera* pCamera)\r\n{\r\n\tstatic const float ClearColor[] = { 0.35f, 0.35f, 0.35f, 1.0f };\r\n\tID3D12GraphicsCommandList* pCommandList = pFrame->pCommandList;\r\n\r\n\t//\r\n\t// Setup viewport and scissor rect.\r\n\t//\r\n\t{\r\n\t\tD3D12_VIEWPORT Viewport;\r\n\t\tViewport.TopLeftX = 0.0f;\r\n\t\tViewport.TopLeftY = 0.0f;\r\n\t\tViewport.Width = static_cast<FLOAT>(m_WindowWidth);\r\n\t\tViewport.Height = static_cast<FLOAT>(m_WindowHeight);\r\n\t\tViewport.MinDepth = 0.0f;\r\n\t\tViewport.MaxDepth = 1.0f;\r\n\t\tpCommandList->RSSetViewports(1, &Viewport);\r\n\r\n\t\tD3D12_RECT ScissorRect;\r\n\t\tScissorRect.left = 0;\r\n\t\tScissorRect.top = 0;\r\n\t\tScissorRect.right = m_WindowWidth;\r\n\t\tScissorRect.bottom = m_WindowHeight;\r\n\t\tpCommandList->RSSetScissorRects(1, &ScissorRect);\r\n\t}\r\n\r\n\tUINT BackBufferIndex = m_pDXGISwapChain->GetCurrentBackBufferIndex();\r\n\tpCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_pRenderTargets[BackBufferIndex], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));\r\n\r\n\tCD3DX12_CPU_DESCRIPTOR_HANDLE RtvHandle(m_pRtvHeap->GetCPUDescriptorHandleForHeapStart(), BackBufferIndex, m_DescriptorInfo.RtvDescriptorSize);\r\n\tpCommandList->OMSetRenderTargets(1, &RtvHandle, true, nullptr);\r\n\tpCommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr);\r\n\r\n\t//\r\n\t// Reset the buffers and descriptor heaps for the new frame.\r\n\t//\r\n\tpFrame->VertexBuffer.Reset();\r\n\tpFrame->ConstantBuffer.Reset();\r\n\tpFrame->SrvCbvHeap.Reset();\r\n\r\n\tUINT32 ConstantBufferSize = CalculateConstantBufferSize(sizeof(DirectX::XMMATRIX));\r\n\r\n\t//\r\n\t// Setup camera information for this frame.\r\n\t//\r\n\tvoid* pViewProjection;\r\n\tUINT32 ViewProjectionOffset;\r\n\tpFrame->ConstantBuffer.Allocate(ConstantBufferSize, 1, &pViewProjection, &ViewProjectionOffset);\r\n\r\n\t*(DirectX::XMMATRIX*)pViewProjection = pCamera->GetViewProjectionMatrix();\r\n\r\n\tpFrame->CameraAddress = pFrame->ConstantBuffer.GetGPUVirtualAddress() + ViewProjectionOffset;\r\n}\r\n\r\nstatic float CalculateDeltaTime(LONGLONG CurrentTick, LONGLONG PreviousTick, LONGLONG PerformanceFrequency)\r\n{\r\n\treturn (float)(((CurrentTick - PreviousTick) / (double)PerformanceFrequency));\r\n}\r\n\r\nHRESULT DX12Framework::RenderInternal()\r\n{\r\n\tHRESULT hr;\r\n\r\n\tLARGE_INTEGER PrevTick = m_LastFrameCounter;\r\n\tLARGE_INTEGER CurrentTick;\r\n\tQueryPerformanceCounter(&CurrentTick);\r\n\r\n\tm_StatTimeBetweenFrames[m_StatIndex] = CalculateDeltaTime(CurrentTick.QuadPart, PrevTick.QuadPart, m_PerformanceFrequency.QuadPart);\r\n\tm_LastFrameCounter = CurrentTick;\r\n\r\n\t//\r\n\t// Prepare for a new frame.\r\n\t//\r\n\tPrepareRendering();\r\n\tm_RenderContext.Begin();\r\n\r\n\tRenderFrame* pFrame = m_RenderContext.GetCurrentFrame();\r\n\r\n\tPrepareFrame(pFrame, m_pSceneCamera);\r\n\r\n\tRectF ViewportBounds;\r\n\r\n\t//\r\n\t// Calculate the bounds for the scene camera and render the scene.\r\n\t//\r\n\tViewportBounds = m_pSceneCamera->GenerateViewportBounds();\r\n\t{\r\n\t\tQueryPerformanceCounter(&PrevTick);\r\n\t\tRenderScene(ViewportBounds);\r\n\t\tQueryPerformanceCounter(&CurrentTick);\r\n\r\n\t\tm_StatRenderScene[m_StatIndex] = CalculateDeltaTime(CurrentTick.QuadPart, PrevTick.QuadPart, m_PerformanceFrequency.QuadPart);\r\n\t}\r\n\r\n\t//\r\n\t// Execute the command lists generated for the scene geometry. We will draw the\r\n\t// UI in a second pass using the D3D11On12 interface using D2D for rendering.\r\n\t//\r\n\thr = m_RenderContext.Execute();\r\n\tassert(SUCCEEDED(hr));\r\n\r\n\t//\r\n\t// Optionally simulate a failure for debugging.\r\n\t//\r\n\tif (SUCCEEDED(hr) && m_SimulatedRenderResult != S_OK)\r\n\t{\r\n\t\thr = m_SimulatedRenderResult;\r\n\t\tm_SimulatedRenderResult = S_OK;\r\n\t}\r\n\r\n\t//\r\n\t// Render the UI.\r\n\t//\r\n\tif (SUCCEEDED(hr))\r\n\t{\r\n\t\tQueryPerformanceCounter(&PrevTick);\r\n\r\n\t\thr = RenderUI();\r\n\r\n\t\tQueryPerformanceCounter(&CurrentTick);\r\n\r\n\t\tm_StatRenderUI[m_StatIndex] = CalculateDeltaTime(CurrentTick.QuadPart, PrevTick.QuadPart, m_PerformanceFrequency.QuadPart);\r\n\t}\r\n\r\n\t//\r\n\t// Ending the frame signals the fence on the command queue, allowing us to synchronize\r\n\t// GPU access by waiting on the fence. The fence will be completed by the graphics\r\n\t// kernel when the hardware completes the frame, and then the frame will be retired.\r\n\t//\r\n\tm_RenderContext.End();\r\n\r\n\tm_StatIndex = ((m_StatIndex + 1) % STATISTIC_COUNT);\r\n\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Rendering operations failed, likely device removed, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\t//\r\n\t// Present and update the frame index for the next frame.\r\n\t//\r\n\thr = m_pDXGISwapChain->Present(m_bPresentOnVsync, 0);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to present swap chain, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tDXGI_FRAME_STATISTICS FrameStatistics;\r\n\thr = m_pDXGISwapChain->GetFrameStatistics(&FrameStatistics);\r\n\r\n\tif (FrameStatistics.PresentCount > m_PreviousPresentCount)\r\n\t{\r\n\t\tif (m_PreviousRefreshCount > 0 &&\r\n\t\t\t(FrameStatistics.PresentRefreshCount - m_PreviousRefreshCount) > (FrameStatistics.PresentCount - m_PreviousPresentCount))\r\n\t\t{\r\n\t\t\t++m_GlitchCount;\r\n\t\t}\r\n\t}\r\n\tm_PreviousPresentCount = FrameStatistics.PresentCount;\r\n\tm_PreviousRefreshCount = FrameStatistics.SyncRefreshCount;\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid DX12Framework::SetShader(RenderFrame* pFrame, const Shader* pShader)\r\n{\r\n\t//\r\n\t// Setup the current shader by binding the pipeline state, root signature,\r\n\t// and vertex layout information.\r\n\t//\r\n\tif (pShader != m_pCurrentShader)\r\n\t{\r\n\t\tID3D12GraphicsCommandList* pCommandList = pFrame->pCommandList;\r\n\r\n\t\tpCommandList->SetGraphicsRootSignature(pShader->GetRootSignature());\r\n\t\tpCommandList->SetPipelineState(pShader->GetPipelineState());\r\n\t\tpCommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\r\n\r\n\t\tID3D12DescriptorHeap* ppHeaps[] = { pFrame->SrvCbvHeap.m_pHeap->pHeap };\r\n\t\tpCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);\r\n\t\tpCommandList->SetGraphicsRootConstantBufferView(0, pFrame->CameraAddress);\r\n\r\n\t\tpFrame->VertexBuffer.Align(pShader->GetVertexSize());\r\n\r\n\t\tD3D12_VERTEX_BUFFER_VIEW Vbv = {};\r\n\t\tVbv.BufferLocation = pFrame->VertexBuffer.GetGPUVirtualAddress();\r\n\t\tVbv.StrideInBytes = pShader->GetVertexSize();\r\n\t\tVbv.SizeInBytes = DYNAMIC_BUFFER_SIZE;\r\n\r\n\t\tpCommandList->IASetVertexBuffers(0, 1, &Vbv);\r\n\r\n\t\tm_pCurrentShader = pShader;\r\n\t}\r\n}\r\n\r\nUINT8 DX12Framework::ReferenceResource(Resource* pResource, RenderFrame* pFrame, UINT8 RequestedMip)\r\n{\r\n\tRequestedMip = ChooseMoreDetailedMip(RequestedMip, GetResourceMipCount(pResource) - 1);\r\n\r\n\t//\r\n\t// Grab the reference lock so we can choose the mipmap to display and mark\r\n\t// it with a reference fence. The reference fence is used by the paging thread\r\n\t// to synchronize access to the mipmap's heaps when it needs to be trimmed. We\r\n\t// cannot evict physical memory while the allocation can be touched by the GPU.\r\n\t//\r\n\tEnterCriticalSection(&pResource->ReferenceLock);\r\n\r\n\tUINT8 Mip = ChooseLessDetailedMip(RequestedMip, pResource->MostDetailedMipResident);\r\n\tMip = ChooseLessDetailedMip(Mip, pResource->MipRestriction);\r\n\tUINT8 MipHeapIndex = GetMipHeapIndexForResource(pResource, Mip);\r\n\tpResource->pDeviceState->Mips[MipHeapIndex].ReferenceFence = pFrame->CompletionFence;\r\n\r\n\tLeaveCriticalSection(&pResource->ReferenceLock);\r\n\r\n\treturn Mip;\r\n}\r\n\r\nHRESULT DX12Framework::PageInNextLevelOfDetail(Resource* pResource)\r\n{\r\n\tHRESULT hr = S_OK;\r\n\r\n\tUINT8 ResidentMip = pResource->MostDetailedMipResident;\r\n\tassert(ResidentMip != 0);\r\n\r\n\tUINT8 Mip = ResidentMip - 1;\r\n\r\n\tassert(IsMoreDetailedMip(ResidentMip, Mip));\r\n\r\n\tUINT32 MipHeap = GetMipHeapIndexForResource(pResource, Mip);\r\n\tResourceMip* pResourceMip = &pResource->pDeviceState->Mips[MipHeap];\r\n\r\n\tif (*pResourceMip->ppHeaps == nullptr || Mip >= pResource->PackedMipHeapIndex)\r\n\t{\r\n\t\t//\r\n\t\t// We need to create the heap and page in the texture from disk, since this\r\n\t\t// mipmap has not yet been created. There is an exception for packed mipmaps,\r\n\t\t// where the heap has been created, but we still need to copy the pixel data\r\n\t\t// and possibly update the virtual address.\r\n\t\t//\r\n\t\thr = LoadMip(pResource, Mip);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failed to load mip\");\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tUINT i;\r\n\r\n\t\t//\r\n\t\t// The texture was already loaded, but we evicted it. Make it resident now.\r\n\t\t//\r\n\t\tUINT HeapCount = GetResourceMipHeapCount(*pResourceMip);\r\n\t\tfor (i = 0; i < HeapCount; ++i)\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// The MakeResident API is synchronous, and the resource is considered to\r\n\t\t\t// be fully resident and usable by the GPU by the time the call returns.\r\n\t\t\t//\r\n\t\t\tID3D12Pageable* pPageable = pResourceMip->ppHeaps[i];\r\n\t\t\thr = m_pDevice->MakeResident(1, &pPageable);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_ERROR(\"Failed to make resource 0x%p mip %d resident, hr=0x%.8x\", pResource, Mip, hr);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tassert(i > 0);\r\n\r\n\t\t\t//\r\n\t\t\t// Undo the MakeResident calls above.\r\n\t\t\t//\r\n\t\t\twhile (i > 0)\r\n\t\t\t{\r\n\t\t\t\tID3D12Pageable* pPageable = pResourceMip->ppHeaps[i];\r\n\t\t\t\tHRESULT hrTemp = m_pDevice->Evict(1, &pPageable);\r\n\t\t\t\tif (FAILED(hrTemp))\r\n\t\t\t\t{\r\n\t\t\t\t\tLOG_WARNING(\"Failed to evict resource 0x%p mip %d, hr=0x%.8x\", pResource, Mip, hrTemp);\r\n\t\t\t\t}\r\n\t\t\t\t--i;\r\n\t\t\t}\r\n\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tpResource->MostDetailedMipResident = Mip;\r\n\t\tpResource->MipRestriction = 0;\r\n\r\n\t\t//\r\n\t\t// Add this mipmap to the commitment lists, which is used to efficiently\r\n\t\t// trim more detailed mips first.\r\n\t\t//\r\n\t\tAddResourceCommitment(pResource);\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nbool DX12Framework::TrimToTarget(ResourceTrimPass MaxPass, UINT64 TargetUsage)\r\n{\r\n\t//\r\n\t// The caller of this function passes a trimming pass restriction. This restriction\r\n\t// is intended to prevent lower priority allocations from trimming higher priority\r\n\t// ones. For example, if we page in a prefetched mip, we do not want to allow that\r\n\t// to trim a visible resource. In addition to being incorrect, and artifically\r\n\t// lowering the quality for the user, it creates a recursive trimming behavior\r\n\t// by allowing the paging thread to issue trimming calls to page in the visible mip,\r\n\t// which may trim the prefetched mip.\r\n\t//\r\n\tfor (ResourceTrimPass CurrentPass = ERTP_NonPrefetchable;\r\n\t\tCurrentPass <= MaxPass;\r\n\t\tCurrentPass = static_cast<ResourceTrimPass>(CurrentPass + 1))\r\n\t{\r\n\t\t//\r\n\t\t// Go through the commitment list for each mip level.\r\n\t\t//\r\n\t\tfor (UINT8 Mip = 0; Mip < MAX_MIP_COUNT; ++Mip)\r\n\t\t{\r\n\t\t\tLIST_ENTRY* pResourceListHead = &m_CommitmentListHeads[Mip];\r\n\r\n\t\t\tLIST_ENTRY* pEntry = pResourceListHead->Flink;\r\n\t\t\twhile (pEntry != pResourceListHead)\r\n\t\t\t{\r\n\t\t\t\tResource* pResource = CONTAINING_RECORD(pEntry, Resource, CommittedListEntry);\r\n\t\t\t\tpEntry = pEntry->Flink;\r\n\r\n\t\t\t\tif (Mip >= GetLeastDetailedMipHeapIndex(pResource))\r\n\t\t\t\t{\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Skip least detailed/packed mips, we cannot evict them.\r\n\t\t\t\t\t//\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tResourceMip* pResourceMip = &pResource->pDeviceState->Mips[Mip];\r\n\r\n\t\t\t\tUINT64 WaitFence = 0;\r\n\r\n\t\t\t\t//\r\n\t\t\t\t// Take the reference lock so we can restrict mipmap detail for the rendering\r\n\t\t\t\t// thread, while simultaneously querying the reference fence that we'll need\r\n\t\t\t\t// to wait on in order to trim the mip.\r\n\t\t\t\t//\r\n\t\t\t\tEnterCriticalSection(&pResource->ReferenceLock);\r\n\r\n\t\t\t\tif (pResourceMip->ReferenceFence > m_RenderContext.GetLastCompletedFence())\r\n\t\t\t\t{\r\n\t\t\t\t\tWaitFence = pResourceMip->ReferenceFence;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (CurrentPass == ERTP_Visible)\r\n\t\t\t\t{\r\n\t\t\t\t\tpResource->MipRestriction = DecreaseMipQuality(Mip, 1);\r\n\t\t\t\t}\r\n\t\t\t\telse if (CurrentPass == ERTP_NonVisible && IsLessDetailedMip(Mip, pResource->VisibleMip))\r\n\t\t\t\t{\r\n\t\t\t\t\tpResource->MipRestriction = DecreaseMipQuality(Mip, 1);\r\n\t\t\t\t}\r\n\t\t\t\telse if (CurrentPass == ERTP_NonPrefetchable && IsLessDetailedMip(Mip, pResource->PrefetchMip))\r\n\t\t\t\t{\r\n\t\t\t\t\tpResource->MipRestriction = DecreaseMipQuality(Mip, 1);\r\n\t\t\t\t}\r\n\t\t\t\tLeaveCriticalSection(&pResource->ReferenceLock);\r\n\r\n\t\t\t\tif (pResource->MipRestriction > Mip)\r\n\t\t\t\t{\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// This mip was used in a render operation that has not been completed. We must wait\r\n\t\t\t\t\t// for the operation to complete before we trim the mipmap.\r\n\t\t\t\t\t//\r\n\t\t\t\t\tif (WaitFence > 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_RenderContext.WaitForFence(WaitFence);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Trim the mipmap, and check if our budget constraints have been met.\r\n\t\t\t\t\t//\r\n\t\t\t\t\tTrimMip(pResource, Mip);\r\n\r\n\t\t\t\t\tUpdateVideoMemoryInfo();\r\n\t\t\t\t\tif (m_LocalVideoMemoryInfo.CurrentUsage < TargetUsage)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid DX12Framework::TrimMip(Resource* pResource, UINT8 Mip)\r\n{\r\n\tResourceMip* pResourceMip = &pResource->pDeviceState->Mips[Mip];\r\n\r\n\t//\r\n\t// Evict all the heaps for this mipmap.\r\n\t//\r\n\tUINT HeapCount = GetResourceMipHeapCount(*pResourceMip);\r\n\tfor (UINT i = 0; i < HeapCount; ++i)\r\n\t{\r\n\t\tID3D12Pageable* pPageable = pResourceMip->ppHeaps[i];\r\n\t\tHRESULT hr = m_pDevice->Evict(1, &pPageable);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failed to evict resource 0x%p mip %d, hr=0x%.8x\", pResource, Mip, hr);\r\n\t\t}\r\n\t}\r\n\r\n\tpResource->MostDetailedMipResident = DecreaseMipQuality(Mip, 1);\r\n\tpResource->MipRestriction = 0;\r\n\r\n\t//\r\n\t// Adjust the resource commitment level so it is a lower priority when trimming.\r\n\t//\r\n\tAddResourceCommitment(pResource);\r\n\r\n\t//\r\n\t// Evicting a resource mipmap means that there is some paging work that now must\r\n\t// be done. This may simply be low priority prefetching, but may be higher priority too.\r\n\t//\r\n\tm_pWorkerThread->PrioritizeResource(pResource);\r\n}\r\n\r\nvoid DX12Framework::AddResourceCommitment(Resource* pResource)\r\n{\r\n\t//\r\n\t// Remove the resource from any existing commitment level.\r\n\t//\r\n\tRemoveEntryList(&pResource->CommittedListEntry);\r\n\r\n\t//\r\n\t// One optimization here can be made to improve the quality of selecting resources\r\n\t// for trimming. Not all resources are the same dimensions, which means a resource's\r\n\t// mip level 0 may correspond to both a small and large texture - each will provide\r\n\t// a very different gain from evicting it. It should be a higher priority to evict\r\n\t// mipmaps which provide the most gains at the current trimming pass. This can be\r\n\t// solved by offsetting the resource in the commitment tree based on its dimensions,\r\n\t// providing a \"level of detail\" based not explicitly on the mip levels, but by\r\n\t// total detail level.\r\n\t//\r\n\tUINT CommittedListIndex = pResource->MostDetailedMipResident;\r\n\tInsertTailList(&m_CommitmentListHeads[CommittedListIndex], &pResource->CommittedListEntry);\r\n}\r\n\r\nvoid DX12Framework::RemoveResourceCommitment(Resource* pResource)\r\n{\r\n\tRemoveEntryList(&pResource->CommittedListEntry);\r\n\tInsertTailList(&m_UncommittedListHead, &pResource->CommittedListEntry);\r\n}\r\n\r\nvoid DX12Framework::LoadConfig(int argc, LPCSTR argv[])\r\n{\r\n\t//\r\n\t// Load configuration options here.\r\n\t//\r\n\tfor (int i = 1; i < argc; ++i)\r\n\t{\r\n\t\tLPCSTR pArg = argv[i];\r\n\r\n\t\tif (_strcmpi(pArg, \"-sharedstaging\") == 0)\r\n\t\t{\r\n\t\t\tm_bUseSharedStagingSurface = true;\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Framework.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// Structure to save off descriptor sizes for various descriptor heap types.\r\n// These values never change, and need only be queried by the D3D runtime once.\r\n//\r\nstruct DescriptorInfo\r\n{\r\n\tUINT32 RtvDescriptorSize;\r\n\tUINT32 SamplerDescriptorSize;\r\n\tUINT32 SrvUavCbvDescriptorSize;\r\n};\r\n\r\nstruct BitmapFrameInfo\r\n{\r\n\t// For block compressed formats, this is the width and height of a single\r\n\t// block of texture data. This will commonly be 4x4 texels.\r\n\t// For non-block compressed formats, these will always be 1, and represent\r\n\t// a single texel.\r\n\tUINT BlockWidth;\r\n\tUINT BlockHeight;\r\n\r\n\t// For block compressed formats, this is the width and height of the texture,\r\n\t// in blocks. The resolution of the texture, in texels, would be equal to:\r\n\t// (BlockWidth * WidthInBlocks) x (BlockHeight * HeightInBlocks)\r\n\t// For non-block compressed formats, these will be equal to the texture\r\n\t// resolution, in texels.\r\n\tUINT WidthInBlocks;\r\n\tUINT HeightInBlocks;\r\n\r\n\t// This is the DXGI_FORMAT of the texture.\r\n\tDXGI_FORMAT DxgiFormat;\r\n\r\n\t// These values are only used when loading image formats other than DDS, and\r\n\t// are used to provide WIC with the necessary pixel formats for performing\r\n\t// conversion information as the data is copied from disk.\r\n\tGUID SourcePixelFormat;\r\n\tGUID TargetPixelFormat;\r\n};\r\n\r\nclass DX12Framework\r\n{\r\n\tfriend class RenderContext;\r\n\tfriend class PagingContext;\r\n\r\nprivate:\r\n\t//\r\n\t// Device state management\r\n\t//\r\n\tHRESULT RecreateDeviceDependentState();\r\n\r\n\tHRESULT CreateDeviceIndependentStateInternal();\r\n\tHRESULT CreateDeviceDependentStateInternal();\r\n\tHRESULT CreateResourceDeviceState(Resource* pResource, UINT NumMips, DXGI_FORMAT Format, UINT Width, UINT Height);\r\n\r\n\tvoid DestroyDeviceIndependentStateInternal();\r\n\tvoid DestroyDeviceDependentStateInternal();\r\n\tvoid DestroyResource(Resource* pResource);\r\n\tvoid DestroyResourceDeviceState(Resource* pResource);\r\n\r\n\tHRESULT CreateSwapChainResources();\r\n\tvoid DestroySwapChainResources();\r\n\r\n\tHRESULT QueryCaps();\r\n\r\n\t//\r\n\t// Resource management\r\n\t//\r\n\tHRESULT GetResourceInformation(IWICBitmapDecoder* pDecoder, UINT& NumMips, DXGI_FORMAT& Format, UINT& Width, UINT& Height);\r\n\tUINT8 ReferenceResource(Resource* pResource, RenderFrame* pFrame, UINT8 RequestedMip);\r\n\tvoid TrimMip(Resource* pResource, UINT8 Mip);\r\n\tHRESULT GetDdsFrameInfo(IWICDdsFrameDecode* pFrame, BitmapFrameInfo* pFormatInfo);\r\n\tHRESULT GetBitmapFrameInfo(IWICBitmapFrameDecode* pFrame, BitmapFrameInfo* pFormatInfo);\r\n\tHRESULT LoadMip(Resource* pResource, UINT32 Mip);\r\n\tHRESULT GenerateMip(UINT ImageIndex, WICRect* pRect, UINT RowPitch, UINT BufferSizeInBytes, _In_reads_bytes_(BufferSizeInBytes) UINT* pBuffer);\r\n\tvoid RemoveResourceCommitment(Resource* pResource);\r\n\tvoid AddResourceCommitment(Resource* pResource);\r\n\r\n\r\n\t//\r\n\t// Dynamic buffers\r\n\t//\r\n\tHRESULT InitDynamicBuffer(DynamicBuffer* pBuffer);\r\n\tvoid DestroyDynamicBuffer(DynamicBuffer* pBuffer);\r\n\tHRESULT AllocateVersionedBuffer(Buffer** ppBuffer);\r\n\tvoid FreeVersionedBuffer(Buffer* ppBuffer);\r\n\r\n\tvoid RenameDynamicBuffer(DynamicBuffer* pBuffer);\r\n\tvoid RetireVersionedBuffer(Buffer* pBuffer);\r\n\r\n\t//\r\n\t// Dynamic heaps\r\n\t//\r\n\tHRESULT InitDynamicDescriptorHeap(DynamicDescriptorHeap* pHeap);\r\n\tvoid DestroyDynamicDescriptorHeap(DynamicDescriptorHeap* pHeap);\r\n\tHRESULT AllocateVersionedDescriptorHeap(DescriptorHeap** ppHeap);\r\n\tvoid FreeVersionedDescriptorHeap(DescriptorHeap* ppHeap);\r\n\r\n\tvoid RenameDynamicDescriptorHeap(DynamicDescriptorHeap* pDynamicHeap);\r\n\tvoid RetireVersionedDescriptorHeap(DescriptorHeap* pHeap);\r\n\r\n\t//\r\n\t// Frame management\r\n\t//\r\n\tvoid PrepareFrame(RenderFrame* pFrame, const Camera* pCamera);\r\n\tvoid PrepareRendering();\r\n\tHRESULT RenderInternal();\r\n\r\n\tHRESULT OnSizeChanged();\r\n\r\n\tHRESULT Init();\r\n\r\n\tvoid SetShader(RenderFrame* pFrame, const Shader* pShader);\r\n\tinline void ResetShader(RenderFrame* pFrame)\r\n\t{\r\n\t\tconst Shader* pCurrentShader = m_pCurrentShader;\r\n\t\tm_pCurrentShader = nullptr;\r\n\t\tSetShader(pFrame, pCurrentShader);\r\n\t}\r\n\r\nprotected:\r\n\tIWICImagingFactory* m_pWICFactory = nullptr;\r\n\tIDXGIFactory2* m_pDXGIFactory = nullptr;\r\n\tIDXGIAdapter3* m_pDXGIAdapter = nullptr;\r\n\tID3D12Device* m_pDevice = nullptr;\r\n\tID3D12DescriptorHeap* m_pRtvHeap = nullptr;\r\n\tIDXGISwapChain3* m_pDXGISwapChain = nullptr;\r\n\tID3D12Resource* m_pRenderTargets[SWAPCHAIN_BUFFER_COUNT];\r\n\tID3D12Resource* m_pStagingSurface = nullptr;\r\n\tvoid* m_pStagingSurfaceData = nullptr;\r\n\r\n\t//\r\n\t// 11On12 interface for UI\r\n\t//\r\n\tID3D11Device* m_p11Device = nullptr;\r\n\tID3D11DeviceContext* m_p11Context = nullptr;\r\n\tID3D11On12Device* m_p11On12Device = nullptr;\r\n\tID2D1Factory3* m_pD2DFactory = nullptr;\r\n\tID2D1Device2* m_pD2DDevice = nullptr;\r\n\tID2D1DeviceContext2* m_pD2DContext = nullptr;\r\n\tIDWriteFactory2* m_pDWriteFactory = nullptr;\r\n\r\n\tID3D11Resource* m_pWrappedBackBuffers[SWAPCHAIN_BUFFER_COUNT];\r\n\tID2D1Bitmap1* m_pD2DRenderTargets[SWAPCHAIN_BUFFER_COUNT];\r\n\r\n\tHWND m_Hwnd = nullptr;\r\n\tLONG m_WindowWidth = 0;\r\n\tLONG m_WindowHeight = 0;\r\n\r\n\tRenderContext m_RenderContext;\r\n\tPagingContext m_PagingContext;\r\n\r\n\tPagingWorkerThread* m_pWorkerThread = nullptr;\r\n\r\n\tDescriptorInfo m_DescriptorInfo;\r\n\r\n\tD3D12_FEATURE_DATA_D3D12_OPTIONS m_Options;\r\n\tD3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT m_GpuVaSupport;\r\n\r\n\tDXGI_QUERY_VIDEO_MEMORY_INFO m_LocalVideoMemoryInfo;\r\n\tDXGI_QUERY_VIDEO_MEMORY_INFO m_NonLocalVideoMemoryInfo;\r\n\r\n\tLIST_ENTRY m_ResourceListHead;\r\n\tLIST_ENTRY m_DynamicBufferListHead;\r\n\tLIST_ENTRY m_DynamicDescriptorHeapListHead;\r\n\tLIST_ENTRY m_UnreferencedResourceListHead;\r\n\tLIST_ENTRY m_UncommittedListHead;\r\n\tLIST_ENTRY m_CommitmentListHeads[MAX_MIP_COUNT];\r\n\r\n\tTextureShader m_TextureShader;\r\n\tColorShader m_ColorShader;\r\n\tconst Shader* m_pCurrentShader = nullptr;\r\n\r\n\tDWORD m_ThreadContextWaitHandleIndex = 0;\r\n\tUINT64 m_LocalBudgetOverride = 0;\r\n\r\n\t//\r\n\t// Camera\r\n\t//\r\n\tconst Camera* m_pSceneCamera = nullptr;\r\n\r\n\t//\r\n\t// Perf stats\r\n\t//\r\n\tUINT m_StatIndex = 0;\r\n\tLARGE_INTEGER m_PerformanceFrequency = {};\r\n\tLARGE_INTEGER m_LastFrameCounter = {};\r\n\tfloat m_StatTimeBetweenFrames[STATISTIC_COUNT];\r\n\tfloat m_StatRenderScene[STATISTIC_COUNT];\r\n\tfloat m_StatRenderUI[STATISTIC_COUNT];\r\n\tUINT m_PreviousPresentCount = 0;\r\n\tUINT m_PreviousRefreshCount = 0;\r\n\tUINT m_GlitchCount = 0;\r\n\r\n\tbool m_bUseSharedStagingSurface = false;\r\n\tbool m_bPresentOnVsync = true;\r\n\r\n\tHRESULT m_SimulatedRenderResult = S_OK;\r\n\tUINT m_NewAdapterIndex = 0xFFFFFFFF;\r\n\r\nprotected:\r\n\tDX12Framework();\r\n\tvirtual ~DX12Framework();\r\n\r\n\tvirtual HRESULT CreateDeviceIndependentState() = 0;\r\n\tvirtual HRESULT CreateDeviceDependentState() = 0;\r\n\tvirtual void DestroyDeviceIndependentState() = 0;\r\n\tvirtual void DestroyDeviceDependentState() = 0;\r\n\r\n\tvirtual HRESULT LoadAssets() = 0;\r\n\r\npublic:\r\n\t//\r\n\t// Rendering\r\n\t//\r\n\tvoid DrawRectangle(const RectF* pDest, float Stroke, const ColorF* pColor);\r\n\tvoid FillRectangle(const RectF* pDest, const ColorF* pColor);\r\n\tvoid FillRectangle(const RectF* pDest, const ColorF* pColor, Resource* pResource);\r\n\r\n\tvirtual HRESULT RenderScene(const RectF& ViewportBounds) = 0;\r\n\tvirtual HRESULT RenderUI() = 0;\r\n\r\n\tHRESULT Run();\r\n\tHRESULT UpdateVideoMemoryInfo();\r\n\tvoid LoadConfig(int argc, LPCSTR argv[]);\r\n\tvirtual bool HandleMessage(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);\r\n\r\n\t//\r\n\t// Resource loading\r\n\t//\r\n\tHRESULT CreateResource(LPCWSTR pFileName, Resource** ppResource);\r\n\r\n\t//\r\n\t// Worker Thread\r\n\t//\r\n\tinline void NotifyPagingWork(Resource* pResource)\r\n\t{\r\n\t\tm_pWorkerThread->EnqueueResource(pResource);\r\n\t}\r\n\tHRESULT PageInNextLevelOfDetail(Resource* pResource);\r\n\tbool TrimToTarget(ResourceTrimPass TrimLimit, UINT64 TargetUsage);\r\n\tinline bool TrimToBudget(ResourceTrimPass TrimLimit)\r\n\t{\r\n\t\treturn TrimToTarget(TrimLimit, m_LocalVideoMemoryInfo.Budget);\r\n\t}\r\n\r\n\t//\r\n\t// Camera\r\n\t//\r\n\tinline void SetSceneCamera(const Camera* pCamera)\r\n\t{\r\n\t\tm_pSceneCamera = pCamera;\r\n\t}\r\n\r\n\t//\r\n\t// Budget managemnt\r\n\t//\r\n\tinline void SetLocalBudgetOverride(UINT64 Value)\r\n\t{\r\n\t\tm_LocalBudgetOverride = Value;\r\n\t\tSetEvent(m_pWorkerThread->m_hWakeEvents[EWR_BudgetNotification]);\r\n\t}\r\n\r\n\tinline UINT64 GetLocalBudgetOverride() const\r\n\t{\r\n\t\treturn m_LocalBudgetOverride;\r\n\t}\r\n\r\n\t//\r\n\t// Statistics\r\n\t//\r\n\tinline UINT GetGlitchCount() const\r\n\t{\r\n\t\treturn m_GlitchCount;\r\n\t}\r\n\r\n\t//\r\n\t// Data Access\r\n\t//\r\n\tinline ID3D12Device* GetDevice()\r\n\t{\r\n\t\treturn m_pDevice;\r\n\t}\r\n\r\n\tinline IDXGIAdapter3* GetAdapter()\r\n\t{\r\n\t\treturn m_pDXGIAdapter;\r\n\t}\r\n\r\n\tinline ID3D12DescriptorHeap* GetRtvDescriptorHeap()\r\n\t{\r\n\t\treturn m_pRtvHeap;\r\n\t}\r\n\r\n\tinline const DXGI_QUERY_VIDEO_MEMORY_INFO& GetLocalVideoMemoryInfo() const\r\n\t{\r\n\t\treturn m_LocalVideoMemoryInfo;\r\n\t}\r\n\r\n\tinline const DXGI_QUERY_VIDEO_MEMORY_INFO& GetNonLocalVideoMemoryInfo() const\r\n\t{\r\n\t\treturn m_NonLocalVideoMemoryInfo;\r\n\t}\r\n\r\n\tinline DWORD GetThreadContextWaitHandleIndex() const\r\n\t{\r\n\t\treturn m_ThreadContextWaitHandleIndex;\r\n\t}\r\n\r\n\tbool IsUnderBudget() const\r\n\t{\r\n\t\treturn m_LocalVideoMemoryInfo.CurrentUsage <= m_LocalVideoMemoryInfo.Budget;\r\n\t}\r\n\r\n\tbool IsOverBudget() const\r\n\t{\r\n\t\treturn m_LocalVideoMemoryInfo.CurrentUsage > m_LocalVideoMemoryInfo.Budget;\r\n\t}\r\n\r\n\tbool IsWithinBudgetThreshold(UINT64 Size) const\r\n\t{\r\n\t\treturn m_LocalVideoMemoryInfo.CurrentUsage + Size <= m_LocalVideoMemoryInfo.Budget;\r\n\t}\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/List.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\ninline void InitializeListHead(LIST_ENTRY* pHead)\r\n{\r\n\tpHead->Flink = pHead->Blink = pHead;\r\n}\r\n\r\ninline void InsertHeadList(LIST_ENTRY* pHead, LIST_ENTRY* pEntry)\r\n{\r\n\tpEntry->Blink = pHead;\r\n\tpEntry->Flink = pHead->Flink;\r\n\r\n\tpHead->Flink->Blink = pEntry;\r\n\tpHead->Flink = pEntry;\r\n}\r\n\r\ninline void InsertTailList(LIST_ENTRY* pHead, LIST_ENTRY* pEntry)\r\n{\r\n\tpEntry->Flink = pHead;\r\n\tpEntry->Blink = pHead->Blink;\r\n\r\n\tpHead->Blink->Flink = pEntry;\r\n\tpHead->Blink = pEntry;\r\n}\r\n\r\ninline void RemoveEntryList(LIST_ENTRY* pEntry)\r\n{\r\n\tpEntry->Blink->Flink = pEntry->Flink;\r\n\tpEntry->Flink->Blink = pEntry->Blink;\r\n}\r\n\r\ninline LIST_ENTRY* RemoveHeadList(LIST_ENTRY* pHead)\r\n{\r\n\tLIST_ENTRY* pEntry = pHead->Flink;\r\n\tRemoveEntryList(pEntry);\r\n\treturn pEntry;\r\n}\r\n\r\ninline LIST_ENTRY* RemoveTailList(LIST_ENTRY* pHead)\r\n{\r\n\tLIST_ENTRY* pEntry = pHead->Blink;\r\n\tRemoveEntryList(pEntry);\r\n\treturn pEntry;\r\n}\r\n\r\ninline bool IsListEmpty(LIST_ENTRY* pEntry)\r\n{\r\n\treturn pEntry->Flink == pEntry;\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Log.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n#include <stdio.h>\r\n\r\n#define DISABLE_LOGGING 0\r\n\r\nstatic LPCSTR g_SeverityStrings[_ELS_COUNT] =\r\n{\r\n\t\"Message\",\r\n\t\"Warning\",\r\n\t\"Error\",\r\n\t\"Critical Error\"\r\n};\r\n\r\n_Use_decl_annotations_\r\nvoid LogMessage(LogSeverity Severity, LPCSTR pFormat, ...)\r\n{\r\n\tassert(Severity < _ELS_COUNT);\r\n\r\n#if(!DISABLE_LOGGING)\r\n\tva_list Args;\r\n\tva_start(Args, pFormat);\r\n\r\n\tprintf(\"%s: \", g_SeverityStrings[Severity]);\r\n\tvprintf(pFormat, Args);\r\n\tprintf(\"\\n\");\r\n#endif\r\n\r\n#if(_DEBUG)\r\n\tif (Severity >= ELS_Error)\r\n\t{\r\n\t\t__debugbreak();\r\n\t}\r\n#endif\r\n\r\n\tif (Severity == ELS_Critical)\r\n\t{\r\n\t\tExitProcess(0);\r\n\t}\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Log.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// The severity of a message being logged.\r\n//\r\nenum LogSeverity\r\n{\r\n\tELS_Message,\r\n\tELS_Warning,\r\n\tELS_Error,\r\n\tELS_Critical,\r\n\r\n\t_ELS_COUNT\r\n};\r\n\r\n//\r\n// Logs a formatted message to the command prompt with the specified severity.\r\n//\r\nvoid LogMessage(_In_range_(0, _ELS_COUNT-1) LogSeverity Severity, LPCSTR pFormat, ...);\r\n\r\n#define LOG_MESSAGE(Format, ...) LogMessage(ELS_Message, Format, __VA_ARGS__)\r\n#define LOG_WARNING(Format, ...) LogMessage(ELS_Warning, Format, __VA_ARGS__)\r\n#define LOG_ERROR(Format, ...) LogMessage(ELS_Error, Format, __VA_ARGS__)\r\n#define LOG_CRITICAL_ERROR(Format, ...) LogMessage(ELS_Critical, Format, __VA_ARGS__)\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Paging.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\n//\r\n// PagingWorkerThread\r\n//\r\n// The paging worker thread is the powerhouse of the sample. This is where all the streaming,\r\n// prefetching, trimming, etc occurs. The worker thread is responsible for creating and\r\n// mapping the heaps for the resource mipmaps as they are needed.\r\n//\r\n\r\nPagingWorkerThread::PagingWorkerThread(DX12Framework* pFramework) :\r\n\tm_pFramework(pFramework),\r\n\tm_hThread(nullptr),\r\n\tm_CurrentStatus(EWTS_Suspended),\r\n\tm_RequestedStatus(EWTS_Suspended),\r\n\tm_BudgetNotificationCookie(0)\r\n{\r\n\tInitializeListHead(&m_PrioritizationListHead);\r\n\tfor (int i = 0; i < _ERP_COUNT; ++i)\r\n\t{\r\n\t\tInitializeListHead(&m_PriorityQueues[i]);\r\n\t}\r\n\r\n\tInitializeCriticalSection(&m_PrioritizationListLock);\r\n\r\n\tZeroMemory(m_hWakeEvents, sizeof(m_hWakeEvents));\r\n}\r\n\r\nPagingWorkerThread::~PagingWorkerThread()\r\n{\r\n\tif (m_hThread != INVALID_HANDLE_VALUE)\r\n\t{\r\n\t\t//\r\n\t\t// Signal the paging thread to exit, and wait for completion. The paging thread\r\n\t\t// will drain (discard) any additional work and exit the thread's main function.\r\n\t\t//\r\n\t\tSetStatus(EWTS_Shutdown);\r\n\r\n\t\tWaitForSingleObject(m_hThread, INFINITE);\r\n\t\tCloseHandle(m_hThread);\r\n\t}\r\n\r\n\tfor (UINT i = 0; i < _countof(m_hWakeEvents); ++i)\r\n\t{\r\n\t\tif (m_hWakeEvents[i] != INVALID_HANDLE_VALUE)\r\n\t\t{\r\n\t\t\tCloseHandle(m_hWakeEvents[i]);\r\n\t\t}\r\n\t}\r\n\r\n\tif (m_hStatusChangeEvent != INVALID_HANDLE_VALUE)\r\n\t{\r\n\t\tCloseHandle(m_hStatusChangeEvent);\r\n\t}\r\n\r\n\tif (m_BudgetNotificationCookie != 0)\r\n\t{\r\n\t\tm_pFramework->GetAdapter()->UnregisterVideoMemoryBudgetChangeNotification(m_BudgetNotificationCookie);\r\n\t}\r\n}\r\n\r\nHRESULT PagingWorkerThread::Init()\r\n{\r\n\tHRESULT hr;\r\n\r\n\tfor (UINT i = 0; i < _countof(m_hWakeEvents); ++i)\r\n\t{\r\n\t\tHANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\t\tif (hEvent == nullptr)\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create paging wake event handle, Error=0x%.8x\", GetLastError());\r\n\t\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t\t}\r\n\r\n\t\tm_hWakeEvents[i] = hEvent;\r\n\t}\r\n\r\n\tm_hStatusChangeEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\tif (m_hStatusChangeEvent == nullptr)\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create status change event, Error=0x%.8x\", GetLastError());\r\n\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\tm_hThread = CreateThread(nullptr, 0, PagingWorkerThread::ThreadEntry, this, 0, nullptr);\r\n\tif (m_hThread == nullptr)\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to create paging thread, Error=0x%.8x\", GetLastError());\r\n\t\treturn HRESULT_FROM_WIN32(GetLastError());\r\n\t}\r\n\r\n\t//\r\n\t// Register for a budget change notification from the graphics kernel. This event will be\r\n\t// signaled by kernel any time the process budget changes. The application is then responsible\r\n\t// for responding to that notification, either by trimming resources in the event that the\r\n\t// budget is lowered, or to prefetch more data if the budget increases.\r\n\t//\r\n\tIDXGIAdapter3* pDXGIAdapter = m_pFramework->GetAdapter();\r\n\thr = pDXGIAdapter->RegisterVideoMemoryBudgetChangeNotificationEvent(m_hWakeEvents[EWR_BudgetNotification], &m_BudgetNotificationCookie);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_ERROR(\"Failed to register budget change notification event, hr=0x%.8x\", hr);\r\n\t\treturn hr;\r\n\t}\r\n\r\n\tassert(m_BudgetNotificationCookie != 0);\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid PagingWorkerThread::Flush()\r\n{\r\n\tbool bMoreWork = true;\r\n\twhile (bMoreWork)\r\n\t{\r\n\t\tProcessSubmission(&bMoreWork);\r\n\t}\r\n}\r\n\r\nDWORD CALLBACK PagingWorkerThread::ThreadEntry(void* pArg)\r\n{\r\n\tPagingWorkerThread* pWorkerThread = (PagingWorkerThread*)pArg;\r\n\r\n\t//\r\n\t// Create a waitable event in TLS for the paging thread. This lets us wait on rendering\r\n\t// fences to complete before trimming visible mipmaps.\r\n\t//\r\n\tHANDLE hFlushEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\tif (!hFlushEvent)\r\n\t{\r\n\t\tLOG_CRITICAL_ERROR(\"Failed to create thread wait event, Error=0x%.8x\", GetLastError());\r\n\t}\r\n\r\n\tTlsSetValue(pWorkerThread->m_pFramework->GetThreadContextWaitHandleIndex(), (void*)hFlushEvent);\r\n\r\n\t//\r\n\t// Run worker thread until we are issued a shutdown request.\r\n\t//\r\n\tDWORD Result = pWorkerThread->Run();\r\n\r\n\tCloseHandle(hFlushEvent);\r\n\r\n\treturn Result;\r\n}\r\n\r\nDWORD PagingWorkerThread::Run()\r\n{\r\n\tbool bMoreWork = false;\r\n\r\n\tfor (;;)\r\n\t{\r\n\t\t//\r\n\t\t// By using a timeout of 0 when there is more work, it allows us to detect when\r\n\t\t// an event was signaled and needs processing, but otherwise returns immediately\r\n\t\t// if there is not. Otherwise we will starve notification requests (such as a\r\n\t\t// worker thread state change to 'shutdown'), which will block for long periods\r\n\t\t// of time.\r\n\t\t//\r\n\t\tDWORD Timeout = bMoreWork ? 0 : INFINITE;\r\n\t\tDWORD WaitResult = WaitForMultipleObjects(_countof(m_hWakeEvents), m_hWakeEvents, FALSE, Timeout);\r\n\r\n\t\tif (WaitResult == WAIT_FAILED)\r\n\t\t{\r\n\t\t\tLOG_CRITICAL_ERROR(\"Worker thread wait failed, Error=0x%.8x\", GetLastError());\r\n\t\t}\r\n\t\telse if (WaitResult == WAIT_TIMEOUT)\r\n\t\t{\r\n\t\t\tassert(bMoreWork);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// Get the reason for signaling the worker thread.\r\n\t\t\t//\r\n\t\t\tWakeReason Reason = static_cast<WakeReason>(WaitResult - WAIT_OBJECT_0);\r\n\r\n\t\t\tif (Reason == EWR_ChangeStatus)\r\n\t\t\t{\r\n\t\t\t\tLOG_MESSAGE(\"WT: Status change request from %d to %d\", m_CurrentStatus, m_RequestedStatus);\r\n\r\n\t\t\t\tProcessStatusChangeRequest();\r\n\t\t\t\tif (m_CurrentStatus == EWTS_Shutdown)\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if (Reason == EWR_Submission)\r\n\t\t\t{\r\n\t\t\t\tLOG_MESSAGE(\"WT: New submission\");\r\n\t\t\t\tbMoreWork = true;\r\n\t\t\t}\r\n\t\t\telse if (Reason == EWR_BudgetNotification)\r\n\t\t\t{\r\n\t\t\t\tLOG_MESSAGE(\"WT: Budget change notification\");\r\n\t\t\t\tProcessBudgetChangeNotification();\r\n\t\t\t\tbMoreWork = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tassert(false);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (bMoreWork)\r\n\t\t{\r\n\t\t\t//\r\n\t\t\t// Reprioritize any resources which may have visibility changes.\r\n\t\t\t//\r\n\t\t\tReprioritizeResources();\r\n\r\n\t\t\t//\r\n\t\t\t// Process the next highest priority paging operation.\r\n\t\t\t//\r\n\t\t\tProcessSubmission(&bMoreWork);\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid PagingWorkerThread::DiscardPendingWork()\r\n{\r\n\tfor (int i = 0; i < _ERP_COUNT; ++i)\r\n\t{\r\n\t\tInitializeListHead(&m_PriorityQueues[i]);\r\n\t}\r\n}\r\n\r\nvoid PagingWorkerThread::ProcessStatusChangeRequest()\r\n{\r\n\tassert(m_CurrentStatus != EWTS_Shutdown);\r\n\r\n\tif (m_CurrentStatus != m_RequestedStatus)\r\n\t{\r\n\t\tif (m_RequestedStatus == EWTS_Shutdown)\r\n\t\t{\r\n\t\t\tDiscardPendingWork();\r\n\t\t}\r\n\t}\r\n\r\n\tLOG_MESSAGE(\"WT: Status successfully changed from %d to %d\", m_CurrentStatus, m_RequestedStatus);\r\n\r\n\tm_CurrentStatus = m_RequestedStatus;\r\n\tSetEvent(m_hStatusChangeEvent);\r\n}\r\n\r\nvoid PagingWorkerThread::ProcessSubmission(bool* pMoreWork)\r\n{\r\n\t*pMoreWork = true;\r\n\r\n\t//\r\n\t// Select the highest priority paging operation from the priority queues. SelectResource\r\n\t// may return null if there are no entries, or if none of the operations can be selected\r\n\t// (e.g. paging in the resources may go over the budget)\r\n\t//\r\n\tResource* pResource = SelectResource();\r\n\tif (pResource == nullptr)\r\n\t{\r\n\t\t*pMoreWork = false;\r\n\t\treturn;\r\n\t}\r\n\r\n\t//\r\n\t// Process the request.\r\n\t//\r\n\tHRESULT hr = m_pFramework->PageInNextLevelOfDetail(pResource);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\t*pMoreWork = false;\r\n\t}\r\n\r\n\t//\r\n\t// After the paging operation completes, we need to reprioritize this specific resource.\r\n\t//\r\n\tPrioritizeResource(pResource);\r\n\r\n\t//\r\n\t// Update the video memory info to see if we need to trim anything. This may be the case\r\n\t// if the kernel recalculated the budget while processing the operation, or if we paged in\r\n\t// a critical resource (such as a packed mipmap), which can let us go over budget.\r\n\t//\r\n\tm_pFramework->UpdateVideoMemoryInfo();\r\n\tif (m_pFramework->IsOverBudget())\r\n\t{\r\n\t\tm_pFramework->TrimToBudget(pResource->TrimLimit);\r\n\t}\r\n}\r\n\r\nvoid PagingWorkerThread::ProcessBudgetChangeNotification()\r\n{\r\n\tHRESULT hr;\r\n\r\n\t//\r\n\t// Update our budgeting information, and trim our usage until it is under the budget.\r\n\t//\r\n\thr = m_pFramework->UpdateVideoMemoryInfo();\r\n\tif (SUCCEEDED(hr))\r\n\t{\r\n\t\tDXGI_QUERY_VIDEO_MEMORY_INFO VideoMemoryInfo = m_pFramework->GetLocalVideoMemoryInfo();\r\n\t\tif (VideoMemoryInfo.CurrentUsage > VideoMemoryInfo.Budget)\r\n\t\t{\r\n\t\t\tm_pFramework->TrimToBudget(ERTP_Visible);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PagingWorkerThread::SetStatus(WorkerThreadStatus Status)\r\n{\r\n\tm_RequestedStatus = Status;\r\n\tSetEvent(m_hWakeEvents[EWR_ChangeStatus]);\r\n\r\n\tWaitForSingleObject(m_hStatusChangeEvent, INFINITE);\r\n}\r\n\r\nvoid PagingWorkerThread::EnqueueResource(Resource* pResource)\r\n{\r\n\t//\r\n\t// Take the prioritization lock as we insert resources into the prioritization list.\r\n\t// This synchronizes the rendering thread queuing work items with the paging thread\r\n\t// prioritizing it.\r\n\t//\r\n\tEnterCriticalSection(&m_PrioritizationListLock);\r\n\r\n\tif (pResource->PrioritizationEntry.Flink != nullptr)\r\n\t{\r\n\t\tRemoveEntryList(&pResource->PrioritizationEntry);\r\n\t}\r\n\tInsertTailList(&m_PrioritizationListHead, &pResource->PrioritizationEntry);\r\n\r\n\tLeaveCriticalSection(&m_PrioritizationListLock);\r\n\r\n\tSetEvent(m_hWakeEvents[EWR_Submission]);\r\n}\r\n\r\nvoid PagingWorkerThread::ReprioritizeResources()\r\n{\r\n\tEnterCriticalSection(&m_PrioritizationListLock);\r\n\twhile (!IsListEmpty(&m_PrioritizationListHead))\r\n\t{\r\n\t\tLIST_ENTRY* pEntry = RemoveHeadList(&m_PrioritizationListHead);\r\n\t\tResource* pResource = CONTAINING_RECORD(pEntry, Resource, PrioritizationEntry);\r\n\t\tpResource->PrioritizationEntry.Flink = nullptr;\r\n\r\n\t\tPrioritizeResource(pResource);\r\n\t}\r\n\tLeaveCriticalSection(&m_PrioritizationListLock);\r\n}\r\n\r\nvoid PagingWorkerThread::PrioritizeResource(Resource* pResource)\r\n{\r\n\tUINT8 MostDetailedMipResident = pResource->MostDetailedMipResident;\r\n\tUINT8 VisibleMip = pResource->VisibleMip;\r\n\tUINT8 PrefetchMip = pResource->PrefetchMip;\r\n\r\n\tif (pResource->PagingEntry.Flink != nullptr)\r\n\t{\r\n\t\tRemoveEntryList(&pResource->PagingEntry);\r\n\t\tpResource->PagingEntry.Flink = nullptr;\r\n\t}\r\n\r\n\tbool AnyPackedMipsMissing = MostDetailedMipResident > GetLeastDetailedMipHeapIndex(pResource);\r\n\tbool IsInPrefetchZone = (PrefetchMip != UNDEFINED_MIPMAP_INDEX);\r\n\r\n\tif (AnyPackedMipsMissing && IsInPrefetchZone)\r\n\t{\r\n\t\t//\r\n\t\t// If the resource has not been loaded at all, and it's in the prefetch zone,\r\n\t\t// consider it very high priority. We will not only add it to the high priority\r\n\t\t// queue, but also push it in at the front to ensure this occurs before anything\r\n\t\t// else. We want to make sure the user has *something* to see, even if it's just\r\n\t\t// the 1x1 mipmap of a rough color.\r\n\t\t//\r\n\t\tInsertTailList(&m_PriorityQueues[ERP_VeryHigh], &pResource->PagingEntry);\r\n\t\tpResource->TrimLimit = ERTP_Visible;\r\n\t\tpResource->bIgnoreBudget = true;\r\n\t}\r\n\telse if (IsMoreDetailedMip(MostDetailedMipResident, VisibleMip))\r\n\t{\r\n\t\t//\r\n\t\t// The user has requested a visible mipmap that is of a greater detail than the\r\n\t\t// one currently resident. This is high priority, because we want what's on screen\r\n\t\t// to be visually correct.\r\n\t\t//\r\n\t\tInsertTailList(&m_PriorityQueues[ERP_High], &pResource->PagingEntry);\r\n\t\tpResource->TrimLimit = ERTP_NonVisible;\r\n\t}\r\n\telse if (AnyPackedMipsMissing)\r\n\t{\r\n\t\t//\r\n\t\t// The resource has not been loaded, but is a somewhat safe distance away from the\r\n\t\t// camera to be considered a lower priority. We will make sure that the stuff the user\r\n\t\t// sees on screen gets loaded before this.\r\n\t\t//\r\n\t\tInsertHeadList(&m_PriorityQueues[ERP_Medium], &pResource->PagingEntry);\r\n\t\tpResource->TrimLimit = ERTP_Visible;\r\n\t\tpResource->bIgnoreBudget = true;\r\n\t}\r\n\telse if (IsMoreDetailedMip(MostDetailedMipResident, PrefetchMip))\r\n\t{\r\n\t\t//\r\n\t\t// This is a proximity prefetched mipmap. The user cannot see this mipmap yet, but it\r\n\t\t// is nearby. We want to reduce any texture popping that may occur as the user scrolls\r\n\t\t//\r\n\t\tInsertTailList(&m_PriorityQueues[ERP_Medium], &pResource->PagingEntry);\r\n\t\tpResource->TrimLimit = ERTP_NonPrefetchable;\r\n\r\n\t\tassert(PrefetchMip != UNDEFINED_MIPMAP_INDEX);\r\n\t}\r\n\telse if (MostDetailedMipResident != 0)\r\n\t{\r\n\t\t//\r\n\t\t// This texture is not near the user, but we are under our budget and we haven't loaded\r\n\t\t// all the mipmaps for this texture yet. This is a low priority work item that will\r\n\t\t// occur after everything else, but will help guarantee that the user gets a smooth\r\n\t\t// experience at all times by prefetching the texture data prior to being needed.\r\n\t\t//\r\n\t\tInsertTailList(&m_PriorityQueues[ERP_Low], &pResource->PagingEntry);\r\n\t\tpResource->TrimLimit = ERTP_None;\r\n\t}\r\n}\r\n\r\n//\r\n// SelectResource will look at each of the priority queues and select the best operation\r\n// to process. Unless marked otherwise, paging operations will not be selected if the\r\n// resulting paging operation is within a specific threshold of going over the budget.\r\n//\r\nResource* PagingWorkerThread::SelectResource()\r\n{\r\n\tfor (int i = 0; i < _ERP_COUNT; ++i)\r\n\t{\r\n\t\t//\r\n\t\t// A small bias is applied to the current local budget to help prevent resources from\r\n\t\t// going over. The size calculated by the driver may differ slightly from the size\r\n\t\t// calculated by the kernel (due to various alignment and segment restrictions), and so\r\n\t\t// a buffer is used to prevent the operation from accidentally going over.\r\n\t\t//\r\n\t\t// The bias is determined by the priority of the operation. There is a 1MB minimum\r\n\t\t// bias as a \"safety zone,\" and an 8MB buffer for each priority after that.\r\n\t\t//\r\n\t\tUINT64 BudgetBias = _1MB + _8MB * i;\r\n\r\n\t\tif (!IsListEmpty(&m_PriorityQueues[i]))\r\n\t\t{\r\n\t\t\tLIST_ENTRY* pEntry = m_PriorityQueues[i].Flink;\r\n\t\t\tResource* pResource = CONTAINING_RECORD(pEntry, Resource, PagingEntry);\r\n\r\n\t\t\t//\r\n\t\t\t// The paging thread will only page in one mipmap at a time to be fair to all\r\n\t\t\t// resources. This allows resources to be selected in a round-robin sequence,\r\n\t\t\t// preventing prefetching of low priority allocations to delay visibility changes\r\n\t\t\t// from reprioritizing operations.\r\n\t\t\t//\r\n\t\t\t// Even though the paging operations are asycnhronous from rendering (i.e. they\r\n\t\t\t// should not impact performance), it is still possible for the paging operations,\r\n\t\t\t// if long enough, to block loading mipmaps that are otherwise important. For example,\r\n\t\t\t// loading a large 8Kx8K mipmap far off screen could cause a significant enough delay\r\n\t\t\t// to prevent a mipmap on screen from being loaded by the time it is actually visible.\r\n\t\t\t//\r\n\t\t\tUINT NextMip = IncreaseMipQuality(pResource->MostDetailedMipResident, 1);\r\n\t\t\tUINT64 MipSize = 0;\r\n\t\t\tif (NextMip < pResource->PackedMipHeapIndex)\r\n\t\t\t{\r\n\t\t\t\tMipSize = GetNonPackedMipSize(pResource, NextMip);\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\t\t\t// When prioritizing operations, packed mipmaps are considered critical operations,\r\n\t\t\t// and should never be restricted by the budget. This is because packed mipmaps represent\r\n\t\t\t// the application's minimum working set. Although the application should try as hard as\r\n\t\t\t// possible to remain under its budget, every application will have a minimum requirement\r\n\t\t\t// to run. For this sample, packed mipmaps are considered the lowest quality that will\r\n\t\t\t// be tolerated. It is not expected for packed mipmaps to account for a significant amount\r\n\t\t\t// of space, since most will fit within a single 64KB tile. This means the rough estimate\r\n\t\t\t// cost of all packed mipmaps is 64KB*NumResources.\r\n\t\t\t//\r\n\t\t\tif (!pResource->bIgnoreBudget)\r\n\t\t\t{\r\n\t\t\t\tDXGI_QUERY_VIDEO_MEMORY_INFO MemoryInfo = m_pFramework->GetLocalVideoMemoryInfo();\r\n\t\t\t\tUINT64 TargetUsage = MemoryInfo.Budget - (MipSize + BudgetBias);\r\n\r\n\t\t\t\tif (!m_pFramework->IsWithinBudgetThreshold(MipSize + BudgetBias))\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!m_pFramework->TrimToTarget(pResource->TrimLimit, TargetUsage))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tRemoveEntryList(pEntry);\r\n\t\t\tpEntry->Flink = nullptr;\r\n\t\t\tpResource->bIgnoreBudget = false;\r\n\r\n\t\t\treturn pResource;\r\n\t\t}\r\n\t}\r\n\r\n\treturn nullptr;\r\n}\r\n\r\n//\r\n// PagingContext\r\n//\r\n#define PAGING_CONTEXT_COMMAND_LIST_TYPE D3D12_COMMAND_LIST_TYPE_COPY\r\n\r\nPagingContext::PagingContext(DX12Framework* pFramework) :\r\n\tContext(pFramework)\r\n{\r\n}\r\n\r\nPagingContext::~PagingContext()\r\n{\r\n}\r\n\r\nHRESULT PagingContext::CreateDeviceDependentState()\r\n{\r\n\tHRESULT hr;\r\n\r\n\thr = Context::CreateDeviceDependentState(PAGING_CONTEXT_COMMAND_LIST_TYPE);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize paging context\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\ttry\r\n\t{\r\n\t\t//\r\n\t\t// The paging context always has only a single frame, since we will only process\r\n\t\t// one paging operation at a time.\r\n\t\t//\r\n\t\tPagingFrame* pFrame = new PagingFrame();\r\n\r\n\t\thr = InitializeFrame(pFrame, PAGING_CONTEXT_COMMAND_LIST_TYPE);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_WARNING(\"Failed to initialize frame object, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\t//\r\n\t\t// Frames are inserted into the free frame list on creation, so the destructor\r\n\t\t// will be able to clean up any created frames.\r\n\t\t//\r\n\t\tLOG_ERROR(\"Failed to allocate frame tracking structure\");\r\n\t\treturn E_OUTOFMEMORY;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid PagingContext::DestroyDeviceDependentState()\r\n{\r\n\t//\r\n\t// Flush all pending operations before we tear down the device dependent state of the context.\r\n\t//\r\n\tFlush();\r\n\r\n\tassert(IsListEmpty(&m_ActiveFrameListHead));\r\n\r\n\tLIST_ENTRY* pEntry = m_FreeFrameListHead.Flink;\r\n\r\n\twhile (pEntry != &m_FreeFrameListHead)\r\n\t{\r\n\t\tPagingFrame* pFrame = static_cast<PagingFrame*>(pEntry);\r\n\t\tpEntry = pEntry->Flink;\r\n\r\n\t\tRemoveEntryList(pFrame);\r\n\r\n\t\tSafeRelease(pFrame->pCommandAllocator);\r\n\t\tSafeRelease(pFrame->pCommandList);\r\n\r\n\t\tSafeDelete(pFrame);\r\n\t}\r\n\r\n\tContext::DestroyDeviceDependentState();\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Paging.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// Specifies the reason that the paging thread was woken up.\r\n//\r\nenum WakeReason\r\n{\r\n\t// Indicates that another thread has requested that the paging thread change\r\n\t// states, such as shutting down to exit the process.\r\n\tEWR_ChangeStatus,\r\n\r\n\t// Indicates that the state of one or more resources has changed, and the\r\n\t// worker thread should reprioritize the resources and perform more paging work.\r\n\tEWR_Submission,\r\n\r\n\t// Indicates that the graphics kernel has changed this process's memory budget,\r\n\t// and the worker thread may need to react accordingly. If the budget has\r\n\t// increased, the worker thread may retry failed paging operations (such as\r\n\t// prefetching) that failed because the operaiton would bring the process\r\n\t// over budget. If the budget has decreased, the paging thread must trim\r\n\t// resources to remain under the budget.\r\n\tEWR_BudgetNotification,\r\n\r\n\t_EWR_COUNT\r\n};\r\n\r\n//\r\n// The current status of the worker thread.\r\n//\r\nenum WorkerThreadStatus\r\n{\r\n\tEWTS_Suspended,\r\n\tEWTS_Running,\r\n\tEWTS_Shutdown,\r\n\r\n\t_EWTS_COUNT\r\n};\r\n\r\n//\r\n// The paging worker thread is the powerhouse behind all paging and texture streaming\r\n// for the sample.\r\n//\r\n// The worker thread's primary goal is to stream texture data for the rendering pipeline\r\n// asynchronously, and prioritize video memory based on the new budgetting information\r\n// present in DXGI.\r\n//\r\nclass PagingWorkerThread\r\n{\r\nprivate:\r\n\tfriend class DX12Framework;\r\n\r\n\tDX12Framework* m_pFramework;\r\n\r\n\tWorkerThreadStatus m_CurrentStatus;\r\n\tWorkerThreadStatus m_RequestedStatus;\r\n\r\n\t//\r\n\t// Thread management\r\n\t//\r\n\tHANDLE m_hThread;\r\n\tHANDLE m_hWakeEvents[_EWR_COUNT];\r\n\tHANDLE m_hStatusChangeEvent;\r\n\tDWORD m_BudgetNotificationCookie;\r\n\r\n\t// Lock for accessing the prioritization list head, which is accessed by both\r\n\t// the rendering and paging threads.\r\n\tCRITICAL_SECTION m_PrioritizationListLock;\r\n\r\n\t// A list of unprioritized resources. A resource must be prioritized before\r\n\t// any paging operations can occur, so that the paging thread knows how to process\r\n\t// the resource.\r\n\tLIST_ENTRY m_PrioritizationListHead;\r\n\r\n\t// An array of priority-ordered linked list heads. The worker thread will process\r\n\t// resources in these arrays in strict order.\r\n\tLIST_ENTRY m_PriorityQueues[_ERP_COUNT];\r\n\r\nprivate:\r\n\tPagingWorkerThread(DX12Framework* pFramework);\r\n\t~PagingWorkerThread();\r\n\r\n\tHRESULT Init();\r\n\r\n\tvoid Flush();\r\n\tvoid DiscardPendingWork();\r\n\tDWORD Run();\r\n\r\n\tvoid EnqueueResource(Resource* pResource);\r\n\tvoid ReprioritizeResources();\r\n\tvoid PrioritizeResource(Resource* pResource);\r\n\tResource* SelectResource();\r\n\r\n\tvoid ProcessStatusChangeRequest();\r\n\tvoid ProcessSubmission(bool* pMoreWork);\r\n\tvoid ProcessBudgetChangeNotification();\r\n\r\n\tvoid SetStatus(WorkerThreadStatus Status);\r\n\r\n\tstatic DWORD CALLBACK ThreadEntry(void* pArg);\r\n};\r\n\r\n//\r\n// A paging frame does not have any special state.\r\n//\r\nstruct PagingFrame : Frame\r\n{\r\n};\r\n\r\n//\r\n// The paging context is a specialization of the Context object that creates a\r\n// unique D3D12 command queue and set of frames for paging operations. The command\r\n// queue is created as a copy command queue, which can map to paging engines on\r\n// the graphics hardware. In addition to the scheduling granularity offered by\r\n// the graphics kernel scheduler, being mapped to a hardware paging engine allows\r\n// the paging operations to run completely in parallel with 3D graphics work\r\n// submitted on the 3D engines.\r\n//\r\nclass PagingContext : public Context\r\n{\r\npublic:\r\n\tPagingContext(DX12Framework* pFramework);\r\n\t~PagingContext();\r\n\r\n\tHRESULT CreateDeviceDependentState();\r\n\tvoid DestroyDeviceDependentState();\r\n\r\n\tinline PagingFrame* GetCurrentFrame() const\r\n\t{\r\n\t\treturn static_cast<PagingFrame*>(m_pCurrentFrame);\r\n\t}\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Render.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\n//\r\n// Render contexts should use direct command lists to execute on the GPU's 3D engine.\r\n//\r\n#define RENDER_CONTEXT_COMMAND_LIST_TYPE D3D12_COMMAND_LIST_TYPE_DIRECT\r\n\r\nRenderContext::RenderContext(DX12Framework* pFramework) :\r\n\tContext(pFramework)\r\n{\r\n}\r\n\r\nRenderContext::~RenderContext()\r\n{\r\n}\r\n\r\nHRESULT RenderContext::CreateDeviceDependentState(UINT FrameCount)\r\n{\r\n\tHRESULT hr;\r\n\r\n\thr = Context::CreateDeviceDependentState(RENDER_CONTEXT_COMMAND_LIST_TYPE);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to initialize render context\");\r\n\t\treturn hr;\r\n\t}\r\n\r\n\ttry\r\n\t{\r\n\t\t//\r\n\t\t// Create the frame tracking objects for the context.\r\n\t\t//\r\n\t\tfor (UINT i = 0; i < FrameCount; ++i)\r\n\t\t{\r\n\t\t\tRenderFrame* pFrame = new RenderFrame();\r\n\r\n\t\t\thr = InitializeFrame(pFrame, RENDER_CONTEXT_COMMAND_LIST_TYPE);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_WARNING(\"Failed to initialize frame object, hr=0x%.8x\", hr);\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = m_pFramework->InitDynamicBuffer(&pFrame->VertexBuffer);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_WARNING(\"Failed to initialize dynamic vertex buffer\");\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = m_pFramework->InitDynamicBuffer(&pFrame->ConstantBuffer);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_WARNING(\"Failed to initialize dynamic constant buffer\");\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\thr = m_pFramework->InitDynamicDescriptorHeap(&pFrame->SrvCbvHeap);\r\n\t\t\tif (FAILED(hr))\r\n\t\t\t{\r\n\t\t\t\tLOG_WARNING(\"Failed to initialize dynamic descriptor heap\");\r\n\t\t\t\treturn hr;\r\n\t\t\t}\r\n\r\n\t\t\tInitializeListHead(&pFrame->PendingBufferListHead);\r\n\t\t\tInitializeListHead(&pFrame->PendingHeapListHead);\r\n\t\t}\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\t//\r\n\t\t// Frames are inserted into the free frame list on creation, so the destructor\r\n\t\t// will be able to clean up any created frames.\r\n\t\t//\r\n\t\tLOG_ERROR(\"Failed to allocate frame tracking structure\");\r\n\t\treturn E_OUTOFMEMORY;\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid RenderContext::DestroyDeviceDependentState()\r\n{\r\n\tFlush();\r\n\r\n\tassert(IsListEmpty(&m_ActiveFrameListHead));\r\n\r\n\tLIST_ENTRY* pEntry = m_FreeFrameListHead.Flink;\r\n\r\n\twhile (pEntry != &m_FreeFrameListHead)\r\n\t{\r\n\t\tRenderFrame* pFrame = static_cast<RenderFrame*>(pEntry);\r\n\t\tpEntry = pEntry->Flink;\r\n\r\n\t\tRemoveEntryList(pFrame);\r\n\r\n\t\tSafeRelease(pFrame->pCommandAllocator);\r\n\t\tSafeRelease(pFrame->pCommandList);\r\n\t\tm_pFramework->DestroyDynamicBuffer(&pFrame->VertexBuffer);\r\n\t\tm_pFramework->DestroyDynamicBuffer(&pFrame->ConstantBuffer);\r\n\t\tm_pFramework->DestroyDynamicDescriptorHeap(&pFrame->SrvCbvHeap);\r\n\r\n\t\tSafeDelete(pFrame);\r\n\t}\r\n\r\n\tContext::DestroyDeviceDependentState();\r\n}\r\n\r\nvoid RenderContext::CloseBuffer(Buffer* pBuffer)\r\n{\r\n\tRenderFrame* pFrame = (RenderFrame*)m_pCurrentFrame;\r\n\tif (pFrame == nullptr)\r\n\t{\r\n\t\tLOG_CRITICAL_ERROR(\"Trying to close a buffer for renaming outside the context of a frame\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tInsertTailList(&pFrame->PendingBufferListHead, pBuffer);\r\n}\r\n\r\nvoid RenderContext::CloseHeap(DescriptorHeap* pHeap)\r\n{\r\n\tRenderFrame* pFrame = (RenderFrame*)m_pCurrentFrame;\r\n\tif (pFrame == nullptr)\r\n\t{\r\n\t\tLOG_CRITICAL_ERROR(\"Trying to close a buffer for renaming outside the context of a frame\");\r\n\t\treturn;\r\n\t}\r\n\r\n\tInsertTailList(&pFrame->PendingHeapListHead, pHeap);\r\n}\r\n\r\nvoid RenderContext::RetireFrame(Frame* pFrame)\r\n{\r\n\tRenderFrame* pRenderFrame = (RenderFrame*)pFrame;\r\n\r\n\tLIST_ENTRY* pEntry;\r\n\r\n\tpEntry = RemoveHeadList(&pRenderFrame->PendingBufferListHead);\r\n\twhile (pEntry != &pRenderFrame->PendingBufferListHead)\r\n\t{\r\n\t\tBuffer* pBuffer = (Buffer*)pEntry;\r\n\t\tm_pFramework->RetireVersionedBuffer(pBuffer);\r\n\r\n\t\tpEntry = RemoveHeadList(&pRenderFrame->PendingBufferListHead);\r\n\t}\r\n\r\n\tpEntry = RemoveHeadList(&pRenderFrame->PendingHeapListHead);\r\n\twhile (pEntry != &pRenderFrame->PendingHeapListHead)\r\n\t{\r\n\t\tDescriptorHeap* pDescriptorHeap = (DescriptorHeap*)pEntry;\r\n\t\tm_pFramework->RetireVersionedDescriptorHeap(pDescriptorHeap);\r\n\r\n\t\tpEntry = RemoveHeadList(&pRenderFrame->PendingHeapListHead);\r\n\t}\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Render.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// A render frame has additional information used to track objects and data used\r\n// during rendering operations. This is limited mostly to buffers and heaps which\r\n// can grow dynamically when they run out of space. For example, if the vertex\r\n// buffer hits its capacity while generating geometry, a new vertex buffer can be\r\n// generating in a process called 'renaming,' allowing us to track the old buffer,\r\n// while using the new one. Once the rendering frame is retired, the renamed buffers\r\n// are then released back to the system to prevent memory leaks.\r\n//\r\nstruct RenderFrame : Frame\r\n{\r\n\tLIST_ENTRY PendingBufferListHead;\r\n\tLIST_ENTRY PendingHeapListHead;\r\n\r\n\tDynamicBuffer VertexBuffer;\r\n\tDynamicBuffer ConstantBuffer;\r\n\tDynamicDescriptorHeap SrvCbvHeap;\r\n\r\n\tD3D12_GPU_VIRTUAL_ADDRESS CameraAddress;\r\n};\r\n\r\n//\r\n// The render context is a specialization of the Context which creates a unique\r\n// command queue for 3D rendering workloads, which can run asynchronously from\r\n// paging operations.\r\n//\r\nclass RenderContext : public Context\r\n{\r\nprotected:\r\n\tvirtual void RetireFrame(Frame* pFrame);\r\n\r\npublic:\r\n\tRenderContext(DX12Framework* pFramework);\r\n\t~RenderContext();\r\n\r\n\tHRESULT CreateDeviceDependentState(UINT MaxFrameCount);\r\n\tvoid DestroyDeviceDependentState();\r\n\r\n\tvoid CloseBuffer(Buffer* pBuffer);\r\n\tvoid CloseHeap(DescriptorHeap* pHeap);\r\n\r\n\tinline RenderFrame* GetCurrentFrame() const\r\n\t{\r\n\t\treturn static_cast<RenderFrame*>(m_pCurrentFrame);\r\n\t}\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Resource.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// Used to describe each mip index.\r\n// Each resource will have one MipDescription per standard mipmap, and one shared\r\n// MipDescription for all packed mips.\r\n//\r\nstruct MipDescription\r\n{\r\n\tUINT WidthInTiles;\r\n\tUINT HeightInTiles;\r\n\tUINT HeapStartIndex;\r\n};\r\n\r\n//\r\n// Stores information about each mipmap in a resource. This includes tile information,\r\n// an array of heaps backing the resource, and the last rendering fence which\r\n// referenced this specific mipmap.\r\n// Each mipmap may be backed by multiple heaps, currently defined in 16MB chunks.\r\n// Breaking large allocations into smaller chunks helps reduce pressure in the kernel's\r\n// memory manager when finding space to place the resource in VRAM, and reduces overall\r\n// memory fragmentation.\r\n//\r\nstruct ResourceMip\r\n{\r\n\tMipDescription Desc;\r\n\tID3D12Heap** ppHeaps;\r\n\tUINT64 ReferenceFence;\r\n};\r\n\r\n//\r\n// Describes the priority which the worker thread uses to page in a resource. A\r\n// higher priority resource will always be paged in before a lower priority resource.\r\n//\r\nenum ResourcePriority\r\n{\r\n\tERP_VeryHigh,\r\n\tERP_High,\r\n\tERP_Medium,\r\n\tERP_Low,\r\n\t_ERP_COUNT\r\n};\r\n\r\n//\r\n// This enum is used to restrict the extent of trimming operations when the process\r\n// is over its local memory budget. This helps ensure that lower priority resources not\r\n// cause higher priority resources to be trimmed, and prevents the worker thread from\r\n// recursively paging in new content.\r\n// e.g. a high quality prefetched mip will not trim a mipmap that is currently\r\n// visible on the screen.\r\n//\r\nenum ResourceTrimPass\r\n{\r\n\tERTP_None,\r\n\tERTP_NonPrefetchable,\r\n\tERTP_NonVisible,\r\n\tERTP_Visible,\r\n};\r\n\r\n//\r\n// Stores the per-resource device dependent state. This data must be recreated when\r\n// the graphics device is removed due to TDR, driver upgrade, surprise removal, etc.\r\n// Mipmap information and heap count must be recalculated because the newly chosen\r\n// video adapter may tile resources differently than the current one, and so the actual\r\n// size of Mips[] may vary from device to device.\r\n//\r\nstruct ResourceDeviceState\r\n{\r\n\tID3D12Resource* pD3DResource;\r\n\tUINT32 NumHeaps;\r\n\r\n\t//\r\n\t// Mips must always be the last element, since it is actually a dynamic array.\r\n\t// The actual count of the array is equal to the number of unique mip heaps.\r\n\t// There is one mip heap for all packed mipmaps (mipmaps which can be packed\r\n\t// into one or few tiles), and one mip heap for each standard mipmap (mipmaps\r\n\t// which cannot be packed).\r\n\t//\r\n\tResourceMip Mips[1];\r\n};\r\n\r\n//\r\n// A resource object stores the device independent state information about a resource\r\n// which does not have to be recreated when a device is removed.\r\n//\r\nstruct Resource\r\n{\r\n\t// List entry for tracking the existence of the Resource object.\r\n\tLIST_ENTRY ListEntry;\r\n\r\n\t// List entry for tracking the commitment of mipmaps for this resource.\r\n\tLIST_ENTRY CommittedListEntry;\r\n\r\n\t// List entry used by the worker thread to prioritize paging operations.\r\n\tLIST_ENTRY PrioritizationEntry;\r\n\r\n\t// List entry used to track paging requests.\r\n\tLIST_ENTRY PagingEntry;\r\n\r\n\tCRITICAL_SECTION ReferenceLock;\r\n\r\n#if(_DEBUG)\r\n\t// Store the file name of the resource for easy identification during debugging.\r\n\tconst wchar_t* pFileName;\r\n#endif\r\n\r\n\t// The image decoder associated with this resource if it is backed by a file.\r\n\tIWICBitmapDecoder* pDecoder;\r\n\r\n\t// The image index associated with this resource if it is generated at runtime.\r\n\tUINT GeneratedImageIndex;\r\n\r\n\t// The number of tiles required to store packed mipmaps.\r\n\tUINT32 PackedMipTileCount;\r\n\tunion\r\n\t{\r\n\t\t// The number of standard mipmaps in this resource.\r\n\t\tUINT8 NumStandardMips : MAX_MIP_COUNT_BITS;\r\n\r\n\t\t// Index to the first packed mipmap.\r\n\t\tUINT8 PackedMipHeapIndex : MAX_MIP_COUNT_BITS;\r\n\t};\r\n\r\n\t// The number of packed mipmaps in this resource.\r\n\tUINT8 NumPackedMips : MAX_MIP_COUNT_BITS;\r\n\r\n\t// Set by the paging thread to indicate the most detailed mip level that is\r\n\t// currently paged in and fully resident.\r\n\tUINT8 MostDetailedMipResident : MAX_MIP_COUNT_BITS;\r\n\r\n\t// Used to restrict the maximum mip quality that can be used during rendering\r\n\t// when preparing to trim mipmaps from visible resources.\r\n\tUINT8 MipRestriction : MAX_MIP_COUNT_BITS;\r\n\r\n\t// The current mip level that is visible on screen for this resource. When\r\n\t// the resource is not visible, this value will be UNDEFINED_MIPMAP_INDEX.\r\n\tUINT8 VisibleMip : MAX_MIP_COUNT_BITS;\r\n\r\n\t// The minimum mip level, requested by the render thread, that the paging thread\r\n\t// should attempt to prefetch to avoid texture popping issues caused by fast\r\n\t// camera movement.\r\n\tUINT8 PrefetchMip : MAX_MIP_COUNT_BITS;\r\n\r\n\t// True if the paging operation determined during prioritization should ignore\r\n\t// the local memory budget. This is used when paging in minimum quality mipmaps\r\n\t// to ensure that every resource has at least some low quality content.\r\n\tbool bIgnoreBudget : 1;\r\n\r\n\t// The maximum trimming pass that should be used to help resolve paging failures\r\n\t// when paging in a resource would normally go over the budget. This limitation\r\n\t// prevents resources from recursively trimming one another by preventing lower\r\n\t// priority resources from trimming higher priority ones.\r\n\tResourceTrimPass TrimLimit;\r\n\r\n\t//\r\n\t// Device dependent state information.\r\n\t//\r\n\tResourceDeviceState* pDeviceState;\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Shader.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\nShader::Shader(UINT32 VertexSize) :\r\n\tm_pPipelineState(nullptr),\r\n\tm_VertexSize(VertexSize)\r\n{\r\n}\r\n\r\nShader::~Shader()\r\n{\r\n}\r\n\r\nHRESULT Shader::CreateDeviceDependentState(\r\n\tID3D12Device* pDevice,\r\n\tconst wchar_t* pShaderFile,\r\n\tD3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n\tD3D12_INPUT_ELEMENT_DESC* pInputElements,\r\n\tUINT InputElementCount,\r\n\tbool bEnableAlpha)\r\n{\r\n\tHRESULT hr;\r\n\r\n\t//\r\n\t// Create the root signature.\r\n\t//\r\n\t{\r\n\t\tD3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {};\r\n\r\n\t\t// This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.\r\n\t\tfeatureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n\r\n\t\tif (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData))))\r\n\t\t{\r\n\t\t\tfeatureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n\t\t}\r\n\r\n\t\tComPtr<ID3DBlob> pSignature;\r\n\t\tComPtr<ID3DBlob> pErrors;\r\n\t\thr = D3DX12SerializeVersionedRootSignature(pRootSignatureDesc, featureData.HighestVersion, &pSignature, &pErrors);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to serialize root signature, hr=0x%.8x\", hr);\r\n\t\t\tif (pErrors)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Error description:\\n%s\", (LPCSTR)pErrors->GetBufferPointer());\r\n\t\t\t}\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\thr = pDevice->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(&m_pRootSignature));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create root signature, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\t//\r\n\t// Compile and create shaders and pipeline state.\r\n\t//\r\n\t{\r\n\t\tComPtr<ID3DBlob> pVertexShader;\r\n\t\tComPtr<ID3DBlob> pPixelShader;\r\n\t\tComPtr<ID3DBlob> pErrors;\r\n\r\n#if _DEBUG\r\n\t\tUINT CompileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;\r\n#else\r\n\t\tUINT CompileFlags = 0;\r\n#endif\r\n\r\n\t\tWCHAR FileName[MAX_PATH];\r\n\t\tGetWorkingDir(FileName, MAX_PATH);\r\n\t\twcscat_s(FileName, pShaderFile);\r\n\r\n\t\tstatic LPCSTR VSEntryPoint = \"VShader\";\r\n\t\tstatic LPCSTR VSCompilerTarget = \"vs_5_0\";\r\n\r\n\t\thr = D3DCompileFromFile(FileName, nullptr, nullptr, VSEntryPoint, VSCompilerTarget, CompileFlags, 0, &pVertexShader, &pErrors);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\r\n\t\t\t\t\"Failed to compile vertex shader. File=%ls, EntryPoint=%s, Target=%s, hr=0x%.8x\",\r\n\t\t\t\tFileName,\r\n\t\t\t\tVSEntryPoint,\r\n\t\t\t\tVSCompilerTarget,\r\n\t\t\t\thr);\r\n\t\t\tif (pErrors)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Error description:\\n%s\", (LPCSTR)pErrors->GetBufferPointer());\r\n\t\t\t}\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tstatic LPCSTR PSEntryPoint = \"PShader\";\r\n\t\tstatic LPCSTR PSCompilerTarget = \"ps_5_0\";\r\n\r\n\t\thr = D3DCompileFromFile(FileName, nullptr, nullptr, PSEntryPoint, PSCompilerTarget, CompileFlags, 0, &pPixelShader, nullptr);\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\r\n\t\t\t\t\"Failed to compile pixel shader. File=%ls, EntryPoint=%s, Target=%s, hr=0x%.8x\",\r\n\t\t\t\tFileName,\r\n\t\t\t\tPSEntryPoint,\r\n\t\t\t\tPSCompilerTarget,\r\n\t\t\t\thr);\r\n\t\t\tif (pErrors)\r\n\t\t\t{\r\n\t\t\t\tprintf(\"Error description:\\n%s\", (LPCSTR)pErrors->GetBufferPointer());\r\n\t\t\t}\r\n\t\t\treturn hr;\r\n\t\t}\r\n\r\n\t\tD3D12_GRAPHICS_PIPELINE_STATE_DESC PsoDesc = {};\r\n\t\tPsoDesc.InputLayout = { pInputElements, InputElementCount };\r\n\t\tPsoDesc.pRootSignature = m_pRootSignature;\r\n\t\tPsoDesc.VS = { reinterpret_cast<UINT8*>(pVertexShader->GetBufferPointer()), pVertexShader->GetBufferSize() };\r\n\t\tPsoDesc.PS = { reinterpret_cast<UINT8*>(pPixelShader->GetBufferPointer()), pPixelShader->GetBufferSize() };\r\n\t\tPsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);\r\n\t\tPsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);\r\n\t\tif (bEnableAlpha)\r\n\t\t{\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].BlendEnable = TRUE;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;\r\n\t\t\tPsoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0x0f;\r\n\t\t}\r\n\t\tPsoDesc.DepthStencilState.DepthEnable = FALSE;\r\n\t\tPsoDesc.DepthStencilState.StencilEnable = FALSE;\r\n\t\tPsoDesc.SampleMask = UINT_MAX;\r\n\t\tPsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;\r\n\t\tPsoDesc.NumRenderTargets = 1;\r\n\t\tPsoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;\r\n\t\tPsoDesc.SampleDesc.Count = 1;\r\n\r\n\t\thr = pDevice->CreateGraphicsPipelineState(&PsoDesc, IID_PPV_ARGS(&m_pPipelineState));\r\n\t\tif (FAILED(hr))\r\n\t\t{\r\n\t\t\tLOG_ERROR(\"Failed to create graphics pipeline state, hr=0x%.8x\", hr);\r\n\t\t\treturn hr;\r\n\t\t}\r\n\t}\r\n\r\n\treturn S_OK;\r\n}\r\n\r\nvoid Shader::DestroyDeviceDependentState()\r\n{\r\n\tSafeRelease(m_pPipelineState);\r\n\tSafeRelease(m_pRootSignature);\r\n}\r\n\r\n//\r\n// TextureShader\r\n//\r\nTextureShader::TextureShader() :\r\n\tShader(sizeof(VertexFormat))\r\n{\r\n}\r\n\r\nHRESULT TextureShader::CreateDeviceDependentState(ID3D12Device* pDevice, const wchar_t* pShaderFile)\r\n{\r\n\tCD3DX12_DESCRIPTOR_RANGE1 DescriptorRanges[1];\r\n\tDescriptorRanges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);\r\n\r\n\tCD3DX12_ROOT_PARAMETER1 RootParameters[2];\r\n\tRootParameters[0].InitAsConstantBufferView(0);\r\n\tRootParameters[1].InitAsDescriptorTable(1, &DescriptorRanges[0], D3D12_SHADER_VISIBILITY_PIXEL);\r\n\r\n\tCD3DX12_STATIC_SAMPLER_DESC StaticSamplerDesc(0);\r\n\tStaticSamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;\r\n\tStaticSamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;\r\n\r\n\tCD3DX12_VERSIONED_ROOT_SIGNATURE_DESC RootSignatureDesc;\r\n\tRootSignatureDesc.Init_1_1(_countof(RootParameters), RootParameters, 1, &StaticSamplerDesc, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);\r\n\r\n\tD3D12_INPUT_ELEMENT_DESC InputElementDescs[] =\r\n\t{\r\n\t\t{ \"POSITION\", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0,  0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n\t\t{ \"TEXCOORD\", 0, DXGI_FORMAT_R32G32_FLOAT,       0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n\t\t{ \"COLOR\",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }\r\n\t};\r\n\r\n\treturn Shader::CreateDeviceDependentState(pDevice, pShaderFile, &RootSignatureDesc, InputElementDescs, _countof(InputElementDescs), false);\r\n}\r\n\r\n//\r\n// ColorShader\r\n//\r\nColorShader::ColorShader() :\r\n\tShader(sizeof(VertexFormat))\r\n{\r\n\r\n}\r\n\r\nHRESULT ColorShader::CreateDeviceDependentState(ID3D12Device* pDevice, const wchar_t* pShaderFile)\r\n{\r\n\tCD3DX12_ROOT_PARAMETER1 RootParameters[1];\r\n\tRootParameters[0].InitAsConstantBufferView(0, 0, D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC);\r\n\r\n\tCD3DX12_VERSIONED_ROOT_SIGNATURE_DESC RootSignatureDesc;\r\n\tRootSignatureDesc.Init_1_1(_countof(RootParameters), RootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);\r\n\r\n\tD3D12_INPUT_ELEMENT_DESC InputElementDescs[] =\r\n\t{\r\n\t\t{ \"POSITION\", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0,  0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\r\n\t\t{ \"COLOR\",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }\r\n\t};\r\n\r\n\treturn Shader::CreateDeviceDependentState(pDevice, pShaderFile, &RootSignatureDesc, InputElementDescs, _countof(InputElementDescs), true);\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Shader.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// Identifies a unique shader with its own unique root signature and pipeline state.\r\n//\r\nclass Shader\r\n{\r\nprotected:\r\n\tUINT32 m_VertexSize;\r\n\tID3D12RootSignature* m_pRootSignature = nullptr;\r\n\tID3D12PipelineState* m_pPipelineState = nullptr;\r\n\r\n\tHRESULT CreateDeviceDependentState(\r\n\t\tID3D12Device* pDevice,\r\n\t\tconst wchar_t* pShaderFile,\r\n\t\tD3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n\t\tD3D12_INPUT_ELEMENT_DESC* pInputElements,\r\n\t\tUINT InputElementCount,\r\n\t\tbool bEnableAlpha);\r\n\r\npublic:\r\n\tShader(UINT32 VertexSize);\r\n\t~Shader();\r\n\r\n\tvoid DestroyDeviceDependentState();\r\n\r\n\tUINT32 GetVertexSize() const\r\n\t{\r\n\t\treturn m_VertexSize;\r\n\t}\r\n\r\n\tinline ID3D12RootSignature* GetRootSignature() const\r\n\t{\r\n\t\treturn m_pRootSignature;\r\n\t}\r\n\r\n\tinline ID3D12PipelineState* GetPipelineState() const\r\n\t{\r\n\t\treturn m_pPipelineState;\r\n\t}\r\n};\r\n\r\n//\r\n// Creates a shader with a root signature and pipeline state that matches the vertex\r\n// format used for a vertex containing UV coordinate information for textured quads.\r\n//\r\nclass TextureShader : public Shader\r\n{\r\npublic:\r\n\tstruct VertexFormat\r\n\t{\r\n\t\tfloat Position[3];\r\n\t\tfloat TexCoords[2];\r\n\t\tfloat Color[4];\r\n\t};\r\n\r\n\tTextureShader();\r\n\r\n\tHRESULT CreateDeviceDependentState(ID3D12Device* pDevice, const wchar_t* pShaderFile);\r\n};\r\n\r\n//\r\n// Creates a shader with a root signature and pipeline state that matches the vertex\r\n// format used for a vertex containing color information for colored quads.\r\n//\r\nclass ColorShader : public Shader\r\n{\r\npublic:\r\n\tstruct VertexFormat\r\n\t{\r\n\t\tfloat Position[3];\r\n\t\tfloat ColorRGBA[4];\r\n\t};\r\n\r\n\tColorShader();\r\n\r\n\tHRESULT CreateDeviceDependentState(ID3D12Device* pDevice, const wchar_t* pShaderFile);\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Texture.hlsl",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\nTexture2D GTexture : register(t0);\r\nSamplerState GSampler : register(s0);\r\n\r\ncbuffer Projection : register(b0)\r\n{\r\n\tfloat4x4 GProjectionMatrix;\r\n};\r\n\r\nstruct PSInput\r\n{\r\n\tfloat4 Position : SV_POSITION;\r\n\tfloat4 Color : COLOR;\r\n\tfloat2 UV : TEXCOORD;\r\n};\r\n\r\nPSInput VShader(float3 Position : POSITION, float2 UV : TEXCOORD, float4 Color : COLOR)\r\n{\r\n\tPSInput Result;\r\n\r\n\tResult.Position = float4(Position, 1.0f);\r\n\tResult.Position = mul(GProjectionMatrix, Result.Position);\r\n\tResult.UV = UV;\r\n\tResult.Color = Color;\r\n\r\n\treturn Result;\r\n}\r\n\r\nfloat4 PShader(PSInput Input) : SV_TARGET\r\n{\r\n\treturn GTexture.Sample(GSampler, Input.UV) * Input.Color;\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Util.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\n//\r\n// WICPixelFormat translation data.\r\n//\r\nstruct WICTranslate\r\n{\r\n\tGUID wic;\r\n\tDXGI_FORMAT format;\r\n};\r\n\r\nstatic WICTranslate g_WICFormats[] =\r\n{\r\n\t{ GUID_WICPixelFormat128bppRGBAFloat,       DXGI_FORMAT_R32G32B32A32_FLOAT },\r\n\r\n\t{ GUID_WICPixelFormat64bppRGBAHalf,         DXGI_FORMAT_R16G16B16A16_FLOAT },\r\n\t{ GUID_WICPixelFormat64bppRGBA,             DXGI_FORMAT_R16G16B16A16_UNORM },\r\n\r\n\t{ GUID_WICPixelFormat32bppRGBA,             DXGI_FORMAT_R8G8B8A8_UNORM },\r\n\t{ GUID_WICPixelFormat32bppBGRA,             DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1\r\n\t{ GUID_WICPixelFormat32bppBGR,              DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1\r\n\r\n\t{ GUID_WICPixelFormat32bppRGBA1010102XR,    DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1\r\n\t{ GUID_WICPixelFormat32bppRGBA1010102,      DXGI_FORMAT_R10G10B10A2_UNORM },\r\n\r\n\t{ GUID_WICPixelFormat16bppBGRA5551,         DXGI_FORMAT_B5G5R5A1_UNORM },\r\n\t{ GUID_WICPixelFormat16bppBGR565,           DXGI_FORMAT_B5G6R5_UNORM },\r\n\r\n\t{ GUID_WICPixelFormat32bppGrayFloat,        DXGI_FORMAT_R32_FLOAT },\r\n\t{ GUID_WICPixelFormat16bppGrayHalf,         DXGI_FORMAT_R16_FLOAT },\r\n\t{ GUID_WICPixelFormat16bppGray,             DXGI_FORMAT_R16_UNORM },\r\n\t{ GUID_WICPixelFormat8bppGray,              DXGI_FORMAT_R8_UNORM },\r\n\r\n\t{ GUID_WICPixelFormat8bppAlpha,             DXGI_FORMAT_A8_UNORM },\r\n};\r\n\r\n//\r\n// WICPixelFormat nearest conversion table.\r\n//\r\nstruct WICConvert\r\n{\r\n\tGUID source;\r\n\tGUID target;\r\n};\r\n\r\nstatic WICConvert g_WICConvert[] =\r\n{\r\n\t//\r\n\t// Note target GUID in this conversion table must be one of those directly supported formats (above).\r\n\t//\r\n\r\n\t{ GUID_WICPixelFormatBlackWhite,            GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM\r\n\r\n\t{ GUID_WICPixelFormat1bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat2bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat4bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat8bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\r\n\t{ GUID_WICPixelFormat2bppGray,              GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM\r\n\t{ GUID_WICPixelFormat4bppGray,              GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM\r\n\r\n\t{ GUID_WICPixelFormat16bppGrayFixedPoint,   GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT\r\n\t{ GUID_WICPixelFormat32bppGrayFixedPoint,   GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT\r\n\r\n\t{ GUID_WICPixelFormat16bppBGR555,           GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM\r\n\r\n\t{ GUID_WICPixelFormat32bppBGR101010,        GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM\r\n\r\n\t{ GUID_WICPixelFormat24bppBGR,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat24bppRGB,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat32bppPBGRA,            GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat32bppPRGBA,            GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\r\n\t{ GUID_WICPixelFormat48bppRGB,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat48bppBGR,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat64bppBGRA,             GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat64bppPRGBA,            GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat64bppPBGRA,            GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\r\n\t{ GUID_WICPixelFormat48bppRGBFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\t{ GUID_WICPixelFormat48bppBGRFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\t{ GUID_WICPixelFormat64bppRGBAFixedPoint,   GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\t{ GUID_WICPixelFormat64bppBGRAFixedPoint,   GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\t{ GUID_WICPixelFormat64bppRGBFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\t{ GUID_WICPixelFormat48bppRGBHalf,          GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\t{ GUID_WICPixelFormat64bppRGBHalf,          GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n\r\n\t{ GUID_WICPixelFormat128bppPRGBAFloat,      GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT\r\n\t{ GUID_WICPixelFormat128bppRGBFloat,        GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT\r\n\t{ GUID_WICPixelFormat128bppRGBAFixedPoint,  GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT\r\n\t{ GUID_WICPixelFormat128bppRGBFixedPoint,   GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT\r\n\t{ GUID_WICPixelFormat32bppRGBE,             GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT\r\n\r\n\t{ GUID_WICPixelFormat32bppCMYK,             GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat64bppCMYK,             GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat40bppCMYKAlpha,        GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat80bppCMYKAlpha,        GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\r\n\t{ GUID_WICPixelFormat32bppRGB,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM\r\n\t{ GUID_WICPixelFormat64bppRGB,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM\r\n\t{ GUID_WICPixelFormat64bppPRGBAHalf,        GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT\r\n};\r\n\r\nbool GetTargetPixelFormat(const GUID* pSourceFormat, GUID* pTargetFormat)\r\n{\r\n\t*pTargetFormat = *pSourceFormat;\r\n\r\n\tfor (size_t i = 0; i < _countof(g_WICConvert); ++i)\r\n\t{\r\n\t\tif (InlineIsEqualGUID(g_WICConvert[i].source, *pSourceFormat))\r\n\t\t{\r\n\t\t\t*pTargetFormat = g_WICConvert[i].target;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nDXGI_FORMAT GetDXGIFormatFromPixelFormat(const GUID* pPixelFormat)\r\n{\r\n\tfor (size_t i = 0; i < _countof(g_WICFormats); ++i)\r\n\t{\r\n\t\tif (InlineIsEqualGUID(g_WICFormats[i].wic, *pPixelFormat))\r\n\t\t{\r\n\t\t\treturn g_WICFormats[i].format;\r\n\t\t}\r\n\t}\r\n\r\n\treturn DXGI_FORMAT_UNKNOWN;\r\n}\r\n\r\nstatic UINT g_GeneratedImageColors[] =\r\n{\r\n\t0xff0000ff,\t// Red\r\n\t0xff0088ff,\t// Orange\r\n\t0xff00ffff,\t// Yellow\r\n\t0xff009900,\t// Green\r\n\t0xffffff00,\t// Cyan\r\n\t0xffff0000,\t// Blue\r\n\t0xffff00ff,\t// Magenta\r\n\t0xff000000,\t// Black\r\n};\r\nstatic const UINT imageColorCount = _countof(g_GeneratedImageColors);\r\n\r\nUINT GetGeneratedImageColor(UINT ImageIndex)\r\n{\r\n\treturn g_GeneratedImageColors[ImageIndex % imageColorCount];\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Util.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// Converts the provided source WIC pixel format into the closest matching\r\n// target format which we can use with tiled resources.\r\n//\r\nbool GetTargetPixelFormat(const GUID* pSourceFormat, GUID* pTargetFormat);\r\n\r\n//\r\n// Converts the WIC pixel format to the corresponding DXGI format. Returns\r\n// DXGI_FORMAT_UNKNOWN if the pixel format is not supported.\r\n//\r\nDXGI_FORMAT GetDXGIFormatFromPixelFormat(const GUID* pPixelFormat);\r\n\r\n//\r\n// Gets the index to the least detailed mipmap for the specified resource.\r\n//\r\ninline UINT8 GetLeastDetailedMipIndex(_In_ const Resource* pResource)\r\n{\r\n\treturn pResource->NumStandardMips + pResource->NumPackedMips - 1;\r\n}\r\n\r\n//\r\n// Gets the index to the heap corresponding to the least detailed mipmap\r\n// in the resource. All packed mipmaps share a single heap index, so this value\r\n// is not equal to the least detailed mipmap index.\r\n//\r\ninline UINT8 GetLeastDetailedMipHeapIndex(_In_ const Resource* pResource)\r\n{\r\n\tif (pResource->NumPackedMips != 0)\r\n\t{\r\n\t\treturn pResource->PackedMipHeapIndex;\r\n\t}\r\n\treturn pResource->NumStandardMips - 1;\r\n}\r\n\r\n//\r\n// Returns true if 'MipToCheck' is less detailed that 'CurrentMip'\r\n//\r\ninline bool IsLessDetailedMip(UINT8 CurrentMip, UINT8 MipToCheck)\r\n{\r\n\treturn MipToCheck > CurrentMip;\r\n}\r\n\r\n//\r\n// Returns true if 'MipToCheck' is more detailed that 'CurrentMip'\r\n//\r\ninline bool IsMoreDetailedMip(UINT8 CurrentMip, UINT8 MipToCheck)\r\n{\r\n\treturn MipToCheck < CurrentMip;\r\n}\r\n\r\n//\r\n// Calculates the mipmap level that would be used when sampling a resource, given\r\n// the orthographic camera zoom level.\r\n//\r\ninline float CalculateRequiredMipLevel(_In_ const Resource* pResource, float ImageScale)\r\n{\r\n\tD3D12_RESOURCE_DESC Desc = pResource->pDeviceState->pD3DResource->GetDesc();\r\n\r\n\t//\r\n\t// Calculate rough derivative, knowing that the image is a screen-space quad.\r\n\t// This should be equal to the ratio of texels per pixel (ImageScale is equal\r\n\t// to the screen space pixel size of the texture with projection zoom applied).\r\n\t//\r\n\tfloat d = Desc.Width / ImageScale;\r\n\tfloat dSqr = d * d;\r\n\r\n\t//\r\n\t// Mip = log2(DerivativeSquared) / 2\r\n\t//\r\n\tfloat Log = log(dSqr) / log(2.0f);\r\n\tfloat Mip = 0.5f * Log;\r\n\treturn max(Mip, 0.0f);\r\n}\r\n\r\n//\r\n// Gets the total number of mipmaps in this resource.\r\n//\r\ninline UINT8 GetResourceMipCount(_In_ const Resource* pResource)\r\n{\r\n\treturn pResource->NumStandardMips + pResource->NumPackedMips;\r\n}\r\n\r\n//\r\n// Gets the accent color for the generated image.\r\n//\r\nUINT GetGeneratedImageColor(UINT ImageIndex);\r\n\r\n//\r\n// Returns true if the two rectangles intersect.\r\n//\r\ninline bool RectIntersects(const RectF& a, const RectF& b)\r\n{\r\n\treturn a.Left < b.Right && a.Right > b.Left &&\r\n\t\ta.Top < b.Bottom && a.Bottom > b.Top;\r\n}\r\n\r\n//\r\n// Returns true if the two rectangles are with the specified Tolerence distance from one another.\r\n//\r\ninline bool RectNearlyIntersects(const RectF& a, const RectF& b, float Tolerence)\r\n{\r\n\treturn a.Left - Tolerence < b.Right && a.Right + Tolerence > b.Left &&\r\n\t\ta.Top - Tolerence < b.Bottom && a.Bottom + Tolerence> b.Top;\r\n}\r\n\r\n//\r\n// Inflates a rectangle by the specified size on all sides.\r\n//\r\ninline void InflateRectangle(RectF& Rectangle, float Size)\r\n{\r\n\tRectangle.Bottom += Size;\r\n\tRectangle.Left -= Size;\r\n\tRectangle.Right += Size;\r\n\tRectangle.Top -= Size;\r\n}\r\n\r\n//\r\n// Returns the more detailed of two mipmap levels.\r\n//\r\ninline UINT8 ChooseMoreDetailedMip(UINT8 MipA, UINT8 MipB)\r\n{\r\n\treturn min(MipA, MipB);\r\n}\r\n\r\n//\r\n// Returns the less detailed of two mipmap levels.\r\n//\r\ninline UINT8 ChooseLessDetailedMip(UINT8 MipA, UINT8 MipB)\r\n{\r\n\treturn max(MipA, MipB);\r\n}\r\n\r\n//\r\n// Returns the mip level after increasing the quality by 'IncreaseBy' levels of quality,\r\n// and clamping the quality to 0.\r\n//\r\ninline UINT8 IncreaseMipQuality(UINT8 Mip, UINT8 IncreaseBy)\r\n{\r\n\tif (IncreaseBy > Mip)\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\treturn Mip - IncreaseBy;\r\n}\r\n\r\n//\r\n// Returns the mip level after decreasing the quality by 'DecreaseBy' levels of quality.\r\n//\r\ninline UINT8 DecreaseMipQuality(UINT8 Mip, UINT8 DecreaseBy)\r\n{\r\n\treturn Mip + DecreaseBy;\r\n}\r\n\r\n//\r\n// Translates a lowercase character to the equivalent virtual key\r\n//\r\ninline UINT GetVirtualKeyFromCharacter(char c)\r\n{\r\n\treturn 0x41 + (c - 'a');\r\n}\r\n\r\n//\r\n// Calculates the number of heaps required to page in the provided resource mipmap, based\r\n// on the maximimum heap size.\r\n//\r\ninline UINT GetResourceMipHeapCount(const ResourceMip& rMip)\r\n{\r\n\treturn ((rMip.Desc.WidthInTiles * rMip.Desc.HeightInTiles * TILE_SIZE) + MAX_HEAP_SIZE - 1) / MAX_HEAP_SIZE;\r\n}\r\n\r\n//\r\n// Gets the heap index for a resource, given the mip level. All packed mipmaps\r\n// share a single heap index.\r\n//\r\ninline UINT8 GetMipHeapIndexForResource(_In_ const Resource* pResource, UINT8 Mip)\r\n{\r\n\tUINT8 Index = Mip;\r\n\tif (Index > pResource->PackedMipHeapIndex)\r\n\t{\r\n\t\tIndex = pResource->PackedMipHeapIndex;\r\n\t}\r\n\r\n\treturn Index;\r\n}\r\n\r\n//\r\n// Calculates the size of a non-packed mipmap, in bytes.\r\n//\r\ninline UINT64 GetNonPackedMipSize(_In_ const Resource* pResource, UINT MipHeapIndex)\r\n{\r\n\tResourceMip* pMip = &pResource->pDeviceState->Mips[MipHeapIndex];\r\n\treturn (UINT64)pMip->Desc.WidthInTiles * (UINT64)pMip->Desc.HeightInTiles * TILE_SIZE;\r\n}\r\n\r\n//\r\n// Gets a friendly string for the provided D3D feature level.\r\n//\r\ninline LPCSTR GetFeatureLevelName(D3D_FEATURE_LEVEL FeatureLevel)\r\n{\r\n\tswitch (FeatureLevel)\r\n\t{\r\n\tcase D3D_FEATURE_LEVEL_9_1: return \"9.1\";\r\n\tcase D3D_FEATURE_LEVEL_9_2: return \"9.2\";\r\n\tcase D3D_FEATURE_LEVEL_9_3: return \"9.3\";\r\n\tcase D3D_FEATURE_LEVEL_10_0: return \"10.0\";\r\n\tcase D3D_FEATURE_LEVEL_10_1: return \"10.1\";\r\n\tcase D3D_FEATURE_LEVEL_11_0: return \"11.0\";\r\n\tcase D3D_FEATURE_LEVEL_11_1: return \"11.1\";\r\n\tcase D3D_FEATURE_LEVEL_12_0: return \"12.0\";\r\n\tcase D3D_FEATURE_LEVEL_12_1: return \"12.1\";\r\n\r\n\tdefault: return \"12.1+\";\r\n\t}\r\n}\r\n\r\n//\r\n// Calculates the required size of a constant buffer, based on the D3D12 alignment\r\n// restriction of constant buffers (256 bytes).\r\n//\r\ninline UINT32 CalculateConstantBufferSize(UINT32 Size)\r\n{\r\n\t//\r\n\t// Constant buffers are required to be 256 byte aligned, and multiples of 256 bytes.\r\n\t//\r\n\treturn (Size + (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1);\r\n}\r\n\r\n//\r\n// Get the absolute path to the running exe.\r\n//\r\ninline void GetWorkingDir(_Out_writes_z_(pathSize) WCHAR* path, UINT pathSize)\r\n{\r\n\tif (path == nullptr)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tDWORD size = GetModuleFileName(nullptr, path, pathSize);\r\n\r\n\tif (size == 0 || size == pathSize)\r\n\t{\r\n\t\t// Method failed or path was truncated.\r\n\t\t*path = L'\\0';\r\n\t\treturn;\r\n\t}\r\n\r\n\tWCHAR* lastSlash = wcsrchr(path, L'\\\\');\r\n\tif (lastSlash)\r\n\t{\r\n\t\t*(lastSlash+1) = L'\\0';\r\n\t}\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Versioning.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\n_Use_decl_annotations_\r\nHRESULT DynamicBuffer::Allocate(UINT32 ElementSize, UINT32 ElementCount, void** pData, UINT32* pOffset)\r\n{\r\n\tUINT32 AllocationSize = ElementSize * ElementCount;\r\n\tassert(AllocationSize <= DYNAMIC_BUFFER_SIZE);\r\n\r\n\tULONG_PTR pCurrentAddress = (ULONG_PTR)m_pCurrentAddress;\r\n\tULONG_PTR pEndAddress = (ULONG_PTR)m_pBuffer->pBaseAddress + DYNAMIC_BUFFER_SIZE;\r\n\r\n\tif (pCurrentAddress + AllocationSize > pEndAddress)\r\n\t{\r\n\t\t//\r\n\t\t// Allocation would overflow buffer, return out of memory to signal to\r\n\t\t// the caller to flush whatever they're doing, rename the buffer,\r\n\t\t// and try again afterwards.\r\n\t\t//\r\n\t\treturn E_OUTOFMEMORY;\r\n\t}\r\n\r\n\t*pData = (void*)pCurrentAddress;\r\n\t*pOffset = (UINT32)(m_pCurrentAddress - m_pBuffer->pBaseAddress);\r\n\r\n\tm_pCurrentAddress = pCurrentAddress + AllocationSize;\r\n\treturn S_OK;\r\n}\r\n\r\nHRESULT DX12Framework::AllocateVersionedBuffer(Buffer** ppBuffer)\r\n{\r\n\t//\r\n\t// Grab a buffer from our lookaside list if possible.\r\n\t//\r\n\tif (!IsListEmpty(&m_DynamicBufferListHead))\r\n\t{\r\n\t\tLIST_ENTRY* pEntry = RemoveHeadList(&m_DynamicBufferListHead);\r\n\t\t*ppBuffer = static_cast<Buffer*>(pEntry);\r\n\t\treturn S_OK;\r\n\t}\r\n\r\n\t//\r\n\t// No available buffers, let's try to allocate a new one.\r\n\t//\r\n\tHRESULT hr;\r\n\tID3D12Resource* pD3DBuffer = nullptr;\r\n\tCD3DX12_RANGE readRange(0, 0);\r\n\tvoid* pBaseAddress = nullptr;\r\n\r\n\thr = m_pDevice->CreateCommittedResource(\r\n\t\t&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),\r\n\t\tD3D12_HEAP_FLAG_NONE,\r\n\t\t&CD3DX12_RESOURCE_DESC::Buffer(DYNAMIC_BUFFER_SIZE),\r\n\t\tD3D12_RESOURCE_STATE_GENERIC_READ,\r\n\t\tnullptr,\r\n\t\tIID_PPV_ARGS(&pD3DBuffer));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create D3D12 buffer resource, hr=0x%.8x\", hr);\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\t//\r\n\t// Obtain a permanent CPU visible address for this buffer. In D3D12, it is okay to\r\n\t// keep a permanent virtual address mapped to an allocation while the resource is\r\n\t// accessed by the GPU. In this case, the semantics of the mapping operation are\r\n\t// always equivalent to the D3D11 MAP_WRITE_NO_OVERWRITE value.\r\n\t//\r\n\thr = pD3DBuffer->Map(0, &readRange, &pBaseAddress);\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to map base address for buffer, hr=0x%.8x\", hr);\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\tBuffer* pBuffer = nullptr;\r\n\ttry\r\n\t{\r\n\t\tpBuffer = new Buffer();\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to allocate dynamic buffer\");\r\n\t\thr = E_OUTOFMEMORY;\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\tpBuffer->pBaseAddress = (ULONG_PTR)pBaseAddress;\r\n\tpBuffer->pBuffer = pD3DBuffer;\r\n\r\n\t*ppBuffer = pBuffer;\r\n\r\n\treturn S_OK;\r\n\r\ncleanup:\r\n\tif (pBaseAddress)\r\n\t{\r\n\t\tpD3DBuffer->Unmap(0, nullptr);\r\n\t}\r\n\tSafeRelease(pD3DBuffer);\r\n\treturn hr;\r\n}\r\n\r\nvoid DX12Framework::RetireVersionedBuffer(Buffer* pBuffer)\r\n{\r\n\t//\r\n\t// Buffer is done being accessed by the GPU; add it to the lookaside list to be reused later.\r\n\t// A lookaside list will greatly reduce the overhead as buffers get renamed.\r\n\t//\r\n\tInsertHeadList(&m_DynamicBufferListHead, pBuffer);\r\n}\r\n\r\nvoid DX12Framework::RenameDynamicBuffer(DynamicBuffer* pDynamicBuffer)\r\n{\r\n\tHRESULT hr;\r\n\r\nretry_allocation:\r\n\tBuffer* pBuffer = nullptr;\r\n\thr = AllocateVersionedBuffer(&pBuffer);\r\n\r\n\tif (pBuffer != nullptr)\r\n\t{\r\n\t\t//\r\n\t\t// New allocation successful, so we do not need to wait. Release this one\r\n\t\t// to the frame so it can be retired and reused later.\r\n\t\t//\r\n\t\tm_RenderContext.CloseBuffer(pDynamicBuffer->m_pBuffer);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//\r\n\t\t// Check if there are pending frames in flight. If so, we should wait a frame\r\n\t\t// and try again. In that time we may retire a pending buffer, or may end up\r\n\t\t// trimming or freeing enough memory to allocate a new one.\r\n\t\t//\r\n\r\n\t\tif (m_RenderContext.GetActiveFrameCount() > 0)\r\n\t\t{\r\n\t\t\tm_RenderContext.WaitForSingleFrame();\r\n\r\n\t\t\tif (m_RenderContext.GetActiveFrameCount() > 0)\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Only retry the allocation if this was not our last frame. Otherwise\r\n\t\t\t\t// our current buffer is already retired, so let's just reuse it at no\r\n\t\t\t\t// cost.\r\n\t\t\t\t//\r\n\t\t\t\tgoto retry_allocation;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// We've waited for all pending frames and weren't able to allocate a new buffer,\r\n\t\t// so we can just reuse the current one.\r\n\t\t//\r\n\t\tpBuffer = pDynamicBuffer->m_pBuffer;\r\n\t}\r\n\r\n\t//\r\n\t// Assign the new versioned buffer, and set the current pointer to the start.\r\n\t//\r\n\tpDynamicBuffer->m_pBuffer = pBuffer;\r\n\tpDynamicBuffer->m_pCurrentAddress = pBuffer->pBaseAddress;\r\n}\r\n\r\n//\r\n// Aligns the buffer's current location to the provided value. Alignment does not\r\n// need to be a power of two. This function is used to allow a single vertex buffer\r\n// to be shared across multiple vertex types (of different sizes).\r\n//\r\nvoid DynamicBuffer::Align(UINT32 Alignment)\r\n{\r\n\tULONG_PTR Offset = (m_pCurrentAddress - m_pBuffer->pBaseAddress) + Alignment - 1;\r\n\tULONG_PTR AlignedAligned = Offset - (Offset % Alignment);\r\n\tm_pCurrentAddress = m_pBuffer->pBaseAddress + AlignedAligned;\r\n}\r\n\r\n//\r\n// Dynamic heaps are conceptually the same concept as dynamic buffers, but for descriptors\r\n// instead of buffer data.\r\n//\r\nHRESULT DX12Framework::AllocateVersionedDescriptorHeap(DescriptorHeap** ppHeap)\r\n{\r\n\t//\r\n\t// Grab a heap from our lookaside list if possible.\r\n\t//\r\n\tif (!IsListEmpty(&m_DynamicDescriptorHeapListHead))\r\n\t{\r\n\t\tLIST_ENTRY* pEntry = RemoveHeadList(&m_DynamicDescriptorHeapListHead);\r\n\t\t*ppHeap = static_cast<DescriptorHeap*>(pEntry);\r\n\t\treturn S_OK;\r\n\t}\r\n\r\n\t//\r\n\t// No available buffers, let's try to allocate a new one.\r\n\t//\r\n\tHRESULT hr;\r\n\tID3D12DescriptorHeap* pD3DDescriptorHeap = nullptr;\r\n\r\n\tD3D12_DESCRIPTOR_HEAP_DESC Desc = {};\r\n\tDesc.NumDescriptors = DYNAMIC_HEAP_SIZE;\r\n\tDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;\r\n\tDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;\r\n\r\n\thr = m_pDevice->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(&pD3DDescriptorHeap));\r\n\tif (FAILED(hr))\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to create D3D12 descriptor heap, hr=0x%.8x\", hr);\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\tDescriptorHeap* pHeap = nullptr;\r\n\ttry\r\n\t{\r\n\t\tpHeap = new DescriptorHeap();\r\n\t}\r\n\tcatch (std::bad_alloc&)\r\n\t{\r\n\t\tLOG_WARNING(\"Failed to allocate dynamic descriptor heap\");\r\n\t\thr = E_OUTOFMEMORY;\r\n\t\tgoto cleanup;\r\n\t}\r\n\r\n\tpHeap->pHeap = pD3DDescriptorHeap;\r\n\r\n\t*ppHeap = pHeap;\r\n\r\n\treturn S_OK;\r\n\r\ncleanup:\r\n\tSafeRelease(pD3DDescriptorHeap);\r\n\treturn hr;\r\n}\r\n\r\nvoid DX12Framework::RetireVersionedDescriptorHeap(DescriptorHeap* pHeap)\r\n{\r\n\t//\r\n\t// Heap is done being accessed by the GPU; add it to the lookaside list to be reused later.\r\n\t// A lookaside list will greatly reduce the overhead as heaps get renamed.\r\n\t//\r\n\tInsertHeadList(&m_DynamicDescriptorHeapListHead, pHeap);\r\n}\r\n\r\nvoid DX12Framework::RenameDynamicDescriptorHeap(DynamicDescriptorHeap* pDynamicHeap)\r\n{\r\n\tHRESULT hr;\r\n\r\nretry_allocation:\r\n\tDescriptorHeap* pHeap = nullptr;\r\n\thr = AllocateVersionedDescriptorHeap(&pHeap);\r\n\r\n\tif (pHeap != nullptr)\r\n\t{\r\n\t\t//\r\n\t\t// New allocation successful, so we do not need to wait. Release this one\r\n\t\t// to the frame so it can be retired and reused later.\r\n\t\t//\r\n\t\tm_RenderContext.CloseHeap(pDynamicHeap->m_pHeap);\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//\r\n\t\t// Check if there are pending frames in flight. If so, we should wait a frame\r\n\t\t// and try again. In that time we may retire a pending buffer, or may end up\r\n\t\t// trimming or freeing enough memory to allocate a new one.\r\n\t\t//\r\n\t\tif (m_RenderContext.GetActiveFrameCount() > 0)\r\n\t\t{\r\n\t\t\tm_RenderContext.WaitForSingleFrame();\r\n\r\n\t\t\tif (m_RenderContext.GetActiveFrameCount() > 0)\r\n\t\t\t{\r\n\t\t\t\t//\r\n\t\t\t\t// Only retry the allocation if this was not our last frame. Otherwise\r\n\t\t\t\t// our current heap is already retired, so let's just reuse it at no\r\n\t\t\t\t// cost.\r\n\t\t\t\t//\r\n\t\t\t\tgoto retry_allocation;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t//\r\n\t\t// We've waited for all pending frames and weren't able to allocate a new heap,\r\n\t\t// so we can just reuse the current one.\r\n\t\t//\r\n\t\tpHeap = pDynamicHeap->m_pHeap;\r\n\t}\r\n\r\n\t//\r\n\t// Assign the new versioned heap, and set the current descriptor to the start.\r\n\t//\r\n\tpDynamicHeap->m_pHeap = pHeap;\r\n\tpDynamicHeap->m_CurrentHandleIndex = 0;\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/Versioning.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n//\r\n// A Buffer that encapsulates a D3D12 resource, and the base address of the allocation.\r\n// A buffer object is part of a dynamic buffer, and can be versioned (or renamed) on\r\n// demand.\r\n//\r\nstruct Buffer : LIST_ENTRY\r\n{\r\n\tID3D12Resource* pBuffer;\r\n\tULONG_PTR pBaseAddress;\r\n};\r\n\r\n//\r\n// A DynamicBuffer allows the application to allocate buffer storage from a backing\r\n// D3D12 resource, while maintaining information used for versioning the buffers as\r\n// they run out of space.\r\n//\r\nclass DynamicBuffer\r\n{\r\n\tfriend class DX12Framework;\r\n\r\nprivate:\r\n\tBuffer* m_pBuffer;\r\n\tULONG_PTR m_pCurrentAddress;\r\n\r\npublic:\r\n\t//\r\n\t// Align does not need to be a power of two, simply a boundary to align to. This is\r\n\t// used to share the vertex buffer across shaders by aligning the vertices\r\n\t// to multiples of the vertex stride.\r\n\t//\r\n\tvoid Align(UINT32 Alignment);\r\n\tHRESULT Allocate(UINT32 ElementSize, UINT32 ElementCount, _Outptr_ void** pData, UINT32* pOffset);\r\n\r\n\tinline D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress() const\r\n\t{\r\n\t\treturn m_pBuffer->pBuffer->GetGPUVirtualAddress();\r\n\t}\r\n\r\n\tinline void Reset()\r\n\t{\r\n\t\tm_pCurrentAddress = m_pBuffer->pBaseAddress;\r\n\t}\r\n};\r\n\r\n//\r\n// A DescriptorHeap keeps track of a single instance of a renamable D3D12 descriptor\r\n// heap. It is part of a DynamicDescriptorHeap object, which can be versioned on demand.\r\n//\r\nstruct DescriptorHeap : LIST_ENTRY\r\n{\r\n\tID3D12DescriptorHeap* pHeap;\r\n};\r\n\r\n//\r\n// A DynamicDescriptorHeap allows the application to allocate descriptors from a backing\r\n// D3D12 descriptor heap, while maintaining information used for versioning the heaps as\r\n// they run out of space.\r\n//\r\nclass DynamicDescriptorHeap\r\n{\r\n\tfriend class DX12Framework;\r\n\r\nprivate:\r\n\tDescriptorHeap* m_pHeap;\r\n\tUINT32 m_CurrentHandleIndex;\r\n\tUINT32 m_DescriptorSize;\r\n\r\npublic:\r\n\tDynamicDescriptorHeap() :\r\n\t\tm_CurrentHandleIndex(0)\r\n\t{\r\n\t}\r\n\r\n\tHRESULT Allocate(UINT32 ElementCount, D3D12_GPU_DESCRIPTOR_HANDLE* pGpuHandleStart, D3D12_CPU_DESCRIPTOR_HANDLE* pCpuHandleStart)\r\n\t{\r\n\t\tif (m_CurrentHandleIndex + ElementCount > DYNAMIC_HEAP_SIZE)\r\n\t\t{\r\n\t\t\treturn E_OUTOFMEMORY;\r\n\t\t}\r\n\r\n\t\tUINT32 Offset = m_CurrentHandleIndex * m_DescriptorSize;\r\n\t\tCD3DX12_GPU_DESCRIPTOR_HANDLE GpuHandle(m_pHeap->pHeap->GetGPUDescriptorHandleForHeapStart(), Offset);\r\n\t\tCD3DX12_CPU_DESCRIPTOR_HANDLE CpuHandle(m_pHeap->pHeap->GetCPUDescriptorHandleForHeapStart(), Offset);\r\n\r\n\t\t*pGpuHandleStart = GpuHandle;\r\n\t\t*pCpuHandleStart = CpuHandle;\r\n\r\n\t\tm_CurrentHandleIndex += ElementCount;\r\n\r\n\t\treturn S_OK;\r\n\t}\r\n\r\n\tvoid Reset()\r\n\t{\r\n\t\tm_CurrentHandleIndex = 0;\r\n\t}\r\n};\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/d3dx12.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#ifndef __D3DX12_H__\r\n#define __D3DX12_H__\r\n\r\n#include \"d3d12.h\"\r\n\r\n#if defined( __cplusplus )\r\n\r\nstruct CD3DX12_DEFAULT {};\r\nextern const DECLSPEC_SELECTANY CD3DX12_DEFAULT D3D12_DEFAULT;\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator==( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{\r\n    return l.TopLeftX == r.TopLeftX && l.TopLeftY == r.TopLeftY && l.Width == r.Width &&\r\n        l.Height == r.Height && l.MinDepth == r.MinDepth && l.MaxDepth == r.MaxDepth;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool operator!=( const D3D12_VIEWPORT& l, const D3D12_VIEWPORT& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RECT : public D3D12_RECT\r\n{\r\n    CD3DX12_RECT()\r\n    {}\r\n    explicit CD3DX12_RECT( const D3D12_RECT& o ) :\r\n        D3D12_RECT( o )\r\n    {}\r\n    explicit CD3DX12_RECT(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        right = Right;\r\n        bottom = Bottom;\r\n    }\r\n    ~CD3DX12_RECT() {}\r\n    operator const D3D12_RECT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VIEWPORT : public D3D12_VIEWPORT\r\n{\r\n    CD3DX12_VIEWPORT()\r\n    {}\r\n    explicit CD3DX12_VIEWPORT( const D3D12_VIEWPORT& o ) :\r\n        D3D12_VIEWPORT( o )\r\n    {}\r\n    explicit CD3DX12_VIEWPORT(\r\n        FLOAT topLeftX,\r\n        FLOAT topLeftY,\r\n        FLOAT width,\r\n        FLOAT height,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        TopLeftX = topLeftX;\r\n        TopLeftY = topLeftY;\r\n        Width = width;\r\n        Height = height;\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    explicit CD3DX12_VIEWPORT(\r\n        _In_ ID3D12Resource* pResource,\r\n        UINT mipSlice = 0,\r\n        FLOAT topLeftX = 0.0f,\r\n        FLOAT topLeftY = 0.0f,\r\n        FLOAT minDepth = D3D12_MIN_DEPTH,\r\n        FLOAT maxDepth = D3D12_MAX_DEPTH )\r\n    {\r\n        D3D12_RESOURCE_DESC Desc = pResource->GetDesc();\r\n        const UINT64 SubresourceWidth = Desc.Width >> mipSlice;\r\n        const UINT64 SubresourceHeight = Desc.Height >> mipSlice;\r\n        switch (Desc.Dimension)\r\n        {\r\n        case D3D12_RESOURCE_DIMENSION_BUFFER:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = Desc.Width - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE1D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = 0.0f;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = 1.0f;\r\n            break;\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE2D:\r\n        case D3D12_RESOURCE_DIMENSION_TEXTURE3D:\r\n            TopLeftX = topLeftX;\r\n            TopLeftY = topLeftY;\r\n            Width = (SubresourceWidth ? SubresourceWidth : 1.0f) - topLeftX;\r\n            Height = (SubresourceHeight ? SubresourceHeight: 1.0f) - topLeftY;\r\n            break;\r\n        default: break;\r\n        }\r\n\r\n        MinDepth = minDepth;\r\n        MaxDepth = maxDepth;\r\n    }\r\n    ~CD3DX12_VIEWPORT() {}\r\n    operator const D3D12_VIEWPORT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BOX : public D3D12_BOX\r\n{\r\n    CD3DX12_BOX()\r\n    {}\r\n    explicit CD3DX12_BOX( const D3D12_BOX& o ) :\r\n        D3D12_BOX( o )\r\n    {}\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Right )\r\n    {\r\n        left = Left;\r\n        top = 0;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = 1;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Right,\r\n        LONG Bottom )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = 0;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = 1;\r\n    }\r\n    explicit CD3DX12_BOX(\r\n        LONG Left,\r\n        LONG Top,\r\n        LONG Front,\r\n        LONG Right,\r\n        LONG Bottom,\r\n        LONG Back )\r\n    {\r\n        left = Left;\r\n        top = Top;\r\n        front = Front;\r\n        right = Right;\r\n        bottom = Bottom;\r\n        back = Back;\r\n    }\r\n    ~CD3DX12_BOX() {}\r\n    operator const D3D12_BOX&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{\r\n    return l.left == r.left && l.top == r.top && l.front == r.front &&\r\n        l.right == r.right && l.bottom == r.bottom && l.back == r.back;\r\n}\r\ninline bool operator!=( const D3D12_BOX& l, const D3D12_BOX& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC\r\n{\r\n    CD3DX12_DEPTH_STENCIL_DESC()\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) :\r\n        D3D12_DEPTH_STENCIL_DESC( o )\r\n    {}\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        DepthEnable = TRUE;\r\n        DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;\r\n        DepthFunc = D3D12_COMPARISON_FUNC_LESS;\r\n        StencilEnable = FALSE;\r\n        StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;\r\n        StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;\r\n        const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =\r\n        { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };\r\n        FrontFace = defaultStencilOp;\r\n        BackFace = defaultStencilOp;\r\n    }\r\n    explicit CD3DX12_DEPTH_STENCIL_DESC(\r\n        BOOL depthEnable,\r\n        D3D12_DEPTH_WRITE_MASK depthWriteMask,\r\n        D3D12_COMPARISON_FUNC depthFunc,\r\n        BOOL stencilEnable,\r\n        UINT8 stencilReadMask,\r\n        UINT8 stencilWriteMask,\r\n        D3D12_STENCIL_OP frontStencilFailOp,\r\n        D3D12_STENCIL_OP frontStencilDepthFailOp,\r\n        D3D12_STENCIL_OP frontStencilPassOp,\r\n        D3D12_COMPARISON_FUNC frontStencilFunc,\r\n        D3D12_STENCIL_OP backStencilFailOp,\r\n        D3D12_STENCIL_OP backStencilDepthFailOp,\r\n        D3D12_STENCIL_OP backStencilPassOp,\r\n        D3D12_COMPARISON_FUNC backStencilFunc )\r\n    {\r\n        DepthEnable = depthEnable;\r\n        DepthWriteMask = depthWriteMask;\r\n        DepthFunc = depthFunc;\r\n        StencilEnable = stencilEnable;\r\n        StencilReadMask = stencilReadMask;\r\n        StencilWriteMask = stencilWriteMask;\r\n        FrontFace.StencilFailOp = frontStencilFailOp;\r\n        FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;\r\n        FrontFace.StencilPassOp = frontStencilPassOp;\r\n        FrontFace.StencilFunc = frontStencilFunc;\r\n        BackFace.StencilFailOp = backStencilFailOp;\r\n        BackFace.StencilDepthFailOp = backStencilDepthFailOp;\r\n        BackFace.StencilPassOp = backStencilPassOp;\r\n        BackFace.StencilFunc = backStencilFunc;\r\n    }\r\n    ~CD3DX12_DEPTH_STENCIL_DESC() {}\r\n    operator const D3D12_DEPTH_STENCIL_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC\r\n{\r\n    CD3DX12_BLEND_DESC()\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) :\r\n        D3D12_BLEND_DESC( o )\r\n    {}\r\n    explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        AlphaToCoverageEnable = FALSE;\r\n        IndependentBlendEnable = FALSE;\r\n        const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =\r\n        {\r\n            FALSE,FALSE,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,\r\n            D3D12_LOGIC_OP_NOOP,\r\n            D3D12_COLOR_WRITE_ENABLE_ALL,\r\n        };\r\n        for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)\r\n            RenderTarget[ i ] = defaultRenderTargetBlendDesc;\r\n    }\r\n    ~CD3DX12_BLEND_DESC() {}\r\n    operator const D3D12_BLEND_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC\r\n{\r\n    CD3DX12_RASTERIZER_DESC()\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) :\r\n        D3D12_RASTERIZER_DESC( o )\r\n    {}\r\n    explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT )\r\n    {\r\n        FillMode = D3D12_FILL_MODE_SOLID;\r\n        CullMode = D3D12_CULL_MODE_BACK;\r\n        FrontCounterClockwise = FALSE;\r\n        DepthBias = D3D12_DEFAULT_DEPTH_BIAS;\r\n        DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;\r\n        SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;\r\n        DepthClipEnable = TRUE;\r\n        MultisampleEnable = FALSE;\r\n        AntialiasedLineEnable = FALSE;\r\n        ForcedSampleCount = 0;\r\n        ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;\r\n    }\r\n    explicit CD3DX12_RASTERIZER_DESC(\r\n        D3D12_FILL_MODE fillMode,\r\n        D3D12_CULL_MODE cullMode,\r\n        BOOL frontCounterClockwise,\r\n        INT depthBias,\r\n        FLOAT depthBiasClamp,\r\n        FLOAT slopeScaledDepthBias,\r\n        BOOL depthClipEnable,\r\n        BOOL multisampleEnable,\r\n        BOOL antialiasedLineEnable, \r\n        UINT forcedSampleCount, \r\n        D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster)\r\n    {\r\n        FillMode = fillMode;\r\n        CullMode = cullMode;\r\n        FrontCounterClockwise = frontCounterClockwise;\r\n        DepthBias = depthBias;\r\n        DepthBiasClamp = depthBiasClamp;\r\n        SlopeScaledDepthBias = slopeScaledDepthBias;\r\n        DepthClipEnable = depthClipEnable;\r\n        MultisampleEnable = multisampleEnable;\r\n        AntialiasedLineEnable = antialiasedLineEnable;\r\n        ForcedSampleCount = forcedSampleCount;\r\n        ConservativeRaster = conservativeRaster;\r\n    }\r\n    ~CD3DX12_RASTERIZER_DESC() {}\r\n    operator const D3D12_RASTERIZER_DESC&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_ALLOCATION_INFO : public D3D12_RESOURCE_ALLOCATION_INFO\r\n{\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_ALLOCATION_INFO( const D3D12_RESOURCE_ALLOCATION_INFO& o ) :\r\n        D3D12_RESOURCE_ALLOCATION_INFO( o )\r\n    {}\r\n    CD3DX12_RESOURCE_ALLOCATION_INFO(\r\n        UINT64 size,\r\n        UINT64 alignment )\r\n    {\r\n        SizeInBytes = size;\r\n        Alignment = alignment;\r\n    }\r\n    operator const D3D12_RESOURCE_ALLOCATION_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES\r\n{\r\n    CD3DX12_HEAP_PROPERTIES()\r\n    {}\r\n    explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) :\r\n        D3D12_HEAP_PROPERTIES(o)\r\n    {}\r\n    CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference,\r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = D3D12_HEAP_TYPE_CUSTOM;\r\n        CPUPageProperty = cpuPageProperty;\r\n        MemoryPoolPreference = memoryPoolPreference;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    explicit CD3DX12_HEAP_PROPERTIES( \r\n        D3D12_HEAP_TYPE type, \r\n        UINT creationNodeMask = 1, \r\n        UINT nodeMask = 1 )\r\n    {\r\n        Type = type;\r\n        CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;\r\n        MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;\r\n        CreationNodeMask = creationNodeMask;\r\n        VisibleNodeMask = nodeMask;\r\n    }\r\n    operator const D3D12_HEAP_PROPERTIES&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    {\r\n        return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&\r\n            (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));\r\n    }\r\n};\r\ninline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{\r\n    return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty && \r\n        l.MemoryPoolPreference == r.MemoryPoolPreference &&\r\n        l.CreationNodeMask == r.CreationNodeMask &&\r\n        l.VisibleNodeMask == r.VisibleNodeMask;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_HEAP_DESC : public D3D12_HEAP_DESC\r\n{\r\n    CD3DX12_HEAP_DESC()\r\n    {}\r\n    explicit CD3DX12_HEAP_DESC(const D3D12_HEAP_DESC &o) :\r\n        D3D12_HEAP_DESC(o)\r\n    {}\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_PROPERTIES properties, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = properties;\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_HEAP_TYPE type, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        UINT64 size, \r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        UINT64 alignment = 0, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = size;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_PROPERTIES properties, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = properties;\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_HEAP_TYPE type, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( type );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    CD3DX12_HEAP_DESC( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_CPU_PAGE_PROPERTY cpuPageProperty, \r\n        D3D12_MEMORY_POOL memoryPoolPreference, \r\n        D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE )\r\n    {\r\n        SizeInBytes = resAllocInfo.SizeInBytes;\r\n        Properties = CD3DX12_HEAP_PROPERTIES( cpuPageProperty, memoryPoolPreference );\r\n        Alignment = resAllocInfo.Alignment;\r\n        Flags = flags;\r\n    }\r\n    operator const D3D12_HEAP_DESC&() const { return *this; }\r\n    bool IsCPUAccessible() const\r\n    { return static_cast< const CD3DX12_HEAP_PROPERTIES* >( &Properties )->IsCPUAccessible(); }\r\n};\r\ninline bool operator==( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{\r\n    return l.SizeInBytes == r.SizeInBytes &&\r\n        l.Properties == r.Properties && \r\n        l.Alignment == r.Alignment &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_HEAP_DESC& l, const D3D12_HEAP_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CLEAR_VALUE : public D3D12_CLEAR_VALUE\r\n{\r\n    CD3DX12_CLEAR_VALUE()\r\n    {}\r\n    explicit CD3DX12_CLEAR_VALUE(const D3D12_CLEAR_VALUE &o) :\r\n        D3D12_CLEAR_VALUE(o)\r\n    {}\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        const FLOAT color[4] )\r\n    {\r\n        Format = format;\r\n        memcpy( Color, color, sizeof( Color ) );\r\n    }\r\n    CD3DX12_CLEAR_VALUE( \r\n        DXGI_FORMAT format, \r\n        FLOAT depth,\r\n        UINT8 stencil )\r\n    {\r\n        Format = format;\r\n        /* Use memcpy to preserve NAN values */\r\n        memcpy( &DepthStencil.Depth, &depth, sizeof( depth ) );\r\n        DepthStencil.Stencil = stencil;\r\n    }\r\n    operator const D3D12_CLEAR_VALUE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RANGE : public D3D12_RANGE\r\n{\r\n    CD3DX12_RANGE()\r\n    {}\r\n    explicit CD3DX12_RANGE(const D3D12_RANGE &o) :\r\n        D3D12_RANGE(o)\r\n    {}\r\n    CD3DX12_RANGE( \r\n        SIZE_T begin, \r\n        SIZE_T end )\r\n    {\r\n        Begin = begin;\r\n        End = end;\r\n    }\r\n    operator const D3D12_RANGE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE\r\n{\r\n    CD3DX12_SHADER_BYTECODE()\r\n    {}\r\n    explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) :\r\n        D3D12_SHADER_BYTECODE(o)\r\n    {}\r\n    CD3DX12_SHADER_BYTECODE(\r\n        _In_ ID3DBlob* pShaderBlob )\r\n    {\r\n        pShaderBytecode = pShaderBlob->GetBufferPointer();\r\n        BytecodeLength = pShaderBlob->GetBufferSize();\r\n    }\r\n    CD3DX12_SHADER_BYTECODE(\r\n        _In_reads_(bytecodeLength) const void* _pShaderBytecode,\r\n        SIZE_T bytecodeLength )\r\n    {\r\n        pShaderBytecode = _pShaderBytecode;\r\n        BytecodeLength = bytecodeLength;\r\n    }\r\n    operator const D3D12_SHADER_BYTECODE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILED_RESOURCE_COORDINATE : public D3D12_TILED_RESOURCE_COORDINATE\r\n{\r\n    CD3DX12_TILED_RESOURCE_COORDINATE()\r\n    {}\r\n    explicit CD3DX12_TILED_RESOURCE_COORDINATE(const D3D12_TILED_RESOURCE_COORDINATE &o) :\r\n        D3D12_TILED_RESOURCE_COORDINATE(o)\r\n    {}\r\n    CD3DX12_TILED_RESOURCE_COORDINATE( \r\n        UINT x, \r\n        UINT y, \r\n        UINT z, \r\n        UINT subresource ) \r\n    {\r\n        X = x;\r\n        Y = y;\r\n        Z = z;\r\n        Subresource = subresource;\r\n    }\r\n    operator const D3D12_TILED_RESOURCE_COORDINATE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_REGION_SIZE : public D3D12_TILE_REGION_SIZE\r\n{\r\n    CD3DX12_TILE_REGION_SIZE()\r\n    {}\r\n    explicit CD3DX12_TILE_REGION_SIZE(const D3D12_TILE_REGION_SIZE &o) :\r\n        D3D12_TILE_REGION_SIZE(o)\r\n    {}\r\n    CD3DX12_TILE_REGION_SIZE( \r\n        UINT numTiles, \r\n        BOOL useBox, \r\n        UINT width, \r\n        UINT16 height, \r\n        UINT16 depth ) \r\n    {\r\n        NumTiles = numTiles;\r\n        UseBox = useBox;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n    }\r\n    operator const D3D12_TILE_REGION_SIZE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_TILING : public D3D12_SUBRESOURCE_TILING\r\n{\r\n    CD3DX12_SUBRESOURCE_TILING()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_TILING(const D3D12_SUBRESOURCE_TILING &o) :\r\n        D3D12_SUBRESOURCE_TILING(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_TILING( \r\n        UINT widthInTiles, \r\n        UINT16 heightInTiles, \r\n        UINT16 depthInTiles, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        WidthInTiles = widthInTiles;\r\n        HeightInTiles = heightInTiles;\r\n        DepthInTiles = depthInTiles;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_TILING&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TILE_SHAPE : public D3D12_TILE_SHAPE\r\n{\r\n    CD3DX12_TILE_SHAPE()\r\n    {}\r\n    explicit CD3DX12_TILE_SHAPE(const D3D12_TILE_SHAPE &o) :\r\n        D3D12_TILE_SHAPE(o)\r\n    {}\r\n    CD3DX12_TILE_SHAPE( \r\n        UINT widthInTexels, \r\n        UINT heightInTexels, \r\n        UINT depthInTexels ) \r\n    {\r\n        WidthInTexels = widthInTexels;\r\n        HeightInTexels = heightInTexels;\r\n        DepthInTexels = depthInTexels;\r\n    }\r\n    operator const D3D12_TILE_SHAPE&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER\r\n{\r\n    CD3DX12_RESOURCE_BARRIER()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) :\r\n        D3D12_RESOURCE_BARRIER(o)\r\n    {}\r\n    static inline CD3DX12_RESOURCE_BARRIER Transition(\r\n        _In_ ID3D12Resource* pResource,\r\n        D3D12_RESOURCE_STATES stateBefore,\r\n        D3D12_RESOURCE_STATES stateAfter,\r\n        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,\r\n        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\r\n        result.Flags = flags;\r\n        barrier.Transition.pResource = pResource;\r\n        barrier.Transition.StateBefore = stateBefore;\r\n        barrier.Transition.StateAfter = stateAfter;\r\n        barrier.Transition.Subresource = subresource;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER Aliasing(\r\n        _In_ ID3D12Resource* pResourceBefore,\r\n        _In_ ID3D12Resource* pResourceAfter)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;\r\n        barrier.Aliasing.pResourceBefore = pResourceBefore;\r\n        barrier.Aliasing.pResourceAfter = pResourceAfter;\r\n        return result;\r\n    }\r\n    static inline CD3DX12_RESOURCE_BARRIER UAV(\r\n        _In_ ID3D12Resource* pResource)\r\n    {\r\n        CD3DX12_RESOURCE_BARRIER result;\r\n        ZeroMemory(&result, sizeof(result));\r\n        D3D12_RESOURCE_BARRIER &barrier = result;\r\n        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;\r\n        barrier.UAV.pResource = pResource;\r\n        return result;\r\n    }\r\n    operator const D3D12_RESOURCE_BARRIER&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_PACKED_MIP_INFO : public D3D12_PACKED_MIP_INFO\r\n{\r\n    CD3DX12_PACKED_MIP_INFO()\r\n    {}\r\n    explicit CD3DX12_PACKED_MIP_INFO(const D3D12_PACKED_MIP_INFO &o) :\r\n        D3D12_PACKED_MIP_INFO(o)\r\n    {}\r\n    CD3DX12_PACKED_MIP_INFO( \r\n        UINT8 numStandardMips, \r\n        UINT8 numPackedMips, \r\n        UINT numTilesForPackedMips, \r\n        UINT startTileIndexInOverallResource ) \r\n    {\r\n        NumStandardMips = numStandardMips;\r\n        NumPackedMips = numPackedMips;\r\n        NumTilesForPackedMips = numTilesForPackedMips;\r\n        StartTileIndexInOverallResource = startTileIndexInOverallResource;\r\n    }\r\n    operator const D3D12_PACKED_MIP_INFO&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_SUBRESOURCE_FOOTPRINT : public D3D12_SUBRESOURCE_FOOTPRINT\r\n{\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT()\r\n    {}\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT(const D3D12_SUBRESOURCE_FOOTPRINT &o) :\r\n        D3D12_SUBRESOURCE_FOOTPRINT(o)\r\n    {}\r\n    CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        DXGI_FORMAT format, \r\n        UINT width, \r\n        UINT height, \r\n        UINT depth, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = format;\r\n        Width = width;\r\n        Height = height;\r\n        Depth = depth;\r\n        RowPitch = rowPitch;\r\n    }\r\n    explicit CD3DX12_SUBRESOURCE_FOOTPRINT( \r\n        const D3D12_RESOURCE_DESC& resDesc, \r\n        UINT rowPitch ) \r\n    {\r\n        Format = resDesc.Format;\r\n        Width = UINT( resDesc.Width );\r\n        Height = resDesc.Height;\r\n        Depth = (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? resDesc.DepthOrArraySize : 1);\r\n        RowPitch = rowPitch;\r\n    }\r\n    operator const D3D12_SUBRESOURCE_FOOTPRINT&() const { return *this; }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION\r\n{ \r\n    CD3DX12_TEXTURE_COPY_LOCATION()\r\n    {}\r\n    explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) :\r\n        D3D12_TEXTURE_COPY_LOCATION(o)\r\n    {}\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes) { pResource = pRes; }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\r\n        PlacedFootprint = Footprint;\r\n    }\r\n    CD3DX12_TEXTURE_COPY_LOCATION(ID3D12Resource* pRes, UINT Sub)\r\n    {\r\n        pResource = pRes;\r\n        Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\r\n        SubresourceIndex = Sub;\r\n    }\r\n}; \r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE : public D3D12_DESCRIPTOR_RANGE\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE(const D3D12_DESCRIPTOR_RANGE &o) :\r\n        D3D12_DESCRIPTOR_RANGE(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE : public D3D12_ROOT_DESCRIPTOR_TABLE\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE(const D3D12_ROOT_DESCRIPTOR_TABLE &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_CONSTANTS : public D3D12_ROOT_CONSTANTS\r\n{\r\n    CD3DX12_ROOT_CONSTANTS() {}\r\n    explicit CD3DX12_ROOT_CONSTANTS(const D3D12_ROOT_CONSTANTS &o) :\r\n        D3D12_ROOT_CONSTANTS(o)\r\n    {}\r\n    CD3DX12_ROOT_CONSTANTS(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_CONSTANTS &rootConstants,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        rootConstants.Num32BitValues = num32BitValues;\r\n        rootConstants.ShaderRegister = shaderRegister;\r\n        rootConstants.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR : public D3D12_ROOT_DESCRIPTOR\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR(const D3D12_ROOT_DESCRIPTOR &o) :\r\n        D3D12_ROOT_DESCRIPTOR(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    static inline void Init(_Out_ D3D12_ROOT_DESCRIPTOR &table, UINT shaderRegister, UINT registerSpace = 0)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER : public D3D12_ROOT_PARAMETER\r\n{\r\n    CD3DX12_ROOT_PARAMETER() {}\r\n    explicit CD3DX12_ROOT_PARAMETER(const D3D12_ROOT_PARAMETER &o) :\r\n        D3D12_ROOT_PARAMETER(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR::Init(rootParam.Descriptor, shaderRegister, registerSpace);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_STATIC_SAMPLER_DESC : public D3D12_STATIC_SAMPLER_DESC\r\n{\r\n    CD3DX12_STATIC_SAMPLER_DESC() {}\r\n    explicit CD3DX12_STATIC_SAMPLER_DESC(const D3D12_STATIC_SAMPLER_DESC &o) :\r\n        D3D12_STATIC_SAMPLER_DESC(o)\r\n    {}\r\n    CD3DX12_STATIC_SAMPLER_DESC(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_STATIC_SAMPLER_DESC &samplerDesc,\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        samplerDesc.ShaderRegister = shaderRegister;\r\n        samplerDesc.Filter = filter;\r\n        samplerDesc.AddressU = addressU;\r\n        samplerDesc.AddressV = addressV;\r\n        samplerDesc.AddressW = addressW;\r\n        samplerDesc.MipLODBias = mipLODBias;\r\n        samplerDesc.MaxAnisotropy = maxAnisotropy;\r\n        samplerDesc.ComparisonFunc = comparisonFunc;\r\n        samplerDesc.BorderColor = borderColor;\r\n        samplerDesc.MinLOD = minLOD;\r\n        samplerDesc.MaxLOD = maxLOD;\r\n        samplerDesc.ShaderVisibility = shaderVisibility;\r\n        samplerDesc.RegisterSpace = registerSpace;\r\n    }\r\n    inline void Init(\r\n         UINT shaderRegister,\r\n         D3D12_FILTER filter = D3D12_FILTER_ANISOTROPIC,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         D3D12_TEXTURE_ADDRESS_MODE addressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP,\r\n         FLOAT mipLODBias = 0,\r\n         UINT maxAnisotropy = 16,\r\n         D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL,\r\n         D3D12_STATIC_BORDER_COLOR borderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,\r\n         FLOAT minLOD = 0.f,\r\n         FLOAT maxLOD = D3D12_FLOAT32_MAX,\r\n         D3D12_SHADER_VISIBILITY shaderVisibility = D3D12_SHADER_VISIBILITY_ALL, \r\n         UINT registerSpace = 0)\r\n    {\r\n        Init(\r\n            *this,\r\n            shaderRegister,\r\n            filter,\r\n            addressU,\r\n            addressV,\r\n            addressW,\r\n            mipLODBias,\r\n            maxAnisotropy,\r\n            comparisonFunc,\r\n            borderColor,\r\n            minLOD,\r\n            maxLOD,\r\n            shaderVisibility,\r\n            registerSpace);\r\n    }\r\n    \r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_SIGNATURE_DESC : public D3D12_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    CD3DX12_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.NumParameters = numParameters;\r\n        desc.pParameters = _pParameters;\r\n        desc.NumStaticSamplers = numStaticSamplers;\r\n        desc.pStaticSamplers = _pStaticSamplers;\r\n        desc.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_DESCRIPTOR_RANGE1 : public D3D12_DESCRIPTOR_RANGE1\r\n{\r\n    CD3DX12_DESCRIPTOR_RANGE1() { }\r\n    explicit CD3DX12_DESCRIPTOR_RANGE1(const D3D12_DESCRIPTOR_RANGE1 &o) :\r\n        D3D12_DESCRIPTOR_RANGE1(o)\r\n    {}\r\n    CD3DX12_DESCRIPTOR_RANGE1(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    inline void Init(\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        Init(*this, rangeType, numDescriptors, baseShaderRegister, registerSpace, flags, offsetInDescriptorsFromTableStart);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_DESCRIPTOR_RANGE1 &range,\r\n        D3D12_DESCRIPTOR_RANGE_TYPE rangeType,\r\n        UINT numDescriptors,\r\n        UINT baseShaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_DESCRIPTOR_RANGE_FLAGS flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE,\r\n        UINT offsetInDescriptorsFromTableStart =\r\n        D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)\r\n    {\r\n        range.RangeType = rangeType;\r\n        range.NumDescriptors = numDescriptors;\r\n        range.BaseShaderRegister = baseShaderRegister;\r\n        range.RegisterSpace = registerSpace;\r\n        range.Flags = flags;\r\n        range.OffsetInDescriptorsFromTableStart = offsetInDescriptorsFromTableStart;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR_TABLE1 : public D3D12_ROOT_DESCRIPTOR_TABLE1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR_TABLE1(const D3D12_ROOT_DESCRIPTOR_TABLE1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR_TABLE1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR_TABLE1(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        Init(*this, numDescriptorRanges, _pDescriptorRanges);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR_TABLE1 &rootDescriptorTable,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_opt_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* _pDescriptorRanges)\r\n    {\r\n        rootDescriptorTable.NumDescriptorRanges = numDescriptorRanges;\r\n        rootDescriptorTable.pDescriptorRanges = _pDescriptorRanges;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_DESCRIPTOR1 : public D3D12_ROOT_DESCRIPTOR1\r\n{\r\n    CD3DX12_ROOT_DESCRIPTOR1() {}\r\n    explicit CD3DX12_ROOT_DESCRIPTOR1(const D3D12_ROOT_DESCRIPTOR1 &o) :\r\n        D3D12_ROOT_DESCRIPTOR1(o)\r\n    {}\r\n    CD3DX12_ROOT_DESCRIPTOR1(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void Init(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        Init(*this, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    static inline void Init(\r\n        _Out_ D3D12_ROOT_DESCRIPTOR1 &table, \r\n        UINT shaderRegister, \r\n        UINT registerSpace = 0, \r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE)\r\n    {\r\n        table.ShaderRegister = shaderRegister;\r\n        table.RegisterSpace = registerSpace;\r\n        table.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_ROOT_PARAMETER1 : public D3D12_ROOT_PARAMETER1\r\n{\r\n    CD3DX12_ROOT_PARAMETER1() {}\r\n    explicit CD3DX12_ROOT_PARAMETER1(const D3D12_ROOT_PARAMETER1 &o) :\r\n        D3D12_ROOT_PARAMETER1(o)\r\n    {}\r\n    \r\n    static inline void InitAsDescriptorTable(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR_TABLE1::Init(rootParam.DescriptorTable, numDescriptorRanges, pDescriptorRanges);\r\n    }\r\n\r\n    static inline void InitAsConstants(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_CONSTANTS::Init(rootParam.Constants, num32BitValues, shaderRegister, registerSpace);\r\n    }\r\n\r\n    static inline void InitAsConstantBufferView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsShaderResourceView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n\r\n    static inline void InitAsUnorderedAccessView(\r\n        _Out_ D3D12_ROOT_PARAMETER1 &rootParam,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;\r\n        rootParam.ShaderVisibility = visibility;\r\n        CD3DX12_ROOT_DESCRIPTOR1::Init(rootParam.Descriptor, shaderRegister, registerSpace, flags);\r\n    }\r\n    \r\n    inline void InitAsDescriptorTable(\r\n        UINT numDescriptorRanges,\r\n        _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE1* pDescriptorRanges,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsDescriptorTable(*this, numDescriptorRanges, pDescriptorRanges, visibility);\r\n    }\r\n    \r\n    inline void InitAsConstants(\r\n        UINT num32BitValues,\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstants(*this, num32BitValues, shaderRegister, registerSpace, visibility);\r\n    }\r\n\r\n    inline void InitAsConstantBufferView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsConstantBufferView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsShaderResourceView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsShaderResourceView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n\r\n    inline void InitAsUnorderedAccessView(\r\n        UINT shaderRegister,\r\n        UINT registerSpace = 0,\r\n        D3D12_ROOT_DESCRIPTOR_FLAGS flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,\r\n        D3D12_SHADER_VISIBILITY visibility = D3D12_SHADER_VISIBILITY_ALL)\r\n    {\r\n        InitAsUnorderedAccessView(*this, shaderRegister, registerSpace, flags, visibility);\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC : public D3D12_VERSIONED_ROOT_SIGNATURE_DESC\r\n{\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC() {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC &o) :\r\n        D3D12_VERSIONED_ROOT_SIGNATURE_DESC(o)\r\n    {}\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        Desc_1_0 = o;\r\n    }\r\n    explicit CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(const D3D12_ROOT_SIGNATURE_DESC1 &o)\r\n    {\r\n        Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        Desc_1_1 = o;\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC(CD3DX12_DEFAULT)\r\n    {\r\n        Init_1_1(0, NULL, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE);\r\n    }\r\n    \r\n    inline void Init_1_0(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_0(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_0(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_0;\r\n        desc.Desc_1_0.NumParameters = numParameters;\r\n        desc.Desc_1_0.pParameters = _pParameters;\r\n        desc.Desc_1_0.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_0.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_0.Flags = flags;\r\n    }\r\n\r\n    inline void Init_1_1(\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        Init_1_1(*this, numParameters, _pParameters, numStaticSamplers, _pStaticSamplers, flags);\r\n    }\r\n\r\n    static inline void Init_1_1(\r\n        _Out_ D3D12_VERSIONED_ROOT_SIGNATURE_DESC &desc,\r\n        UINT numParameters,\r\n        _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER1* _pParameters,\r\n        UINT numStaticSamplers = 0,\r\n        _In_reads_opt_(numStaticSamplers) const D3D12_STATIC_SAMPLER_DESC* _pStaticSamplers = NULL,\r\n        D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)\r\n    {\r\n        desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;\r\n        desc.Desc_1_1.NumParameters = numParameters;\r\n        desc.Desc_1_1.pParameters = _pParameters;\r\n        desc.Desc_1_1.NumStaticSamplers = numStaticSamplers;\r\n        desc.Desc_1_1.pStaticSamplers = _pStaticSamplers;\r\n        desc.Desc_1_1.Flags = flags;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_CPU_DESCRIPTOR_HANDLE : public D3D12_CPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_CPU_DESCRIPTOR_HANDLE(const D3D12_CPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_CPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    bool operator==(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    bool operator!=(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_CPU_DESCRIPTOR_HANDLE &operator=(const D3D12_CPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_CPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE\r\n{\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE() {}\r\n    explicit CD3DX12_GPU_DESCRIPTOR_HANDLE(const D3D12_GPU_DESCRIPTOR_HANDLE &o) :\r\n        D3D12_GPU_DESCRIPTOR_HANDLE(o)\r\n    {}\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(CD3DX12_DEFAULT) { ptr = 0; }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetScaledByIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &other, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(other, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    { \r\n        ptr += offsetInDescriptors * descriptorIncrementSize;\r\n        return *this;\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE& Offset(INT offsetScaledByIncrementSize) \r\n    { \r\n        ptr += offsetScaledByIncrementSize;\r\n        return *this;\r\n    }\r\n    inline bool operator==(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr == other.ptr);\r\n    }\r\n    inline bool operator!=(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE& other) const\r\n    {\r\n        return (ptr != other.ptr);\r\n    }\r\n    CD3DX12_GPU_DESCRIPTOR_HANDLE &operator=(const D3D12_GPU_DESCRIPTOR_HANDLE &other)\r\n    {\r\n        ptr = other.ptr;\r\n        return *this;\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetScaledByIncrementSize);\r\n    }\r\n    \r\n    inline void InitOffsetted(_In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        InitOffsetted(*this, base, offsetInDescriptors, descriptorIncrementSize);\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetScaledByIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetScaledByIncrementSize;\r\n    }\r\n    \r\n    static inline void InitOffsetted(_Out_ D3D12_GPU_DESCRIPTOR_HANDLE &handle, _In_ const D3D12_GPU_DESCRIPTOR_HANDLE &base, INT offsetInDescriptors, UINT descriptorIncrementSize)\r\n    {\r\n        handle.ptr = base.ptr + offsetInDescriptors * descriptorIncrementSize;\r\n    }\r\n};\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )\r\n{ \r\n    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize; \r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ntemplate <typename T, typename U, typename V>\r\ninline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice )\r\n{\r\n    MipSlice = static_cast<T>(Subresource % MipLevels);\r\n    ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);\r\n    PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline UINT8 D3D12GetFormatPlaneCount(\r\n    _In_ ID3D12Device* pDevice,\r\n    DXGI_FORMAT Format\r\n    )\r\n{\r\n    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {Format};\r\n    if (FAILED(pDevice->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo))))\r\n    {\r\n        return 0;\r\n    }\r\n    return formatInfo.PlaneCount;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\nstruct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC\r\n{\r\n    CD3DX12_RESOURCE_DESC()\r\n    {}\r\n    explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) :\r\n        D3D12_RESOURCE_DESC( o )\r\n    {}\r\n    CD3DX12_RESOURCE_DESC( \r\n        D3D12_RESOURCE_DIMENSION dimension,\r\n        UINT64 alignment,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depthOrArraySize,\r\n        UINT16 mipLevels,\r\n        DXGI_FORMAT format,\r\n        UINT sampleCount,\r\n        UINT sampleQuality,\r\n        D3D12_TEXTURE_LAYOUT layout,\r\n        D3D12_RESOURCE_FLAGS flags )\r\n    {\r\n        Dimension = dimension;\r\n        Alignment = alignment;\r\n        Width = width;\r\n        Height = height;\r\n        DepthOrArraySize = depthOrArraySize;\r\n        MipLevels = mipLevels;\r\n        Format = format;\r\n        SampleDesc.Count = sampleCount;\r\n        SampleDesc.Quality = sampleQuality;\r\n        Layout = layout;\r\n        Flags = flags;\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes, \r\n            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Buffer( \r\n        UINT64 width,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1, \r\n            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex1D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex2D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 arraySize = 1,\r\n        UINT16 mipLevels = 0,\r\n        UINT sampleCount = 1,\r\n        UINT sampleQuality = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize, \r\n            mipLevels, format, sampleCount, sampleQuality, layout, flags );\r\n    }\r\n    static inline CD3DX12_RESOURCE_DESC Tex3D( \r\n        DXGI_FORMAT format,\r\n        UINT64 width,\r\n        UINT height,\r\n        UINT16 depth,\r\n        UINT16 mipLevels = 0,\r\n        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,\r\n        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,\r\n        UINT64 alignment = 0 )\r\n    {\r\n        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth, \r\n            mipLevels, format, 1, 0, layout, flags );\r\n    }\r\n    inline UINT16 Depth() const\r\n    { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT16 ArraySize() const\r\n    { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1); }\r\n    inline UINT8 PlaneCount(_In_ ID3D12Device* pDevice) const\r\n    { return D3D12GetFormatPlaneCount(pDevice, Format); }\r\n    inline UINT Subresources(_In_ ID3D12Device* pDevice) const\r\n    { return MipLevels * ArraySize() * PlaneCount(pDevice); }\r\n    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice)\r\n    { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }\r\n    operator const D3D12_RESOURCE_DESC&() const { return *this; }\r\n};\r\ninline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{\r\n    return l.Dimension == r.Dimension &&\r\n        l.Alignment == r.Alignment &&\r\n        l.Width == r.Width &&\r\n        l.Height == r.Height &&\r\n        l.DepthOrArraySize == r.DepthOrArraySize &&\r\n        l.MipLevels == r.MipLevels &&\r\n        l.Format == r.Format &&\r\n        l.SampleDesc.Count == r.SampleDesc.Count &&\r\n        l.SampleDesc.Quality == r.SampleDesc.Quality &&\r\n        l.Layout == r.Layout &&\r\n        l.Flags == r.Flags;\r\n}\r\ninline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r )\r\n{ return !( l == r ); }\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Row-by-row memcpy\r\ninline void MemcpySubresource(\r\n    _In_ const D3D12_MEMCPY_DEST* pDest,\r\n    _In_ const D3D12_SUBRESOURCE_DATA* pSrc,\r\n    SIZE_T RowSizeInBytes,\r\n    UINT NumRows,\r\n    UINT NumSlices)\r\n{\r\n    for (UINT z = 0; z < NumSlices; ++z)\r\n    {\r\n        BYTE* pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;\r\n        const BYTE* pSrcSlice = reinterpret_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * z;\r\n        for (UINT y = 0; y < NumRows; ++y)\r\n        {\r\n            memcpy(pDestSlice + pDest->RowPitch * y,\r\n                   pSrcSlice + pSrc->RowPitch * y,\r\n                   RowSizeInBytes);\r\n        }\r\n    }\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Returns required size of a buffer to be used for data upload\r\ninline UINT64 GetRequiredIntermediateSize(\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources)\r\n{\r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    UINT64 RequiredSize = 0;\r\n    \r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// All arrays must be populated (e.g. by calling GetCopyableFootprints)\r\ninline UINT64 UpdateSubresources(\r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    UINT64 RequiredSize,\r\n    _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,\r\n    _In_reads_(NumSubresources) const UINT* pNumRows,\r\n    _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,\r\n    _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    // Minor validation\r\n    D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();\r\n    D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();\r\n    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || \r\n        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || \r\n        RequiredSize > (SIZE_T)-1 || \r\n        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && \r\n            (FirstSubresource != 0 || NumSubresources != 1)))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    BYTE* pData;\r\n    HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));\r\n    if (FAILED(hr))\r\n    {\r\n        return 0;\r\n    }\r\n    \r\n    for (UINT i = 0; i < NumSubresources; ++i)\r\n    {\r\n        if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;\r\n        D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };\r\n        MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);\r\n    }\r\n    pIntermediate->Unmap(0, NULL);\r\n    \r\n    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\r\n    {\r\n        CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );\r\n        pCmdList->CopyBufferRegion(\r\n            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);\r\n    }\r\n    else\r\n    {\r\n        for (UINT i = 0; i < NumSubresources; ++i)\r\n        {\r\n            CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);\r\n            CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);\r\n            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);\r\n        }\r\n    }\r\n    return RequiredSize;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Heap-allocating UpdateSubresources implementation\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,\r\n    _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;\r\n    if (MemToAlloc > SIZE_MAX)\r\n    {\r\n       return 0;\r\n    }\r\n    void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));\r\n    if (pMem == NULL)\r\n    {\r\n       return 0;\r\n    }\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);\r\n    UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);\r\n    UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);\r\n    HeapFree(GetProcessHeap(), 0, pMem);\r\n    return Result;\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// Stack-allocating UpdateSubresources implementation\r\ntemplate <UINT MaxSubresources>\r\ninline UINT64 UpdateSubresources( \r\n    _In_ ID3D12GraphicsCommandList* pCmdList,\r\n    _In_ ID3D12Resource* pDestinationResource,\r\n    _In_ ID3D12Resource* pIntermediate,\r\n    UINT64 IntermediateOffset,\r\n    _In_range_(0, MaxSubresources) UINT FirstSubresource,\r\n    _In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,\r\n    _In_reads_(NumSubresources) D3D12_SUBRESOURCE_DATA* pSrcData)\r\n{\r\n    UINT64 RequiredSize = 0;\r\n    D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];\r\n    UINT NumRows[MaxSubresources];\r\n    UINT64 RowSizesInBytes[MaxSubresources];\r\n    \r\n    D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();\r\n    ID3D12Device* pDevice;\r\n    pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast<void**>(&pDevice));\r\n    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);\r\n    pDevice->Release();\r\n    \r\n    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout )\r\n{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }\r\n\r\n//------------------------------------------------------------------------------------------------\r\ninline ID3D12CommandList * const * CommandListCast(ID3D12GraphicsCommandList * const * pp)\r\n{\r\n    // This cast is useful for passing strongly typed command list pointers into\r\n    // ExecuteCommandLists.\r\n    // This cast is valid as long as the const-ness is respected. D3D12 APIs do\r\n    // respect the const-ness of their arguments.\r\n    return reinterpret_cast<ID3D12CommandList * const *>(pp);\r\n}\r\n\r\n//------------------------------------------------------------------------------------------------\r\n// D3D12 exports a new method for serializing root signatures in the Windows 10 Anniversary Update.\r\n// To help enable root signature 1.1 features when they are available and not require maintaining\r\n// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when\r\n// 1.1 is not supported.\r\ninline HRESULT D3DX12SerializeVersionedRootSignature(\r\n    _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,\r\n    D3D_ROOT_SIGNATURE_VERSION MaxVersion,\r\n    _Outptr_ ID3DBlob** ppBlob,\r\n    _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob)\r\n{\r\n    if (ppErrorBlob != NULL)\r\n    {\r\n        *ppErrorBlob = NULL;\r\n    }\r\n\r\n    switch (MaxVersion)\r\n    {\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n            switch (pRootSignatureDesc->Version)\r\n            {\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_0:\r\n                    return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n\r\n                case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n                {\r\n                    HRESULT hr = S_OK;\r\n                    const D3D12_ROOT_SIGNATURE_DESC1& desc_1_1 = pRootSignatureDesc->Desc_1_1;\r\n\r\n                    const SIZE_T ParametersSize = sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters;\r\n                    void* pParameters = (ParametersSize > 0) ? HeapAlloc(GetProcessHeap(), 0, ParametersSize) : NULL;\r\n                    if (ParametersSize > 0 && pParameters == NULL)\r\n                    {\r\n                        hr = E_OUTOFMEMORY;\r\n                    }\r\n                    D3D12_ROOT_PARAMETER* pParameters_1_0 = reinterpret_cast<D3D12_ROOT_PARAMETER*>(pParameters);\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            __analysis_assume(ParametersSize == sizeof(D3D12_ROOT_PARAMETER) * desc_1_1.NumParameters);\r\n                            pParameters_1_0[n].ParameterType = desc_1_1.pParameters[n].ParameterType;\r\n                            pParameters_1_0[n].ShaderVisibility = desc_1_1.pParameters[n].ShaderVisibility;\r\n\r\n                            switch (desc_1_1.pParameters[n].ParameterType)\r\n                            {\r\n                            case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:\r\n                                pParameters_1_0[n].Constants.Num32BitValues = desc_1_1.pParameters[n].Constants.Num32BitValues;\r\n                                pParameters_1_0[n].Constants.RegisterSpace = desc_1_1.pParameters[n].Constants.RegisterSpace;\r\n                                pParameters_1_0[n].Constants.ShaderRegister = desc_1_1.pParameters[n].Constants.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_CBV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_SRV:\r\n                            case D3D12_ROOT_PARAMETER_TYPE_UAV:\r\n                                pParameters_1_0[n].Descriptor.RegisterSpace = desc_1_1.pParameters[n].Descriptor.RegisterSpace;\r\n                                pParameters_1_0[n].Descriptor.ShaderRegister = desc_1_1.pParameters[n].Descriptor.ShaderRegister;\r\n                                break;\r\n\r\n                            case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:\r\n                                const D3D12_ROOT_DESCRIPTOR_TABLE1& table_1_1 = desc_1_1.pParameters[n].DescriptorTable;\r\n\r\n                                const SIZE_T DescriptorRangesSize = sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges;\r\n                                void* pDescriptorRanges = (DescriptorRangesSize > 0 && SUCCEEDED(hr)) ? HeapAlloc(GetProcessHeap(), 0, DescriptorRangesSize) : NULL;\r\n                                if (DescriptorRangesSize > 0 && pDescriptorRanges == NULL)\r\n                                {\r\n                                    hr = E_OUTOFMEMORY;\r\n                                }\r\n                                D3D12_DESCRIPTOR_RANGE* pDescriptorRanges_1_0 = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pDescriptorRanges);\r\n\r\n                                if (SUCCEEDED(hr))\r\n                                {\r\n                                    for (UINT x = 0; x < table_1_1.NumDescriptorRanges; x++)\r\n                                    {\r\n                                        __analysis_assume(DescriptorRangesSize == sizeof(D3D12_DESCRIPTOR_RANGE) * table_1_1.NumDescriptorRanges);\r\n                                        pDescriptorRanges_1_0[x].BaseShaderRegister = table_1_1.pDescriptorRanges[x].BaseShaderRegister;\r\n                                        pDescriptorRanges_1_0[x].NumDescriptors = table_1_1.pDescriptorRanges[x].NumDescriptors;\r\n                                        pDescriptorRanges_1_0[x].OffsetInDescriptorsFromTableStart = table_1_1.pDescriptorRanges[x].OffsetInDescriptorsFromTableStart;\r\n                                        pDescriptorRanges_1_0[x].RangeType = table_1_1.pDescriptorRanges[x].RangeType;\r\n                                        pDescriptorRanges_1_0[x].RegisterSpace = table_1_1.pDescriptorRanges[x].RegisterSpace;\r\n                                    }\r\n                                }\r\n\r\n                                D3D12_ROOT_DESCRIPTOR_TABLE& table_1_0 = pParameters_1_0[n].DescriptorTable;\r\n                                table_1_0.NumDescriptorRanges = table_1_1.NumDescriptorRanges;\r\n                                table_1_0.pDescriptorRanges = pDescriptorRanges_1_0;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (SUCCEEDED(hr))\r\n                    {\r\n                        CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, desc_1_1.pStaticSamplers, desc_1_1.Flags);\r\n                        hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);\r\n                    }\r\n\r\n                    if (pParameters)\r\n                    {\r\n                        for (UINT n = 0; n < desc_1_1.NumParameters; n++)\r\n                        {\r\n                            if (desc_1_1.pParameters[n].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)\r\n                            {\r\n                                HeapFree(GetProcessHeap(), 0, reinterpret_cast<void*>(const_cast<D3D12_DESCRIPTOR_RANGE*>(pParameters_1_0[n].DescriptorTable.pDescriptorRanges)));\r\n                            }\r\n                        }\r\n                        HeapFree(GetProcessHeap(), 0, pParameters);\r\n                    }\r\n                    return hr;\r\n                }\r\n            }\r\n            break;\r\n\r\n        case D3D_ROOT_SIGNATURE_VERSION_1_1:\r\n            return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);\r\n    }\r\n\r\n    return E_INVALIDARG;\r\n}\r\n\r\n\r\n#endif // defined( __cplusplus )\r\n\r\n#endif //__D3DX12_H__\r\n\r\n\r\n\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/main.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n\r\nint __cdecl main(int argc, LPCSTR argv[])\r\n{\r\n\t{\r\n\t\tD3D12MemoryManagement App;\r\n\t\tApp.LoadConfig(argc, argv);\r\n\t\tApp.Run();\r\n\t}\r\n\tCoUninitialize();\r\n}\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/stdafx.cpp",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#include \"stdafx.h\"\r\n"
  },
  {
    "path": "TechniqueDemos/D3D12MemoryManagement/src/stdafx.h",
    "content": "//*********************************************************\r\n//\r\n// Copyright (c) Microsoft. All rights reserved.\r\n// This code is licensed under the MIT License (MIT).\r\n// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF\r\n// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY\r\n// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR\r\n// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.\r\n//\r\n//*********************************************************\r\n\r\n#pragma once\r\n\r\n#define _KB(x) (x * 1024)\r\n#define _MB(x) (x * 1024 * 1024)\r\n\r\n#define _64KB _KB(64)\r\n#define _1MB _MB(1)\r\n#define _2MB _MB(2)\r\n#define _4MB _MB(4)\r\n#define _8MB _MB(8)\r\n#define _16MB _MB(16)\r\n#define _32MB _MB(32)\r\n#define _64MB _MB(64)\r\n#define _128MB _MB(128)\r\n#define _256MB _MB(256)\r\n\r\n#define TILE_SIZE _64KB\r\n#define MAX_HEAP_SIZE _16MB\r\n\r\n//\r\n// Specifies the default size of a buffer in a dynamic buffer.\r\n//\r\n#define DYNAMIC_BUFFER_SIZE (_64KB * 4)\r\n\r\n//\r\n// Specifies the default number of descriptors in a dynamic descriptor heap.\r\n//\r\n#define DYNAMIC_HEAP_SIZE 2048\r\n\r\n//\r\n// A texture can have a maximum dimension of 16384, or 2^14. This means\r\n// a texture can have a maximum of 15 mip levels, ranging from [0, 14].\r\n//\r\n#define MAX_MIP_COUNT_BITS 4\r\n#define MAX_MIP_COUNT (1 << MAX_MIP_COUNT_BITS)\r\n#define UNDEFINED_MIPMAP_INDEX (MAX_MIP_COUNT - 1)\r\n#define MAX_GENERATED_IMAGES 8\r\n\r\n#define SWAPCHAIN_BUFFER_COUNT 2\r\n#define STATISTIC_COUNT 60\r\n\r\n#ifndef WIN32_LEAN_AND_MEAN\r\n#define WIN32_LEAN_AND_MEAN\r\n#endif\r\n#include <Windows.h>\r\n#include <dxgi1_4.h>\r\n#include <d3d12.h>\r\n#include \"d3dx12.h\"\r\n#include <d3dcompiler.h>\r\n#include <DirectXMath.h>\r\n#include <d3d11on12.h>\r\n#include <d2d1_3.h>\r\n#include <dwrite_2.h>\r\n#include <wincodec.h>\r\n#include <stdio.h>\r\n#include <new>\r\n#include <vector>\r\n#include <wrl.h>\r\n\r\nusing Microsoft::WRL::ComPtr;\r\n\r\nstruct Frame;\r\nstruct PagingFrame;\r\nstruct RenderFrame;\r\nstruct ResourceMip;\r\nstruct ResourceDeviceState;\r\nstruct Resource;\r\nstruct Buffer;\r\nstruct DescriptorHeap;\r\n\r\nclass DX12Framework;\r\nclass Camera;\r\nclass Context;\r\nclass PagingWorkerThread;\r\nclass PagingContext;\r\nclass RenderContext;\r\nclass Shader;\r\nclass TextureShader;\r\nclass ColorShader;\r\nclass DynamicBuffer;\r\nclass DynamicDescriptorHeap;\r\n\r\nstruct RectF\r\n{\r\n\tfloat Left;\r\n\tfloat Top;\r\n\tfloat Right;\r\n\tfloat Bottom;\r\n};\r\n\r\nstruct PointF\r\n{\r\n\tfloat X;\r\n\tfloat Y;\r\n};\r\n\r\nstruct ColorF\r\n{\r\n\tfloat R;\r\n\tfloat G;\r\n\tfloat B;\r\n\tfloat A;\r\n};\r\n\r\n#include \"Log.h\"\r\n#include \"List.h\"\r\n\r\n#include \"Camera.h\"\r\n#include \"Shader.h\"\r\n#include \"Versioning.h\"\r\n#include \"Resource.h\"\r\n#include \"Util.h\"\r\n#include \"Context.h\"\r\n#include \"Render.h\"\r\n#include \"Paging.h\"\r\n#include \"Framework.h\"\r\n\r\ntemplate<typename T>\r\ninline void SafeRelease(T *&rpInterface)\r\n{\r\n\tT* pInterface = rpInterface;\r\n\r\n\tif (pInterface)\r\n\t{\r\n\t\tpInterface->Release();\r\n\t\trpInterface = nullptr;\r\n\t}\r\n}\r\n\r\ntemplate<typename T>\r\ninline void SafeDelete(T *&rpObject)\r\n{\r\n\tT* pObject = rpObject;\r\n\r\n\tif (pObject)\r\n\t{\r\n\t\tdelete pObject;\r\n\t\trpObject = nullptr;\r\n\t}\r\n}\r\n\r\n#include \"D3D12MemoryManagement.h\"\r\n\r\n#ifdef _DEBUG\r\n#include <Initguid.h>\r\n#include <dxgidebug.h>\r\n#endif\r\n"
  },
  {
    "path": "todo.md",
    "content": "# todo\n-custom upscaling algorithm with hdr rendering path\n\n"
  }
]