/*
 * SEGS - Super Entity Game Server
 * http://example.com
 */

/*!
 * @addtogroup CRUDP_Protocol Projects/CoX/Common/CRUDP_Protocol
 * @{
 */

#include "PacketCodec.h"

#include <QtCore/QtEndian>

uint32_t PacketCodecNull::Checksum(const uint8_t *buf,size_t size)
{
    uint16_t c1 = 1, c2 = 0;
    uint32_t sum1 = 1, sum2 = 0;

    for(uint32_t i = 0; i < size; i++)
    {
        sum1 += buf[i];
        sum2 += sum1;

        if(sum1 >= 0xFFF1)
            sum1 -= 0xFFF1;
    }

    sum2 %= 0xFFF1;

    c1 = (uint16_t)sum1

    c2 = (uint16_t)sum2;
    return  (((uint32_t)qToBigEndian(c1))<<16)|qToBigEndian (c2) ;
}


for(uint32_t i = 0; i < size; i++)
    {
        sum1 += buf[i];
        sum2 += sum1;

        if(sum1 >= 0xFFF1)
            sum1 -= 0xFFF1;
    }

/*
 * SEGS - Super Entity Game Server
 * http://example.com
 */

/*!
 * @addtogroup CRUDP_Protocol Projects/CoX/Common/CRUDP_Protocol
 * @{
 */

#include "PacketCodec.h"

#include <QtCore/QtEndian>

uint32_t PacketCodecNull::Checksum(const uint8_t *buf,size_t size)
{
    uint16_t c1 = 1, c2 = 0;
    uint32_t sum1 = 1, sum2 = 0;

    sum2 %= 0xFFF1;

    c1 = (uint16_t)sum1;
    c2 = (uint16_t)sum2;
    return  (((uint32_t)qToBigEndian(c1))<<16)|qToBigEndian (c2) ;
}


static void fresnel( double xxa, double *ssa, double *cca )

{
    double f, g, cc, ss, c, s, t, u;
    double x, x2;

    x  = fabs( xxa );
    x2 = x * x;

    if ( x2 < 2.5625 )
    {
        t = x2 * x2;
        ss = x * x2 * polevl (t, sn, 5) / p1evl (t, sd, 6);
        cc = x * polevl (t, cn, 5) / polevl (t, cd, 6);
    }
    else if ( x > 36974.0 )
    {
        cc = 0.5;
        ss = 0.5;
    }
    else
    {
        x2 = x * x;
        t = M_PI * x2;
        u = 1.0 / (t * t);
        t = 1.0 / t;
        f = 1.0 - u * polevl (u, fn, 9) / p1evl(u, fd, 10);
        g = t * polevl (u, gn, 10) / p1evl (u, gd, 11);

        t = M_PI * 0.5 * x2;
        c = cos (t);
        s = sin (t);
        t = M_PI * x;
        cc = 0.5 + (f * s - g * c) / t;
        ss = 0.5 - (f * c + g * s) / t;
    }

    if ( xxa < 0.0 )
    {
        cc = -cc;
        ss = -ss;
    }

    *cca = cc;
    *ssa = ss;
}

/**
* compute the actual "standard" spiral, starting with curvature 0
* @param s      run-length along spiral
* @param cDot   first derivative of curvature [1/m2]
* @param x      resulting x-coordinate in spirals local co-ordinate system [m]
* @param y      resulting y-coordinate in spirals local co-ordinate system [m]
* @param t      tangent direction at s [rad]
*/

void odrSpiral( double s, double cDot, double *x, double *y, double *t )
{
    double a;

    a = 1.0 / sqrt( fabs( cDot ) );
    a *= sqrt( M_PI );

    fresnel( s / a, y, x );

    *x *= a;
    *y *= a;

    if ( cDot < 0.0 )
        *y *= -1.0;

    *t = s * s * cDot * 0.5;
}


{
    double a;

    a = 1.0 / sqrt( fabs( cDot ) );
    a *= sqrt( M_PI );

    fresnel( s / a, y, x );

    *x *= a;
    *y *= a;

    if ( cDot < 0.0 )
        *y *= -1.0;

    *t = s * s * cDot * 0.5;
}


    int i;

    ans = x + *p++;
    i   = n - 1;

    do
    {
        ans = ans * x + *p++;
    }
    while (--i);

    return ans;
}

static void fresnel( double xxa, double *ssa, double *cca )
{
    double f, g, cc, ss, c, s, t, u;
    double x, x2;

    x  = fabs( xxa );
    x2 = x * x;

    if ( x2 < 2.5625 )
    {
        t = x2 * x2;
        ss = x * x2 * polevl (t, sn, 5) / p1evl (t, sd, 6);
        cc = x * polevl (t, cn, 5) / polevl (t, cd, 6);
    }
    else if ( x > 36974.0 )
    {
        cc = 0.5;
        ss = 0.5;
    }
    else
    {
        x2 = x * x;
        t = M_PI * x2;
        u = 1.0 / (t * t);
        t = 1.0 / t;
        f = 1.0 - u * polevl (u, fn, 9) / p1evl(u, fd, 10);
        g = t * polevl (u, gn, 10) / p1evl (u, gd, 11);

        t = M_PI * 0.5 * x2;
        c = cos (t);
        s = sin (t);
        t = M_PI * x;
        cc = 0.5 + (f * s - g * c) / t;
        ss = 0.5 - (f * c + g * s) / t;
    }

    if ( xxa < 0.0 )
    {
        cc = -cc;
        ss = -ss;
    }

    *cca = cc;
    *ssa = ss;
}

/**
* compute the actual "standard" spiral, starting with curvature 0
* @param s      run-length along spiral
* @param cDot   first derivative of curvature [1/m2]
* @param x      resulting x-coordinate in spirals local co-ordinate system [m]
* @param y      resulting y-coordinate in spirals local co-ordinate system [m]
* @param t      tangent direction at s [rad]
*/

void odrSpiral( double s, double cDot, double *x, double *y, double *t )
{
    double a;

    a = 1.0 / sqrt( fabs( cDot ) );
    a *= sqrt( M_PI );

    fresnel( s / a, y, x );

    *x *= a;
    *y *= a;

    if ( cDot < 0.0 )
        *y *= -1.0;

    *t = s * s * cDot * 0.5;
}


void odrSpiral( double s, double cDot, double *x, double *y, double *t )
{
    double a;

    a = 1.0 / sqrt( fabs( cDot ) );
    a *= sqrt( M_PI );

    fresnel( s / a, y, x );

    *x *= a;
    *y *= a;

    if ( cDot < 0.0 )
        *y *= -1.0;

    *t = s * s * cDot * 0.5;
}


 using namespace std;
 #include<iostream>
 #include<bits/stdc++.h>

{
     long long N,i,j,sum=0,count=0;
     cin>>N;
     long long *arr=new long long[N];
     for(i=0;i<N;i++)
     {
         cin>>arr[i];
     }
     sort(arr,arr+N);
     if(arr[N-1]<0)
     {
         cout<<arr[N-1]<<" "<<"1";
         return 0;
     }
     else
     {
         for(i=0;i<N;i++)
         {
             if(arr[i]>=0)
             {
                 sum+=arr[i];
                 count++;
             }
         }
         cout<<sum<<" "<<count;
     }
     return 0;
 }


{
     long long N,i,j,sum=0,count=0;
     cin>>N;
     long long *arr=new long long[N];
     for(i=0;i<N;i++)
     {
         cin>>arr[i];
     }
     sort(arr,arr+N);
     if(arr[N-1]<0)
     {
         cout<<arr[N-1]<<" "<<"1";
         return 0;
     }
     else
     {
         for(i=0;i<N;i++)
         {
             if(arr[i]>=0)
             {
                 sum+=arr[i];
                 count++;
             }
         }
         cout<<sum<<" "<<count;
     }
     return 0;
 }

 using namespace std;
 #include<iostream>
 #include<bits/stdc++.h>
 int main()


 using namespace std;
 #include<iostream>
 #include<bits/stdc++.h>
 int main()
 {
     long long N,i,j,sum=0,count

     cin>>N;
     long long *arr=new long long[N];
     for(i=0;i<N;i++)
     {
         cin>>arr[i];
     }
     sort(arr,arr+N);
     if(arr[N-1]<0)
     {
         cout<<arr[N-1]<<" "<<"1";
         return 0;
     }
     else
     {
         for(i=0;i<N;i++)
         {
             if(arr[i]>=0)
             {
                 sum+=arr[i];
                 count++;
             }
         }
         cout<<sum<<" "<<count;
     }
     return 0;
 }


 using namespace std;
 #include<iostream>
 #include<bits/stdc++.h>
 int main()
 {
     long long N,i,j,sum=0,count=0;
     cin>>N;
     long long *arr=new long long[N];

     sort(arr,arr+N);
     if(arr[N-1]<0)
     {
         cout<<arr[N-1]<<" "<<"1";
         return 0;
     }
     else
     {
         for(i=0;i<N;i++)
         {
             if(arr[i]>=0)
             {
                 sum+=arr[i];
                 count++;
             }
         }
         cout<<sum<<" "<<count;
     }
     return 0;
 }


int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)

//	Shadows Sample
//  by MJP

#include "PCH.h"

#include "Shadows.h"
#include "resource.h"
#include "SharedConstants.h"
#include "AppSettings.h"

#include "SampleFramework11/InterfacePointers.h"
#include "SampleFramework11/Window.h"
#include "SampleFramework11/DeviceManager.h"
#include "SampleFramework11/Input.h"
#include "SampleFramework11/SpriteRenderer.h"
#include "SampleFramework11/Model.h"
#include "SampleFramework11/Utility.h"
#include "SampleFramework11/Camera.h"
#include "SampleFramework11/ShaderCompilation.h"
#include "SampleFramework11/Profiler.h"
#include "SampleFramework11/Settings.h"
#include "SampleFramework11/TwHelper.h"

using namespace SampleFramework11;
using std::wstring;

const uint32 WindowWidth = 1280;
const uint32 WindowHeight = 720;
const float WindowWidthF = static_cast<float>(WindowWidth);
const float WindowHeightF = static_cast<float>(WindowHeight);

static const float NearClip = 0.25f;
static const float FarClip = 250.0f;

// Mesh filenames
static const wstring MeshFileNames[] =
{
    L"Powerplant\\Powerplant.sdkmesh",
    L"Tower\\Tower.sdkmesh",
    L"Columns\\Columns.sdkmesh",
};

// Scale values applied to the mesh
static const float MeshScales[] =
{
    0.5f,
    0.025f,
    0.25f,
};

static const float CharacterScale = 1.0f;
static const Float3 CharacterPos = Float3(25.0f, 0.0f, 3.0f);

ShadowsApp::ShadowsApp() :  App(L"Shadows", MAKEINTRESOURCEW(IDI_ICON1)),
                                camera(WindowWidthF / WindowHeightF, XM_PIDIV4 * 0.75f, NearClip, FarClip)
{
    deviceManager.SetMinFeatureLevel(D3D_FEATURE_LEVEL_11_0);
}

void ShadowsApp::BeforeReset()
{
    App::BeforeReset();
}

void ShadowsApp::AfterReset()
{
    App::AfterReset();

    float aspect = static_cast<float>(deviceManager.BackBufferWidth()) / deviceManager.BackBufferHeight();
    camera.SetAspectRatio(aspect);

    CreateRenderTargets();

    postProcessor.AfterReset(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());
}

void ShadowsApp::Initialize()
{
    App::Initialize();

    AppSettings::Initialize(deviceManager.Device());

    TwHelper::SetGlobalHelpText("Shadows Sample - implements various cascaded shadow map techniques, "
                                "as well as several methods for filtering shadow maps");

    ID3D11DevicePtr device = deviceManager.Device();
    ID3D11DeviceContextPtr deviceContext = deviceManager.ImmediateContext();

    // Camera setup
    camera.SetPosition(Float3(40.0f, 5.0f, 5.0f));
    camera.SetYRotation(-XM_PIDIV2);

    // Load the meshes
    for(uint32 i = 0; i < uint32(Scene::NumValues); ++i)
    {
        wstring path(L"..\\Content\\Models\\");
        path += MeshFileNames[i];
        models[i].CreateFromSDKMeshFile(device, path.c_str());
    }

    wstring characterPath(L"..\\Content\\Models\\Soldier\\Soldier.sdkmesh");
    characterMesh.CreateFromSDKMeshFile(device, characterPath.c_str());

    meshRenderer.Initialize(device, deviceManager.ImmediateContext());

    ID3D11DeviceContext* context = deviceManager.ImmediateContext();

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[(int)AppSettings::CurrentScene]);
    meshRenderer.SetSceneMesh(context, &models[(int)AppSettings::CurrentScene], meshWorld);

    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);
    meshRenderer.SetCharacterMesh(context, &characterMesh, characterWorld);

    skybox.Initialize(device);

    // Init the post processor
    postProcessor.Initialize(device);
}

