Skip to content
Permalink
Browse files

Decouple XFB scanout from presentation

  • Loading branch information...
stenzek committed Nov 28, 2018
1 parent f1e7fb5 commit e4b205c76937d379cd9043939e2cef1651b1a21b
@@ -125,6 +125,7 @@ void FramebufferManager::BindEFBRenderTarget(bool bind_depth)

FramebufferManager::FramebufferManager(int target_width, int target_height)
{
static constexpr std::array<float, 4> clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
m_target_width = static_cast<unsigned int>(std::max(target_width, 1));
m_target_height = static_cast<unsigned int>(std::max(target_height, 1));
DXGI_SAMPLE_DESC sample_desc;
@@ -154,6 +155,7 @@ FramebufferManager::FramebufferManager(int target_width, int target_height)
D3D::SetDebugObjectName(m_efb.color_tex->GetTex(), "EFB color texture");
D3D::SetDebugObjectName(m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
D3D::SetDebugObjectName(m_efb.color_tex->GetRTV(), "EFB color texture render target view");
D3D::context->ClearRenderTargetView(m_efb.color_tex->GetRTV(), clear_color.data());

// Temporary EFB color texture - used in ReinterpretPixelData
texdesc =
@@ -173,6 +175,7 @@ FramebufferManager::FramebufferManager(int target_width, int target_height)
"EFB color temp texture shader resource view");
D3D::SetDebugObjectName(m_efb.color_temp_tex->GetRTV(),
"EFB color temp texture render target view");
D3D::context->ClearRenderTargetView(m_efb.color_temp_tex->GetRTV(), clear_color.data());

// Integer render targets for EFB, used for logic op
CD3D11_RENDER_TARGET_VIEW_DESC int_rtv_desc(m_efb.color_tex->GetTex(),
@@ -222,6 +225,7 @@ FramebufferManager::FramebufferManager(int target_width, int target_height)
D3D::SetDebugObjectName(m_efb.depth_tex->GetTex(), "EFB depth texture");
D3D::SetDebugObjectName(m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view");
D3D::SetDebugObjectName(m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
D3D::context->ClearDepthStencilView(m_efb.depth_tex->GetDSV(), D3D11_CLEAR_DEPTH, 0.0f, 0);

// Render buffer for AccessEFB (depth data)
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 1, D3D11_BIND_RENDER_TARGET);
@@ -66,19 +66,10 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height, float backbuffer
: ::Renderer(backbuffer_width, backbuffer_height, backbuffer_scale,
AbstractTextureFormat::RGBA8)
{
m_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_stereo_mode = g_ActiveConfig.stereo_mode != StereoMode::Off;
m_last_fullscreen_state = D3D::GetFullscreenState();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
SetupDeviceObjects();

// Clear EFB textures
constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(),
clear_color.data());
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(),
D3D11_CLEAR_DEPTH, 0.f, 0);

D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)m_target_width, (float)m_target_height);
D3D::context->RSSetViewports(1, &vp);
FramebufferManager::BindEFBRenderTarget();
@@ -560,68 +551,33 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
RestoreAPIState();
}

// This function has the final picture. We adjust the aspect ratio here.
void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks)
void Renderer::BindBackbuffer(const ClearColor& clear_color)
{
ResetAPIState();

// Prepare to copy the XFBs to our backbuffer
CheckForSurfaceChange();
CheckForSurfaceResize();
UpdateDrawRectangle();

TargetRectangle targetRc = GetTargetRectangle();
static constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), clear_color.data());
m_current_framebuffer = nullptr;
m_current_framebuffer_width = m_backbuffer_width;
m_current_framebuffer_height = m_backbuffer_height;
}

// activate linear filtering for the buffer copies
D3D::SetLinearCopySampler();
auto* xfb_texture = static_cast<DXTexture*>(texture);

BlitScreen(xfb_region, targetRc, xfb_texture->GetRawTexIdentifier(),
xfb_texture->GetConfig().width, xfb_texture->GetConfig().height);

// Reset viewport for drawing text
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.0f, 0.0f, static_cast<float>(m_backbuffer_width),
static_cast<float>(m_backbuffer_height));
D3D::context->RSSetViewports(1, &vp);
DrawImGui();

g_texture_cache->Cleanup(frameCount);

// Enable configuration changes
UpdateActiveConfig();
g_texture_cache->OnConfigChanged(g_ActiveConfig);

