From 5e803c3db3fa27b943d3d7789086789946eed6a7 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 28 Nov 2015 20:04:36 +1000 Subject: D3D: Fix EFB->XFB copies incorrectly scaling, match GL behavior --- Source/Core/VideoBackends/D3D/FramebufferManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoBackends/D3D/FramebufferManager.cpp') diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index f9f798f262..8ba8074d40 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -199,12 +199,13 @@ void XFBSource::CopyEFB(float Gamma) // Copy EFB data to XFB and restore render target again const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight); + const D3D11_RECT rect = CD3D11_RECT(0, 0, texWidth, texHeight); D3D::context->RSSetViewports(1, &vp); D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), nullptr); - D3D::SetLinearCopySampler(); + D3D::SetPointCopySampler(); - D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(), + D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &rect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader(), Gamma); -- cgit v1.2.3 From 63264ac23f3b9cfaa725cf90d995497ba1601449 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 28 Nov 2015 21:33:47 +1000 Subject: D3D: Fix EFB depth buffer copies, filtering on scaled EFB copies when MSAA is enabled, real XFB filtering Since ResolveSubresource cannot be used with depth textures (and throws an error with the debug layer enabled), use a shader which selects the minimum depth value from all samples. Changes the sampler by XFBEncoder to use a linear filter, rather than point, to match GL behavior. --- .../Core/VideoBackends/D3D/FramebufferManager.cpp | 46 ++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'Source/Core/VideoBackends/D3D/FramebufferManager.cpp') diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index 8ba8074d40..ae7ca4b973 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -4,6 +4,7 @@ #include "Core/HW/Memmap.h" #include "VideoBackends/D3D/D3DBase.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DUtil.h" #include "VideoBackends/D3D/FramebufferManager.h" #include "VideoBackends/D3D/GeometryShaderCache.h" @@ -20,6 +21,7 @@ static XFBEncoder s_xfbEncoder; FramebufferManager::Efb FramebufferManager::m_efb; unsigned int FramebufferManager::m_target_width; unsigned int FramebufferManager::m_target_height; +ID3D11DepthStencilState* FramebufferManager::m_depth_resolve_depth_state; D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; } ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; } @@ -44,8 +46,29 @@ D3DTexture2D* &FramebufferManager::GetResolvedEFBDepthTexture() { if (g_ActiveConfig.iMultisampleMode) { - for (int i = 0; i < m_efb.slices; i++) - D3D::context->ResolveSubresource(m_efb.resolved_depth_tex->GetTex(), D3D11CalcSubresource(0, i, 1), m_efb.depth_tex->GetTex(), D3D11CalcSubresource(0, i, 1), DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + // ResolveSubresource does not work with depth textures. + // Instead, we use a shader that selects the minimum depth from all samples. + + // Clear render state, and enable depth writes. + g_renderer->ResetAPIState(); + D3D::stateman->PushDepthState(m_depth_resolve_depth_state); + + // Set up to render to resolved depth texture. + const D3D11_VIEWPORT viewport = CD3D11_VIEWPORT(0.f, 0.f, (float)m_target_width, (float)m_target_height); + D3D::context->RSSetViewports(1, &viewport); + D3D::context->OMSetRenderTargets(0, nullptr, m_efb.resolved_depth_tex->GetDSV()); + + // Render a quad covering the entire target, writing SV_Depth. + const D3D11_RECT source_rect = CD3D11_RECT(0, 0, m_target_width, m_target_height); + D3D::drawShadedTexQuad(m_efb.depth_tex->GetSRV(), &source_rect, m_target_width, m_target_height, + PixelShaderCache::GetDepthResolveProgram(), VertexShaderCache::GetSimpleVertexShader(), + VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader()); + + // Restore render state. + D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); + D3D::stateman->PopDepthState(); + g_renderer->RestoreAPIState(); + return m_efb.resolved_depth_tex; } else @@ -77,7 +100,6 @@ FramebufferManager::FramebufferManager() hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf); CHECK(hr==S_OK, "create EFB color texture (size: %dx%d; hr=%#x)", m_target_width, m_target_height, hr); m_efb.color_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1)); - CHECK(m_efb.color_tex!=nullptr, "create EFB color texture (size: %dx%d)", m_target_width, m_target_height); SAFE_RELEASE(buf); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view"); @@ -88,7 +110,6 @@ FramebufferManager::FramebufferManager() hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf); CHECK(hr==S_OK, "create EFB color temp texture (size: %dx%d; hr=%#x)", m_target_width, m_target_height, hr); m_efb.color_temp_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1)); - CHECK(m_efb.color_temp_tex!=nullptr, "create EFB color temp texture (size: %dx%d)", m_target_width, m_target_height); SAFE_RELEASE(buf); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetTex(), "EFB color temp texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetSRV(), "EFB color temp texture shader resource view"); @@ -130,24 +151,34 @@ FramebufferManager::FramebufferManager() // Framebuffer resolve textures (color+depth) texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1); hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf); + CHECK(hr==S_OK, "create EFB color resolve texture (size: %dx%d; hr=%#x)", m_target_width, m_target_height, hr); m_efb.resolved_color_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM); - CHECK(m_efb.resolved_color_tex!=nullptr, "create EFB color resolve texture (size: %dx%d)", m_target_width, m_target_height); SAFE_RELEASE(buf); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetTex(), "EFB color resolve texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetSRV(), "EFB color resolve texture shader resource view"); - texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, m_target_width, m_target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE); + texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, m_target_width, m_target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL); hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf); CHECK(hr==S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", m_target_width, m_target_height, hr); - m_efb.resolved_depth_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R24_UNORM_X8_TYPELESS); + m_efb.resolved_depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL), DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT); SAFE_RELEASE(buf); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_depth_tex->GetTex(), "EFB depth resolve texture"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_depth_tex->GetSRV(), "EFB depth resolve texture shader resource view"); + + // Depth state used when writing resolved depth texture + D3D11_DEPTH_STENCIL_DESC depth_resolve_depth_state = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT()); + depth_resolve_depth_state.DepthEnable = TRUE; + depth_resolve_depth_state.DepthFunc = D3D11_COMPARISON_ALWAYS; + depth_resolve_depth_state.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + hr = D3D::device->CreateDepthStencilState(&depth_resolve_depth_state, &m_depth_resolve_depth_state); + CHECK(hr == S_OK, "create depth resolve depth stencil state"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_depth_resolve_depth_state, "depth resolve depth stencil state"); } else { m_efb.resolved_color_tex = nullptr; m_efb.resolved_depth_tex = nullptr; + m_depth_resolve_depth_state = nullptr; } s_xfbEncoder.Init(); @@ -165,6 +196,7 @@ FramebufferManager::~FramebufferManager() SAFE_RELEASE(m_efb.depth_staging_buf); SAFE_RELEASE(m_efb.depth_read_texture); SAFE_RELEASE(m_efb.resolved_depth_tex); + SAFE_RELEASE(m_depth_resolve_depth_state); } void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) -- cgit v1.2.3