// Creates all required render targets
void ShadowsApp::CreateRenderTargets()
{
    ID3D11Device* device = deviceManager.Device();
    uint32 width = deviceManager.BackBufferWidth();
    uint32 height = deviceManager.BackBufferHeight();

    const uint32 MSAALevel = 4;
    colorTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, MSAALevel, 0);
    depthBuffer.Initialize(device, width, height, DXGI_FORMAT_D24_UNORM_S8_UINT, true, MSAALevel, 0);

    if(MSAALevel > 1)
        resolveTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, 1, 0);
    else
        resolveTarget = colorTarget;

    meshRenderer.CreateReductionTargets(width, height);
}

void ShadowsApp::Update(const Timer& timer)
{
    MouseState mouseState = MouseState::GetMouseState(window);
    KeyboardState kbState = KeyboardState::GetKeyboardState(window);

    if (kbState.IsKeyDown(KeyboardState::Escape))
        window.Destroy();

    float CamMoveSpeed = 5.0f * timer.DeltaSecondsF();
    const float CamRotSpeed = 0.180f * timer.DeltaSecondsF();
    const float MeshRotSpeed = 0.180f * timer.DeltaSecondsF();

    // Move the camera with keyboard input
    if (kbState.IsKeyDown(KeyboardState::LeftShift))
        CamMoveSpeed *= 0.25f;

    Float3 camPos = camera.Position();
    if (kbState.IsKeyDown(KeyboardState::W))
        camPos += camera.Forward() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::S))
        camPos += camera.Back() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::A))
        camPos += camera.Left() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::D))
        camPos += camera.Right() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::Q))
        camPos += camera.Up() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::E))
        camPos += camera.Down() * CamMoveSpeed;

    camera.SetPosition(camPos);

    // Rotate the camera with the mouse
    if(mouseState.RButton.Pressed && mouseState.IsOverWindow)
    {
        float xRot = camera.XRotation();
        float yRot = camera.YRotation();
        xRot += mouseState.DY * CamRotSpeed;
        yRot += mouseState.DX * CamRotSpeed;
        camera.SetXRotation(xRot);
        camera.SetYRotation(yRot);
    }

    if(AppSettings::AnimateLight)
    {
        float rotY = XMScalarModAngle(timer.DeltaSecondsF() * 0.25f);
        Quaternion rotation = Quaternion::FromAxisAngle(Float3(0.0f, 1.0f, 0.0f), rotY);
        Float3 lightDir = AppSettings::LightDirection;
        lightDir = Float3::Transform(lightDir, rotation);
        AppSettings::LightDirection.SetValue(lightDir);
    }

    // Toggle VSYNC
    if(kbState.RisingEdge(KeyboardState::V))
        deviceManager.SetVSYNCEnabled(!deviceManager.VSYNCEnabled());

    if(AppSettings::CurrentScene.Changed())
    {
        float scale = MeshScales[AppSettings::CurrentScene];
        meshRenderer.SetSceneMesh(deviceManager.ImmediateContext(), &models[AppSettings::CurrentScene],
                             XMMatrixScaling(scale, scale, scale));
    }

    AppSettings::Update();

    meshRenderer.Update();
}

void ShadowsApp::Render(const Timer& timer)
{
    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    AppSettings::UpdateCBuffer(context);

    RenderMainPass();

    if(colorTarget.MultiSamples > 1)
        context->ResolveSubresource(resolveTarget.Texture, 0, colorTarget.Texture, 0, colorTarget.Format);

    // Kick off post-processing
    D3DPERF_BeginEvent(0xFFFFFFFF, L"Post Processing");
    PostProcessor::Constants constants;
    constants.BloomThreshold = AppSettings::BloomThreshold;
    constants.BloomMagnitude = AppSettings::BloomMagnitude;
    constants.BloomBlurSigma = AppSettings::BloomBlurSigma;
    constants.Tau = AppSettings::AdaptationRate;
    constants.KeyValue = AppSettings::KeyValue;
    constants.TimeDelta = timer.DeltaSecondsF();

    postProcessor.SetConstants(constants);
    postProcessor.Render(context, resolveTarget.SRView, deviceManager.BackBuffer());
    D3DPERF_EndEvent();

    ID3D11RenderTargetView* renderTargets[1] = { deviceManager.BackBuffer() };
    context->OMSetRenderTargets(1, renderTargets, NULL);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(deviceManager.BackBufferWidth());
    vp.Height = static_cast<float>(deviceManager.BackBufferHeight());
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    vp.MinDepth = 0;
    vp.MaxDepth = 1;
    context->RSSetViewports(1, &vp);

    /*spriteRenderer.Begin(context, SpriteRenderer::Linear);

    ID3D11ShaderResourceView* srv =  meshRenderer.ShadowMap().SRView;
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    srv->GetDesc(&srvDesc);
    srvDesc.Texture2DArray.ArraySize = 1;
    ID3D11ShaderResourceViewPtr newSrv;
    deviceManager.Device()->CreateShaderResourceView(meshRenderer.ShadowMap().Texture, &srvDesc, &newSrv);

    spriteRenderer.Render(newSrv, Float4x4());

    spriteRenderer.End();*/

    RenderHUD();
}

void ShadowsApp::RenderMainPass()
{
    PIXEvent event(L"Main Pass");

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    ID3D11RenderTargetView* renderTargets[1] = { NULL };
    ID3D11DepthStencilView* ds = depthBuffer.DSView;

    context->OMSetRenderTargets(1, renderTargets, ds);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(colorTarget.Width);
    vp.Height = static_cast<float>(colorTarget.Height);
    vp.TopLeftX = 0.0f;
    vp.TopLeftY = 0.0f;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    context->RSSetViewports(1, &vp);

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    context->ClearRenderTargetView(colorTarget.RTView, clearColor);
    context->ClearDepthStencilView(ds, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[AppSettings::CurrentScene]);
    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);

    {
        ProfileBlock block(L"Depth Prepass");
        if(AppSettings::GPUSceneSubmission)
            meshRenderer.RenderDepthGPU(context, camera, meshWorld, characterWorld, false);
        else
            meshRenderer.RenderDepthCPU(context, camera, meshWorld, characterWorld, false);
    }

    if(AppSettings::AutoComputeDepthBounds)
        meshRenderer.ReduceDepth(context, depthBuffer.SRView, camera);

    if(AppSettings::GPUSceneSubmission)
        meshRenderer.RenderShadowMapGPU(context, camera, meshWorld, characterWorld);
    else
        meshRenderer.RenderShadowMap(context, camera, meshWorld, characterWorld);

    renderTargets[0] = colorTarget.RTView;
    context->OMSetRenderTargets(1, renderTargets, ds);

    context->RSSetViewports(1, &vp);

    Float3 lightDir = AppSettings::LightDirection;
    meshRenderer.Render(context, camera, meshWorld, characterWorld);

    skybox.RenderSky(context, lightDir, true, camera.ViewMatrix(), camera.ProjectionMatrix());
}

void ShadowsApp::RenderHUD()
{
    PIXEvent event(L"HUD Pass");

    spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point);

    Float4x4 transform = Float4x4::TranslationMatrix(Float3(25.0f, 25.0f, 0.0f));
    wstring fpsText(L"FPS: ");
    fpsText += ToString(fps) + L" (" + ToString(1000.0f / fps) + L"ms)";
    spriteRenderer.RenderText(font, fpsText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    transform._42 += 25.0f;
    wstring vsyncText(L"VSYNC (V): ");
    vsyncText += deviceManager.VSYNCEnabled() ? L"Enabled" : L"Disabled";
    spriteRenderer.RenderText(font, vsyncText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    spriteRenderer.End();
}


//	Shadows Sample
//  by MJP

#include "PCH.h"

#include "Shadows.h"
#include "resource.h"
#include "SharedConstants.h"
#include "AppSettings.h"

#include "SampleFramework11/InterfacePointers.h"
#include "SampleFramework11/Window.h"
#include "SampleFramework11/DeviceManager.h"
#include "SampleFramework11/Input.h"
#include "SampleFramework11/SpriteRenderer.h"
#include "SampleFramework11/Model.h"
#include "SampleFramework11/Utility.h"
#include "SampleFramework11/Camera.h"
#include "SampleFramework11/ShaderCompilation.h"
#include "SampleFramework11/Profiler.h"
#include "SampleFramework11/Settings.h"
#include "SampleFramework11/TwHelper.h"

using namespace SampleFramework11;
using std::wstring;

const uint32 WindowWidth = 1280;
const uint32 WindowHeight = 720;
const float WindowWidthF = static_cast<float>(WindowWidth);
const float WindowHeightF = static_cast<float>(WindowHeight);

static const float NearClip = 0.25f;
static const float FarClip = 250.0f;

// Mesh filenames
static const wstring MeshFileNames[] =
{
    L"Powerplant\\Powerplant.sdkmesh",
    L"Tower\\Tower.sdkmesh",
    L"Columns\\Columns.sdkmesh",
};

// Scale values applied to the mesh
static const float MeshScales[] =
{
    0.5f,
    0.025f,
    0.25f,
};

static const float CharacterScale = 1.0f;
static const Float3 CharacterPos = Float3(25.0f, 0.0f, 3.0f);

ShadowsApp::ShadowsApp() :  App(L"Shadows", MAKEINTRESOURCEW(IDI_ICON1)),
                                camera(WindowWidthF / WindowHeightF, XM_PIDIV4 * 0.75f, NearClip, FarClip)
{
    deviceManager.SetMinFeatureLevel(D3D_FEATURE_LEVEL_11_0);
}

void ShadowsApp::BeforeReset()
{
    App::BeforeReset();
}

void ShadowsApp::AfterReset()
{
    App::AfterReset();

    float aspect = static_cast<float>(deviceManager.BackBufferWidth()) / deviceManager.BackBufferHeight();
    camera.SetAspectRatio(aspect);

    CreateRenderTargets();

    postProcessor.AfterReset(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());
}

void ShadowsApp::Initialize()
{
    App::Initialize();

    AppSettings::Initialize(deviceManager.Device());

    TwHelper::SetGlobalHelpText("Shadows Sample - implements various cascaded shadow map techniques, "
                                "as well as several methods for filtering shadow maps");

    ID3D11DevicePtr device = deviceManager.Device();
    ID3D11DeviceContextPtr deviceContext = deviceManager.ImmediateContext();

    // Camera setup
    camera.SetPosition(Float3(40.0f, 5.0f, 5.0f));
    camera.SetYRotation(-XM_PIDIV2);

    // Load the meshes
    for(uint32 i = 0; i < uint32(Scene::NumValues); ++i)
    {
        wstring path(L"..\\Content\\Models\\");
        path += MeshFileNames[i];
        models[i].CreateFromSDKMeshFile(device, path.c_str());
    }

    wstring characterPath(L"..\\Content\\Models\\Soldier\\Soldier.sdkmesh");
    characterMesh.CreateFromSDKMeshFile(device, characterPath.c_str());

    meshRenderer.Initialize(device, deviceManager.ImmediateContext());

    ID3D11DeviceContext* context = deviceManager.ImmediateContext();

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[(int)AppSettings::CurrentScene]);
    meshRenderer.SetSceneMesh(context, &models[(int)AppSettings::CurrentScene], meshWorld);

    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);
    meshRenderer.SetCharacterMesh(context, &characterMesh, characterWorld);

    skybox.Initialize(device);

    // Init the post processor
    postProcessor.Initialize(device);
}

// Creates all required render targets
void ShadowsApp::CreateRenderTargets()
{
    ID3D11Device* device = deviceManager.Device();
    uint32 width = deviceManager.BackBufferWidth();
    uint32 height = deviceManager.BackBufferHeight();

    const uint32 MSAALevel = 4;
    colorTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, MSAALevel, 0);
    depthBuffer.Initialize(device, width, height, DXGI_FORMAT_D24_UNORM_S8_UINT, true, MSAALevel, 0);

    if(MSAALevel > 1)
        resolveTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, 1, 0);
    else
        resolveTarget = colorTarget;

    meshRenderer.CreateReductionTargets(width, height);
}