// Flip/present backbuffer to frontbuffer here
if (D3D::swapchain)
D3D::Present();
void Renderer::PresentBackbuffer()
{
D3D::Present();
}

void Renderer::OnConfigChanged(u32 bits)
{
// Resize the back buffers NOW to avoid flickering
if (CalculateTargetSize() || m_last_multisamples != g_ActiveConfig.iMultisamples ||
m_last_stereo_mode != (g_ActiveConfig.stereo_mode != StereoMode::Off))
if (bits & (CONFIG_CHANGE_BIT_TARGET_SIZE | CONFIG_CHANGE_BIT_MULTISAMPLES |
CONFIG_CHANGE_BIT_STEREO_MODE))
{
m_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_stereo_mode = g_ActiveConfig.stereo_mode != StereoMode::Off;
PixelShaderCache::InvalidateMSAAShaders();
UpdateDrawRectangle();

g_framebuffer_manager.reset();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(),
clear_color.data());
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(),
D3D11_CLEAR_DEPTH, 0.f, 0);
}

CheckForHostConfigChanges();

// begin next frame
RestoreAPIState();
}

void Renderer::CheckForSurfaceChange()
@@ -780,28 +736,34 @@ void Renderer::BBoxWrite(int index, u16 _value)
BBox::Set(index, value);
}

void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
u32 src_width, u32 src_height)
void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc)
{
const CD3D11_RECT source_rc(rc.left, rc.top, rc.right, rc.bottom);
const TargetRectangle target_rc = GetTargetRectangle();

// activate linear filtering for the buffer copies
D3D::SetLinearCopySampler();

if (g_ActiveConfig.stereo_mode == StereoMode::SBS ||
g_ActiveConfig.stereo_mode == StereoMode::TAB)
{
TargetRectangle leftRc, rightRc;
std::tie(leftRc, rightRc) = ConvertStereoRectangle(dst);

D3D11_VIEWPORT leftVp = CD3D11_VIEWPORT((float)leftRc.left, (float)leftRc.top,
(float)leftRc.GetWidth(), (float)leftRc.GetHeight());
D3D11_VIEWPORT rightVp = CD3D11_VIEWPORT((float)rightRc.left, (float)rightRc.top,
(float)rightRc.GetWidth(), (float)rightRc.GetHeight());

D3D::context->RSSetViewports(1, &leftVp);
D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height,
TargetRectangle left_rc, right_rc;
std::tie(left_rc, right_rc) = ConvertStereoRectangle(target_rc);

SetViewport(static_cast<float>(left_rc.left), static_cast<float>(left_rc.top),
static_cast<float>(left_rc.GetWidth()), static_cast<float>(right_rc.GetHeight()),
0.0f, 1.0f);
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
&source_rc, texture->GetWidth(), texture->GetHeight(),
PixelShaderCache::GetColorCopyProgram(false),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), nullptr, 0);

D3D::context->RSSetViewports(1, &rightVp);
D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height,
SetViewport(static_cast<float>(right_rc.left), static_cast<float>(right_rc.top),
static_cast<float>(right_rc.GetWidth()), static_cast<float>(right_rc.GetHeight()),
0.0f, 1.0f);
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
&source_rc, texture->GetWidth(), texture->GetHeight(),
PixelShaderCache::GetColorCopyProgram(false),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), nullptr, 1);
@@ -811,29 +773,33 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D
if (!m_3d_vision_texture)
Create3DVisionTexture(m_backbuffer_width, m_backbuffer_height);

D3D11_VIEWPORT leftVp = CD3D11_VIEWPORT((float)dst.left, (float)dst.top, (float)dst.GetWidth(),
(float)dst.GetHeight());
D3D11_VIEWPORT rightVp = CD3D11_VIEWPORT((float)(dst.left + m_backbuffer_width), (float)dst.top,
(float)dst.GetWidth(), (float)dst.GetHeight());
const CD3D11_VIEWPORT left_vp(
static_cast<float>(target_rc.left), static_cast<float>(target_rc.top),
static_cast<float>(target_rc.GetWidth()), static_cast<float>(target_rc.GetHeight()));
const CD3D11_VIEWPORT right_vp(
static_cast<float>(target_rc.left + m_backbuffer_width), static_cast<float>(target_rc.top),
static_cast<float>(target_rc.GetWidth()), static_cast<float>(target_rc.GetHeight()));

