//---------------------------------------------------------------------------------
static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice,
                                     _In_opt_ ID3D11DeviceContext* d3dContext,
                                     _In_ IWICBitmapFrameDecode *frame,
                                     _In_ size_t maxsize,
                                     _In_ D3D11_USAGE usage,
                                     _In_ unsigned int bindFlags,
                                     _In_ unsigned int cpuAccessFlags,
                                     _In_ unsigned int miscFlags,
                                     _In_ bool forceSRGB,
                                     _Out_opt_ ID3D11Resource** texture,
                                     _Out_opt_ ID3D11ShaderResourceView** textureView )
{
    UINT width, height;
    HRESULT hr = frame->GetSize( &width, &height );
    if ( FAILED(hr) )
        return hr;

    assert( width > 0 && height > 0 );

    if ( !maxsize )
    {
        // This is a bit conservative because the hardware could support larger textures than
        // the Feature Level defined minimums, but doing it this way is much easier and more
        // performant for WIC than the 'fail and retry' model used by DDSTextureLoader

        switch( d3dDevice->GetFeatureLevel() )
        {
            case D3D_FEATURE_LEVEL_9_1:
            case D3D_FEATURE_LEVEL_9_2:
                maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                break;

            case D3D_FEATURE_LEVEL_9_3:
                maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                break;

            case D3D_FEATURE_LEVEL_10_0:
            case D3D_FEATURE_LEVEL_10_1:
                maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                break;

            default:
                maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
                break;
        }
    }

    assert( maxsize > 0 );

    UINT twidth, theight;
    if ( width > maxsize || height > maxsize )
    {
        float ar = static_cast<float>(height) / static_cast<float>(width);
        if ( width > height )
        {
            twidth = static_cast<UINT>( maxsize );
            theight = static_cast<UINT>( static_cast<float>(maxsize) * ar );
        }
        else
        {
            theight = static_cast<UINT>( maxsize );
            twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar );
        }
        assert( twidth <= maxsize && theight <= maxsize );
    }
    else
    {
        twidth = width;
        theight = height;
    }

    // Determine format
    WICPixelFormatGUID pixelFormat;
    hr = frame->GetPixelFormat( &pixelFormat );
    if ( FAILED(hr) )
        return hr;

    WICPixelFormatGUID convertGUID;
    memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) );

    size_t bpp = 0;

    DXGI_FORMAT format = _WICToDXGI( pixelFormat );
    if ( format == DXGI_FORMAT_UNKNOWN )
    {
        if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
        {
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
            if ( g_WIC2 )
            {
                memcpy( &convertGUID, &GUID_WICPixelFormat96bppRGBFloat, sizeof(WICPixelFormatGUID) );
                format = DXGI_FORMAT_R32G32B32_FLOAT;
            }
            else
#endif
            {
                memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) );
                format = DXGI_FORMAT_R32G32B32A32_FLOAT;
            }
        }
        else
        {
            for( size_t i=0; i < _countof(g_WICConvert); ++i )
            {
                if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
                {
                    memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) );

                    format = _WICToDXGI( g_WICConvert[i].target );
                    assert( format != DXGI_FORMAT_UNKNOWN );
                    bpp = _WICBitsPerPixel( convertGUID );
                    break;
                }
            }
        }

        if ( format == DXGI_FORMAT_UNKNOWN )
            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
    }
    else
    {
        bpp = _WICBitsPerPixel( pixelFormat );
    }

#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
    if ( (format == DXGI_FORMAT_R32G32B32_FLOAT) && d3dContext != 0 && textureView != 0 )
    {
        // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT 
        UINT fmtSupport = 0;
        hr = d3dDevice->CheckFormatSupport( DXGI_FORMAT_R32G32B32_FLOAT, &fmtSupport );
        if ( FAILED(hr) || !( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) )
        {
            // Use R32G32B32A32_FLOAT instead which is required for Feature Level 10.0 and up
            memcpy( &convertGUID, &GUID_WICPixelFormat128bppRGBAFloat, sizeof(WICPixelFormatGUID) );
            format = DXGI_FORMAT_R32G32B32A32_FLOAT;
            bpp = 128;
        }
    }