void ShadowsApp::Update(const Timer& timer)
{
    MouseState mouseState = MouseState::GetMouseState(window);
    KeyboardState kbState = KeyboardState::GetKeyboardState(window);

    if (kbState.IsKeyDown(KeyboardState::Escape))
        window.Destroy();

    float CamMoveSpeed = 5.0f * timer.DeltaSecondsF();
    const float CamRotSpeed = 0.180f * timer.DeltaSecondsF();
    const float MeshRotSpeed = 0.180f * timer.DeltaSecondsF();

    // Move the camera with keyboard input
    if (kbState.IsKeyDown(KeyboardState::LeftShift))
        CamMoveSpeed *= 0.25f;

    Float3 camPos = camera.Position();
    if (kbState.IsKeyDown(KeyboardState::W))
        camPos += camera.Forward() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::S))
        camPos += camera.Back() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::A))
        camPos += camera.Left() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::D))
        camPos += camera.Right() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::Q))
        camPos += camera.Up() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::E))
        camPos += camera.Down() * CamMoveSpeed;

    camera.SetPosition(camPos);

    // Rotate the camera with the mouse
    if(mouseState.RButton.Pressed && mouseState.IsOverWindow)
    {
        float xRot = camera.XRotation();
        float yRot = camera.YRotation();
        xRot += mouseState.DY * CamRotSpeed;
        yRot += mouseState.DX * CamRotSpeed;
        camera.SetXRotation(xRot);
        camera.SetYRotation(yRot);
    }

    if(AppSettings::AnimateLight)
    {
        float rotY = XMScalarModAngle(timer.DeltaSecondsF() * 0.25f);
        Quaternion rotation = Quaternion::FromAxisAngle(Float3(0.0f, 1.0f, 0.0f), rotY);
        Float3 lightDir = AppSettings::LightDirection;
        lightDir = Float3::Transform(lightDir, rotation);
        AppSettings::LightDirection.SetValue(lightDir);
    }

    // Toggle VSYNC
    if(kbState.RisingEdge(KeyboardState::V))
        deviceManager.SetVSYNCEnabled(!deviceManager.VSYNCEnabled());

    if(AppSettings::CurrentScene.Changed())
    {
        float scale = MeshScales[AppSettings::CurrentScene];
        meshRenderer.SetSceneMesh(deviceManager.ImmediateContext(), &models[AppSettings::CurrentScene],
                             XMMatrixScaling(scale, scale, scale));
    }

    AppSettings::Update();

    meshRenderer.Update();
}

void ShadowsApp::Render(const Timer& timer)
{
    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    AppSettings::UpdateCBuffer(context);

    RenderMainPass();

    if(colorTarget.MultiSamples > 1)
        context->ResolveSubresource(resolveTarget.Texture, 0, colorTarget.Texture, 0, colorTarget.Format);

    // Kick off post-processing
    D3DPERF_BeginEvent(0xFFFFFFFF, L"Post Processing");
    PostProcessor::Constants constants;
    constants.BloomThreshold = AppSettings::BloomThreshold;
    constants.BloomMagnitude = AppSettings::BloomMagnitude;
    constants.BloomBlurSigma = AppSettings::BloomBlurSigma;
    constants.Tau = AppSettings::AdaptationRate;
    constants.KeyValue = AppSettings::KeyValue;
    constants.TimeDelta = timer.DeltaSecondsF();

    postProcessor.SetConstants(constants);
    postProcessor.Render(context, resolveTarget.SRView, deviceManager.BackBuffer());
    D3DPERF_EndEvent();

    ID3D11RenderTargetView* renderTargets[1] = { deviceManager.BackBuffer() };
    context->OMSetRenderTargets(1, renderTargets, NULL);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(deviceManager.BackBufferWidth());
    vp.Height = static_cast<float>(deviceManager.BackBufferHeight());
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    vp.MinDepth = 0;
    vp.MaxDepth = 1;
    context->RSSetViewports(1, &vp);

    /*spriteRenderer.Begin(context, SpriteRenderer::Linear);

    ID3D11ShaderResourceView* srv =  meshRenderer.ShadowMap().SRView;
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    srv->GetDesc(&srvDesc);
    srvDesc.Texture2DArray.ArraySize = 1;
    ID3D11ShaderResourceViewPtr newSrv;
    deviceManager.Device()->CreateShaderResourceView(meshRenderer.ShadowMap().Texture, &srvDesc, &newSrv);

    spriteRenderer.Render(newSrv, Float4x4());

    spriteRenderer.End();*/

    RenderHUD();
}

void ShadowsApp::RenderMainPass()
{
    PIXEvent event(L"Main Pass");

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    ID3D11RenderTargetView* renderTargets[1] = { NULL };
    ID3D11DepthStencilView* ds = depthBuffer.DSView;

    context->OMSetRenderTargets(1, renderTargets, ds);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(colorTarget.Width);
    vp.Height = static_cast<float>(colorTarget.Height);
    vp.TopLeftX = 0.0f;
    vp.TopLeftY = 0.0f;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    context->RSSetViewports(1, &vp);

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    context->ClearRenderTargetView(colorTarget.RTView, clearColor);
    context->ClearDepthStencilView(ds, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[AppSettings::CurrentScene]);
    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);

    {
        ProfileBlock block(L"Depth Prepass");
        if(AppSettings::GPUSceneSubmission)
            meshRenderer.RenderDepthGPU(context, camera, meshWorld, characterWorld, false);
        else
            meshRenderer.RenderDepthCPU(context, camera, meshWorld, characterWorld, false);
    }

    if(AppSettings::AutoComputeDepthBounds)
        meshRenderer.ReduceDepth(context, depthBuffer.SRView, camera);

    if(AppSettings::GPUSceneSubmission)
        meshRenderer.RenderShadowMapGPU(context, camera, meshWorld, characterWorld);
    else
        meshRenderer.RenderShadowMap(context, camera, meshWorld, characterWorld);

    renderTargets[0] = colorTarget.RTView;
    context->OMSetRenderTargets(1, renderTargets, ds);

    context->RSSetViewports(1, &vp);

    Float3 lightDir = AppSettings::LightDirection;
    meshRenderer.Render(context, camera, meshWorld, characterWorld);

    skybox.RenderSky(context, lightDir, true, camera.ViewMatrix(), camera.ProjectionMatrix());
}

void ShadowsApp::RenderHUD()
{
    PIXEvent event(L"HUD Pass");

    spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point);

    Float4x4 transform = Float4x4::TranslationMatrix(Float3(25.0f, 25.0f, 0.0f));
    wstring fpsText(L"FPS: ");
    fpsText += ToString(fps) + L" (" + ToString(1000.0f / fps) + L"ms)";
    spriteRenderer.RenderText(font, fpsText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    transform._42 += 25.0f;
    wstring vsyncText(L"VSYNC (V): ");
    vsyncText += deviceManager.VSYNCEnabled() ? L"Enabled" : L"Disabled";
    spriteRenderer.RenderText(font, vsyncText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    spriteRenderer.End();
}

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)


//	Shadows Sample
//  by MJP

#include "PCH.h"

#include "Shadows.h"
#include "resource.h"
#include "SharedConstants.h"
#include "AppSettings.h"

#include "SampleFramework11/InterfacePointers.h"
#include "SampleFramework11/Window.h"
#include "SampleFramework11/DeviceManager.h"
#include "SampleFramework11/Input.h"
#include "SampleFramework11/SpriteRenderer.h"
#include "SampleFramework11/Model.h"
#include "SampleFramework11/Utility.h"
#include "SampleFramework11/Camera.h"
#include "SampleFramework11/ShaderCompilation.h"
#include "SampleFramework11/Profiler.h"
#include "SampleFramework11/Settings.h"
#include "SampleFramework11/TwHelper.h"

using namespace SampleFramework11;
using std::wstring;

const uint32 WindowWidth = 1280;
const uint32 WindowHeight = 720;
const float WindowWidthF = static_cast<float>(WindowWidth);
const float WindowHeightF = static_cast<float>(WindowHeight);

static const float NearClip = 0.25f;
static const float FarClip = 250.0f;

// Mesh filenames
static const wstring MeshFileNames[] =
{
    L"Powerplant\\Powerplant.sdkmesh",
    L"Tower\\Tower.sdkmesh",
    L"Columns\\Columns.sdkmesh",
};

// Scale values applied to the mesh
static const float MeshScales[] =
{
    0.5f,
    0.025f,
    0.25f,
};

static const float CharacterScale = 1.0f;
static const Float3 CharacterPos = Float3(25.0f, 0.0f, 3.0f);

ShadowsApp::ShadowsApp() :  App(L"Shadows", MAKEINTRESOURCEW(IDI_ICON1)),
                                camera(WindowWidthF / WindowHeightF, XM_PIDIV4 * 0.75f, NearClip, FarClip)
{
    deviceManager.SetMinFeatureLevel(D3D_FEATURE_LEVEL_11_0);
}

void ShadowsApp::BeforeReset()
{
    App::BeforeReset();
}

void ShadowsApp::AfterReset()
{
    App::AfterReset();

    float aspect = static_cast<float>(deviceManager.BackBufferWidth()) / deviceManager.BackBufferHeight();
    camera.SetAspectRatio(aspect);

    CreateRenderTargets();

    postProcessor.AfterReset(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());
}

void ShadowsApp::Initialize()
{
    App::Initialize();

    AppSettings::Initialize(deviceMana

    TwHelper::SetGlobalHelpText("Shadows Sample - implements various cascaded shadow map techniques, "
                                "as well as several methods for filtering shadow maps");

    ID3D11DevicePtr device = deviceManager.Device();
    ID3D11DeviceContextPtr deviceContext = deviceManager.ImmediateContext();

    // Camera setup
    camera.SetPosition(Float3(40.0f, 5.0f, 5.0f));
    camera.SetYRotation(-XM_PIDIV2);

    // Load the meshes
    for(uint32 i = 0; i < uint32(Scene::NumValues); ++i)
    {
        wstring path(L"..\\Content\\Models\\");
        path += MeshFileNames[i];
        models[i].CreateFromSDKMeshFile(device, path.c_str());
    }

    wstring characterPath(L"..\\Content\\Models\\Soldier\\Soldier.sdkmesh");
    characterMesh.CreateFromSDKMeshFile(device, characterPath.c_str());

    meshRenderer.Initialize(device, deviceManager.ImmediateContext());

    ID3D11DeviceContext* context = deviceManager.ImmediateContext();

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[(int)AppSettings::CurrentScene]);
    meshRenderer.SetSceneMesh(context, &models[(int)AppSettings::CurrentScene], meshWorld);

    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);
    meshRenderer.SetCharacterMesh(context, &characterMesh, characterWorld);

    skybox.Initialize(device);

    // Init the post processor
    postProcessor.Initialize(device);
}

// Creates all required render targets
void ShadowsApp::CreateRenderTargets()
{
    ID3D11Device* device = deviceManager.Device();
    uint32 width = deviceManager.BackBufferWidth();
    uint32 height = deviceManager.BackBufferHeight();

    const uint32 MSAALevel = 4;
    colorTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, MSAALevel, 0);
    depthBuffer.Initialize(device, width, height, DXGI_FORMAT_D24_UNORM_S8_UINT, true, MSAALevel, 0);

    if(MSAALevel > 1)
        resolveTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, 1, 0);
    else
        resolveTarget = colorTarget;

    meshRenderer.CreateReductionTargets(width, height);
}