// Render to staging texture which is double the width of the backbuffer
D3D::context->OMSetRenderTargets(1, &m_3d_vision_texture->GetRTV(), nullptr);

D3D::context->RSSetViewports(1, &leftVp);
D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height,
D3D::context->RSSetViewports(1, &left_vp);
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
&source_rc, texture->GetWidth(), texture->GetHeight(),
PixelShaderCache::GetColorCopyProgram(false),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), nullptr, 0);

D3D::context->RSSetViewports(1, &rightVp);
D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height,
D3D::context->RSSetViewports(1, &right_vp);
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
&source_rc, texture->GetWidth(), texture->GetHeight(),
PixelShaderCache::GetColorCopyProgram(false),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), nullptr, 1);

// Copy the left eye to the backbuffer, if Nvidia 3D Vision is enabled it should
// recognize the signature and automatically include the right eye frame.
D3D11_BOX box = CD3D11_BOX(0, 0, 0, m_backbuffer_width, m_backbuffer_height, 1);
const CD3D11_BOX box(0, 0, 0, m_backbuffer_width, m_backbuffer_height, 1);
D3D::context->CopySubresourceRegion(D3D::GetBackBuffer()->GetTex(), 0, 0, 0, 0,
m_3d_vision_texture->GetTex(), 0, &box);

@@ -842,17 +808,18 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D
}
else
{
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)dst.left, (float)dst.top, (float)dst.GetWidth(),
(float)dst.GetHeight());
D3D::context->RSSetViewports(1, &vp);
SetViewport(static_cast<float>(target_rc.left), static_cast<float>(target_rc.top),
static_cast<float>(target_rc.GetWidth()), static_cast<float>(target_rc.GetHeight()),
0.0f, 1.0f);

ID3D11PixelShader* pixelShader = (g_Config.stereo_mode == StereoMode::Anaglyph) ?
PixelShaderCache::GetAnaglyphProgram() :
PixelShaderCache::GetColorCopyProgram(false);
ID3D11GeometryShader* geomShader = (g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer) ?
GeometryShaderCache::GetCopyGeometryShader() :
nullptr;
D3D::drawShadedTexQuad(src_texture->GetSRV(), src.AsRECT(), src_width, src_height, pixelShader,
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
&source_rc, texture->GetWidth(), texture->GetHeight(), pixelShader,
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), geomShader);
}
@@ -52,6 +52,8 @@ class Renderer : public ::Renderer
float far_depth) override;
void Draw(u32 base_vertex, u32 num_vertices) override;
void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
void BindBackbuffer(const ClearColor& clear_color = {}) override;
void PresentBackbuffer() override;
void SetFullscreen(bool enable_fullscreen) override;
bool IsFullscreen() const override;

@@ -66,7 +68,8 @@ class Renderer : public ::Renderer

TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;

void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks) override;
void RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc) override;
void OnConfigChanged(u32 bits) override;

void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override;
@@ -81,9 +84,6 @@ class Renderer : public ::Renderer
void CheckForSurfaceResize();
void UpdateBackbufferSize();

void BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
u32 src_width, u32 src_height);

StateCache m_state_cache;

std::array<ID3D11BlendState*, 4> m_clear_blend_states{};
@@ -95,8 +95,6 @@ class Renderer : public ::Renderer
ID3D11Texture2D* m_screenshot_texture = nullptr;
D3DTexture2D* m_3d_vision_texture = nullptr;

u32 m_last_multisamples = 1;
bool m_last_stereo_mode = false;
bool m_last_fullscreen_state = false;
};
}
@@ -157,13 +157,14 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
VertexShaderCache::Init();
PixelShaderCache::Init();
GeometryShaderCache::Init();
if (!g_shader_cache->Initialize())

if (!g_renderer->Initialize() || !g_shader_cache->Initialize())
return false;

D3D::InitUtils();
BBox::Init();

return g_renderer->Initialize();
return true;
}

void VideoBackend::Shutdown()
@@ -92,9 +92,4 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
return result;
}

void Renderer::SwapImpl(AbstractTexture*, const EFBRectangle&, u64)
{
UpdateActiveConfig();
}

} // namespace Null
@@ -35,8 +35,6 @@ class Renderer : public ::Renderer
void BBoxWrite(int index, u16 value) override {}
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;

void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks) override;

void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override
{

0 comments on commit e4b205c

Please sign in to comment.
You can’t perform that action at this time.