Decouple XFB scanout from presentation

This commit is contained in:
Stenzek
2018-11-28 14:30:47 +10:00
parent f1e7fb505b
commit e4b205c769
16 changed files with 319 additions and 383 deletions

View File

@ -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);
TargetRectangle left_rc, right_rc;
std::tie(left_rc, right_rc) = ConvertStereoRectangle(target_rc);
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,
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,9 +808,9 @@ 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() :
@ -852,7 +818,8 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D
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);
}