void ShadowsApp::Update(const Timer& timer)
{
    MouseState mouseState = MouseState::GetMouseState(window);
    KeyboardState kbState = KeyboardState::GetKeyboardState(window);

    if (kbState.IsKeyDown(KeyboardState::Escape))
        window.Destroy();

    float CamMoveSpeed = 5.0f * timer.DeltaSecondsF();
    const float CamRotSpeed = 0.180f * timer.DeltaSecondsF();
    const float MeshRotSpeed = 0.180f * timer.DeltaSecondsF();

    // Move the camera with keyboard input
    if (kbState.IsKeyDown(KeyboardState::LeftShift))
        CamMoveSpeed *= 0.25f;

    Float3 camPos = camera.Position();
    if (kbState.IsKeyDown(KeyboardState::W))
        camPos += camera.Forward() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::S))
        camPos += camera.Back() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::A))
        camPos += camera.Left() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::D))
        camPos += camera.Right() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::Q))
        camPos += camera.Up() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::E))
        camPos += camera.Down() * CamMoveSpeed;

    camera.SetPosition(camPos);

    // Rotate the camera with the mouse
    if(mouseState.RButton.Pressed && mouseState.IsOverWindow)
    {
        float xRot = camera.XRotation();
        float yRot = camera.YRotation();
        xRot += mouseState.DY * CamRotSpeed;
        yRot += mouseState.DX * CamRotSpeed;
        camera.SetXRotation(xRot);
        camera.SetYRotation(yRot);
    }

    if(AppSettings::AnimateLight)
    {
        float rotY = XMScalarModAngle(timer.DeltaSecondsF() * 0.25f);
        Quaternion rotation = Quaternion::FromAxisAngle(Float3(0.0f, 1.0f, 0.0f), rotY);
        Float3 lightDir = AppSettings::LightDirection;
        lightDir = Float3::Transform(lightDir, rotation);
        AppSettings::LightDirection.SetValue(lightDir);
    }

    // Toggle VSYNC
    if(kbState.RisingEdge(KeyboardState::V))
        deviceManager.SetVSYNCEnabled(!deviceManager.VSYNCEnabled());

    if(AppSettings::CurrentScene.Changed())
    {
        float scale = MeshScales[AppSettings::CurrentScene];
        meshRenderer.SetSceneMesh(deviceManager.ImmediateContext(), &models[AppSettings::CurrentScene],
                             XMMatrixScaling(scale, scale, scale));
    }

    AppSettings::Update();

    meshRenderer.Update();
}

void ShadowsApp::Render(const Timer& timer)
{
    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    AppSettings::UpdateCBuffer(context);

    RenderMainPass();

    if(colorTarget.MultiSamples > 1)
        context->ResolveSubresource(resolveTarget.Texture, 0, colorTarget.Texture, 0, colorTarget.Format);

    // Kick off post-processing
    D3DPERF_BeginEvent(0xFFFFFFFF, L"Post Processing");
    PostProcessor::Constants constants;
    constants.BloomThreshold = AppSettings::BloomThreshold;
    constants.BloomMagnitude = AppSettings::BloomMagnitude;
    constants.BloomBlurSigma = AppSettings::BloomBlurSigma;
    constants.Tau = AppSettings::AdaptationRate;
    constants.KeyValue = AppSettings::KeyValue;
    constants.TimeDelta = timer.DeltaSecondsF();

    postProcessor.SetConstants(constants);
    postProcessor.Render(context, resolveTarget.SRView, deviceManager.BackBuffer());
    D3DPERF_EndEvent();

    ID3D11RenderTargetView* renderTargets[1] = { deviceManager.BackBuffer() };
    context->OMSetRenderTargets(1, renderTargets, NULL);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(deviceManager.BackBufferWidth());
    vp.Height = static_cast<float>(deviceManager.BackBufferHeight());
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    vp.MinDepth = 0;
    vp.MaxDepth = 1;
    context->RSSetViewports(1, &vp);

    /*spriteRenderer.Begin(context, SpriteRenderer::Linear);

    ID3D11ShaderResourceView* srv =  meshRenderer.ShadowMap().SRView;
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    srv->GetDesc(&srvDesc);
    srvDesc.Texture2DArray.ArraySize = 1;
    ID3D11ShaderResourceViewPtr newSrv;
    deviceManager.Device()->CreateShaderResourceView(meshRenderer.ShadowMap().Texture, &srvDesc, &newSrv);

    spriteRenderer.Render(newSrv, Float4x4());

    spriteRenderer.End();*/

    RenderHUD();
}

void ShadowsApp::RenderMainPass()
{
    PIXEvent event(L"Main Pass");

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    ID3D11RenderTargetView* renderTargets[1] = { NULL };
    ID3D11DepthStencilView* ds = depthBuffer.DSView;

    context->OMSetRenderTargets(1, renderTargets, ds);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(colorTarget.Width);
    vp.Height = static_cast<float>(colorTarget.Height);
    vp.TopLeftX = 0.0f;
    vp.TopLeftY = 0.0f;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    context->RSSetViewports(1, &vp);

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    context->ClearRenderTargetView(colorTarget.RTView, clearColor);
    context->ClearDepthStencilView(ds, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[AppSettings::CurrentScene]);
    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);

    {
        ProfileBlock block(L"Depth Prepass");
        if(AppSettings::GPUSceneSubmission)
            meshRenderer.RenderDepthGPU(context, camera, meshWorld, characterWorld, false);
        else
            meshRenderer.RenderDepthCPU(context, camera, meshWorld, characterWorld, false);
    }

    if(AppSettings::AutoComputeDepthBounds)
        meshRenderer.ReduceDepth(context, depthBuffer.SRView, camera);

    if(AppSettings::GPUSceneSubmission)
        meshRenderer.RenderShadowMapGPU(context, camera, meshWorld, characterWorld);
    else
        meshRenderer.RenderShadowMap(context, camera, meshWorld, characterWorld);

    renderTargets[0] = colorTarget.RTView;
    context->OMSetRenderTargets(1, renderTargets, ds);

    context->RSSetViewports(1, &vp);

    Float3 lightDir = AppSettings::LightDirection;
    meshRenderer.Render(context, camera, meshWorld, characterWorld);

    skybox.RenderSky(context, lightDir, true, camera.ViewMatrix(), camera.ProjectionMatrix());
}

void ShadowsApp::RenderHUD()
{
    PIXEvent event(L"HUD Pass");

    spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point);

    Float4x4 transform = Float4x4::TranslationMatrix(Float3(25.0f, 25.0f, 0.0f));
    wstring fpsText(L"FPS: ");
    fpsText += ToString(fps) + L" (" + ToString(1000.0f / fps) + L"ms)";
    spriteRenderer.RenderText(font, fpsText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    transform._42 += 25.0f;
    wstring vsyncText(L"VSYNC (V): ");
    vsyncText += deviceManager.VSYNCEnabled() ? L"Enabled" : L"Disabled";
    spriteRenderer.RenderText(font, vsyncText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    spriteRenderer.End();
}

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    ShadowsApp app;
    app.Run();
}


for(uint32 i = 0; i < uint32(Scene::NumValues); ++i)
    {
        wstring path(L"..\\Content\\Models\\");
        path += MeshFileNames[i];
        models[i].CreateFromSDKMeshFile(device, path.c_str());
    }

//	Shadows Sample
//  by MJP

#include "PCH.h"

#include "Shadows.h"
#include "resource.h"
#include "SharedConstants.h"
#include "AppSettings.h"

#include "SampleFramework11/InterfacePointers.h"
#include "SampleFramework11/Window.h"
#include "SampleFramework11/DeviceManager.h"
#include "SampleFramework11/Input.h"
#include "SampleFramework11/SpriteRenderer.h"
#include "SampleFramework11/Model.h"
#include "SampleFramework11/Utility.h"
#include "SampleFramework11/Camera.h"
#include "SampleFramework11/ShaderCompilation.h"
#include "SampleFramework11/Profiler.h"
#include "SampleFramework11/Settings.h"
#include "SampleFramework11/TwHelper.h"

using namespace SampleFramework11;
using std::wstring;

const uint32 WindowWidth = 1280;
const uint32 WindowHeight = 720;
const float WindowWidthF = static_cast<float>(WindowWidth);
const float WindowHeightF = static_cast<float>(WindowHeight);

static const float NearClip = 0.25f;
static const float FarClip = 250.0f;

// Mesh filenames
static const wstring MeshFileNames[] =
{
    L"Powerplant\\Powerplant.sdkmesh",
    L"Tower\\Tower.sdkmesh",
    L"Columns\\Columns.sdkmesh",
};

// Scale values applied to the mesh
static const float MeshScales[] =
{
    0.5f,
    0.025f,
    0.25f,
};

static const float CharacterScale = 1.0f;
static const Float3 CharacterPos = Float3(25.0f, 0.0f, 3.0f);

ShadowsApp::ShadowsApp() :  App(L"Shadows", MAKEINTRESOURCEW(IDI_ICON1)),
                                camera(WindowWidthF / WindowHeightF, XM_PIDIV4 * 0.75f, NearClip, FarClip)
{
    deviceManager.SetMinFeatureLevel(D3D_FEATURE_LEVEL_11_0);
}

void ShadowsApp::BeforeReset()
{
    App::BeforeReset();
}

void ShadowsApp::AfterReset()
{
    App::AfterReset();

    float aspect = static_cast<float>(deviceManager.BackBufferWidth()) / deviceManager.BackBufferHeight();
    camera.SetAspectRatio(aspect);

    CreateRenderTargets();

    postProcessor.AfterReset(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight());
}

void ShadowsApp::Initialize()
{
    App::Initialize();

    AppSettings::Initialize(deviceManager.Device());

    TwHelper::SetGlobalHelpText("Shadows Sample - implements various cascaded shadow map techniques, "
                                "as well as several methods for filtering shadow maps");

    ID3D11DevicePtr device = deviceManager.Device();
    ID3D11DeviceContextPtr deviceContext = deviceManager.ImmediateContext();

    // Camera setup
    camera.SetPosition(Float3(40.0f, 5.0f, 5.0f));
    camera.SetYRotation(-XM_PIDIV2);

    // Load the meshes

    wstring characterPath(L"..\\Content\\Models\\Soldier\\Soldier.sdkmesh");
    characterMesh.CreateFromSDKMeshFile(device, characterPath.c_str());

    meshRenderer.Initialize(device, deviceManager.ImmediateContext());

    ID3D11DeviceContext* context = deviceManager.ImmediateContext();

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[(int)AppSettings::CurrentScene]);
    meshRenderer.SetSceneMesh(context, &models[(int)AppSettings::CurrentScene], meshWorld);

    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);
    meshRenderer.SetCharacterMesh(context, &characterMesh, characterWorld);

    skybox.Initialize(device);

    // Init the post processor
    postProcessor.Initialize(device);
}

// Creates all required render targets
void ShadowsApp::CreateRenderTargets()
{
    ID3D11Device* device = deviceManager.Device();
    uint32 width = deviceManager.BackBufferWidth();
    uint32 height = deviceManager.BackBufferHeight();

    const uint32 MSAALevel = 4;
    colorTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, MSAALevel, 0);
    depthBuffer.Initialize(device, width, height, DXGI_FORMAT_D24_UNORM_S8_UINT, true, MSAALevel, 0);

    if(MSAALevel > 1)
        resolveTarget.Initialize(device, width, height, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, 1, 0);
    else
        resolveTarget = colorTarget;

    meshRenderer.CreateReductionTargets(width, height);
}

void ShadowsApp::Update(const Timer& timer)
{
    MouseState mouseState = MouseState::GetMouseState(window);
    KeyboardState kbState = KeyboardState::GetKeyboardState(window);

    if (kbState.IsKeyDown(KeyboardState::Escape))
        window.Destroy();

    float CamMoveSpeed = 5.0f * timer.DeltaSecondsF();
    const float CamRotSpeed = 0.180f * timer.DeltaSecondsF();
    const float MeshRotSpeed = 0.180f * timer.DeltaSecondsF();

    // Move the camera with keyboard input
    if (kbState.IsKeyDown(KeyboardState::LeftShift))
        CamMoveSpeed *= 0.25f;

    Float3 camPos = camera.Position();
    if (kbState.IsKeyDown(KeyboardState::W))
        camPos += camera.Forward() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::S))
        camPos += camera.Back() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::A))
        camPos += camera.Left() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::D))
        camPos += camera.Right() * CamMoveSpeed;
    if (kbState.IsKeyDown(KeyboardState::Q))
        camPos += camera.Up() * CamMoveSpeed;
    else if (kbState.IsKeyDown(KeyboardState::E))
        camPos += camera.Down() * CamMoveSpeed;

    camera.SetPosition(camPos);

    // Rotate the camera with the mouse
    if(mouseState.RButton.Pressed && mouseState.IsOverWindow)
    {
        float xRot = camera.XRotation();
        float yRot = camera.YRotation();
        xRot += mouseState.DY * CamRotSpeed;
        yRot += mouseState.DX * CamRotSpeed;
        camera.SetXRotation(xRot);
        camera.SetYRotation(yRot);
    }

    if(AppSettings::AnimateLight)
    {
        float rotY = XMScalarModAngle(timer.DeltaSecondsF() * 0.25f);
        Quaternion rotation = Quaternion::FromAxisAngle(Float3(0.0f, 1.0f, 0.0f), rotY);
        Float3 lightDir = AppSettings::LightDirection;
        lightDir = Float3::Transform(lightDir, rotation);
        AppSettings::LightDirection.SetValue(lightDir);
    }

    // Toggle VSYNC
    if(kbState.RisingEdge(KeyboardState::V))
        deviceManager.SetVSYNCEnabled(!deviceManager.VSYNCEnabled());

    if(AppSettings::CurrentScene.Changed())
    {
        float scale = MeshScales[AppSettings::CurrentScene];
        meshRenderer.SetSceneMesh(deviceManager.ImmediateContext(), &models[AppSettings::CurrentScene],
                             XMMatrixScaling(scale, scale, scale));
    }

    AppSettings::Update();

    meshRenderer.Update();
}