#endif

    if ( !bpp )
        return E_FAIL;

    // Verify our target format is supported by the current device
    // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
    UINT support = 0;
    hr = d3dDevice->CheckFormatSupport( format, &support );
    if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) )
    {
        // Fallback to RGBA 32-bit format which is supported by all devices
        memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) );
        format = DXGI_FORMAT_R8G8B8A8_UNORM;
        bpp = 32;
    }

    // Allocate temporary memory for image
    size_t rowPitch = ( twidth * bpp + 7 ) / 8;
    size_t imageSize = rowPitch * theight;

    std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ imageSize ] );
    if (!temp)
        return E_OUTOFMEMORY;

    // Load image data
    if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0
         && twidth == width
         && theight == height )
    {
        // No format conversion or resize needed
        hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );  
        if ( FAILED(hr) )
            return hr;
    }
    else if ( twidth != width || theight != height )
    {
        // Resize
        IWICImagingFactory* pWIC = _GetWIC();
        if ( !pWIC )
            return E_NOINTERFACE;

        ScopedObject<IWICBitmapScaler> scaler;
        hr = pWIC->CreateBitmapScaler( &scaler );
        if ( FAILED(hr) )
            return hr;

        hr = scaler->Initialize( frame, twidth, theight, WICBitmapInterpolationModeFant );
        if ( FAILED(hr) )
            return hr;

        WICPixelFormatGUID pfScaler;
        hr = scaler->GetPixelFormat( &pfScaler );
        if ( FAILED(hr) )
            return hr;

        if ( memcmp( &convertGUID, &pfScaler, sizeof(GUID) ) == 0 )
        {
            // No format conversion needed
            hr = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );  
            if ( FAILED(hr) )
                return hr;
        }
        else
        {
            ScopedObject<IWICFormatConverter> FC;
            hr = pWIC->CreateFormatConverter( &FC );
            if ( FAILED(hr) )
                return hr;

            hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
            if ( FAILED(hr) )
                return hr;

            hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );  
            if ( FAILED(hr) )
                return hr;
        }
    }
    else
    {
        // Format conversion but no resize
        IWICImagingFactory* pWIC = _GetWIC();
        if ( !pWIC )
            return E_NOINTERFACE;

        ScopedObject<IWICFormatConverter> FC;
        hr = pWIC->CreateFormatConverter( &FC );
        if ( FAILED(hr) )
            return hr;

        hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
        if ( FAILED(hr) )
            return hr;

        hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );  
        if ( FAILED(hr) )
            return hr;
    }

    // See if format is supported for auto-gen mipmaps (varies by feature level)
    bool autogen = false;
    if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps
    {
        UINT fmtSupport = 0;
        hr = d3dDevice->CheckFormatSupport( format, &fmtSupport );
        if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) )
        {
            autogen = true;
        }
    }

    // Create texture
    D3D11_TEXTURE2D_DESC desc;
    desc.Width = twidth;
    desc.Height = theight;
    desc.MipLevels = (autogen) ? 0 : 1;
    desc.ArraySize = 1;
    desc.Format = (forceSRGB) ? MakeSRGB( format ) : format;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Usage = usage;
    desc.CPUAccessFlags = cpuAccessFlags;

    if ( autogen )
    {
        desc.BindFlags = bindFlags | D3D11_BIND_RENDER_TARGET;
        desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_GENERATE_MIPS;
    }
    else
    {
        desc.BindFlags = bindFlags;
        desc.MiscFlags = miscFlags;
    }

    D3D11_SUBRESOURCE_DATA initData;
    initData.pSysMem = temp.get();
    initData.SysMemPitch = static_cast<UINT>( rowPitch );
    initData.SysMemSlicePitch = static_cast<UINT>( imageSize );

    ID3D11Texture2D* tex = nullptr;
    hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex );
    if ( SUCCEEDED(hr) && tex != 0 )
    {
        if (textureView != 0)
        {
            D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
            memset( &SRVDesc, 0, sizeof( SRVDesc ) );
            SRVDesc.Format = desc.Format;

            SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
            SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;

            hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );
            if ( FAILED(hr) )
            {
                tex->Release();
                return hr;
            }

            if ( autogen )
            {
                assert( d3dContext != 0 );
                d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) );
                d3dContext->GenerateMips( *textureView );
            }
        }

        if (texture != 0)
        {
            *texture = tex;
        }
        else
        {
            SetDebugObjectName(tex, "WICTextureLoader");
            tex->Release();
        }
    }

    return hr;
}
Beispiel #2
0
// 建立渲染窗口
/////////////////////////////////////////////////////////////////////////////////
void RenderEngine::CreateRenderWindow(std::string const & name, RenderSettings& settings)
{
    if (settings.stereo_method != STM_OculusVR)
    {
        stereo_separation_ = settings.stereo_separation;
    }
    this->DoCreateRenderWindow(name, settings);
    this->CheckConfig(settings);
    RenderDeviceCaps const & caps = this->DeviceCaps();

    screen_frame_buffer_ = cur_frame_buffer_;

    uint32_t const screen_width = screen_frame_buffer_->Width();
    uint32_t const screen_height = screen_frame_buffer_->Height();
    float const screen_aspect = static_cast<float>(screen_width) / screen_height;
    if (!MathLib::equal(screen_aspect, static_cast<float>(settings.width) / settings.height))
    {
        settings.width = static_cast<uint32_t>(settings.height * screen_aspect + 0.5f);
    }

    RenderFactory& rf = Context::Instance().RenderFactoryInstance();

    pp_rl_ = rf.MakeRenderLayout();
    pp_rl_->TopologyType(RenderLayout::TT_TriangleStrip);

    float2 pos[] =
    {
        float2(-1, +1),
        float2(+1, +1),
        float2(-1, -1),
        float2(+1, -1)
    };
    GraphicsBufferPtr pp_pos_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, sizeof(pos), &pos[0]);
    pp_rl_->BindVertexStream(pp_pos_vb, std::make_tuple(vertex_element(VEU_Position, 0, EF_GR32F)));

    uint32_t const render_width = static_cast<uint32_t>(settings.width * default_render_width_scale_ + 0.5f);
    uint32_t const render_height = static_cast<uint32_t>(settings.height * default_render_height_scale_ + 0.5f);

    hdr_enabled_ = settings.hdr;
    if (settings.hdr)
    {
        hdr_pp_ = MakeSharedPtr<HDRPostProcess>(settings.fft_lens_effects);
        skip_hdr_pp_ = SyncLoadPostProcess("Copy.ppml", "copy");
    }

    ppaa_enabled_ = settings.ppaa ? 1 : 0;
    gamma_enabled_ = settings.gamma;
    color_grading_enabled_ = settings.color_grading;
    if (settings.ppaa || settings.color_grading || settings.gamma)
    {
        for (size_t i = 0; i < 12; ++ i)
        {
            ldr_pps_[i] = SyncLoadPostProcess("PostToneMapping.ppml",
                                              "PostToneMapping" + boost::lexical_cast<std::string>(i));
        }

        ldr_pp_ = ldr_pps_[ppaa_enabled_ * 4 + gamma_enabled_ * 2 + color_grading_enabled_];
    }

    bool need_resize = false;
    if (!settings.hide_win)
    {
        need_resize = ((render_width != screen_width) || (render_height != screen_height));

        resize_pps_[0] = SyncLoadPostProcess("Resizer.ppml", "bilinear");
        resize_pps_[1] = MakeSharedPtr<BicubicFilteringPostProcess>();

        float const scale_x = static_cast<float>(screen_width) / render_width;
        float const scale_y = static_cast<float>(screen_height) / render_height;

        float2 pos_scale;
        if (scale_x < scale_y)
        {
            pos_scale.x() = 1;
            pos_scale.y() = (scale_x * render_height) / screen_height;
        }
        else
        {
            pos_scale.x() = (scale_y * render_width) / screen_width;
            pos_scale.y() = 1;
        }

        for (size_t i = 0; i < 2; ++ i)
        {
            resize_pps_[i]->SetParam(0, pos_scale);
        }
    }

    for (int i = 0; i < 4; ++ i)
    {
        default_frame_buffers_[i] = screen_frame_buffer_;
    }

    RenderViewPtr ds_view;
    if (hdr_pp_ || ldr_pp_ || (settings.stereo_method != STM_None))
    {
        ds_tex_ = this->ScreenDepthStencilTexture();
        if (ds_tex_ && (screen_width == render_width) && (screen_height == render_height))
        {
            ds_view = rf.Make2DDepthStencilRenderView(*ds_tex_, 0, 1, 0);
        }
        else
        {
            if (caps.texture_format_support(EF_D32F) || caps.texture_format_support(EF_D24S8)
                    || caps.texture_format_support(EF_D16))
            {
                ElementFormat fmt;
                if ((settings.depth_stencil_fmt != EF_Unknown)
                        && caps.texture_format_support(settings.depth_stencil_fmt))
                {
                    fmt = settings.depth_stencil_fmt;
                }
                else
                {
                    BOOST_ASSERT(caps.texture_format_support(EF_D16));

                    fmt = EF_D16;
                }
                ds_tex_ = rf.MakeTexture2D(render_width, render_height, 1, 1, fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
                ds_view = rf.Make2DDepthStencilRenderView(*ds_tex_, 0, 1, 0);
            }
            else
            {
                ElementFormat fmt;
                if ((settings.depth_stencil_fmt != EF_Unknown)
                        && caps.rendertarget_format_support(settings.depth_stencil_fmt, 1, 0))
                {
                    fmt = settings.depth_stencil_fmt;
                }
                else
                {
                    BOOST_ASSERT(caps.rendertarget_format_support(EF_D16, 1, 0));

                    fmt = EF_D16;
                }
                ds_view = rf.Make2DDepthStencilRenderView(render_width, render_height, fmt, 1, 0);
            }
        }
    }

    if (settings.stereo_method != STM_None)
    {
        mono_frame_buffer_ = rf.MakeFrameBuffer();
        mono_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        ElementFormat fmt;
        if (caps.texture_format_support(settings.color_fmt) && caps.rendertarget_format_support(settings.color_fmt, 1, 0))
        {
            fmt = settings.color_fmt;
        }
        else
        {
            if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
            {
                fmt = EF_ABGR8;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));

                fmt = EF_ARGB8;
            }
        }

        mono_tex_ = rf.MakeTexture2D(screen_width, screen_height, 1, 1,
                                     fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
        mono_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*mono_tex_, 0, 1, 0));

        default_frame_buffers_[0] = default_frame_buffers_[1]
                                    = default_frame_buffers_[2] = mono_frame_buffer_;

        overlay_frame_buffer_ = rf.MakeFrameBuffer();
        overlay_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        overlay_tex_ = rf.MakeTexture2D(screen_width, screen_height, 1, 1,
                                        fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
        overlay_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*overlay_tex_, 0, 1, 0));

        RenderViewPtr screen_size_ds_view;
        if (need_resize)
        {
            screen_size_ds_view = rf.Make2DDepthStencilRenderView(screen_width, screen_height, ds_view->Format(), 1, 0);
        }
        else
        {
            screen_size_ds_view = ds_view;
        }
        overlay_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil, screen_size_ds_view);
    }
    else
    {
        if (need_resize)
        {
            resize_frame_buffer_ = rf.MakeFrameBuffer();
            resize_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

            ElementFormat fmt;
            if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
            {
                fmt = EF_ABGR8;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));

                fmt = EF_ARGB8;
            }

            resize_tex_ = rf.MakeTexture2D(render_width, render_height, 1, 1,
                                           fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
            resize_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*resize_tex_, 0, 1, 0));

            ElementFormat ds_fmt;
            if ((settings.depth_stencil_fmt != EF_Unknown) && caps.rendertarget_format_support(settings.depth_stencil_fmt, 1, 0))
            {
                ds_fmt = settings.depth_stencil_fmt;
            }
            else
            {
                BOOST_ASSERT(caps.rendertarget_format_support(EF_D16, 1, 0));

                ds_fmt = EF_D16;
            }
            resize_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil,
                                         rf.Make2DDepthStencilRenderView(render_width, render_height, ds_fmt, 1, 0));

            default_frame_buffers_[0] = default_frame_buffers_[1]
                                        = default_frame_buffers_[2] = resize_frame_buffer_;
        }
    }

    if (ldr_pp_)
    {
        ldr_frame_buffer_ = rf.MakeFrameBuffer();
        ldr_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        ElementFormat fmt;
        if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
        {
            fmt = EF_ABGR8;
        }
        else
        {
            BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));

            fmt = EF_ARGB8;
        }
        ElementFormat fmt_srgb = MakeSRGB(fmt);
        if (caps.texture_format_support(fmt_srgb) && caps.rendertarget_format_support(fmt_srgb, 1, 0))
        {
            fmt = fmt_srgb;
        }

        ldr_tex_ = rf.MakeTexture2D(render_width, render_height, 1, 1, fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write, nullptr);
        ldr_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*ldr_tex_, 0, 1, 0));
        ldr_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil, ds_view);

        default_frame_buffers_[0] = default_frame_buffers_[1] = ldr_frame_buffer_;
    }

    if (hdr_pp_)
    {
        hdr_frame_buffer_ = rf.MakeFrameBuffer();
        hdr_frame_buffer_->GetViewport()->camera = cur_frame_buffer_->GetViewport()->camera;

        ElementFormat fmt;
        if (caps.fp_color_support)
        {
            if (caps.texture_format_support(EF_B10G11R11F) && caps.rendertarget_format_support(EF_B10G11R11F, 1, 0))
            {
                fmt = EF_B10G11R11F;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ABGR16F) && caps.rendertarget_format_support(EF_ABGR16F, 1, 0));
                fmt = EF_ABGR16F;
            }
        }
        else
        {
            if (caps.texture_format_support(EF_ABGR8) && caps.rendertarget_format_support(EF_ABGR8, 1, 0))
            {
                fmt = EF_ABGR8;
            }
            else
            {
                BOOST_ASSERT(caps.texture_format_support(EF_ARGB8) && caps.rendertarget_format_support(EF_ARGB8, 1, 0));
                fmt = EF_ARGB8;
            }

            ElementFormat fmt_srgb = MakeSRGB(fmt);
            if (caps.rendertarget_format_support(fmt_srgb, 1, 0))
            {
                fmt = fmt_srgb;
            }
        }
        hdr_tex_ = rf.MakeTexture2D(render_width, render_height, 4, 1, fmt, 1, 0, EAH_GPU_Read | EAH_GPU_Write | EAH_Generate_Mips, nullptr);
        hdr_frame_buffer_->Attach(FrameBuffer::ATT_Color0, rf.Make2DRenderView(*hdr_tex_, 0, 1, 0));
        hdr_frame_buffer_->Attach(FrameBuffer::ATT_DepthStencil, ds_view);

        default_frame_buffers_[0] = hdr_frame_buffer_;
    }

    this->BindFrameBuffer(default_frame_buffers_[0]);
    this->Stereo(settings.stereo_method);

#ifndef KLAYGE_SHIP
    PerfProfiler& profiler = PerfProfiler::Instance();
    hdr_pp_perf_ = profiler.CreatePerfRange(0, "HDR PP");
    ldr_pp_perf_ = profiler.CreatePerfRange(0, "LDR PP");
    resize_pp_perf_ = profiler.CreatePerfRange(0, "Resize PP");
    stereoscopic_pp_perf_ = profiler.CreatePerfRange(0, "Stereoscopic PP");
#endif
}