This commit is contained in:
TheRazerMD committed 2026-10-20 12:33:45 +02:00
commit b8b5b729b4
10 files changed
+828 -122

No files matched your search

+4
View File
@@ -518,6 +518,9 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
<ClInclude Include="resource.h" />
<ClInclude Include="scanner\rtti.h" />
<ClInclude Include="scanner\scanner.h" />
<ClInclude Include="shaders\auto_exposure\AE_Common.h" />
<ClInclude Include="shaders\auto_exposure\AE_Dx12.h" />
<ClInclude Include="shaders\auto_exposure\precompile\AE_Shader.h" />
<ClInclude Include="shaders\bias\Bias_Common.h" />
<ClInclude Include="shaders\bias\Bias_Dx11.h" />
<ClInclude Include="shaders\bias\Bias_Dx12.h" />
@@ -819,6 +822,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
<ClCompile Include="scanner\rtti.cpp" />
<ClCompile Include="scanner\scanner.cpp" />
<ClCompile Include="shaders\bias\Bias_Dx11.cpp" />
<ClCompile Include="shaders\auto_exposure\AE_Dx12.cpp" />
<ClCompile Include="shaders\bias\Bias_Dx12.cpp" />
<ClCompile Include="shaders\format_transfer\FT_Dx12.cpp" />
<ClCompile Include="shaders\output_scaling\OS_Dx11.cpp" />
+12
View File
@@ -188,6 +188,15 @@
<ClInclude Include="State.h">
<Filter>Config</Filter>
</ClInclude>
<ClInclude Include="shaders\auto_exposure\AE_Common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shaders\auto_exposure\AE_Dx12.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shaders\auto_exposure\precompile\AE_Shader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shaders\bias\Bias_Common.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1280,6 +1289,9 @@
<ClCompile Include="shaders\bias\Bias_Dx11.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shaders\auto_exposure\AE_Dx12.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shaders\bias\Bias_Dx12.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -0,0 +1,122 @@
#pragma once
#include "SysUtils.h"
static std::string aeShader = R"(
// Auto exposure from the log average luminance of the renderSize part of color, same as FSR2.
// FSR3 clamps the log luma instead of the luma, which makes every pixel darker than 1 count as 1
// and caps the exposure way too low for typical pre-exposed input.
cbuffer Params : register(b0)
{
uint2 RenderSize;
uint GroupCountX;
uint GroupCount;
float DeltaTime; // seconds
uint Reset;
uint PassIndex;
float PreExposure;
};
Texture2D<float4> Color : register(t0);
// [0] smoothed log luma carried between frames, [1..] per group log luma sums
RWStructuredBuffer<float> Data : register(u0);
RWTexture2D<float> Exposure : register(u1);
#define THREADS 256
#define TILE 32
static const float Epsilon = 6.10e-05f;
static const float Fp16Max = 65504.0f;
groupshared float Shared[THREADS];
float LogLuma(uint2 pos)
{
// Exposure is applied after FSR removes pre-exposure, so it has to be measured without it too
const float3 rgb = max(0.0f, Color.Load(int3(pos, 0)).rgb) / PreExposure;
const float luma = min(dot(rgb, float3(0.2126f, 0.7152f, 0.0722f)), Fp16Max);
return log(max(Epsilon, luma));
}
float GroupSum(float value, uint tid)
{
Shared[tid] = value;
GroupMemoryBarrierWithGroupSync();
[unroll]
for (uint stride = THREADS / 2; stride > 0; stride >>= 1)
{
if (tid < stride)
Shared[tid] += Shared[tid + stride];
GroupMemoryBarrierWithGroupSync();
}
return Shared[0];
}
float ComputeAutoExposureFromLavg(float Lavg)
{
Lavg = exp(Lavg);
const float S = 100.0f; // ISO arithmetic speed
const float K = 12.5f;
const float ExposureISO100 = log2((Lavg * S) / K);
const float q = 0.65f;
const float Lmax = (78.0f / (q * S)) * pow(2.0f, ExposureISO100);
return 1.0f / Lmax;
}
[numthreads(16, 16, 1)]
void CSMain(uint3 gid : SV_GroupID, uint3 gtid : SV_GroupThreadID, uint tid : SV_GroupIndex)
{
if (PassIndex == 0)
{
float sum = 0.0f;
[unroll]
for (uint y = 0; y < TILE; y += 16)
{
[unroll]
for (uint x = 0; x < TILE; x += 16)
{
const uint2 pos = gid.xy * TILE + gtid.xy + uint2(x, y);
if (all(pos < RenderSize))
sum += LogLuma(pos);
}
}
const float total = GroupSum(sum, tid);
if (tid == 0)
Data[1 + gid.y * GroupCountX + gid.x] = total;
}
else
{
float sum = 0.0f;
for (uint i = tid; i < GroupCount; i += THREADS)
sum += Data[1 + i];
const float total = GroupSum(sum, tid);
if (tid == 0)
{
float logLuma = total / (float(RenderSize.x) * float(RenderSize.y));
if (Reset == 0)
{
const float prevLogLuma = Data[0];
logLuma = prevLogLuma + (logLuma - prevLogLuma) * (1.0f - exp(-DeltaTime));
}
Data[0] = logLuma;
Exposure[uint2(0, 0)] = ComputeAutoExposureFromLavg(logLuma);
}
}
}
)";
@@ -0,0 +1,215 @@
#include "pch.h"
#include "AE_Dx12.h"
#include "AE_Common.h"
#include "precompile/AE_Shader.h"
#include <Config.h>
using Microsoft::WRL::ComPtr;
static constexpr uint32_t AE_THREADS = 256;
static constexpr uint32_t AE_TILE = 32;
bool AE_Dx12::CreateRootSignature(ID3D12Device* InDevice)
{
CD3DX12_DESCRIPTOR_RANGE1 ranges[2];
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 2, 0);
// Root constants, so every dispatch has its own values without a constant buffer per frame
CD3DX12_ROOT_PARAMETER1 rootParameters[2];
rootParameters[0].InitAsConstants(sizeof(InternalConstants) / sizeof(uint32_t), 0);
rootParameters[1].InitAsDescriptorTable(_countof(ranges), ranges);
CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSigDesc {};
rootSigDesc.Init_1_1(_countof(rootParameters), rootParameters);
ComPtr<ID3DBlob> errorBlob;
ComPtr<ID3DBlob> signatureBlob;
auto hr = D3D12SerializeVersionedRootSignature(&rootSigDesc, &signatureBlob, &errorBlob);
if (FAILED(hr))
{
LOG_ERROR("[{0}] D3D12SerializeVersionedRootSignature error {1:x}", _name, hr);
return false;
}
hr = InDevice->CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(),
IID_PPV_ARGS(&_rootSignature));
if (FAILED(hr))
{
LOG_ERROR("[{0}] CreateRootSignature error {1:x}", _name, hr);
return false;
}
return true;
}
bool AE_Dx12::EnsureDataBuffer(uint32_t InElements)
{
if (_data != nullptr && _dataElements >= InElements)
return true;
// Previous frames can still be using it
DeferredRelease::Release(_data);
_dataElements = 0;
_historyValid = false;
auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
auto desc = CD3DX12_RESOURCE_DESC::Buffer(InElements * sizeof(float), D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
auto hr = _device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&_data));
if (hr != S_OK)
{
LOG_ERROR("[{0}] CreateCommittedResource error {1:x}", _name, (unsigned int) hr);
return false;
}
_data->SetName(L"AE_Data");
_dataElements = InElements;
return true;
}
bool AE_Dx12::Dispatch(ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InColor, uint32_t InRenderWidth,
uint32_t InRenderHeight, float InPreExposure, float InDeltaTimeSeconds, bool InReset)
{
if (!_init || _device == nullptr || InCmdList == nullptr || InColor == nullptr || InRenderWidth == 0 ||
InRenderHeight == 0)
return false;
LOG_DEBUG("[{0}] Start!", _name);
const uint32_t groupCountX = (InRenderWidth + AE_TILE - 1) / AE_TILE;
const uint32_t groupCountY = (InRenderHeight + AE_TILE - 1) / AE_TILE;
const uint32_t groupCount = groupCountX * groupCountY;
if (!EnsureDataBuffer(groupCount + 1))
return false;
ScopedGpuTime_Dx12 scopedGpuTime(GpuTime.get(), InCmdList);
_counter++;
_counter = _counter % AE_NUM_OF_HEAPS;
FrameDescriptorHeap& currentHeap = _frameHeaps[_counter];
CreateShaderResourceView(_device, InColor, currentHeap.GetSrvCPU(0));
D3D12_UNORDERED_ACCESS_VIEW_DESC dataUav {};
dataUav.Format = DXGI_FORMAT_UNKNOWN;
dataUav.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
dataUav.Buffer.NumElements = _dataElements;
dataUav.Buffer.StructureByteStride = sizeof(float);
_device->CreateUnorderedAccessView(_data, nullptr, &dataUav, currentHeap.GetUavCPU(0));
CreateUnorderedAccessView(_device, _exposure, currentHeap.GetUavCPU(1), 0);
SetBufferState(InCmdList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, _exposure, &_exposureState);
// Previous pass 1 may still be reading the sums
auto dataBarrier = CD3DX12_RESOURCE_BARRIER::UAV(_data);
InCmdList->ResourceBarrier(1, &dataBarrier);
ID3D12DescriptorHeap* heaps[] = { currentHeap.GetHeapCSU() };
InCmdList->SetDescriptorHeaps(_countof(heaps), heaps);
InCmdList->SetComputeRootSignature(_rootSignature);
InCmdList->SetPipelineState(_pipelineState);
InCmdList->SetComputeRootDescriptorTable(1, currentHeap.GetTableGPUStart());
InternalConstants constants {};
constants.RenderWidth = InRenderWidth;
constants.RenderHeight = InRenderHeight;
constants.GroupCountX = groupCountX;
constants.GroupCount = groupCount;
constants.DeltaTime = std::clamp(InDeltaTimeSeconds, 0.0f, 1.0f);
constants.PreExposure = InPreExposure > 0.0f ? InPreExposure : 1.0f;
// Without history the scene luma is taken as is instead of adapting from a stale value
constants.Reset = (InReset || !_historyValid) ? 1 : 0;
// Per tile log luma sums
constants.PassIndex = 0;
InCmdList->SetComputeRoot32BitConstants(0, sizeof(constants) / sizeof(uint32_t), &constants, 0);
InCmdList->Dispatch(groupCountX, groupCountY, 1);
InCmdList->ResourceBarrier(1, &dataBarrier);
// Average, temporal adaptation and exposure
constants.PassIndex = 1;
InCmdList->SetComputeRoot32BitConstants(0, sizeof(constants) / sizeof(uint32_t), &constants, 0);
InCmdList->Dispatch(1, 1, 1);
SetBufferState(InCmdList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, _exposure, &_exposureState);
_historyValid = true;
return true;
}
AE_Dx12::AE_Dx12(std::string InName, ID3D12Device* InDevice) : Shader_Dx12(InName, InDevice)
{
if (InDevice == nullptr)
{
LOG_ERROR("InDevice is nullptr!");
return;
}
LOG_DEBUG("{0} start!", _name);
if (!CreateRootSignature(InDevice))
{
LOG_ERROR("Failed to create root signature");
return;
}
if (!CreateComputePipeline(InDevice, &_pipelineState, AE_cso, sizeof(AE_cso), aeShader.c_str()))
{
LOG_ERROR("[{0}] Failed to create compute pipeline", _name);
return;
}
auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
auto desc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 1, 1, 0,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
auto hr = InDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, _exposureState, nullptr,
IID_PPV_ARGS(&_exposure));
if (hr != S_OK)
{
LOG_ERROR("[{0}] CreateCommittedResource error {1:x}", _name, (unsigned int) hr);
return;
}
_exposure->SetName(L"AE_Exposure");
ScopedSkipHeapCapture skipHeapCapture {};
for (int i = 0; i < AE_NUM_OF_HEAPS; i++)
{
if (!_frameHeaps[i].Initialize(InDevice, 1, 2, 0))
{
LOG_ERROR("[{0}] Failed to init heap", _name);
return;
}
}
_init = true;
}
AE_Dx12::~AE_Dx12()
{
if (State::Instance().isShuttingDown)
return;
for (int i = 0; i < AE_NUM_OF_HEAPS; i++)
_frameHeaps[i].ReleaseHeaps();
DeferredRelease::Release(_data);
DeferredRelease::Release(_exposure);
}
@@ -0,0 +1,49 @@
#pragma once
#include <d3d12.h>
#include <d3dx/d3dx12.h>
#include <shaders/Shader_Dx12Utils.h>
#include <shaders/Shader_Dx12.h>
#define AE_NUM_OF_HEAPS 2
// Computes an FSR2 style auto exposure from the renderSize part of color into a 1x1 R32_FLOAT texture
class AE_Dx12 : public Shader_Dx12
{
private:
struct InternalConstants
{
uint32_t RenderWidth;
uint32_t RenderHeight;
uint32_t GroupCountX;
uint32_t GroupCount;
float DeltaTime;
uint32_t Reset;
uint32_t PassIndex;
float PreExposure;
};
FrameDescriptorHeap _frameHeaps[AE_NUM_OF_HEAPS];
// [0] smoothed log luma, [1..] per group sums
ID3D12Resource* _data = nullptr;
uint32_t _dataElements = 0;
ID3D12Resource* _exposure = nullptr;
D3D12_RESOURCE_STATES _exposureState = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
bool _historyValid = false;
bool CreateRootSignature(ID3D12Device* InDevice);
bool EnsureDataBuffer(uint32_t InElements);
public:
// Leaves Exposure() in NON_PIXEL_SHADER_RESOURCE
bool Dispatch(ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InColor, uint32_t InRenderWidth,
uint32_t InRenderHeight, float InPreExposure, float InDeltaTimeSeconds, bool InReset);
ID3D12Resource* Exposure() { return _exposure; }
AE_Dx12(std::string InName, ID3D12Device* InDevice);
~AE_Dx12();
};
@@ -0,0 +1,116 @@
// Auto exposure from the log average luminance of the renderSize part of color, same as FSR2.
// FSR3 clamps the log luma instead of the luma, which makes every pixel darker than 1 count as 1
// and caps the exposure way too low for typical pre-exposed input.
cbuffer Params : register(b0)
{
uint2 RenderSize;
uint GroupCountX;
uint GroupCount;
float DeltaTime; // seconds
uint Reset;
uint PassIndex;
float PreExposure;
};
Texture2D<float4> Color : register(t0);
// [0] smoothed log luma carried between frames, [1..] per group log luma sums
RWStructuredBuffer<float> Data : register(u0);
RWTexture2D<float> Exposure : register(u1);
#define THREADS 256
#define TILE 32
static const float Epsilon = 6.10e-05f;
static const float Fp16Max = 65504.0f;
groupshared float Shared[THREADS];
float LogLuma(uint2 pos)
{
// Exposure is applied after FSR removes pre-exposure, so it has to be measured without it too
const float3 rgb = max(0.0f, Color.Load(int3(pos, 0)).rgb) / PreExposure;
const float luma = min(dot(rgb, float3(0.2126f, 0.7152f, 0.0722f)), Fp16Max);
return log(max(Epsilon, luma));
}
float GroupSum(float value, uint tid)
{
Shared[tid] = value;
GroupMemoryBarrierWithGroupSync();
[unroll]
for (uint stride = THREADS / 2; stride > 0; stride >>= 1)
{
if (tid < stride)
Shared[tid] += Shared[tid + stride];
GroupMemoryBarrierWithGroupSync();
}
return Shared[0];
}
float ComputeAutoExposureFromLavg(float Lavg)
{
Lavg = exp(Lavg);
const float S = 100.0f; // ISO arithmetic speed
const float K = 12.5f;
const float ExposureISO100 = log2((Lavg * S) / K);
const float q = 0.65f;
const float Lmax = (78.0f / (q * S)) * pow(2.0f, ExposureISO100);
return 1.0f / Lmax;
}
[numthreads(16, 16, 1)]
void CSMain(uint3 gid : SV_GroupID, uint3 gtid : SV_GroupThreadID, uint tid : SV_GroupIndex)
{
if (PassIndex == 0)
{
float sum = 0.0f;
[unroll]
for (uint y = 0; y < TILE; y += 16)
{
[unroll]
for (uint x = 0; x < TILE; x += 16)
{
const uint2 pos = gid.xy * TILE + gtid.xy + uint2(x, y);
if (all(pos < RenderSize))
sum += LogLuma(pos);
}
}
const float total = GroupSum(sum, tid);
if (tid == 0)
Data[1 + gid.y * GroupCountX + gid.x] = total;
}
else
{
float sum = 0.0f;
for (uint i = tid; i < GroupCount; i += THREADS)
sum += Data[1 + i];
const float total = GroupSum(sum, tid);
if (tid == 0)
{
float logLuma = total / (float(RenderSize.x) * float(RenderSize.y));
if (Reset == 0)
{
const float prevLogLuma = Data[0];
logLuma = prevLogLuma + (logLuma - prevLogLuma) * (1.0f - exp(-DeltaTime));
}
Data[0] = logLuma;
Exposure[uint2(0, 0)] = ComputeAutoExposureFromLavg(logLuma);
}
}
}
@@ -0,0 +1,270 @@
#pragma once
inline static const unsigned char AE_cso[] = {
0x44, 0x58, 0x42, 0x43, 0xd2, 0x6a, 0x7a, 0xda, 0xbb, 0xd6, 0x4d, 0xc4, 0xb8, 0x47, 0xc3, 0x30, 0x1f, 0x66, 0xb0,
0x6d, 0x01, 0x00, 0x00, 0x00, 0xb4, 0x13, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48, 0x00,
0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x53,
0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0xb0, 0x00, 0x00, 0x00, 0x34, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x43, 0x53, 0x4d, 0x61, 0x69, 0x6e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x0c, 0x61, 0x0f,
0xc3, 0xec, 0x9f, 0x9f, 0x6a, 0x57, 0x95, 0xca, 0xfe, 0x32, 0x60, 0xf8, 0x44, 0x58, 0x49, 0x4c, 0x70, 0x12, 0x00,
0x00, 0x60, 0x00, 0x05, 0x00, 0x9c, 0x04, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x58, 0x12, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x93, 0x04, 0x00, 0x00, 0x0b,
0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45,
0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90,
0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41,
0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03,
0x20, 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x36, 0x18, 0xc4, 0xff, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x03, 0x48, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20,
0x4c, 0x08, 0x86, 0x09, 0x01, 0x01, 0x00, 0x89, 0x20, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09,
0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c,
0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0xdc, 0xc1, 0x0c, 0x40, 0x02, 0x0a, 0x00, 0x83, 0x08, 0xc1, 0x30, 0x02, 0x50,
0x82, 0x81, 0x88, 0x39, 0x02, 0x30, 0x28, 0x83, 0x61, 0x18, 0x74, 0x14, 0xc1, 0x30, 0x28, 0x29, 0x03, 0x60, 0x00,
0xb4, 0xcc, 0x11, 0x20, 0xd4, 0xdc, 0x33, 0x5c, 0xfe, 0x84, 0x3d, 0x84, 0xe4, 0x87, 0x40, 0x33, 0x2c, 0x04, 0x0a,
0x9c, 0xb2, 0x0c, 0xc6, 0x63, 0x18, 0x06, 0x00, 0x00, 0x40, 0x43, 0x50, 0x21, 0x00, 0x03, 0x00, 0x48, 0xba, 0x69,
0xb8, 0xfc, 0x09, 0x7b, 0x08, 0xc9, 0x5f, 0x09, 0x69, 0x25, 0x26, 0xbf, 0xb8, 0x6d, 0x54, 0x00, 0x00, 0x00, 0x18,
0x45, 0xa1, 0x8c, 0xc7, 0x30, 0x0c, 0xc3, 0x30, 0x0c, 0xaa, 0x0a, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x40, 0x57,
0x19, 0x06, 0xc3, 0xa0, 0xec, 0xa8, 0xe1, 0xf2, 0x27, 0xec, 0x21, 0x24, 0x9f, 0xdb, 0xa8, 0x62, 0x25, 0x26, 0xbf,
0xb8, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x62, 0x33, 0x1e, 0x83, 0xb8, 0xa3, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90,
0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98, 0x7c, 0xe4, 0xb6, 0x11, 0x61, 0x18, 0x86, 0x51, 0x08, 0xcf, 0x78, 0x0c, 0xfa,
0xe6, 0x08, 0x82, 0x62, 0x3c, 0x46, 0x63, 0x18, 0x21, 0x89, 0x45, 0x19, 0x8c, 0xc7, 0x30, 0x00, 0x00, 0x00, 0x1a,
0x22, 0x4b, 0x41, 0x19, 0x8f, 0x61, 0x90, 0x39, 0x10, 0x30, 0x8c, 0x40, 0x00, 0x33, 0xb5, 0xc1, 0x38, 0xb0, 0x43,
0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29,
0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0,
0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x81, 0x1e, 0xe8, 0x41, 0x3b, 0xa4, 0x03, 0x3c, 0xcc, 0xc3,
0x2f, 0xd0, 0x43, 0x3e, 0xc0, 0x43, 0x39, 0xa0, 0xc0, 0x98, 0x49, 0x0c, 0xc6, 0x81, 0x1d, 0xc2, 0x61, 0x1e, 0xe6,
0xc1, 0x0d, 0x68, 0xa1, 0x1c, 0xf0, 0x81, 0x1e, 0xea, 0x41, 0x1e, 0xca, 0x41, 0x0e, 0x48, 0x81, 0x0f, 0xec, 0xa1,
0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xf8, 0xc0, 0x1c, 0xd8, 0xe1, 0x1d, 0xc2, 0x81, 0x1e, 0xd8, 0x00, 0x0c,
0xe8, 0xc0, 0x0f, 0xc0, 0xc0, 0x0f, 0x90, 0x90, 0xaa, 0xb4, 0xce, 0xf4, 0x8d, 0x03, 0x3b, 0x84, 0xc3, 0x3c, 0xcc,
0x83, 0x1b, 0xc8, 0xc2, 0x2d, 0xcc, 0x02, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xd4, 0x83, 0x3c, 0x94, 0x03,
0x39, 0x88, 0x42, 0x3d, 0x98, 0x83, 0x39, 0x94, 0x83, 0x3c, 0xf0, 0x81, 0x39, 0xb0, 0xc3, 0x3b, 0x84, 0x03, 0x3d,
0xf8, 0x01, 0x0a, 0x00, 0x6a, 0x67, 0xc2, 0xc6, 0x81, 0x1d, 0xc2, 0x61, 0x1e, 0xe6, 0xc1, 0x0d, 0x64, 0xe1, 0x16,
0x68, 0xa1, 0x1c, 0xf0, 0x81, 0x1e, 0xea, 0x41, 0x1e, 0xca, 0x41, 0x0e, 0x48, 0x81, 0x0f, 0xcc, 0x81, 0x1d, 0xde,
0x21, 0x1c, 0xe8, 0xc1, 0x0f, 0x50, 0x00, 0xd0, 0x3b, 0x8c, 0x20, 0x18, 0x67, 0xa4, 0x40, 0x04, 0x30, 0x12, 0x3a,
0x62, 0xc3, 0x00, 0x0c, 0x03, 0x20, 0x79, 0x8e, 0x00, 0x14, 0xa6, 0x00, 0x06, 0x11, 0x80, 0x01, 0x00, 0x00, 0x00,
0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d,
0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20,
0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07,
0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76,
0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60,
0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07,
0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x3a, 0x0f, 0x24, 0x90, 0x21, 0x23, 0x45, 0x44, 0x00, 0x76, 0x00, 0xf0, 0x90,
0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0xcf, 0x01, 0x04, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x9e, 0x03, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x86, 0x3c, 0x09, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x16, 0x20, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x40, 0x40, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0xe4, 0x91, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x53, 0x01, 0x01,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xe7, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x21, 0x4f, 0x06, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x1e, 0x0e,
0x08, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x1f, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0xc4, 0x00, 0x08, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
0x3c, 0x64, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x1e, 0x33, 0x00, 0x02, 0x60,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x18,
0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x32, 0x4a, 0x60, 0x04, 0xa0, 0x24, 0x8a, 0xa1,
0x08, 0x0a, 0xa3, 0x10, 0x0a, 0xa8, 0x40, 0x28, 0x1c, 0x01, 0x20, 0x7a, 0x04, 0xa0, 0x40, 0x08, 0x9e, 0x01, 0xa0,
0x79, 0x06, 0x80, 0xdc, 0x19, 0x00, 0x62, 0x67, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x1a,
0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x8f, 0x0c, 0x6f, 0xec, 0xed, 0x4d, 0x0c, 0x24, 0xc6, 0x25, 0xc7, 0x45,
0xc6, 0x06, 0x46, 0xc6, 0x25, 0xe6, 0x06, 0x04, 0x45, 0x26, 0x86, 0x4c, 0x06, 0xc7, 0xec, 0x46, 0xe6, 0x26, 0x65,
0x43, 0x10, 0x4c, 0x10, 0x0c, 0x68, 0x82, 0x60, 0x44, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x18, 0xd2, 0x06, 0x61, 0x30,
0x28, 0x8c, 0xcd, 0x4d, 0x10, 0x8c, 0x69, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x81, 0x0d, 0x3e, 0x02, 0x13, 0x04, 0x83,
0xda, 0x20, 0x10, 0xc6, 0x86, 0x84, 0x58, 0x18, 0x82, 0x18, 0x1a, 0xc2, 0xd9, 0x10, 0x3c, 0x13, 0x04, 0x37, 0xf0,
0x26, 0x08, 0x46, 0x35, 0x41, 0x08, 0x83, 0x6c, 0x82, 0x60, 0x58, 0x1b, 0x84, 0x81, 0xda, 0xb0, 0x10, 0x11, 0x43,
0x10, 0x83, 0x34, 0x4d, 0x53, 0x35, 0x41, 0x80, 0x03, 0x6e, 0xc3, 0x32, 0x5c, 0x0c, 0x31, 0x0c, 0xcd, 0x34, 0x4d,
0xce, 0x06, 0xc1, 0xc2, 0x26, 0x08, 0x73, 0xd0, 0x4d, 0x10, 0x8c, 0x6b, 0x03, 0x42, 0x68, 0x0c, 0x41, 0x0c, 0x1b,
0xb0, 0x21, 0xe0, 0x36, 0x10, 0x50, 0xd6, 0x01, 0x13, 0x84, 0x22, 0xa0, 0x31, 0x34, 0xd5, 0x14, 0x96, 0xe6, 0x36,
0x41, 0xa0, 0x83, 0x6d, 0x82, 0x60, 0x60, 0x1b, 0x06, 0x31, 0x10, 0x83, 0x61, 0x03, 0x41, 0x84, 0x01, 0x35, 0x06,
0x1b, 0x8a, 0x0f, 0x0c, 0x00, 0x8f, 0x0c, 0x58, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xf1, 0x79, 0x6b, 0x73, 0x4b, 0x83,
0x7b, 0xa3, 0x2b, 0x73, 0xa3, 0x03, 0x19, 0x43, 0x0b, 0x93, 0x63, 0x34, 0x95, 0xd6, 0x06, 0xc7, 0x56, 0x06, 0x32,
0xf4, 0x32, 0xb4, 0xb2, 0x02, 0x42, 0x25, 0x14, 0x14, 0xb4, 0x21, 0x40, 0x83, 0x09, 0x02, 0x1d, 0x68, 0x1b, 0x86,
0x33, 0x48, 0x03, 0x35, 0xd8, 0x30, 0x98, 0xc1, 0x1a, 0xa8, 0xc1, 0x86, 0x81, 0x0d, 0xd8, 0x40, 0x0d, 0xaa, 0xb0,
0xb1, 0xd9, 0xb5, 0xb9, 0xa4, 0x91, 0x95, 0xb9, 0xd1, 0x4d, 0x09, 0x82, 0x2a, 0x64, 0x78, 0x2e, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x53, 0x02, 0xa2, 0x09, 0x19, 0x9e, 0x8b, 0x5d, 0x18, 0x9b, 0x5d, 0x99, 0xdc, 0x94, 0xc0,
0xa8, 0x43, 0x86, 0xe7, 0x32, 0x87, 0x16, 0x46, 0x56, 0x26, 0xd7, 0xf4, 0x46, 0x56, 0xc6, 0x36, 0x25, 0x48, 0xca,
0x90, 0xe1, 0xb9, 0xc8, 0x95, 0xcd, 0xbd, 0xd5, 0xc9, 0x8d, 0x95, 0xcd, 0x4d, 0x09, 0xba, 0x3a, 0x64, 0x78, 0x2e,
0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x02, 0x32, 0x00, 0x00, 0x00, 0x79, 0x18,
0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43,
0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88,
0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70,
0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87,
0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83,
0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07,
0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8,
0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81,
0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3,
0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xca, 0xc3, 0x0e,
0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xec, 0xf0, 0x0e, 0xef, 0x00, 0x0f, 0x33, 0x22, 0x88, 0x1c, 0xf0, 0xc1, 0x0d,
0xc8, 0x41, 0x1c, 0xce, 0xc1, 0x0d, 0xec, 0x21, 0x1c, 0xe4, 0x81, 0x1d, 0xc2, 0x21, 0x1f, 0xde, 0xa1, 0x1e, 0xe8,
0x61, 0x06, 0x13, 0x91, 0x03, 0x3e, 0xb8, 0x81, 0x38, 0xc8, 0x43, 0x39, 0x84, 0xc3, 0x3a, 0xb8, 0x81, 0x38, 0xc8,
0x03, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x04, 0x7e, 0x53, 0x74, 0x58,
0x5e, 0x26, 0x03, 0x81, 0x33, 0x68, 0xb0, 0x19, 0xb4, 0x00, 0x83, 0x63, 0x4d, 0x00, 0x69, 0x4c, 0xa1, 0x19, 0x2e,
0xdf, 0x79, 0xfc, 0x00, 0x88, 0x22, 0x84, 0x88, 0xec, 0x00, 0x1a, 0x2e, 0xdf, 0x79, 0xfc, 0x00, 0x69, 0x80, 0x08,
0xf3, 0x8b, 0xdb, 0xb6, 0x07, 0x6a, 0xb8, 0x7c, 0xe7, 0xf1, 0x03, 0xaa, 0x28, 0x88, 0xa8, 0x74, 0x80, 0xc1, 0x2f,
0x6e, 0xdb, 0x1c, 0xaa, 0xe1, 0xf2, 0x9d, 0xc7, 0x0f, 0xa8, 0xa2, 0x20, 0x22, 0x76, 0x72, 0x22, 0xc2, 0x2f, 0x6e,
0xdb, 0x16, 0xb6, 0xe1, 0xf2, 0x9d, 0xc7, 0x17, 0x02, 0xaa, 0x28, 0x88, 0xa8, 0x74, 0x80, 0xa1, 0x24, 0x0c, 0x40,
0xc0, 0xfc, 0xe2, 0xb6, 0x8d, 0x61, 0x1b, 0x2e, 0xdf, 0x79, 0x7c, 0x21, 0xa0, 0x8a, 0x82, 0x88, 0x4a, 0x07, 0x18,
0x4a, 0xc2, 0x00, 0x04, 0xcc, 0x47, 0x6e, 0xdb, 0x1a, 0xa4, 0xe1, 0xf2, 0x9d, 0xc7, 0x17, 0x22, 0x02, 0x98, 0x88,
0x10, 0x68, 0x86, 0x85, 0xb0, 0x04, 0x67, 0xb8, 0x7c, 0xe7, 0xf1, 0x07, 0x67, 0xba, 0xfd, 0xe2, 0xb6, 0x8d, 0x40,
0x0c, 0x86, 0xcb, 0x77, 0x1e, 0xbf, 0x58, 0x80, 0x69, 0x22, 0x1a, 0x62, 0x68, 0x8f, 0x88, 0x00, 0x06, 0x71, 0x10,
0x1b, 0x30, 0x72, 0xa8, 0xc7, 0x47, 0x6e, 0xdb, 0x04, 0xa2, 0xe1, 0xf2, 0x9d, 0xc7, 0x37, 0x22, 0x87, 0x7a, 0xc4,
0xc1, 0x47, 0x6e, 0xdb, 0x10, 0xaa, 0xe1, 0xf2, 0x9d, 0xc7, 0x9f, 0x88, 0x6b, 0xa2, 0x22, 0xa2, 0x74, 0x80, 0xc1,
0x2f, 0x6e, 0xdb, 0x0c, 0xac, 0xe1, 0xf2, 0x9d, 0xc7, 0x9f, 0x88, 0x6b, 0xa2, 0x22, 0x82, 0x9d, 0x9c, 0x88, 0xf0,
0x8b, 0xdb, 0xb6, 0x81, 0x6c, 0xb8, 0x7c, 0xe7, 0xf1, 0xa7, 0x23, 0x22, 0x80, 0x41, 0x1c, 0xc4, 0x06, 0x8c, 0x1c,
0xea, 0xf1, 0x91, 0xdb, 0xb6, 0x82, 0x67, 0xb8, 0x7c, 0xe7, 0xf1, 0xa9, 0x06, 0x88, 0x30, 0xbf, 0xb8, 0x6d, 0x00,
0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x8e, 0x02, 0x00, 0x00, 0x13, 0x04, 0x74, 0x10, 0x0b, 0x04, 0x00, 0x00,
0x25, 0x00, 0x00, 0x00, 0xd4, 0x94, 0x47, 0x11, 0x8c, 0x00, 0x94, 0x00, 0x19, 0x65, 0x18, 0x50, 0x80, 0x04, 0x05,
0x1c, 0x50, 0x88, 0x01, 0xa5, 0x18, 0x50, 0x0a, 0xe5, 0x1b, 0x50, 0xbc, 0x01, 0xa5, 0x52, 0xa0, 0x01, 0x33, 0x00,
0x65, 0x54, 0x76, 0xe5, 0x52, 0x72, 0x45, 0x18, 0x50, 0x6e, 0x85, 0x54, 0x80, 0x02, 0x05, 0x18, 0x50, 0x10, 0x04,
0x8c, 0x11, 0xd4, 0x6a, 0xad, 0xd6, 0xdf, 0x18, 0x01, 0x08, 0x82, 0x20, 0x0c, 0x06, 0x63, 0x04, 0x7b, 0xac, 0xc6,
0xfb, 0x37, 0x46, 0x00, 0x82, 0x20, 0x88, 0x7f, 0x63, 0x04, 0x7b, 0xac, 0xc6, 0xfb, 0x2f, 0x8c, 0x11, 0xe0, 0x30,
0x2f, 0xce, 0xdf, 0x18, 0x01, 0x28, 0xdb, 0xff, 0xc9, 0x8d, 0x11, 0x80, 0x20, 0xfe, 0xdf, 0x63, 0x30, 0x46, 0x80,
0xb3, 0xf7, 0x99, 0x7b, 0x63, 0x04, 0xb9, 0x5e, 0xba, 0xf3, 0x37, 0x46, 0x00, 0xfb, 0xec, 0x5c, 0x7e, 0x33, 0x00,
0x23, 0x00, 0x64, 0x0f, 0x75, 0x04, 0x02, 0x60, 0x44, 0x46, 0x34, 0xd4, 0x11, 0x08, 0x80, 0x11, 0x19, 0x10, 0x00,
0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x20, 0x06, 0x7b, 0x60, 0x95, 0x01, 0x1e, 0xe0, 0xc1, 0x1b, 0x8c, 0x18, 0x24,
0x00, 0x08, 0x82, 0x81, 0x18, 0xf0, 0xc1, 0x65, 0x06, 0x78, 0x80, 0x07, 0x70, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08,
0x06, 0x62, 0xd0, 0x07, 0x18, 0x1a, 0xe4, 0x41, 0x1e, 0xc4, 0xc1, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x88, 0x81,
0x1f, 0x64, 0x6a, 0xa0, 0x07, 0x7a, 0x20, 0x07, 0x23, 0x06, 0x06, 0x00, 0x82, 0x60, 0x70, 0xa8, 0x42, 0x18, 0xec,
0xc1, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x1c, 0xab, 0x20, 0x06, 0x7d, 0x30, 0x62, 0x50, 0x00, 0x20, 0x08, 0x06,
0x89, 0x2a, 0xa0, 0xc1, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x7c, 0xa3, 0xf0, 0x11, 0x7f, 0x30, 0x9a, 0x10, 0x08,
0xc3, 0x0d, 0x01, 0x28, 0x80, 0xc1, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x7c, 0xa6, 0x20, 0x06, 0x47, 0x28, 0xcc,
0x32, 0x04, 0x9b, 0x30, 0x62, 0x60, 0x00, 0x20, 0x08, 0x06, 0x07, 0x2c, 0xa4, 0xc1, 0x28, 0x8c, 0x18, 0x18, 0x00,
0x08, 0x82, 0xc1, 0x11, 0x0b, 0x6a, 0x30, 0x0a, 0x95, 0xb0, 0xc1, 0x55, 0xd2, 0x06, 0x57, 0x83, 0x00, 0x55, 0x08,
0x30, 0x9a, 0x70, 0x00, 0xa3, 0x09, 0x48, 0x30, 0xdc, 0x40, 0x08, 0x64, 0x30, 0xdc, 0x40, 0x08, 0x64, 0x50, 0x42,
0xa0, 0xb3, 0x0c, 0xc2, 0x10, 0x8c, 0x18, 0x34, 0x00, 0x08, 0x82, 0x41, 0x65, 0x0b, 0x6b, 0x40, 0xb5, 0xc2, 0x61,
0xc0, 0x01, 0x1c, 0xc0, 0x01, 0x1c, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x88, 0xc1,
0x01, 0x80, 0x20, 0x18, 0x48, 0xbb, 0x30, 0x07, 0xdd, 0x30, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x12, 0x2f, 0xd0,
0x81, 0x37, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x81, 0xd4, 0x0b, 0x75, 0xf0, 0x0d, 0x23, 0x06, 0x07, 0x00, 0x82,
0x60, 0xc0, 0xe9, 0x42, 0x1d, 0x68, 0xb5, 0x30, 0x9a, 0x10, 0x0c, 0x56, 0x04, 0xf4, 0xb1, 0x42, 0xa0, 0x8f, 0x15,
0x03, 0x7d, 0x46, 0x0c, 0x16, 0x00, 0x04, 0xc1, 0xe0, 0x0a, 0x07, 0x3b, 0x18, 0x84, 0xe0, 0x0c, 0xd0, 0x20, 0x0d,
0x46, 0x0c, 0x0e, 0x00, 0x04, 0xc1, 0x40, 0x22, 0x07, 0x3b, 0x08, 0xd6, 0x60, 0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c,
0xa4, 0x72, 0xe8, 0x83, 0x36, 0x08, 0x46, 0x0c, 0x0c, 0x00, 0x04, 0xc1, 0x60, 0x41, 0x07, 0x3e, 0x08, 0x2c, 0x80,
0x03, 0xf9, 0xcc, 0x12, 0x0c, 0x03, 0x15, 0x80, 0x20, 0xd0, 0x42, 0x50, 0x19, 0x2e, 0xc0, 0x70, 0x43, 0x80, 0x91,
0x41, 0x05, 0x96, 0xce, 0x32, 0x10, 0x45, 0x30, 0x62, 0xd0, 0x00, 0x20, 0x08, 0x06, 0xd5, 0x3a, 0x80, 0x42, 0x1a,
0x88, 0xc3, 0xb0, 0x95, 0x42, 0x29, 0x94, 0x42, 0x29, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c,
0xc2, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x48, 0xf0, 0x80, 0x0a, 0x72, 0x30, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82,
0x81, 0x14, 0x0f, 0xa9, 0x30, 0x07, 0xc3, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x48, 0xf2, 0xa0, 0x0a, 0x74, 0x30,
0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x01, 0xf7, 0x0e, 0xaa, 0xf0, 0x06, 0xea, 0x30, 0x9a, 0x10, 0x0c, 0x56, 0x04,
0xf4, 0xb1, 0x42, 0xa0, 0x8f, 0x15, 0x03, 0x7d, 0x46, 0x0c, 0x16, 0x00, 0x04, 0xc1, 0xe0, 0xb2, 0x87, 0x55, 0x18,
0x84, 0x80, 0x0f, 0xfa, 0xc0, 0x0f, 0x46, 0x0c, 0x0e, 0x00, 0x04, 0xc1, 0x40, 0xca, 0x87, 0x55, 0x08, 0x40, 0x61,
0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0x24, 0x7d, 0x90, 0x05, 0x51, 0x08, 0x46, 0x0c, 0x0c, 0x00, 0x04, 0xc1, 0x60,
0xe9, 0x87, 0x58, 0x08, 0x2c, 0x28, 0x05, 0xf9, 0x58, 0x50, 0xc1, 0x67, 0x96, 0xa0, 0x18, 0xa8, 0x00, 0x04, 0x82,
0x0d, 0x86, 0x72, 0x03, 0x77, 0x80, 0xe1, 0x86, 0xa0, 0x0d, 0xc8, 0xa0, 0xda, 0x20, 0xd0, 0x59, 0x06, 0xe3, 0x08,
0x46, 0x0c, 0x1a, 0x00, 0x04, 0xc1, 0xa0, 0x0a, 0x09, 0x5b, 0xf8, 0x03, 0x7c, 0x90, 0x83, 0x61, 0x17, 0x76, 0x61,
0x17, 0x76, 0x61, 0x34, 0x21, 0x00, 0x46, 0x13, 0x84, 0x60, 0x34, 0x61, 0x10, 0x46, 0x0c, 0x0e, 0x00, 0x04, 0xc1,
0x40, 0x32, 0x09, 0x5f, 0x40, 0x85, 0x61, 0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0xa4, 0x93, 0xf8, 0x85, 0x54, 0x18,
0x46, 0x0c, 0x0e, 0x00, 0x04, 0xc1, 0x40, 0x42, 0x09, 0x70, 0x50, 0x85, 0x61, 0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c,
0xb8, 0x92, 0x00, 0x87, 0x52, 0x00, 0x89, 0xd1, 0x84, 0x60, 0xb0, 0x22, 0xa0, 0x8f, 0x15, 0x02, 0x7d, 0xac, 0x18,
0xe8, 0x33, 0x62, 0xb0, 0x00, 0x20, 0x08, 0x06, 0x17, 0x4b, 0x84, 0xc3, 0x20, 0x04, 0xb2, 0x30, 0x0b, 0xb4, 0x30,
0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xd2, 0x4b, 0x84, 0x43, 0x60, 0x0b, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0x20,
0xc1, 0x04, 0x3a, 0xe0, 0x42, 0x30, 0x62, 0x60, 0x00, 0x20, 0x08, 0x06, 0xcb, 0x4c, 0x9c, 0x43, 0x60, 0xc1, 0x2e,
0xc8, 0xc7, 0x82, 0x0a, 0x3e, 0xb3, 0x04, 0xc7, 0x40, 0x05, 0x20, 0x18, 0x6c, 0x50, 0xd4, 0x1a, 0x54, 0x3a, 0xcb,
0x80, 0x24, 0xc1, 0x88, 0x41, 0x03, 0x80, 0x20, 0x18, 0x54, 0x35, 0xa1, 0x0e, 0xb3, 0xc0, 0x12, 0x6d, 0x70, 0xbd,
0xc3, 0x3b, 0xbc, 0xc3, 0x3b, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x88, 0xc1, 0x01,
0x80, 0x20, 0x18, 0x48, 0x3a, 0x21, 0x0f, 0xbc, 0x30, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x81, 0xb4, 0x13, 0xf3,
0xd0, 0x0b, 0xc3, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x48, 0x3c, 0x41, 0x0f, 0xbe, 0x30, 0x8c, 0x18, 0x1c, 0x00,
0x08, 0x82, 0x01, 0x97, 0x13, 0xf4, 0x90, 0x0b, 0x34, 0x31, 0x9a, 0x10, 0x0c, 0x56, 0x04, 0xf4, 0xb1, 0x42, 0xa0,
0x8f, 0x15, 0x03, 0x7d, 0x46, 0x0c, 0x16, 0x00, 0x04, 0xc1, 0xe0, 0x02, 0x8b, 0x7a, 0x18, 0x84, 0xc0, 0x1c, 0xce,
0x01, 0x1d, 0x46, 0x0c, 0x0e, 0x00, 0x04, 0xc1, 0x40, 0x1a, 0x8b, 0x7a, 0x08, 0xd4, 0x61, 0xc4, 0xe0, 0x00, 0x40,
0x10, 0x0c, 0x24, 0xb2, 0xe0, 0x07, 0x76, 0x08, 0x46, 0x0c, 0x0c, 0x00, 0x04, 0xc1, 0x60, 0x39, 0x8b, 0x7d, 0x08,
0x2c, 0x78, 0x07, 0xf9, 0x58, 0x30, 0xc1, 0x67, 0x96, 0x20, 0x19, 0xa8, 0x00, 0x04, 0x04, 0x0d, 0x8e, 0x15, 0x0c,
0x70, 0xf1, 0x13, 0xe2, 0x30, 0x6c, 0x40, 0x04, 0xc2, 0x00, 0x8c, 0x18, 0x18, 0x00, 0x08, 0x82, 0x41, 0x76, 0x16,
0x24, 0xf1, 0x13, 0xc3, 0x0d, 0xe3, 0xb0, 0x0f, 0x64, 0x30, 0xcb, 0xa0, 0x2c, 0x41, 0x91, 0x03, 0x3f, 0xc0, 0x0a,
0x86, 0xb9, 0x10, 0x8b, 0x80, 0x02, 0x60, 0x50, 0x01, 0x0c, 0x0b, 0x04, 0xf8, 0x0c, 0x1b, 0x10, 0x47, 0x30, 0x00,
0xb3, 0x04, 0xcb, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x64, 0x6d, 0xa1, 0x12, 0x65, 0x31, 0xdc, 0x90, 0x0e, 0x20,
0x41, 0x06, 0xb3, 0x0c, 0x4c, 0x13, 0x94, 0x3a, 0x84, 0x04, 0xac, 0x60, 0xc8, 0x0b, 0xb4, 0x08, 0x28, 0x00, 0x06,
0x2d, 0xc0, 0xb0, 0x40, 0x80, 0xcf, 0xb0, 0x01, 0xd1, 0x04, 0x03, 0x30, 0x4b, 0xd0, 0x8c, 0x18, 0x18, 0x00, 0x08,
0x82, 0x41, 0x36, 0x17, 0x30, 0xb1, 0x16, 0xc3, 0x0d, 0xef, 0x60, 0x16, 0x64, 0x30, 0xcb, 0xe0, 0x3c, 0x41, 0xc1,
0xc3, 0x59, 0xc0, 0x0a, 0x86, 0xbf, 0x70, 0x8b, 0x80, 0x02, 0x60, 0x50, 0x04, 0x0c, 0x0b, 0x04, 0xf8, 0x0c, 0x1b,
0x10, 0x53, 0x30, 0x00, 0xb3, 0x04, 0xcf, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x64, 0x79, 0x61, 0x13, 0x71, 0x31,
0xdc, 0x50, 0x0f, 0x6b, 0x41, 0x06, 0xb3, 0x0c, 0x50, 0x14, 0x94, 0x3d, 0xb0, 0x05, 0xac, 0x60, 0x28, 0x0d, 0xba,
0x08, 0x28, 0x00, 0x06, 0x5d, 0xc0, 0xb0, 0x40, 0x80, 0xcf, 0xb0, 0x01, 0x91, 0x05, 0x03, 0x30, 0x4b, 0x10, 0x8d,
0x18, 0x18, 0x00, 0x08, 0x82, 0x41, 0xf6, 0x17, 0x3c, 0x71, 0x17, 0xc3, 0x0d, 0xfb, 0x10, 0x13, 0x64, 0x30, 0xcb,
0x20, 0x4d, 0x41, 0xf1, 0x83, 0x4c, 0xc0, 0x0a, 0x86, 0xd5, 0xd0, 0x8b, 0x80, 0x02, 0x60, 0x50, 0x07, 0x0c, 0x0b,
0x04, 0xf8, 0x0c, 0x1b, 0x10, 0x5f, 0x30, 0x00, 0xb3, 0x04, 0xd3, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x64, 0xa5,
0x21, 0x16, 0x7d, 0x31, 0xdc, 0x10, 0x12, 0x79, 0x41, 0x06, 0xb3, 0x0c, 0x54, 0x15, 0x94, 0x48, 0xe8, 0x05, 0xac,
0x60, 0x88, 0x0d, 0xd0, 0x08, 0x28, 0x00, 0x06, 0x8d, 0x01, 0x30, 0x2c, 0x10, 0xe0, 0x33, 0x6c, 0x40, 0x94, 0x41,
0x30, 0x00, 0xb3, 0x04, 0xd5, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x64, 0xab, 0x81, 0x16, 0xa3, 0x31, 0xdc, 0x70,
0x12, 0xa1, 0x41, 0x06, 0xb3, 0x0c, 0xd6, 0x15, 0x14, 0x4a, 0x88, 0x06, 0xac, 0x60, 0xb8, 0x0d, 0xd3, 0x08, 0x28,
0x00, 0x06, 0xa5, 0x01, 0x30, 0x2c, 0x10, 0xe0, 0x33, 0x6c, 0x40, 0xac, 0x41, 0x30, 0x00, 0xb3, 0x04, 0xd7, 0x88,
0x81, 0x01, 0x80, 0x20, 0x18, 0x64, 0xb1, 0xe1, 0x16, 0xa9, 0x31, 0xdc, 0xd0, 0x12, 0xaa, 0x01, 0x06, 0xb3, 0x0c,
0x58, 0x16, 0x50, 0x4d, 0x00, 0x83, 0x6e, 0x02, 0x18, 0x16, 0x08, 0xf0, 0x19, 0x36, 0x20, 0x72, 0x22, 0x18, 0x80,
0x59, 0x82, 0x6c, 0xa0, 0x22, 0x0c, 0x10, 0x8c, 0x65, 0xae, 0x11, 0x03, 0x03, 0x00, 0x41, 0x30, 0xc8, 0x6c, 0x63,
0x2e, 0x5c, 0x63, 0x96, 0x41, 0x9b, 0x83, 0x80, 0x74, 0x02, 0x18, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0xf0, 0xd5,
0x46, 0x5c, 0xd8, 0x04, 0x6c, 0x8c, 0x26, 0x04, 0x42, 0x05, 0x36, 0x21, 0x85, 0x13, 0xb4, 0x01, 0x15, 0x08, 0x30,
0x62, 0xd0, 0x00, 0x20, 0x08, 0x06, 0x64, 0x80, 0x1b, 0x7e, 0xd1, 0x13, 0x41, 0x6d, 0x18, 0x62, 0x21, 0x16, 0x62,
0x31, 0x1a, 0xb3, 0x04, 0x73, 0x30, 0x9a, 0x40, 0x13, 0xc3, 0x70, 0x43, 0x4e, 0x04, 0x64, 0x30, 0xcb, 0xc0, 0x7d,
0xc1, 0x2c, 0x41, 0x37, 0x50, 0x01, 0x2c, 0x9d, 0xa9, 0x70, 0x03, 0x15, 0xc6, 0xd2, 0xd9, 0x09, 0x57, 0x81, 0x6e,
0xc0, 0x88, 0x01, 0x02, 0x80, 0x20, 0x18, 0x98, 0x01, 0x6f, 0x90, 0x86, 0x58, 0x04, 0xba, 0x31, 0x9a, 0x10, 0x00,
0x16, 0x14, 0xf0, 0xa9, 0x22, 0x35, 0x60, 0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0xbe, 0xf1, 0xf8, 0x0b, 0xb2, 0xf0,
0x8d, 0xd1, 0x84, 0x60, 0x18, 0x6e, 0x18, 0x02, 0x32, 0x98, 0x65, 0xe8, 0xbc, 0x60, 0x96, 0xe0, 0x1b, 0xa8, 0x00,
0x74, 0x65, 0x53, 0xbc, 0x15, 0x0c, 0xf3, 0x21, 0x1e, 0x65, 0x31, 0x6c, 0x40, 0x04, 0xc2, 0x00, 0x8c, 0x18, 0x18,
0x00, 0x08, 0x82, 0x41, 0xa6, 0x1e, 0xa7, 0x21, 0x1e, 0xc3, 0x0d, 0x66, 0xe1, 0x17, 0x64, 0x30, 0xcb, 0x00, 0x06,
0x61, 0x10, 0xd4, 0x59, 0xfc, 0x05, 0xac, 0x60, 0xb0, 0x8f, 0xf2, 0x08, 0x28, 0x00, 0x06, 0x15, 0xc0, 0xb0, 0x40,
0x80, 0xcf, 0xb0, 0x01, 0x71, 0x04, 0x03, 0x30, 0x4b, 0x10, 0x06, 0x23, 0x06, 0x06, 0x00, 0x82, 0x60, 0x90, 0xc1,
0x47, 0x6b, 0xa0, 0xc7, 0x70, 0x03, 0x5b, 0x8c, 0x06, 0x19, 0xcc, 0x32, 0x88, 0xc1, 0x18, 0x04, 0xd5, 0x16, 0xa4,
0x01, 0x2b, 0x18, 0xf8, 0x63, 0x3d, 0x02, 0x0a, 0x80, 0x41, 0x0b, 0x30, 0x2c, 0x10, 0xe0, 0x33, 0x6c, 0x40, 0x34,
0xc1, 0x00, 0xcc, 0x12, 0x8c, 0xc1, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x64, 0xf6, 0x31, 0x1b, 0xee, 0x31, 0xdc,
0x20, 0x17, 0xe9, 0x41, 0x06, 0xb3, 0x0c, 0x64, 0x50, 0x06, 0x41, 0xcd, 0x85, 0x7a, 0xc0, 0x0a, 0x06, 0x11, 0x89,
0x8f, 0x80, 0x02, 0x60, 0x50, 0x04, 0x0c, 0x0b, 0x04, 0xf8, 0x0c, 0x1b, 0x10, 0x53, 0x30, 0x00, 0xb3, 0x04, 0x65,
0x30, 0x62, 0x60, 0x00, 0x20, 0x08, 0x06, 0x19, 0x7f, 0xe4, 0x06, 0x7d, 0x0c, 0x37, 0xe0, 0x85, 0x7b, 0x90, 0xc1,
0x2c, 0x83, 0x19, 0x9c, 0x41, 0x50, 0x79, 0xf1, 0x1e, 0xb0, 0x82, 0x01, 0x45, 0xee, 0x23, 0xa0, 0x00, 0x18, 0x74,
0x01, 0xc3, 0x02, 0x01, 0x3e, 0xc3, 0x06, 0x44, 0x16, 0x0c, 0xc0, 0x2c, 0xc1, 0x19, 0x8c, 0x18, 0x18, 0x00, 0x08,
0x82, 0x41, 0x26, 0x22, 0xbf, 0xa1, 0x1f, 0xc3, 0x0d, 0x7e, 0x41, 0x1b, 0x64, 0x30, 0xcb, 0x80, 0x06, 0x69, 0x10,
0xd4, 0x5f, 0xd4, 0x06, 0xac, 0x60, 0x70, 0x91, 0xfe, 0x08, 0x28, 0x00, 0x06, 0x75, 0xc0, 0xb0, 0x40, 0x80, 0xcf,
0xb0, 0x01, 0xf1, 0x05, 0x03, 0x30, 0x4b, 0x90, 0x06, 0x23, 0x06, 0x06, 0x00, 0x82, 0x60, 0x90, 0xa1, 0x48, 0x79,
0x80, 0xc8, 0x70, 0x03, 0x69, 0xf0, 0x07, 0x19, 0xcc, 0x32, 0xa8, 0xc1, 0x1a, 0x04, 0x55, 0x1a, 0xfd, 0x01, 0x2b,
0x18, 0x68, 0x64, 0x44, 0x02, 0x0a, 0x80, 0x41, 0x63, 0x00, 0x0c, 0x0b, 0x04, 0xf8, 0x0c, 0x1b, 0x10, 0x65, 0x10,
0x0c, 0xc0, 0x2c, 0xc1, 0x1a, 0x8c, 0x18, 0x18, 0x00, 0x08, 0x82, 0x41, 0xe6, 0x22, 0xeb, 0x61, 0x22, 0xc3, 0x0d,
0xaa, 0x41, 0x22, 0x64, 0x30, 0xcb, 0xc0, 0x06, 0x6d, 0x10, 0xd4, 0x6a, 0x94, 0x08, 0xac, 0x60, 0xd0, 0x91, 0x14,
0x09, 0x28, 0x00, 0x06, 0xa5, 0x01, 0x30, 0x2c, 0x10, 0xe0, 0x33, 0x6c, 0x40, 0xac, 0x41, 0x30, 0x00, 0xb3, 0x04,
0x6d, 0x30, 0x62, 0x60, 0x00, 0x20, 0x08, 0x06, 0x19, 0x8d, 0xc4, 0x07, 0x8b, 0x0c, 0x37, 0xc0, 0x46, 0x8b, 0x80,
0xc1, 0x2c, 0x83, 0x1b, 0xbc, 0x41, 0x40, 0xb8, 0x01, 0x0c, 0xd2, 0x0d, 0x60, 0x58, 0x20, 0xc0, 0x67, 0xd8, 0x80,
0xe0, 0x8d, 0x60, 0x00, 0x66, 0x09, 0xde, 0x60, 0xa0, 0x22, 0x0c, 0x10, 0x37, 0x90, 0xa1, 0x36, 0x18, 0x31, 0x30,
0x00, 0x10, 0x04, 0x83, 0x2c, 0x47, 0xec, 0x23, 0x46, 0x66, 0x19, 0xe0, 0x60, 0x0e, 0x02, 0xea, 0x0d, 0x60, 0x8c,
0x18, 0x1c, 0x00, 0x08, 0x82, 0xc1, 0x87, 0x23, 0xf4, 0x91, 0x1b, 0x33, 0x32, 0x9a, 0x10, 0x00, 0x17, 0x00, 0x35,
0x9a, 0x30, 0x04, 0x17, 0x00, 0x65, 0xc1, 0x20, 0x1f, 0x3b, 0x02, 0xfa, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0xc1,
0xf7, 0x23, 0xfb, 0x01, 0x1e, 0x3b, 0x32, 0x9a, 0x10, 0x04, 0xc3, 0x0d, 0x01, 0x8f, 0x80, 0xc1, 0x2c, 0x43, 0x1c,
0xc8, 0x41, 0x30, 0x62, 0x80, 0x00, 0x20, 0x08, 0x06, 0x66, 0xf0, 0x23, 0x27, 0x52, 0x1e, 0x3d, 0xd2, 0x23, 0xa3,
0x09, 0x01, 0x60, 0x46, 0x10, 0x9f, 0x11, 0x83, 0x03, 0x00, 0x41, 0x30, 0xe0, 0xcc, 0x24, 0x44, 0xcc, 0x23, 0x4c,
0x46, 0x13, 0x02, 0xc0, 0x02, 0xfb, 0x90, 0xcf, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x2c, 0x6f, 0x82, 0x22, 0x81,
0xe5, 0x47, 0x10, 0x1f, 0x0b, 0x0c, 0xf9, 0x58, 0x80, 0xc0, 0x67, 0x96, 0x40, 0x0e, 0x06, 0x2a, 0x00, 0x21, 0x0e,
0x38, 0x38, 0x18, 0x31, 0x68, 0x00, 0x10, 0x04, 0x03, 0x32, 0x58, 0x93, 0x18, 0x81, 0x0f, 0x34, 0x41, 0x93, 0xa0,
0x3e, 0xea, 0xa3, 0x3e, 0x6c, 0xc4, 0x02, 0xff, 0x90, 0xcf, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x2c, 0x75, 0xe2,
0x22, 0x81, 0x05, 0x21, 0x22, 0x9f, 0x11, 0x03, 0x03, 0x00, 0x41, 0x30, 0x58, 0xee, 0x64, 0x45, 0x82, 0x11, 0x03,
0x03, 0x00, 0x41, 0x30, 0x58, 0xf0, 0x24, 0x46, 0x02, 0x2b, 0x91, 0x80, 0x3e, 0x23, 0x06, 0x0e, 0x00, 0x82, 0x60,
0x00, 0xe5, 0xc9, 0x8e, 0xdc, 0x87, 0x9b, 0xb8, 0x49, 0x8c, 0x04, 0x41, 0x10, 0xfc, 0xc8, 0x2c, 0xc1, 0x1c, 0x60,
0x40, 0x0c, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x5b, 0x06, 0x79, 0x08, 0xd8, 0x60, 0xcb, 0x80, 0x0f, 0x01,
0x1b, 0x6c, 0x19, 0xf2, 0x21, 0x60, 0x83, 0x2d, 0xc3, 0x3e, 0x04, 0x6c, 0xb0, 0x65, 0x10, 0x89, 0x80, 0x0d, 0xb6,
0x0c, 0x23, 0x11, 0xb0, 0xc1, 0x96, 0xa1, 0x24, 0x02, 0x36, 0xd8, 0x32, 0xb0, 0x44, 0xc0, 0x06, 0x5b, 0x86, 0x96,
0x08, 0xd8, 0x60, 0xcb, 0xf0, 0x12, 0x01, 0x1b, 0x6c, 0x19, 0x6c, 0x22, 0x60, 0x83, 0x2d, 0xc3, 0x4d, 0x04, 0x6c,
0xb0, 0x65, 0xc8, 0x89, 0x80, 0x0d, 0xb6, 0x0c, 0x60, 0x11, 0xb0, 0xc1, 0x96, 0x21, 0x2c, 0x02, 0x36, 0xd8, 0x32,
0x8c, 0x45, 0xc0, 0x06, 0x5b, 0x06, 0xb5, 0x08, 0xd8, 0x60, 0xcb, 0xb0, 0x16, 0x01, 0x1b, 0x6c, 0x19, 0xda, 0x22,
0x60, 0x83, 0x2d, 0x03, 0x5d, 0x04, 0x6c, 0xb0, 0x65, 0xa8, 0x8b, 0x80, 0x0d, 0xb6, 0x0c, 0x77, 0x11, 0xb0, 0xc1,
0x96, 0x81, 0x2f, 0x02, 0x36, 0xd8, 0x32, 0xf4, 0x45, 0xc0, 0x06, 0x5b, 0x86, 0xbf, 0x08, 0xd8, 0x60, 0xcb, 0x40,
0x1a, 0x01, 0x1b, 0x6c, 0x19, 0x7c, 0x23, 0x60, 0x83, 0x2d, 0x03, 0x79, 0x04, 0x6c, 0xb0, 0x65, 0x28, 0x8f, 0x80,
0x0d, 0xb6, 0x0c, 0xe7, 0x11, 0xb0, 0xc1, 0x96, 0xc1, 0x3d, 0x02, 0x36, 0xd8, 0x32, 0xbc, 0x47, 0xc0, 0x06, 0x5b,
0x86, 0xf8, 0x08, 0xd8, 0x60, 0xcb, 0x80, 0x1f, 0x01, 0x1b, 0x6c, 0x19, 0xf2, 0x23, 0x60, 0x83, 0x2d, 0xc3, 0x7e,
0x04, 0x6c, 0xb0, 0x65, 0x10, 0x91, 0x80, 0x0d, 0xb6, 0x0c, 0x23, 0x12, 0xb0, 0xc1, 0x96, 0xa1, 0x44, 0x02, 0x36,
0xd8, 0x32, 0xb0, 0x48, 0xc0, 0x06, 0x5b, 0x86, 0x16, 0x09, 0xd8, 0x60, 0xcb, 0xf0, 0x22, 0x01, 0x1b, 0x6c, 0x19,
0x6c, 0x24, 0x60, 0x83, 0x2d, 0xc3, 0x8d, 0x04, 0x6c, 0xb0, 0x65, 0xc8, 0x91, 0x80, 0x0d, 0xb6, 0x0c, 0x60, 0x12,
0xb0, 0xc1, 0x96, 0x21, 0x4c, 0x02, 0x36, 0xd8, 0x32, 0x8c, 0x49, 0xc0, 0x06, 0x5b, 0x06, 0x34, 0x09, 0xd8, 0x60,
0xcb, 0x90, 0x26, 0x01, 0x1b, 0x6c, 0x19, 0xd6, 0x24, 0x60, 0x83, 0x2d, 0x03, 0x9c, 0x04, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+37 -118
View File
@@ -38,57 +38,6 @@ bool FFXFeatureDx12::InitInternal(ID3D12GraphicsCommandList* InCommandList, NVSD
return InitFFX(InParameters);
}
bool CreateBufferResourceWithSize(ID3D12Device* device, ID3D12Resource* source, D3D12_RESOURCE_STATES state,
ID3D12Resource** target, UINT width, UINT height)
{
if (device == nullptr || source == nullptr)
return false;
auto inDesc = source->GetDesc();
if (*target != nullptr)
{
auto bufDesc = (*target)->GetDesc();
if (bufDesc.Width != width || bufDesc.Height != height || bufDesc.Format != inDesc.Format ||
bufDesc.Flags != inDesc.Flags)
{
// Previous frames can still be using it
DeferredRelease::Release(*target);
}
else
{
return true;
}
}
D3D12_HEAP_PROPERTIES heapProperties;
D3D12_HEAP_FLAGS heapFlags;
HRESULT hr = source->GetHeapProperties(&heapProperties, &heapFlags);
if (hr != S_OK)
{
LOG_ERROR("GetHeapProperties result: {:X}", (UINT64) hr);
return false;
}
inDesc.Width = width;
inDesc.Height = height;
hr = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &inDesc, state, nullptr,
IID_PPV_ARGS(target));
if (hr != S_OK)
{
LOG_ERROR("CreateCommittedResource result: {:X}", (UINT64) hr);
return false;
}
LOG_DEBUG("Created new one: {}x{}", inDesc.Width, inDesc.Height);
return true;
}
bool FFXFeatureDx12::EvaluateInternal(ID3D12GraphicsCommandList* InCommandList, NVSDK_NGX_Parameter* InParameters)
{
LOG_FUNC();
@@ -161,70 +110,6 @@ bool FFXFeatureDx12::EvaluateInternal(ID3D12GraphicsCommandList* InCommandList,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
}
// WAR for FSR 4's autoexposure shader reading entire underlying resource
// instead of what's specified by renderSize or color's FfxApiResourceDescription.
// Only linear has this issue
if (Version().major >= 4 && AutoExposure() && !Config::Instance()->FsrNonLinearPQ.value_or_default() &&
!Config::Instance()->FsrNonLinearSRGB.value_or_default() &&
!Config::Instance()->FsrNonLinearColorSpace.value_or_default())
{
D3D12_RESOURCE_DESC desc = paramColor->GetDesc();
const auto diffW = static_cast<int>(desc.Width) - static_cast<int>(params.renderSize.width);
const auto diffH = static_cast<int>(desc.Height) - static_cast<int>(params.renderSize.height);
// Seemingly it may only be happening when both axes are 1 pixel too big
// But let's be conservative here and also trigger when just one axis is too big
const bool validW = (diffW >= 0 && diffW <= 2);
const bool validH = (diffH >= 0 && diffH <= 2);
const bool isPadded = (diffW > 0 || diffH > 0);
if (validW && validH && isPadded)
{
static size_t count = 0;
const size_t index = count % 2;
CreateBufferResourceWithSize(Device, paramColor, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
&smallerColor[index], params.renderSize.width, params.renderSize.height);
if (smallerColor[index])
{
ResourceBarrier(InCommandList, paramColor, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_SOURCE);
ResourceBarrier(InCommandList, smallerColor[index], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_DEST);
D3D12_BOX srcBox {};
srcBox.left = 0;
srcBox.top = 0;
srcBox.right = params.renderSize.width;
srcBox.bottom = params.renderSize.height;
srcBox.front = 0;
srcBox.back = 1;
D3D12_TEXTURE_COPY_LOCATION dstLocation {};
dstLocation.pResource = smallerColor[index];
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dstLocation.SubresourceIndex = 0;
D3D12_TEXTURE_COPY_LOCATION srcLocation {};
srcLocation.pResource = paramColor;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
srcLocation.SubresourceIndex = 0;
InCommandList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, &srcBox);
ResourceBarrier(InCommandList, smallerColor[index], D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
paramColor = smallerColor[index];
}
count++;
}
}
params.color = ffxApiGetResourceDX12(paramColor, FFX_API_RESOURCE_STATE_COMPUTE_READ);
}
else
@@ -579,6 +464,19 @@ bool FFXFeatureDx12::EvaluateInternal(ID3D12GraphicsCommandList* InCommandList,
params.upscaleSize.height = TargetHeight();
}
if (_customAutoExposure)
{
if (_autoExposure->Dispatch(InCommandList, paramColor, params.renderSize.width, params.renderSize.height,
params.preExposure, params.frameTimeDelta / 1000.0f, params.reset))
{
params.exposure = ffxApiGetResourceDX12(_autoExposure->Exposure(), FFX_API_RESOURCE_STATE_COMPUTE_READ);
}
else
{
LOG_ERROR("Auto exposure dispatch failed");
}
}
LOG_DEBUG("Dispatch!!");
auto result = FfxApiProxy::D3D12_Dispatch(&_context, &params.header);
@@ -663,12 +561,36 @@ bool FFXFeatureDx12::InitFFX(const NVSDK_NGX_Parameter* InParameters)
State::Instance().ffxUpscalerVersionsDx12.ids.size())
Config::Instance()->FfxUpscalerIndex.set_volatile_value(0);
parse_version(
State::Instance().ffxUpscalerVersionsDx12.names[Config::Instance()->FfxUpscalerIndex.value_or_default()]);
ffxOverrideVersion override = { 0 };
override.header.type = FFX_API_DESC_TYPE_OVERRIDE_VERSION;
override.versionId =
State::Instance().ffxUpscalerVersionsDx12.ids[Config::Instance()->FfxUpscalerIndex.value_or_default()];
backendDesc.header.pNext = &override.header;
// FSR4's own auto exposure reads the whole color texture instead of just renderSize. On UE the padding
// outside the view can hold garbage that makes it think the scene is very bright and black out the frame.
// Run our own auto exposure instead and hand FSR4 the result as a regular exposure texture.
// Only linear input is affected, color space changes recreate the feature.
_customAutoExposure = false;
auto& cfg = *Config::Instance();
if (Version().major >= 4 && AutoExposure() && !cfg.FsrNonLinearPQ.value_or_default() &&
!cfg.FsrNonLinearSRGB.value_or_default() && !cfg.FsrNonLinearColorSpace.value_or_default())
{
if (_autoExposure == nullptr)
_autoExposure = std::make_unique<AE_Dx12>("AutoExposure", Device);
if (_autoExposure->IsInit())
{
_customAutoExposure = true;
_contextDesc.flags &= ~FFX_UPSCALE_ENABLE_AUTO_EXPOSURE;
LOG_INFO("Using OptiScaler auto exposure instead of FSR's");
}
}
LOG_DEBUG("_createContext!");
{
@@ -683,10 +605,7 @@ bool FFXFeatureDx12::InitFFX(const NVSDK_NGX_Parameter* InParameters)
}
}
auto version =
State::Instance().ffxUpscalerVersionsDx12.names[Config::Instance()->FfxUpscalerIndex.value_or_default()];
_name = "FSR";
parse_version(version);
}
SetInit(true);
+3 -4
View File
@@ -4,11 +4,13 @@
#include "dx12/ffx_api_dx12.h"
#include "proxies/FfxApi_Proxy.h"
#include <shaders/auto_exposure/AE_Dx12.h>
class FFXFeatureDx12 : public FFXFeature, public IFeature_Dx12
{
private:
ID3D12Resource* smallerColor[2] {};
std::unique_ptr<AE_Dx12> _autoExposure;
bool _customAutoExposure = false;
NVSDK_NGX_Parameter* SetParameters(NVSDK_NGX_Parameter* InParameters);
@@ -44,8 +46,5 @@ class FFXFeatureDx12 : public FFXFeature, public IFeature_Dx12
if (_context != nullptr)
FfxApiProxy::D3D12_DestroyContext(&_context, NULL);
SAFE_RELEASE(smallerColor[0]);
SAFE_RELEASE(smallerColor[1]);
}
};