void ShadowsApp::Render(const Timer& timer)
{
    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    AppSettings::UpdateCBuffer(context);

    RenderMainPass();

    if(colorTarget.MultiSamples > 1)
        context->ResolveSubresource(resolveTarget.Texture, 0, colorTarget.Texture, 0, colorTarget.Format);

    // Kick off post-processing
    D3DPERF_BeginEvent(0xFFFFFFFF, L"Post Processing");
    PostProcessor::Constants constants;
    constants.BloomThreshold = AppSettings::BloomThreshold;
    constants.BloomMagnitude = AppSettings::BloomMagnitude;
    constants.BloomBlurSigma = AppSettings::BloomBlurSigma;
    constants.Tau = AppSettings::AdaptationRate;
    constants.KeyValue = AppSettings::KeyValue;
    constants.TimeDelta = timer.DeltaSecondsF();

    postProcessor.SetConstants(constants);
    postProcessor.Render(context, resolveTarget.SRView, deviceManager.BackBuffer());
    D3DPERF_EndEvent();

    ID3D11RenderTargetView* renderTargets[1] = { deviceManager.BackBuffer() };
    context->OMSetRenderTargets(1, renderTargets, NULL);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(deviceManager.BackBufferWidth());
    vp.Height = static_cast<float>(deviceManager.BackBufferHeight());
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    vp.MinDepth = 0;
    vp.MaxDepth = 1;
    context->RSSetViewports(1, &vp);

    /*spriteRenderer.Begin(context, SpriteRenderer::Linear);

    ID3D11ShaderResourceView* srv =  meshRenderer.ShadowMap().SRView;
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    srv->GetDesc(&srvDesc);
    srvDesc.Texture2DArray.ArraySize = 1;
    ID3D11ShaderResourceViewPtr newSrv;
    deviceManager.Device()->CreateShaderResourceView(meshRenderer.ShadowMap().Texture, &srvDesc, &newSrv);

    spriteRenderer.Render(newSrv, Float4x4());

    spriteRenderer.End();*/

    RenderHUD();
}

void ShadowsApp::RenderMainPass()
{
    PIXEvent event(L"Main Pass");

    ID3D11DeviceContextPtr context = deviceManager.ImmediateContext();

    ID3D11RenderTargetView* renderTargets[1] = { NULL };
    ID3D11DepthStencilView* ds = depthBuffer.DSView;

    context->OMSetRenderTargets(1, renderTargets, ds);

    D3D11_VIEWPORT vp;
    vp.Width = static_cast<float>(colorTarget.Width);
    vp.Height = static_cast<float>(colorTarget.Height);
    vp.TopLeftX = 0.0f;
    vp.TopLeftY = 0.0f;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    context->RSSetViewports(1, &vp);

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    context->ClearRenderTargetView(colorTarget.RTView, clearColor);
    context->ClearDepthStencilView(ds, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);

    Float4x4 meshWorld = Float4x4::ScaleMatrix(MeshScales[AppSettings::CurrentScene]);
    Float4x4 characterWorld = Float4x4::ScaleMatrix(CharacterScale);
    Float4x4 characterOrientation = Quaternion::ToFloat4x4(AppSettings::CharacterOrientation);
    characterWorld = characterWorld * characterOrientation;
    characterWorld.SetTranslation(CharacterPos);

    {
        ProfileBlock block(L"Depth Prepass");
        if(AppSettings::GPUSceneSubmission)
            meshRenderer.RenderDepthGPU(context, camera, meshWorld, characterWorld, false);
        else
            meshRenderer.RenderDepthCPU(context, camera, meshWorld, characterWorld, false);
    }

    if(AppSettings::AutoComputeDepthBounds)
        meshRenderer.ReduceDepth(context, depthBuffer.SRView, camera);

    if(AppSettings::GPUSceneSubmission)
        meshRenderer.RenderShadowMapGPU(context, camera, meshWorld, characterWorld);
    else
        meshRenderer.RenderShadowMap(context, camera, meshWorld, characterWorld);

    renderTargets[0] = colorTarget.RTView;
    context->OMSetRenderTargets(1, renderTargets, ds);

    context->RSSetViewports(1, &vp);

    Float3 lightDir = AppSettings::LightDirection;
    meshRenderer.Render(context, camera, meshWorld, characterWorld);

    skybox.RenderSky(context, lightDir, true, camera.ViewMatrix(), camera.ProjectionMatrix());
}

void ShadowsApp::RenderHUD()
{
    PIXEvent event(L"HUD Pass");

    spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point);

    Float4x4 transform = Float4x4::TranslationMatrix(Float3(25.0f, 25.0f, 0.0f));
    wstring fpsText(L"FPS: ");
    fpsText += ToString(fps) + L" (" + ToString(1000.0f / fps) + L"ms)";
    spriteRenderer.RenderText(font, fpsText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    transform._42 += 25.0f;
    wstring vsyncText(L"VSYNC (V): ");
    vsyncText += deviceManager.VSYNCEnabled() ? L"Enabled" : L"Disabled";
    spriteRenderer.RenderText(font, vsyncText.c_str(), transform, XMFLOAT4(1, 1, 0, 1));

    spriteRenderer.End();
}

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    ShadowsApp app;
    app.Run();
}


EPuckCommandPacket::EPuckCommandPacket() :
  mDistanceSensorRequested(false),
  mGroundSensorRequested(false),
  mLightSensorRequested(false),
  mAccelerometerRequested(false),
  mEncoderRequested(false)

#include "EPuckCommandPacket.hpp"

#include "Camera.hpp"
#include "Device.hpp"
#include "DeviceManager.hpp"
#include "Led.hpp"
#include "Motor.hpp"
#include "Sensor.hpp"
#include "SingleValueSensor.hpp"
#include "TripleValuesSensor.hpp"

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

{
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
}

EPuckCommandPacket::~EPuckCommandPacket() {
}

void EPuckCommandPacket::clear() {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
  mDistanceSensorRequested = false;
  mGroundSensorRequested = false;
  mLightSensorRequested = false;
  mAccelerometerRequested = false;
  mEncoderRequested = false;
}

int EPuckCommandPacket::apply(int simulationTime) {
  mData[0] = 0x80;  // commands packet
  mData[1] = DeviceManager::instance()->camera()->isEnabled() ? 1 : 0;
  mData[2] = 0;                                                         // send the motor commands (velocity)
  short l = DeviceManager::instance()->motor(0)->velocity() / 0.00628;  // 0.00628 = ( 2 * pi) / encoder_resolution
  short r = DeviceManager::instance()->motor(1)->velocity() / 0.00628;
  if (l > 1000)
    l = 1000;
  else if (l < -1000)
    l = -1000;
  if (r > 1000)
    r = 1000;
  else if (r < -1000)
    r = -1000;
  mData[3] = l & 0xff;
  mData[4] = ((unsigned short)l >> 8) & 0xff;
  mData[5] = r & 0xff;
  mData[6] = ((unsigned short)r >> 8) & 0xff;
  // send the led commands
  mData[7] = 0;
  for (int i = 0; i < 10; i++) {
    Led *led = DeviceManager::instance()->led(i);
    const char d = mData[7];
    const int state = led->state();
    switch (led->index()) {
      case 0:  // LED1
        mData[7] = state ? d | 0b00000001 : d & 0b11111110;
        break;
      case 1:  // LED2
        mData[8] = state & 0xff;
        mData[9] = ((unsigned int)state >> 8) & 0xff;
        mData[10] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 2:  // LED3
        mData[7] = state ? d | 0b00000010 : d & 0b11111101;
        break;
      case 3:  // LED4
        mData[11] = state & 0xff;
        mData[12] = ((unsigned int)state >> 8) & 0xff;
        mData[13] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 4:  // LED5
        mData[7] = state ? d | 0b00000100 : d & 0b11111011;
        break;
      case 5:  // LED6
        mData[14] = state & 0xff;
        mData[15] = ((unsigned int)state >> 8) & 0xff;
        mData[16] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 6:  // LED7
        mData[7] = state ? d | 0b00001000 : d & 0b11110111;
        break;
      case 7:  // LED8
        mData[16] = state & 0xff;
        mData[18] = ((unsigned int)state >> 8) & 0xff;
        mData[19] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 8:  // body LED
        mData[7] = state ? d | 0b00010000 : d & 0b11101111;
        break;
      case 9:  // front LED
        mData[7] = state ? d | 0x00100000 : d & 0b11011111;
        break;
    }
  }
  mData[20] = 0x00;  // don't play any sound
  // Sensors
  if (DeviceManager::instance()->accelerometer()->isEnabled()) {
    mAccelerometerRequested = true;
    mData[1] |= 2;  // enable sensor packet
  }
  for (int i = 0; i < 3; i++) {  // optional ground sensors
    const SingleValueSensor *gs = DeviceManager::instance()->groundSensor(i);
    if (gs && gs->isEnabled()) {
      mGroundSensorRequested = true;  // if at least one sensor is required
      mData[1] |= 2;                  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->distanceSensor(i)->isEnabled()) {
      mDistanceSensorRequested = true;
      mData[1] |= 2;  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->lightSensor(i)->isEnabled()) {
      mLightSensorRequested = true;
      mData[1] |= 2;  // enable packet sensor
      break;
    }
  }
  if (DeviceManager::instance()->positionSensor(0)->isEnabled() || DeviceManager::instance()->positionSensor(1)->isEnabled()) {
    mEncoderRequested = true;
    // FIXME uncomment when next assignment is fixed
    // mData[1] |= 2;  // enable packet sensor
  }
  mData[1] = 3;  // FIXME: remove this
  return mData[1];
}


#include "EPuckCommandPacket.hpp"

#include "Camera.hpp"
#include "Device.hpp"
#include "DeviceManager.hpp"
#include "Led.hpp"
#include "Motor.hpp"
#include "Sensor.hpp"
#include "SingleValueSensor.hpp"
#include "TripleValuesSensor.hpp"

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

EPuckCommandPacket::EPuckCommandPacket() :
  mDistanceSensorRequested(false),
  mGroundSensorRequested(false),
  mLightSensorRequested(false),
  mAccelerometerRequested(false),
  mEncoderRequested(false) {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
}

EPuckCommandPacket::~EPuckCommandPacket()

void EPuckCommandPacket::clear() {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
  mDistanceSensorRequested = false;
  mGroundSensorRequested = false;
  mLightSensorRequested = false;
  mAccelerometerRequested = false;
  mEncoderRequested = false;
}

