/**
* Initialize an EGL context for the current display.
*/
int Engine::InitDisplay()
{
    if( !initialized_resources_ )
    {
        EngineCreationAttribs EngineCreationAttribs;
        EngineCreationAttribs.strShaderCachePath = "/tmp/ShaderCache";
        RefCntAutoPtr<Diligent::IRenderDevice> pRenderDevice;
        SwapChainDesc SwapChainDesc;
        CreateDeviceAndSwapChainGL( EngineCreationAttribs, &pRenderDevice, &pDeviceContext_, SwapChainDesc, app_->window, &pSwapChain_ );

        Diligent::IRenderDeviceGLES *pRenderDeviceOpenGLES;
        pRenderDevice->QueryInterface( Diligent::IID_RenderDeviceGLES, reinterpret_cast<IObject**>(&pRenderDeviceOpenGLES) );
        pRenderDevice_.Attach( pRenderDeviceOpenGLES );

        LoadResources();
        initialized_resources_ = true;

        // Set font scaling
        TwDefine(" GLOBAL fontscaling=3");

        // TW_OPENGL and TW_OPENGL_CORE were designed to select rendering with 
        // very old GL specification. Using these modes results in applying some 
        // odd offsets which distorts everything
        // Latest OpenGL works very much like Direct3D11, and 
        // Tweak Bar will never know if D3D or OpenGL is actually used
        if (!TwInit(TW_DIRECT3D11, pRenderDevice_.RawPtr(), pDeviceContext_.RawPtr(), SwapChainDesc.ColorBufferFormat))
        {
            LOGE( "Failed to Init Ant tweak bar" );
            return 0;
        }

        sample_.reset( CreateSample(pRenderDevice, pDeviceContext_, pSwapChain_) );
    }
    else
    {
        // initialize OpenGL ES and EGL
        if( EGL_SUCCESS != pRenderDevice_->Resume( app_->window ) )
        {
            UnloadResources();
            LoadResources();
        }
    }

    ShowUI();

    auto width = pSwapChain_->GetDesc().Width;
    auto height = pSwapChain_->GetDesc().Height;

    //Note that screen size might have been changed
    pDeviceContext_->SetViewports( 1, nullptr, width, height );
    //renderer_.UpdateViewport();
    
    sample_->WindowResize(width, height);

    // Send the new window size to AntTweakBar
    TwWindowSize(width, height);


    //tap_camera_.SetFlip( 1.f, -1.f, -1.f );
    //tap_camera_.SetPinchTransformFactor( 2.f, 2.f, 8.f );

    return 0;
}
void Tutorial08_Tessellation::Initialize(IRenderDevice *pDevice, IDeviceContext **ppContexts, Uint32 NumDeferredCtx, ISwapChain *pSwapChain)
{
    const auto& deviceCaps = pDevice->GetDeviceCaps();
    if(!deviceCaps.bTessellationSupported)
    {
        throw std::runtime_error("Hardware tessellation is not supported");
    }

    SampleBase::Initialize(pDevice, ppContexts, NumDeferredCtx, pSwapChain);

    ShaderMacroHelper MacroHelper;
    
    {
        // Pipeline state object encompasses configuration of all GPU stages

        PipelineStateDesc PSODesc;
        // Pipeline state name is used by the engine to report issues
        // It is always a good idea to give objects descriptive names
        PSODesc.Name = "Terrain PSO"; 

        // This is a graphics pipeline
        PSODesc.IsComputePipeline = false; 

        // This tutorial will render to a single render target
        PSODesc.GraphicsPipeline.NumRenderTargets = 1;
        // Set render target format which is the format of the swap chain's color buffer
        PSODesc.GraphicsPipeline.RTVFormats[0] = pSwapChain->GetDesc().ColorBufferFormat;
        // Set depth buffer format which is the format of the swap chain's back buffer
        PSODesc.GraphicsPipeline.DSVFormat = pSwapChain->GetDesc().DepthBufferFormat;
        // Primitive topology type defines what kind of primitives will be rendered by this pipeline state
        PSODesc.GraphicsPipeline.PrimitiveTopologyType = PRIMITIVE_TOPOLOGY_TYPE_PATCH;
        // Cull back faces
        PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_BACK;
        // Enable depth testing
        PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = True;

        // Create dynamic uniform buffer that will store shader constants
        CreateUniformBuffer(pDevice, sizeof(GlobalConstants), "Global shader constants CB", &m_ShaderConstants);

        ShaderCreationAttribs CreationAttribs;
        // Tell the system that the shader source code is in HLSL.
        // For OpenGL, the engine will convert this into GLSL behind the scene
        CreationAttribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;

        // In this tutorial, we will load shaders from file. To be able to do that,
        // we need to create a shader source stream factory
        BasicShaderSourceStreamFactory BasicSSSFactory;
        CreationAttribs.pShaderSourceStreamFactory = &BasicSSSFactory;
        // Define variable type that will be used by default
        CreationAttribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC;
        // Create vertex shader
        RefCntAutoPtr<IShader> pVS;
        {
            CreationAttribs.Desc.ShaderType = SHADER_TYPE_VERTEX;
            CreationAttribs.EntryPoint = "TerrainVS";
            CreationAttribs.Desc.Name = "Terrain VS";
            CreationAttribs.FilePath = "terrain.vsh";
            pDevice->CreateShader(CreationAttribs, &pVS);
            pVS->GetShaderVariable("VSConstants")->Set(m_ShaderConstants);
        }

        // Create geometry shader
        RefCntAutoPtr<IShader> pGS;
        {
            CreationAttribs.Desc.ShaderType = SHADER_TYPE_GEOMETRY;
            CreationAttribs.EntryPoint = "TerrainGS";
            CreationAttribs.Desc.Name = "Terrain GS";
            CreationAttribs.FilePath = "terrain.gsh";
            pDevice->CreateShader(CreationAttribs, &pGS);
            pGS->GetShaderVariable("GSConstants")->Set(m_ShaderConstants);
        }

        // Create hull shader
        RefCntAutoPtr<IShader> pHS;
        {
            CreationAttribs.Desc.ShaderType = SHADER_TYPE_HULL;
            CreationAttribs.EntryPoint = "TerrainHS";
            CreationAttribs.Desc.Name = "Terrain HS";
            CreationAttribs.FilePath = "terrain.hsh";

            ShaderVariableDesc Vars[] = 
            {
                {"g_HeightMap", SHADER_VARIABLE_TYPE_MUTABLE}
            };
            CreationAttribs.Desc.VariableDesc = Vars;
            CreationAttribs.Desc.NumVariables = _countof(Vars);

            // Define static sampler for g_Texture. Static samplers should be used whenever possible
            SamplerDesc SamLinearClampDesc( FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, 
                TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP);
            StaticSamplerDesc StaticSamplers[] = 
            {
                {"g_HeightMap", SamLinearClampDesc}
            };
            CreationAttribs.Desc.StaticSamplers = StaticSamplers;
            CreationAttribs.Desc.NumStaticSamplers = _countof(StaticSamplers);

            MacroHelper.AddShaderMacro("BLOCK_SIZE", m_BlockSize);
            CreationAttribs.Macros = MacroHelper;

            pDevice->CreateShader(CreationAttribs, &pHS);
            pHS->GetShaderVariable("HSConstants")->Set(m_ShaderConstants);
        }

        // Create domain shader
        RefCntAutoPtr<IShader> pDS;
        {
            CreationAttribs.Desc.ShaderType = SHADER_TYPE_DOMAIN;
            CreationAttribs.EntryPoint = "TerrainDS";
            CreationAttribs.Desc.Name = "Terrain DS";
            CreationAttribs.FilePath = "terrain.dsh";
            CreationAttribs.Macros = nullptr;
            
            pDevice->CreateShader(CreationAttribs, &pDS);
            pDS->GetShaderVariable("DSConstants")->Set(m_ShaderConstants);
        }

        // Create pixel shader
        RefCntAutoPtr<IShader> pPS, pWirePS;
        {
            CreationAttribs.Desc.ShaderType = SHADER_TYPE_PIXEL;
            CreationAttribs.EntryPoint = "TerrainPS";
            CreationAttribs.Desc.Name = "Terrain PS";
            CreationAttribs.FilePath = "terrain.psh";
            // Shader variables should typically be mutable, which means they are expected
            // to change on a per-instance basis
            ShaderVariableDesc Vars[] = 
            {
                {"g_Texture", SHADER_VARIABLE_TYPE_MUTABLE}
            };
            CreationAttribs.Desc.VariableDesc = Vars;
            CreationAttribs.Desc.NumVariables = _countof(Vars);

            // Define static sampler for g_Texture. Static samplers should be used whenever possible
            SamplerDesc SamLinearClampDesc( FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, FILTER_TYPE_LINEAR, 
                                            TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP, TEXTURE_ADDRESS_CLAMP);
            StaticSamplerDesc StaticSamplers[] = 
            {
                {"g_Texture", SamLinearClampDesc}
            };
            CreationAttribs.Desc.StaticSamplers = StaticSamplers;
            CreationAttribs.Desc.NumStaticSamplers = _countof(StaticSamplers);

            pDevice->CreateShader(CreationAttribs, &pPS);

            CreationAttribs.EntryPoint = "WireTerrainPS";
            CreationAttribs.Desc.Name = "Wireframe Terrain PS";
            CreationAttribs.FilePath = "terrain_wire.psh";
            pDevice->CreateShader(CreationAttribs, &pWirePS);

            pWirePS->GetShaderVariable("PSConstants")->Set(m_ShaderConstants);
        }

        PSODesc.GraphicsPipeline.pVS = pVS;
        PSODesc.GraphicsPipeline.pHS = pHS;
        PSODesc.GraphicsPipeline.pDS = pDS;
        PSODesc.GraphicsPipeline.pPS = pPS;

        pDevice->CreatePipelineState(PSODesc, &m_pPSO[0]);

        PSODesc.GraphicsPipeline.pGS = pGS;
        PSODesc.GraphicsPipeline.pPS = pWirePS;
        pDevice->CreatePipelineState(PSODesc, &m_pPSO[1]);
    }

    {
        // Load texture
        TextureLoadInfo loadInfo;
        loadInfo.IsSRGB = false;
        loadInfo.Name = "Terrain height map";
        RefCntAutoPtr<ITexture> HeightMap;
        CreateTextureFromFile("ps_height_1k.png", loadInfo, m_pDevice, &HeightMap);
        const auto HMDesc = HeightMap->GetDesc();
        m_HeightMapWidth = HMDesc.Width;
        m_HeightMapHeight = HMDesc.Height;
        // Get shader resource view from the texture
        m_HeightMapSRV = HeightMap->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
    }

    {
        TextureLoadInfo loadInfo;
        loadInfo.IsSRGB = true;
        loadInfo.Name = "Terrain color map";
        RefCntAutoPtr<ITexture> ColorMap;
        CreateTextureFromFile("ps_texture_2k.png", loadInfo, m_pDevice, &ColorMap);
        // Get shader resource view from the texture
        m_ColorMapSRV = ColorMap->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
    }

    // Since we are using mutable variable, we must create shader resource binding object
    // http://diligentgraphics.com/2016/03/23/resource-binding-model-in-diligent-engine-2-0/
    for(size_t i=0; i < _countof(m_pPSO); ++i)
    {
        m_pPSO[i]->CreateShaderResourceBinding(&m_SRB[i]);
        // Set texture SRV in the SRB
        m_SRB[i]->GetVariable(SHADER_TYPE_PIXEL, "g_Texture")->Set(m_ColorMapSRV);
        m_SRB[i]->GetVariable(SHADER_TYPE_DOMAIN, "g_HeightMap")->Set(m_HeightMapSRV);
        m_SRB[i]->GetVariable(SHADER_TYPE_HULL, "g_HeightMap")->Set(m_HeightMapSRV);
    }

    // Create a tweak bar
    TwBar *bar = TwNewBar("Settings");
    int barSize[2] = {224 * m_UIScale, 120 * m_UIScale};
    TwSetParam(bar, NULL, "size", TW_PARAM_INT32, 2, barSize);

    // Add grid size control
    TwAddVarRW(bar, "Animate", TW_TYPE_BOOLCPP, &m_Animate, "");
    TwAddVarRW(bar, "Adaptive tessellation", TW_TYPE_BOOLCPP, &m_AdaptiveTessellation, "");
    TwAddVarRW(bar, "Wireframe", TW_TYPE_BOOLCPP, &m_Wireframe, "");
    TwAddVarRW(bar, "Tess density", TW_TYPE_FLOAT, &m_TessDensity, "min=1 max=32 step=0.1");
    TwAddVarRW(bar, "Distance", TW_TYPE_FLOAT, &m_Distance, "min=1 max=20 step=0.1");
}