int EPuckCommandPacket::apply(int simulationTime) {
  mData[0] = 0x80;  // commands packet
  mData[1] = DeviceManager::instance()->camera()->isEnabled() ? 1 : 0;
  mData[2] = 0;                                                         // send the motor commands (velocity)
  short l = DeviceManager::instance()->motor(0)->velocity() / 0.00628;  // 0.00628 = ( 2 * pi) / encoder_resolution
  short r = DeviceManager::instance()->motor(1)->velocity() / 0.00628;
  if (l > 1000)
    l = 1000;
  else if (l < -1000)
    l = -1000;
  if (r > 1000)
    r = 1000;
  else if (r < -1000)
    r = -1000;
  mData[3] = l & 0xff;
  mData[4] = ((unsigned short)l >> 8) & 0xff;
  mData[5] = r & 0xff;
  mData[6] = ((unsigned short)r >> 8) & 0xff;
  // send the led commands
  mData[7] = 0;
  for (int i = 0; i < 10; i++) {
    Led *led = DeviceManager::instance()->led(i);
    const char d = mData[7];
    const int state = led->state();
    switch (led->index()) {
      case 0:  // LED1
        mData[7] = state ? d | 0b00000001 : d & 0b11111110;
        break;
      case 1:  // LED2
        mData[8] = state & 0xff;
        mData[9] = ((unsigned int)state >> 8) & 0xff;
        mData[10] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 2:  // LED3
        mData[7] = state ? d | 0b00000010 : d & 0b11111101;
        break;
      case 3:  // LED4
        mData[11] = state & 0xff;
        mData[12] = ((unsigned int)state >> 8) & 0xff;
        mData[13] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 4:  // LED5
        mData[7] = state ? d | 0b00000100 : d & 0b11111011;
        break;
      case 5:  // LED6
        mData[14] = state & 0xff;
        mData[15] = ((unsigned int)state >> 8) & 0xff;
        mData[16] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 6:  // LED7
        mData[7] = state ? d | 0b00001000 : d & 0b11110111;
        break;
      case 7:  // LED8
        mData[16] = state & 0xff;
        mData[18] = ((unsigned int)state >> 8) & 0xff;
        mData[19] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 8:  // body LED
        mData[7] = state ? d | 0b00010000 : d & 0b11101111;
        break;
      case 9:  // front LED
        mData[7] = state ? d | 0x00100000 : d & 0b11011111;
        break;
    }
  }
  mData[20] = 0x00;  // don't play any sound
  // Sensors
  if (DeviceManager::instance()->accelerometer()->isEnabled()) {
    mAccelerometerRequested = true;
    mData[1] |= 2;  // enable sensor packet
  }
  for (int i = 0; i < 3; i++) {  // optional ground sensors
    const SingleValueSensor *gs = DeviceManager::instance()->groundSensor(i);
    if (gs && gs->isEnabled()) {
      mGroundSensorRequested = true;  // if at least one sensor is required
      mData[1] |= 2;                  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->distanceSensor(i)->isEnabled()) {
      mDistanceSensorRequested = true;
      mData[1] |= 2;  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->lightSensor(i)->isEnabled()) {
      mLightSensorRequested = true;
      mData[1] |= 2;  // enable packet sensor
      break;
    }
  }
  if (DeviceManager::instance()->positionSensor(0)->isEnabled() || DeviceManager::instance()->positionSensor(1)->isEnabled()) {
    mEncoderRequested = true;
    // FIXME uncomment when next assignment is fixed
    // mData[1] |= 2;  // enable packet sensor
  }
  mData[1] = 3;  // FIXME: remove this
  return mData[1];
}


#include "EPuckCommandPacket.hpp"

#include "Camera.hpp"
#include "Device.hpp"
#include "DeviceManager.hpp"
#include "Led.hpp"
#include "Motor.hpp"
#include "Sensor.hpp"
#include "SingleValueSensor.hpp"
#include "TripleValuesSensor.hpp"

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

EPuckCommandPacket::EPuckCommandPacket() :
  mDistanceSensorRequested(false),
  mGroundSensorRequested(false),
  mLightSensorRequested(false),
  mAccelerometerRequested(false),
  mEncoderRequested(false) {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
}

EPuckCommandPacket::~EPuckCommandPacket() {
}

void EPuckCommandPacket::clear() {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
  mDistanceSensorRequested = false;
  mGroundSensorRequested = false;
  mLightSensorRequested = false;
  mAccelerometerRequested = false;
  mEncoderRequested = false;
}

int EPuckCommandPacket::apply(int simulationTime) {
  mData[0] = 0x80;  // commands packet
  mData[1] = DeviceManager::instance()->camera()->isEnabled() ? 1 : 0;
  mDat

                                                         // send the motor commands (velocity)
  short l = DeviceManager::instance()->motor(0)->velocity() / 0.00628;  // 0.00628 = ( 2 * pi) / encoder_resolution
  short r = DeviceManager::instance()->motor(1)->velocity() / 0.00628;
  if (l > 1000)
    l = 1000;
  else if (l < -1000)
    l = -1000;
  if (r > 1000)
    r = 1000;
  else if (r < -1000)
    r = -1000;
  mData[3] = l & 0xff;
  mData[4] = ((unsigned short)l >> 8) & 0xff;
  mData[5] = r & 0xff;
  mData[6] = ((unsigned short)r >> 8) & 0xff;
  // send the led commands
  mData[7] = 0;
  for (int i = 0; i < 10; i++) {
    Led *led = DeviceManager::instance()->led(i);
    const char d = mData[7];
    const int state = led->state();
    switch (led->index()) {
      case 0:  // LED1
        mData[7] = state ? d | 0b00000001 : d & 0b11111110;
        break;
      case 1:  // LED2
        mData[8] = state & 0xff;
        mData[9] = ((unsigned int)state >> 8) & 0xff;
        mData[10] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 2:  // LED3
        mData[7] = state ? d | 0b00000010 : d & 0b11111101;
        break;
      case 3:  // LED4
        mData[11] = state & 0xff;
        mData[12] = ((unsigned int)state >> 8) & 0xff;
        mData[13] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 4:  // LED5
        mData[7] = state ? d | 0b00000100 : d & 0b11111011;
        break;
      case 5:  // LED6
        mData[14] = state & 0xff;
        mData[15] = ((unsigned int)state >> 8) & 0xff;
        mData[16] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 6:  // LED7
        mData[7] = state ? d | 0b00001000 : d & 0b11110111;
        break;
      case 7:  // LED8
        mData[16] = state & 0xff;
        mData[18] = ((unsigned int)state >> 8) & 0xff;
        mData[19] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 8:  // body LED
        mData[7] = state ? d | 0b00010000 : d & 0b11101111;
        break;
      case 9:  // front LED
        mData[7] = state ? d | 0x00100000 : d & 0b11011111;
        break;
    }
  }
  mData[20] = 0x00;  // don't play any sound
  // Sensors
  if (DeviceManager::instance()->accelerometer()->isEnabled()) {
    mAccelerometerRequested = true;
    mData[1] |= 2;  // enable sensor packet
  }
  for (int i = 0; i < 3; i++) {  // optional ground sensors
    const SingleValueSensor *gs = DeviceManager::instance()->groundSensor(i);
    if (gs && gs->isEnabled()) {
      mGroundSensorRequested = true;  // if at least one sensor is required
      mData[1] |= 2;                  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->distanceSensor(i)->isEnabled()) {
      mDistanceSensorRequested = true;
      mData[1] |= 2;  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->lightSensor(i)->isEnabled()) {
      mLightSensorRequested = true;
      mData[1] |= 2;  // enable packet sensor
      break;
    }
  }
  if (DeviceManager::instance()->positionSensor(0)->isEnabled() || DeviceManager::instance()->positionSensor(1)->isEnabled()) {
    mEncoderRequested = true;
    // FIXME uncomment when next assignment is fixed
    // mData[1] |= 2;  // enable packet sensor
  }
  mData[1] = 3;  // FIXME: remove this
  return mData[1];
}


for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->lightSensor(i)->isEnabled()) {
      mLightSensorRequested = true;
      mData[1] |= 2;  // enable packet sensor
      break;
    }
  }

#include "EPuckCommandPacket.hpp"

#include "Camera.hpp"
#include "Device.hpp"
#include "DeviceManager.hpp"
#include "Led.hpp"
#include "Motor.hpp"
#include "Sensor.hpp"
#include "SingleValueSensor.hpp"
#include "TripleValuesSensor.hpp"

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

EPuckCommandPacket::EPuckCommandPacket() :
  mDistanceSensorRequested(false),
  mGroundSensorRequested(false),
  mLightSensorRequested(false),
  mAccelerometerRequested(false),
  mEncoderRequested(false) {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
}

EPuckCommandPacket::~EPuckCommandPacket() {
}

void EPuckCommandPacket::clear() {
  for (size_t i = 0; i < sizeof(mData); i++)
    mData[i] = 0;
  mDistanceSensorRequested = false;
  mGroundSensorRequested = false;
  mLightSensorRequested = false;
  mAccelerometerRequested = false;
  mEncoderRequested = false;
}

int EPuckCommandPacket::apply(int simulationTime) {
  mData[0] = 0x80;  // commands packet
  mData[1] = DeviceManager::instance()->camera()->isEnabled() ? 1 : 0;
  mData[2] = 0;                                                         // send the motor commands (velocity)
  short l = DeviceManager::instance()->motor(0)->velocity() / 0.00628;  // 0.00628 = ( 2 * pi) / encoder_resolution
  short r = DeviceManager::instance()->motor(1)->velocity() / 0.00628;
  if (l > 1000)
    l = 1000;
  else if (l < -1000)
    l = -1000;
  if (r > 1000)
    r = 1000;
  else if (r < -1000)
    r = -1000;
  mData[3] = l & 0xff;
  mData[4] = ((unsigned short)l >> 8) & 0xff;
  mData[5] = r & 0xff;
  mData[6] = ((unsigned short)r >> 8) & 0xff;
  // send the led commands
  mData[7] = 0;
  for (int i = 0; i < 10; i++) {
    Led *led = DeviceManager::instance()->led(i);
    const char d = mData[7];
    const int state = led->state();
    switch (led->index()) {
      case 0:  // LED1
        mData[7] = state ? d | 0b00000001 : d & 0b11111110;
        break;
      case 1:  // LED2
        mData[8] = state & 0xff;
        mData[9] = ((unsigned int)state >> 8) & 0xff;
        mData[10] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 2:  // LED3
        mData[7] = state ? d | 0b00000010 : d & 0b11111101;
        break;
      case 3:  // LED4
        mData[11] = state & 0xff;
        mData[12] = ((unsigned int)state >> 8) & 0xff;
        mData[13] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 4:  // LED5
        mData[7] = state ? d | 0b00000100 : d & 0b11111011;
        break;
      case 5:  // LED6
        mData[14] = state & 0xff;
        mData[15] = ((unsigned int)state >> 8) & 0xff;
        mData[16] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 6:  // LED7
        mData[7] = state ? d | 0b00001000 : d & 0b11110111;
        break;
      case 7:  // LED8
        mData[16] = state & 0xff;
        mData[18] = ((unsigned int)state >> 8) & 0xff;
        mData[19] = ((unsigned int)state >> 16) & 0xff;
        break;
      case 8:  // body LED
        mData[7] = state ? d | 0b00010000 : d & 0b11101111;
        break;
      case 9:  // front LED
        mData[7] = state ? d | 0x00100000 : d & 0b11011111;
        break;
    }
  }
  mData[20] = 0x00;  // don't play any sound
  // Sensors
  if (DeviceManager::instance()->accelerometer()->isEnabled()) {
    mAccelerometerRequested = true;
    mData[1] |= 2;  // enable sensor packet
  }
  for (int i = 0; i < 3; i++) {  // optional ground sensors
    const SingleValueSensor *gs = DeviceManager::instance()->groundSensor(i);
    if (gs && gs->isEnabled()) {
      mGroundSensorRequested = true;  // if at least one sensor is required
      mData[1] |= 2;                  // enable sensor packet
      break;
    }
  }
  for (int i = 0; i < 8; i++) {
    if (DeviceManager::instance()->distanceSensor(i)->isEnabled()) {
      mDistanceSensorRequested = true;
      mData[1] |= 2;  // enable sensor packet
      break;
    }
  }

  if (DeviceManager::instance()->positionSensor(0)->isEnabled() || DeviceManager::instance()->positionSensor(1)->isEnabled()) {
    mEncoderRequested = true;
    // FIXME uncomment when next assignment is fixed
    // mData[1] |= 2;  // enable packet sensor
  }
  mData[1] = 3;  // FIXME: remove this
  return mData[1];
}


/*

*/

/*
    The original source for this example is
    All rights reserved.

*/

/*
 * trace.cpp - This file contains the functions for firing primary rays
 *           and handling subsequent calculations
 */

#include "machine.h"
#include "types.h"
#include "macros.h"
#include "vector.h"
#include "tgafile.h"
#include "trace.h"
#include "light.h"
#include "shade.h"
#include "camera.h"
#include "util.h"
#include "intersect.h"
#include "global.h"
#include "ui.h"
#include "tachyon_video.h"

color trace(ray * primary) {
  if (primary->depth > 0) {
    VNorm(&primary->d);
    reset_intersection(primary->intstruct);
    intersect_objects(primary);
    return shader(primary);
  }

  /* if ray is truncated, return the background as its color */
  return primary->scene->background;
}

{
  thr_io_parms p;

  p= *((thr_io_parms *) parms);
  writetgaregion(p.tga, p.iwidth, p.iheight, p.startx, p.starty,
		p.stopx, p.stopy, p.buffer);
  free(p.buffer); /* free the buffer once we are done with it.. */
  free(parms);

  return(NULL);
}

void trace_shm(scenedef scene, /*char * buffer,  */ int startx, int stopx, int starty, int stopy) {

  thr_parms * parms;

  parms = (thr_parms *) rt_getmem(sizeof(thr_parms));

  parms->tid=0;
  parms->nthr=1;
  parms->scene=scene;
  parms->startx=startx;
  parms->stopx=stopx;
  parms->starty=starty;
  parms->stopy=stopy;

  thread_trace(parms);

  rt_freemem(parms);
}

void trace_region(scenedef scene, void * tga, int startx, int starty, int stopx, int stopy) {

  if (scene.verbosemode) {
    char msgtxt[2048];
    sprintf(msgtxt, "Node %3d tracing region  %4d, %4d  --->  %4d, %4d \n", 0, startx,starty,stopx,stopy);
    rt_ui_message(MSG_0, msgtxt);
  }

  trace_shm(scene, /*buffer,*/ startx, stopx, starty, stopy);
/* not used now
  writetgaregion(tga, scene.hres, scene.vres,
                 startx, starty, stopx, stopy, global_buffer);

  if (scene.rawimage != NULL) {
    int x, y;
    int totalx = stopx - startx + 1;
    for (y=starty; y<=stopy; y++) {
      for (x=0; x<scene.hres; x++) {
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3] = global_buffer[(y-starty)*totalx*3 + x*3 + 2];
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3 +1] = global_buffer[(y-starty)*totalx*3 + x*3 + 1];
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3 +2] = global_buffer[(y-starty)*totalx*3 + x*3];
      }
    }
  }
*/
}


{
  thr_io_parms p;

  p= *((thr_io_parms *) parms);
  writetgaregion(p.tga, p.iwidth, p.iheight, p.startx, p.starty,
		p.stopx, p.stopy, p.buffer);
  free(p.buffer); /* free the buffer once we are done with it.. */
  free(parms);

  return(NULL);
}

/*

*/

/*
    The original source for this example is
    All rights reserved.

*/

/*
 * trace.cpp - This file contains the functions for firing primary rays
 *           and handling subsequent calculations
 */

#include "machine.h"
#include "types.h"
#include "macros.h"
#include "vector.h"
#include "tgafile.h"
#include "trace.h"
#include "light.h"
#include "shade.h"
#include "camera.h"
#include "util.h"
#include "intersect.h"
#include "global.h"
#include "ui.h"
#include "tachyon_video.h"

color trace(ray * primary) {
  if (primary->depth > 0) {
    VNorm(&primary->d);
    reset_intersection(primary->intstruct);
    intersect_objects(primary);
    return shader(primary);
  }

  /* if ray is truncated, return the background as its color */
  return primary->scene->background;
}

void * thread_io(void * parms)

void trace_shm(scenedef scene, /*char * buffer,  */ int startx, int stopx, int starty, int stopy) {

  thr_parms * parms;

  parms = (thr_parms *) rt_getmem(sizeof(thr_parms));

  parms->tid=0;
  parms->nthr=1;
  parms->scene=scene;
  parms->startx=startx;
  parms->stopx=stopx;
  parms->starty=starty;
  parms->stopy=stopy;

  thread_trace(parms);

  rt_freemem(parms);
}

void trace_region(scenedef scene, void * tga, int startx, int starty, int stopx, int stopy) {

  if (scene.verbosemode) {
    char msgtxt[2048];
    sprintf(msgtxt, "Node %3d tracing region  %4d, %4d  --->  %4d, %4d \n", 0, startx,starty,stopx,stopy);
    rt_ui_message(MSG_0, msgtxt);
  }

  trace_shm(scene, /*buffer,*/ startx, stopx, starty, stopy);
/* not used now
  writetgaregion(tga, scene.hres, scene.vres,
                 startx, starty, stopx, stopy, global_buffer);

  if (scene.rawimage != NULL) {
    int x, y;
    int totalx = stopx - startx + 1;
    for (y=starty; y<=stopy; y++) {
      for (x=0; x<scene.hres; x++) {
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3] = global_buffer[(y-starty)*totalx*3 + x*3 + 2];
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3 +1] = global_buffer[(y-starty)*totalx*3 + x*3 + 1];
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3 +2] = global_buffer[(y-starty)*totalx*3 + x*3];
      }
    }
  }
*/
}


/*

*/

/*
    The original source for this example is
    All rights reserved.

*/

/*
 * trace.cpp - This file contains the functions for firing primary rays
 *           and handling subsequent calculations
 */

#include "machine.h"
#include "types.h"
#include "macros.h"
#include "vector.h"
#include "tgafile.h"
#include "trace.h"
#include "light.h"
#include "shade.h"
#include "camera.h"
#include "util.h"
#include "intersect.h"
#include "global.h"
#include "ui.h"
#include "tachyon_video.h"

color trace(ray * primary) {
  if (primary->depth > 0) {
    VNorm(&primary->d);
    reset_intersection(primary->intstruct);
    intersect_objects(primary);
    return shader(primary);
  }

  /* if ray is truncated, return the background as its color */
  return primary->scene->background;
}

void * thread_io(void * parms) {
  thr_io_parms p;

  p= *((thr_io_parms *) parms);
  writetgaregion(p.tga, p.iwidth, p.iheight, p.startx, p.starty,
		p.stopx, p.stopy, p.buffer);
  free(p.b

 /* free the buffer once we are done with it.. */
  free(parms);

  return(NULL);
}

void trace_shm(scenedef scene, /*char * buffer,  */ int startx, int stopx, int starty, int stopy) {

  thr_parms * parms;

  parms = (thr_parms *) rt_getmem(sizeof(thr_parms));

  parms->tid=0;
  parms->nthr=1;
  parms->scene=scene;
  parms->startx=startx;
  parms->stopx=stopx;
  parms->starty=starty;
  parms->stopy=stopy;

  thread_trace(parms);

  rt_freemem(parms);
}

void trace_region(scenedef scene, void * tga, int startx, int starty, int stopx, int stopy) {

  if (scene.verbosemode) {
    char msgtxt[2048];
    sprintf(msgtxt, "Node %3d tracing region  %4d, %4d  --->  %4d, %4d \n", 0, startx,starty,stopx,stopy);
    rt_ui_message(MSG_0, msgtxt);
  }

  trace_shm(scene, /*buffer,*/ startx, stopx, starty, stopy);
/* not used now
  writetgaregion(tga, scene.hres, scene.vres,
                 startx, starty, stopx, stopy, global_buffer);

  if (scene.rawimage != NULL) {
    int x, y;
    int totalx = stopx - startx + 1;
    for (y=starty; y<=stopy; y++) {
      for (x=0; x<scene.hres; x++) {
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3] = global_buffer[(y-starty)*totalx*3 + x*3 + 2];
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3 +1] = global_buffer[(y-starty)*totalx*3 + x*3 + 1];
        scene.rawimage[(scene.vres-y)*scene.hres*3 + x*3 +2] = global_buffer[(y-starty)*totalx*3 + x*3];
      }
    }
  }
*/
}


#include <ATen/Config.h>

#include <ATen/Context.h>

#include <c10/core/TensorOptions.h>
#include <c10/core/CPUAllocator.h>

#include <mutex>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>

#include <ATen/Tensor.h>
#include <ATen/cpu/FlushDenormal.h>

#ifdef USE_FBGEMM
#include <fbgemm/Fbgemm.h>
#endif // USE_FBGEMM

namespace at {

Context::Context()
    : thc_state(nullptr, [](THCState* p) { /* no-op */ }),
      thh_state(nullptr, [](THHState* p) { /* no-op */ }) {}

// TODO: This could be bad juju if someone calls globalContext() in the
// destructor of an object with static lifetime.
Context& globalContext() {
  static Context globalContext_;
  return globalContext_;
}

// NB: This method is *purely* whether or not a user requested
// that CuDNN was enabled, it doesn't actually say anything about
// whether or not CuDNN is actually usable.
bool Context::userEnabledCuDNN() const {
  return enabled_cudnn;
}

void Context::setUserEnabledCuDNN(bool e) {
  enabled_cudnn = e;
}

bool Context::userEnabledMkldnn() const {
  return enabled_mkldnn;
}

void Context::setUserEnabledMkldnn(bool e) {
  enabled_mkldnn = e;
}

bool Context::deterministicCuDNN() const {
  return deterministic_cudnn;
}

void Context::setDeterministicCuDNN(bool b) {
  deterministic_cudnn = b;
}

bool Context::deterministicAlgorithms() const {
  return _deterministic_algorithms;
}

bool Context::deterministicAlgorithmsWarnOnly() const {
  return _deterministic_algorithms_warn_only;
}

void Context::setDeterministicAlgorithms(bool b, bool warn_only=false) {
  _deterministic_algorithms = b;
  _deterministic_algorithms_warn_only = warn_only;
}

void Context::alertNotDeterministic(c10::string_view const& caller) {
  if (globalContext().deterministicAlgorithms()) {
    if (globalContext().deterministicAlgorithmsWarnOnly()) {
      TORCH_WARN(
        caller, " does not have a deterministic implementation, but you set "
        "'torch.use_deterministic_algorithms(True, warn_only=True)'. "
        "You can file an issue at http://example.com "
        "to help us prioritize adding deterministic support for this operation.");
    } else {
      TORCH_CHECK(false,
        caller, " does not have a deterministic implementation, but you set "
        "'torch.use_deterministic_algorithms(True)'. You can turn off "
        "determinism just for this operation, or you can use the "
        "'warn_only=True' option, if that's acceptable for your application. "
        "You can also file an issue at https://github.com/pytorch/pytorch/issues "
        "to help us prioritize adding deterministic support for this operation.");
    }
  }
}

bool Context::allowTF32CuDNN() const {
  return allow_tf32_cudnn;
}

void Context::setAllowTF32CuDNN(bool b) {
  allow_tf32_cudnn = b;
}

static const char cublas_config_var_name[] = "CUBLAS_WORKSPACE_CONFIG";
static const char* const cublas_deterministic_configs[] = { ":4096:8", ":16:8" };

bool Context::checkCuBLASConfigDeterministic() {
  bool cublas_config_deterministic = true;
  // If using CUDA 10.2 or greater, need to make sure CuBLAS workspace config
  // is set to deterministic setting
  if (hasCUDART() && (versionCUDART() >= 10020)) {
    char* workspace_config = std::getenv(cublas_config_var_name);
    cublas_config_deterministic = (workspace_config != nullptr) && (
      (strcmp(workspace_config, cublas_deterministic_configs[0]) == 0)
      || (strcmp(workspace_config, cublas_deterministic_configs[1]) == 0)
    );
  }
  return cublas_config_deterministic;
}

void Context::alertCuBLASConfigNotDeterministic() const {
  static bool cublas_config_deterministic = checkCuBLASConfigDeterministic();
  TORCH_CHECK(!deterministicAlgorithms() || cublas_config_deterministic,
    "Deterministic behavior was enabled with either `torch.use_deterministic_algorithms(True)` or ",
    "`at::Context::setDeterministicAlgorithms(true)`, but this operation is not deterministic because ",
    "it uses CuBLAS and you have CUDA >= 10.2. To enable deterministic behavior in this ",
    "case, you must set an environment variable before running your PyTorch application: ",
    cublas_config_var_name, "=", cublas_deterministic_configs[0], " or ",
    cublas_config_var_name, "=", cublas_deterministic_configs[1], ". For more information, go to ",
    "http://example.com"
  );
}

bool Context::benchmarkCuDNN() const {
  return benchmark_cudnn;
}

void Context::setBenchmarkCuDNN(bool b) {
  benchmark_cudnn = b;
}

bool Context::allowTF32CuBLAS() const {
  return allow_tf32_cublas;
}

void Context::setAllowTF32CuBLAS(bool b) {
  allow_tf32_cublas = b;
}

bool Context::allowFP16ReductionCuBLAS() const {
  return allow_fp16_reduction_cublas;
}

void Context::setAllowFP16ReductionCuBLAS(bool b) {
  allow_fp16_reduction_cublas = b;
}

bool Context::hasMKL() {
#if AT_MKL_ENABLED()
  return true;
#else
  return false;
#endif
}

bool Context::hasMKLDNN() {
#if AT_MKLDNN_ENABLED()
  return true;
#else
  return false;
#endif
}

{
#ifdef _OPENMP
  return true;
#else
  return false;
#endif
}

bool Context::hasLAPACK() {
#if AT_BUILD_WITH_LAPACK()
  return true;
#else
  return false;
#endif
}

at::QEngine Context::qEngine() const {
  // If wasn't explicitly set - take the last one available
  return quantized_engine.value_or(supportedQEngines().back());
}

void Context::setQEngine(at::QEngine e) {
  const auto& qengines = supportedQEngines();
  if (std::find(qengines.begin(), qengines.end(), e) != qengines.end()) {
    quantized_engine = e;
    return;
  }
  TORCH_CHECK(false, "quantized engine ", toString(e), " is not supported");
}

const std::vector<at::QEngine>& Context::supportedQEngines() {
  static auto supported_qengines = []() {
    std::vector<at::QEngine> engines = {};
    // Engines are listed in priority order: later one wins
    // By default we prefer FBGEMM if we're running on server side
    // QNNPACK on server side has some issue, so we disable it by default.
#ifdef C10_MOBILE
    engines.push_back(at::kNoQEngine);
#ifdef USE_PYTORCH_QNNPACK
    engines.push_back(at::kQNNPACK);
#endif
#else  // C10_MOBILE
#ifdef USE_PYTORCH_QNNPACK
    engines.push_back(at::kQNNPACK);
#endif
    engines.push_back(at::kNoQEngine);
#endif // C10_MOBILE

#ifdef USE_FBGEMM
    if (fbgemm::fbgemmSupportedCPU()) {
      engines.push_back(at::kFBGEMM);
    }
#endif
    return engines;
  }();
  return supported_qengines;
}

bool Context::isXNNPACKAvailable() {
#ifdef USE_XNNPACK
  return true;
#else
  return false;
#endif
}

bool Context::releaseWeightsWhenPrepacking() const {
  return release_original_weights;
}

void Context::setReleaseWeightsWhenPrepacking(bool e) {
  release_original_weights = e;
}

bool Context::setFlushDenormal(bool on) {
  return at::cpu::set_flush_denormal(on);
}

Allocator* getCPUAllocator() {
  return c10::GetCPUAllocator();
}

// override_allow_tf32_flag = true
//    means the allow_tf32 flags are overrided and tf32 is force disabled
// override_allow_tf32_flag = false
//    means the original allow_tf32 flags are followed
thread_local bool override_allow_tf32_flag = false;

NoTF32Guard::NoTF32Guard() {
  if (!override_allow_tf32_flag) {
    changed = true;
    override_allow_tf32_flag = true;
  }
}

NoTF32Guard::~NoTF32Guard() {
  if (changed) {
    override_allow_tf32_flag = false;
  }
}

bool NoTF32Guard::should_disable_tf32() {
  return override_allow_tf32_flag;
}

bool Context::areVmapFallbackWarningsEnabled() const {
  return display_vmap_fallback_warnings_;
}

void Context::setDisplayVmapFallbackWarnings(bool enabled) {
  display_vmap_fallback_warnings_ = enabled;
}

void Context::setDefaultMobileCPUAllocator() {
  TORCH_CHECK(prev_allocator_ptr_ == nullptr,
      "Already within the scope of another non-default cpu allocator."
      "Cannot set another allocator.");
  // Setting the priority high to make sure no other allocator gets used instead of this.
  prev_allocator_ptr_ = c10::GetCPUAllocator();
  c10::SetCPUAllocator(c10::GetDefaultMobileCPUAllocator(), /*priority*/ 100);
}

void Context::unsetDefaultMobileCPUAllocator() {
  TORCH_CHECK(prev_allocator_ptr_ != nullptr,
      "setDefaultMobileCPUAllocator must have been called "
      "before unsetDefaultMobileCPUAllocator.");
  // Setting the priority high to make sure no other allocator gets used instead of this.
  c10::SetCPUAllocator(prev_allocator_ptr_ , /*priority*/ 100);
  prev_allocator_ptr_ = nullptr;
}
} // namespace at


#include <ATen/Config.h>

#include <ATen/Context.h>

#include <c10/core/TensorOptions.h>
#include <c10/core/CPUAllocator.h>

#include <mutex>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>

#include <ATen/Tensor.h>
#include <ATen/cpu/FlushDenormal.h>

#ifdef USE_FBGEMM
#include <fbgemm/Fbgemm.h>
#endif // USE_FBGEMM

namespace at {

Context::Context()
    : thc_state(nullptr, [](THCState* p) { /* no-op */ }),
      thh_state(nullptr, [](THHState* p) { /* no-op */ }) {}

// TODO: This could be bad juju if someone calls globalContext() in the
// destructor of an object with static lifetime.
Context& globalContext() {
  static Context globalContext_;
  return globalContext_;
}

// NB: This method is *purely* whether or not a user requested
// that CuDNN was enabled, it doesn't actually say anything about
// whether or not CuDNN is actually usable.
bool Context::userEnabledCuDNN() const {
  return enabled_cudnn;
}

void Context::setUserEnabledCuDNN(bool e) {
  enabled_cudnn = e;
}

bool Context::userEnabledMkldnn() const {
  return enabled_mkldnn;
}

void Context::setUserEnabledMkldnn(bool e) {
  enabled_mkldnn = e;
}

bool Context::deterministicCuDNN() const {
  return deterministic_cudnn;
}

void Context::setDeterministicCuDNN(bool b) {
  deterministic_cudnn = b;
}

bool Context::deterministicAlgorithms() const {
  return _deterministic_algorithms;
}

bool Context::deterministicAlgorithmsWarnOnly() const {
  return _deterministic_algorithms_warn_only;
}

void Context::setDeterministicAlgorithms(bool b, bool warn_only=false) {
  _deterministic_algorithms = b;
  _deterministic_algorithms_warn_only = warn_only;
}

void Context::alertNotDeterministic(c10::string_view const& caller) {
  if (globalContext().deterministicAlgorithms()) {
    if (globalContext().deterministicAlgorithmsWarnOnly()) {
      TORCH_WARN(
        caller, " does not have a deterministic implementation, but you set "
        "'torch.use_deterministic_algorithms(True, warn_only=True)'. "
        "You can file an issue at http://example.com "
        "to help us prioritize adding deterministic support for this operation.");
    } else {
      TORCH_CHECK(false,
        caller, " does not have a deterministic implementation, but you set "
        "'torch.use_deterministic_algorithms(True)'. You can turn off "
        "determinism just for this operation, or you can use the "
        "'warn_only=True' option, if that's acceptable for your application. "
        "You can also file an issue at https://github.com/pytorch/pytorch/issues "
        "to help us prioritize adding deterministic support for this operation.");
    }
  }
}

bool Context::allowTF32CuDNN() const {
  return allow_tf32_cudnn;
}

void Context::setAllowTF32CuDNN(bool b) {
  allow_tf32_cudnn = b;
}

static const char cublas_config_var_name[] = "CUBLAS_WORKSPACE_CONFIG";
static const char* const cublas_deterministic_configs[] = { ":4096:8", ":16:8" };

bool Context::checkCuBLASConfigDeterministic() {
  bool cublas_config_deterministic = true;
  // If using CUDA 10.2 or greater, need to make sure CuBLAS workspace config
  // is set to deterministic setting
  if (hasCUDART() && (versionCUDART() >= 10020)) {
    char* workspace_config = std::getenv(cublas_config_var_name);
    cublas_config_deterministic = (workspace_config != nullptr) && (
      (strcmp(workspace_config, cublas_deterministic_configs[0]) == 0)
      || (strcmp(workspace_config, cublas_deterministic_configs[1]) == 0)
    );
  }
  return cublas_config_deterministic;
}

void Context::alertCuBLASConfigNotDeterministic() const {
  static bool cublas_config_deterministic = checkCuBLASConfigDeterministic();
  TORCH_CHECK(!deterministicAlgorithms() || cublas_config_deterministic,
    "Deterministic behavior was enabled with either `torch.use_deterministic_algorithms(True)` or ",
    "`at::Context::setDeterministicAlgorithms(true)`, but this operation is not deterministic because ",
    "it uses CuBLAS and you have CUDA >= 10.2. To enable deterministic behavior in this ",
    "case, you must set an environment variable before running your PyTorch application: ",
    cublas_config_var_name, "=", cublas_deterministic_configs[0], " or ",
    cublas_config_var_name, "=", cublas_deterministic_configs[1], ". For more information, go to ",
    "http://example.com"
  );
}

bool Context::benchmarkCuDNN() const {
  return benchmark_cudnn;
}

void Context::setBenchmarkCuDNN(bool b) {
  benchmark_cudnn = b;
}

bool Context::allowTF32CuBLAS() const {
  return allow_tf32_cublas;
}

void Context::setAllowTF32CuBLAS(bool b) {
  allow_tf32_cublas = b;
}

bool Context::allowFP16ReductionCuBLAS() const {
  return allow_fp16_reduction_cublas;
}

void Context::setAllowFP16ReductionCuBLAS(bool b) {
  allow_fp16_reduction_cublas = b;
}

bool Context::hasMKL() {
#if AT_MKL_ENABLED()
  return true;
#else
  return false;
#endif
}

bool Context::hasMKLDNN() {
#if AT_MKLDNN_ENABLED()
  return true;
#else
  return false;
#endif
}

bool Context::hasOpenMP() {
#ifdef _OPENMP
  return true;
#else
  return false;
#endif
}

bool Context::hasLAPACK() {
#if AT_BUILD_WITH_LAPACK()
  return true;
#else
  return false;
#endif
}

at::QEngine Context::qEngine() const {
  // If wasn't explicitly set - take the last one available
  return quantized_engine.value_or(supportedQEngines().back());
}

void Context::setQEngine(at::QEngine e) {
  const auto& qengines = supportedQEngines();
  if (std::find(qengines.begin(), qengines.end(), e) != qengines.end()) {
    quantized_engine = e;
    return;
  }
  TORCH_CHECK(false, "quantized engine ", toString(e), " is not supported");
}

const std::vector<at::QEngine>& Context::supportedQEngines() {
  static auto supported_qengines = []() {
    std::vector<at::QEngine> engines = {};
    // Engines are listed in priority order: later one wins
    // By default we prefer FBGEMM if we're running on server side
    // QNNPACK on server side has some issue, so we disable it by default.
#ifdef C10_MOBILE
    engines.push_back(at::kNoQEngine);
#ifdef USE_PYTORCH_QNNPACK
    engines.push_back(at::kQNNPACK);
#endif
#else  // C10_MOBILE
#ifdef USE_PYTORCH_QNNPACK
    engines.push_back(at::kQNNPACK);
#endif
    engines.push_back(at::kNoQEngine);
#endif // C10_MOBILE

#ifdef USE_FBGEMM
    if (fbgemm::fbgemmSupportedCPU()) {
      engines.push_back(at::kFBGEMM);
    }
#endif
    return engines;
  }();
  return supported_qengines;
}

bool Context::isXNNPACKAvailable() {
#ifdef USE_XNNPACK
  return true;
#else
  return false;
#endif
}

bool Context::releaseWeightsWhenPrepacking() const {
  return release_original_weights;
}

void Context::setReleaseWeightsWhenPrepacking(bool e) {
  release_original_weights = e;
}

bool Context::setFlushDenormal(bool on) {
  return at::cpu::set_flush_denormal(on);
}

Allocator* getCPUAllocator() {
  return c10::GetCPUAllocator();
}

// override_allow_tf32_flag = true
//    means the allow_tf32 flags are overrided and tf32 is force disabled
// override_allow_tf32_flag = false
//    means the original allow_tf32 flags are followed
thread_local bool override_allow_tf32_flag = false;

NoTF32Guard::NoTF32Guard() {
  if (!override_allow_tf32_flag) {
    changed = true;
    override_allow_tf32_flag = true;
  }
}

NoTF32Guard::~NoTF32Guard() {
  if (changed) {
    override_allow_tf32_flag = false;
  }
}

bool NoTF32Guard::should_disable_tf32()

bool Context::areVmapFallbackWarningsEnabled() const {
  return display_vmap_fallback_warnings_;
}

void Context::setDisplayVmapFallbackWarnings(bool enabled) {
  display_vmap_fallback_warnings_ = enabled;
}

void Context::setDefaultMobileCPUAllocator() {
  TORCH_CHECK(prev_allocator_ptr_ == nullptr,
      "Already within the scope of another non-default cpu allocator."
      "Cannot set another allocator.");
  // Setting the priority high to make sure no other allocator gets used instead of this.
  prev_allocator_ptr_ = c10::GetCPUAllocator();
  c10::SetCPUAllocator(c10::GetDefaultMobileCPUAllocator(), /*priority*/ 100);
}

void Context::unsetDefaultMobileCPUAllocator() {
  TORCH_CHECK(prev_allocator_ptr_ != nullptr,
      "setDefaultMobileCPUAllocator must have been called "
      "before unsetDefaultMobileCPUAllocator.");
  // Setting the priority high to make sure no other allocator gets used instead of this.
  c10::SetCPUAllocator(prev_allocator_ptr_ , /*priority*/ 100);
  prev_allocator_ptr_ = nullptr;
}
} // namespace at