summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends
diff options
context:
space:
mode:
authoriwubcode <iwubcode@users.noreply.github.com>2017-05-29 17:02:09 -0500
committeriwubcode <iwubcode@users.noreply.github.com>2017-11-17 19:47:56 -0600
commit79387dddb24ddf035b70cd9379a42368dcd49e93 (patch)
tree7b783c46e1ffd052842f11112f58c61993f0af1b /Source/Core/VideoBackends
parent84ca9a4aec0048e5ac01caea8f8be9210eb947f6 (diff)
Add support for hybrid XFB
Diffstat (limited to 'Source/Core/VideoBackends')
-rw-r--r--Source/Core/VideoBackends/D3D/D3D.vcxproj2
-rw-r--r--Source/Core/VideoBackends/D3D/D3D.vcxproj.filters6
-rw-r--r--Source/Core/VideoBackends/D3D/FramebufferManager.cpp6
-rw-r--r--Source/Core/VideoBackends/D3D/FramebufferManager.h1
-rw-r--r--Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp5
-rw-r--r--Source/Core/VideoBackends/D3D/Render.cpp107
-rw-r--r--Source/Core/VideoBackends/D3D/Render.h3
-rw-r--r--Source/Core/VideoBackends/D3D/Television.cpp166
-rw-r--r--Source/Core/VideoBackends/D3D/Television.h45
-rw-r--r--Source/Core/VideoBackends/D3D/main.cpp1
-rw-r--r--Source/Core/VideoBackends/Null/FramebufferManager.h1
-rw-r--r--Source/Core/VideoBackends/Null/Render.cpp2
-rw-r--r--Source/Core/VideoBackends/Null/Render.h3
-rw-r--r--Source/Core/VideoBackends/OGL/FramebufferManager.cpp9
-rw-r--r--Source/Core/VideoBackends/OGL/FramebufferManager.h1
-rw-r--r--Source/Core/VideoBackends/OGL/PostProcessing.cpp6
-rw-r--r--Source/Core/VideoBackends/OGL/Render.cpp156
-rw-r--r--Source/Core/VideoBackends/OGL/Render.h20
-rw-r--r--Source/Core/VideoBackends/OGL/main.cpp1
-rw-r--r--Source/Core/VideoBackends/Software/EfbInterface.cpp34
-rw-r--r--Source/Core/VideoBackends/Software/SWOGLWindow.cpp27
-rw-r--r--Source/Core/VideoBackends/Software/SWOGLWindow.h8
-rw-r--r--Source/Core/VideoBackends/Software/SWRenderer.cpp91
-rw-r--r--Source/Core/VideoBackends/Software/SWRenderer.h9
-rw-r--r--Source/Core/VideoBackends/Software/SWmain.cpp60
-rw-r--r--Source/Core/VideoBackends/Software/Software.vcxproj1
-rw-r--r--Source/Core/VideoBackends/Software/TextureCache.h41
-rw-r--r--Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp14
-rw-r--r--Source/Core/VideoBackends/Vulkan/FramebufferManager.h3
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.cpp54
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.h8
-rw-r--r--Source/Core/VideoBackends/Vulkan/VulkanContext.cpp1
32 files changed, 137 insertions, 755 deletions
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj
index e766387de8..ff63898039 100644
--- a/Source/Core/VideoBackends/D3D/D3D.vcxproj
+++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj
@@ -52,7 +52,6 @@
<ClCompile Include="PixelShaderCache.cpp" />
<ClCompile Include="PSTextureEncoder.cpp" />
<ClCompile Include="Render.cpp" />
- <ClCompile Include="Television.cpp" />
<ClCompile Include="TextureCache.cpp" />
<ClCompile Include="VertexManager.cpp" />
<ClCompile Include="VertexShaderCache.cpp" />
@@ -73,7 +72,6 @@
<ClInclude Include="PixelShaderCache.h" />
<ClInclude Include="PSTextureEncoder.h" />
<ClInclude Include="Render.h" />
- <ClInclude Include="Television.h" />
<ClInclude Include="TextureCache.h" />
<ClInclude Include="VertexManager.h" />
<ClInclude Include="VertexShaderCache.h" />
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
index cc05377bda..e3138ff28f 100644
--- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
+++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
@@ -48,9 +48,6 @@
<ClCompile Include="Render.cpp">
<Filter>Render</Filter>
</ClCompile>
- <ClCompile Include="Television.cpp">
- <Filter>Render</Filter>
- </ClCompile>
<ClCompile Include="TextureCache.cpp">
<Filter>Render</Filter>
</ClCompile>
@@ -108,9 +105,6 @@
<ClInclude Include="Render.h">
<Filter>Render</Filter>
</ClInclude>
- <ClInclude Include="Television.h">
- <Filter>Render</Filter>
- </ClInclude>
<ClInclude Include="TextureCache.h">
<Filter>Render</Filter>
</ClInclude>
diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
index 5853b8e849..3ecd3119f8 100644
--- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
@@ -330,12 +330,6 @@ std::pair<u32, u32> FramebufferManager::GetTargetSize() const
return std::make_pair(m_target_width, m_target_height);
}
-void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
-{
- // DX11's XFB decoder does not use this function.
- // YUYV data is decoded in Render::Swap.
-}
-
void XFBSource::CopyEFB(float Gamma)
{
g_renderer->ResetAPIState(); // reset any game specific settings
diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.h b/Source/Core/VideoBackends/D3D/FramebufferManager.h
index f38a60edc0..96e76118ee 100644
--- a/Source/Core/VideoBackends/D3D/FramebufferManager.h
+++ b/Source/Core/VideoBackends/D3D/FramebufferManager.h
@@ -50,7 +50,6 @@ struct XFBSource : public XFBSourceBase
{
XFBSource(D3DTexture2D* _tex, int slices) : tex(_tex), m_slices(slices) {}
~XFBSource() { tex->Release(); }
- void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override;
void CopyEFB(float Gamma) override;
D3DTexture2D* const tex;
diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
index 9b24783f6a..7c05215948 100644
--- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
+++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp
@@ -41,8 +41,11 @@ void PSTextureEncoder::Init()
HRESULT hr;
// Create output texture RGBA format
+ // TODO: This Texture is overly large and parts of it are unused
+ // EFB2RAM copies use max (EFB_WIDTH * 4) by (EFB_HEIGHT / 4)
+ // XFB2RAM copies use max (EFB_WIDTH / 2) by (EFB_HEIGHT)
D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, EFB_WIDTH * 4,
- EFB_HEIGHT / 4, 1, 1, D3D11_BIND_RENDER_TARGET);
+ EFB_HEIGHT, 1, 1, D3D11_BIND_RENDER_TARGET);
hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_out);
CHECK(SUCCEEDED(hr), "create efb encode output texture");
D3D::SetDebugObjectName(m_out, "efb encoder output texture");
diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp
index 5fce3ab961..55d9267b46 100644
--- a/Source/Core/VideoBackends/D3D/Render.cpp
+++ b/Source/Core/VideoBackends/D3D/Render.cpp
@@ -24,10 +24,10 @@
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/D3DUtil.h"
+#include "VideoBackends/D3D/DXTexture.h"
#include "VideoBackends/D3D/FramebufferManager.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
-#include "VideoBackends/D3D/Television.h"
#include "VideoBackends/D3D/TextureCache.h"
#include "VideoBackends/D3D/VertexShaderCache.h"
@@ -40,6 +40,7 @@
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
+#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/XFMemory.h"
namespace DX11
@@ -66,11 +67,8 @@ struct GXPipelineState
static u32 s_last_multisamples = 1;
static bool s_last_stereo_mode = false;
-static bool s_last_xfb_mode = false;
static bool s_last_fullscreen_mode = false;
-static Television s_television;
-
static std::array<ID3D11BlendState*, 4> s_clear_blend_states{};
static std::array<ID3D11DepthStencilState*, 3> s_clear_depth_states{};
static ID3D11BlendState* s_reset_blend_state = nullptr;
@@ -85,8 +83,6 @@ static StateCache s_gx_state_cache;
static void SetupDeviceObjects()
{
- s_television.Init();
-
HRESULT hr;
D3D11_DEPTH_STENCIL_DESC ddesc;
@@ -182,8 +178,6 @@ static void TeardownDeviceObjects()
SAFE_RELEASE(s_screenshot_texture);
SAFE_RELEASE(s_3d_vision_texture);
- s_television.Shutdown();
-
s_gx_state_cache.Clear();
}
@@ -241,7 +235,6 @@ Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferH
{
s_last_multisamples = g_ActiveConfig.iMultisamples;
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
- s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
s_last_fullscreen_mode = D3D::GetFullscreenState();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
@@ -640,22 +633,11 @@ void Renderer::SetBlendingState(const BlendingState& state)
}
// This function has the final picture. We adjust the aspect ratio here.
-void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
- const EFBRectangle& rc, u64 ticks, float Gamma)
+void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma)
{
- if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
+ if (!m_xfb_written)
{
Core::Callback_VideoCopiedToXFB(false);
- return;
- }
-
- u32 xfbCount = 0;
- const XFBSourceBase* const* xfbSourceList =
- FramebufferManager::GetXFBSource(xfbAddr, fbStride, fbHeight, &xfbCount);
- if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
- {
- Core::Callback_VideoCopiedToXFB(false);
- return;
}
ResetAPIState();
@@ -671,67 +653,11 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
// activate linear filtering for the buffer copies
D3D::SetLinearCopySampler();
+ auto* xfb_texture = static_cast<DXTexture*>(texture);
+ TargetRectangle source_rc = xfb_texture->config.Rect();
- if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)
- {
- // TODO: Television should be used to render Virtual XFB mode as well.
- D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)targetRc.left, (float)targetRc.top,
- (float)targetRc.GetWidth(), (float)targetRc.GetHeight());
- D3D::context->RSSetViewports(1, &vp);
-
- s_television.Submit(xfbAddr, fbStride, fbWidth, fbHeight);
- s_television.Render();
- }
- else if (g_ActiveConfig.bUseXFB)
- {
- // draw each xfb source
- for (u32 i = 0; i < xfbCount; ++i)
- {
- const auto* const xfbSource = static_cast<const XFBSource*>(xfbSourceList[i]);
-
- // use virtual xfb with offset
- int xfbHeight = xfbSource->srcHeight;
- int xfbWidth = xfbSource->srcWidth;
- int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbStride * 2);
-
- TargetRectangle drawRc;
- drawRc.top = targetRc.top + hOffset * targetRc.GetHeight() / (s32)fbHeight;
- drawRc.bottom = targetRc.top + (hOffset + xfbHeight) * targetRc.GetHeight() / (s32)fbHeight;
- drawRc.left = targetRc.left +
- (targetRc.GetWidth() - xfbWidth * targetRc.GetWidth() / (s32)fbStride) / 2;
- drawRc.right = targetRc.left +
- (targetRc.GetWidth() + xfbWidth * targetRc.GetWidth() / (s32)fbStride) / 2;
-
- // The following code disables auto stretch. Kept for reference.
- // scale draw area for a 1 to 1 pixel mapping with the draw target
- // float vScale = (float)fbHeight / (float)s_backbuffer_height;
- // float hScale = (float)fbWidth / (float)s_backbuffer_width;
- // drawRc.top *= vScale;
- // drawRc.bottom *= vScale;
- // drawRc.left *= hScale;
- // drawRc.right *= hScale;
-
- TargetRectangle sourceRc;
- sourceRc.left = xfbSource->sourceRc.left;
- sourceRc.top = xfbSource->sourceRc.top;
- sourceRc.right = xfbSource->sourceRc.right;
- sourceRc.bottom = xfbSource->sourceRc.bottom;
-
- sourceRc.right -= Renderer::EFBToScaledX(fbStride - fbWidth);
-
- BlitScreen(sourceRc, drawRc, xfbSource->tex, xfbSource->texWidth, xfbSource->texHeight,
- Gamma);
- }
- }
- else
- {
- TargetRectangle sourceRc = Renderer::ConvertEFBRectangle(rc);
-
- // TODO: Improve sampling algorithm for the pixel shader so that we can use the multisampled EFB
- // texture as source
- D3DTexture2D* read_texture = FramebufferManager::GetResolvedEFBColorTexture();
- BlitScreen(sourceRc, targetRc, read_texture, GetTargetWidth(), GetTargetHeight(), Gamma);
- }
+ BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width,
+ xfb_texture->config.height, Gamma);
// Dump frames
if (IsFrameDumping())
@@ -773,33 +699,20 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
g_texture_cache->OnConfigChanged(g_ActiveConfig);
VertexShaderCache::RetreiveAsyncShaders();
- SetWindowSize(fbStride, fbHeight);
+ SetWindowSize(xfb_texture->config.width, xfb_texture->config.height);
const bool window_resized = CheckForResize();
const bool fullscreen = D3D::GetFullscreenState();
const bool fs_changed = s_last_fullscreen_mode != fullscreen;
- bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB;
-
- if (FramebufferManagerBase::LastXfbWidth() != fbStride ||
- FramebufferManagerBase::LastXfbHeight() != fbHeight)
- {
- xfbchanged = true;
- unsigned int xfb_w = (fbStride < 1 || fbStride > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbStride;
- unsigned int xfb_h = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight;
- FramebufferManagerBase::SetLastXfbWidth(xfb_w);
- FramebufferManagerBase::SetLastXfbHeight(xfb_h);
- }
-
// Flip/present backbuffer to frontbuffer here
D3D::Present();
// Resize the back buffers NOW to avoid flickering
- if (CalculateTargetSize() || xfbchanged || window_resized || fs_changed ||
+ if (CalculateTargetSize() || window_resized || fs_changed ||
s_last_multisamples != g_ActiveConfig.iMultisamples ||
s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0))
{
- s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
s_last_multisamples = g_ActiveConfig.iMultisamples;
s_last_fullscreen_mode = fullscreen;
PixelShaderCache::InvalidateMSAAShaders();
diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h
index a33eba7cd2..b35e0f9d20 100644
--- a/Source/Core/VideoBackends/D3D/Render.h
+++ b/Source/Core/VideoBackends/D3D/Render.h
@@ -46,8 +46,7 @@ public:
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
- void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
- u64 ticks, float Gamma) override;
+ void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override;
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override;
diff --git a/Source/Core/VideoBackends/D3D/Television.cpp b/Source/Core/VideoBackends/D3D/Television.cpp
deleted file mode 100644
index 79f556cd09..0000000000
--- a/Source/Core/VideoBackends/D3D/Television.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2011 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include "VideoBackends/D3D/Television.h"
-
-#include <vector>
-
-#include "Core/HW/Memmap.h"
-#include "VideoBackends/D3D/D3DBase.h"
-#include "VideoBackends/D3D/D3DShader.h"
-#include "VideoBackends/D3D/D3DState.h"
-#include "VideoBackends/D3D/D3DUtil.h"
-#include "VideoBackends/D3D/VertexShaderCache.h"
-#include "VideoCommon/VideoCommon.h"
-#include "VideoCommon/VideoConfig.h"
-
-namespace DX11
-{
-static const char YUYV_DECODER_PS[] =
- "// dolphin-emu YUYV decoder pixel shader\n"
-
- "Texture2D Tex0 : register(t0);\n"
- "sampler Samp0 : register(s0);\n"
-
- "static const float3x3 YCBCR_TO_RGB = float3x3(\n"
- "1.164, 0.000, 1.596,\n"
- "1.164, -0.392, -0.813,\n"
- "1.164, 2.017, 0.000\n"
- ");\n"
-
- "void main(out float4 ocol0 : SV_Target, in float4 pos : SV_Position, in float2 uv0 : "
- "TEXCOORD0)\n"
- "{\n"
- "float3 sample = Tex0.Sample(Samp0, uv0).rgb;\n"
-
- // GameCube/Wii XFB data is in YUYV format with ITU-R Rec. BT.601 color
- // primaries, compressed to the range Y in 16..235, U and V in 16..240.
- // We want to convert it to RGB format with sRGB color primaries, with
- // range 0..255.
-
- // Recover RGB components
- "float3 yuv_601_sub = sample.grb - float3(16.0/255.0, 128.0/255.0, 128.0/255.0);\n"
- "float3 rgb_601 = mul(YCBCR_TO_RGB, yuv_601_sub);\n"
-
- // If we were really obsessed with accuracy, we would correct for the
- // differing color primaries between BT.601 and sRGB. However, this may not
- // be worth the trouble because:
- // - BT.601 defines two sets of primaries: one for NTSC and one for PAL.
- // - sRGB's color primaries are actually an intermediate between BT.601's
- // NTSC and PAL primaries.
- // - If users even noticed any difference at all, they would be confused by
- // the slightly-different colors in the NTSC and PAL versions of the same
- // game.
- // - Even the game designers probably don't pay close attention to this
- // stuff.
- // Still, instructions on how to do it can be found at
- // <http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC20>
-
- "ocol0 = float4(rgb_601, 1);\n"
- "}\n";
-
-Television::Television() : m_yuyvTexture(nullptr), m_yuyvTextureSRV(nullptr), m_pShader(nullptr)
-{
-}
-
-void Television::Init()
-{
- HRESULT hr;
-
- // Create YUYV texture for real XFB mode
-
- // Initialize the texture with YCbCr black
- //
- // Some games use narrower XFB widths (Nintendo titles are fond of 608),
- // so the sampler's BorderColor won't cover the right side
- // (see sampler state below)
- const unsigned int MAX_XFB_SIZE = 2 * (MAX_XFB_WIDTH)*MAX_XFB_HEIGHT;
- std::vector<u8> fill(MAX_XFB_SIZE);
- for (size_t i = 0; i < MAX_XFB_SIZE / sizeof(u32); ++i)
- reinterpret_cast<u32*>(fill.data())[i] = 0x80108010;
- D3D11_SUBRESOURCE_DATA srd = {fill.data(), 2 * (MAX_XFB_WIDTH), 0};
-
- // This texture format is designed for YUYV data.
- D3D11_TEXTURE2D_DESC t2dd =
- CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_G8R8_G8B8_UNORM, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 1, 1);
- hr = D3D::device->CreateTexture2D(&t2dd, &srd, &m_yuyvTexture);
- CHECK(SUCCEEDED(hr), "create tv yuyv texture");
- D3D::SetDebugObjectName(m_yuyvTexture, "tv yuyv texture");
-
- // Create shader resource view for YUYV texture
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvd = CD3D11_SHADER_RESOURCE_VIEW_DESC(
- m_yuyvTexture, D3D11_SRV_DIMENSION_TEXTURE2D, DXGI_FORMAT_G8R8_G8B8_UNORM);
- hr = D3D::device->CreateShaderResourceView(m_yuyvTexture, &srvd, &m_yuyvTextureSRV);
- CHECK(SUCCEEDED(hr), "create tv yuyv texture srv");
- D3D::SetDebugObjectName(m_yuyvTextureSRV, "tv yuyv texture srv");
-
- // Create YUYV-decoding pixel shader
-
- m_pShader = D3D::CompileAndCreatePixelShader(YUYV_DECODER_PS);
- CHECK(m_pShader != nullptr, "compile and create yuyv decoder pixel shader");
- D3D::SetDebugObjectName(m_pShader, "yuyv decoder pixel shader");
-
- // Create sampler state and set border color
- //
- // The default sampler border color of { 0.f, 0.f, 0.f, 0.f }
- // creates a green border around the image - see issue 6483
- // (remember, the XFB is being interpreted as YUYV, and 0,0,0,0
- // is actually two green pixels in YUYV - black should be 16,128,16,128,
- // but we reverse the order to match DXGI_FORMAT_G8R8_G8B8_UNORM's ordering)
- float border[4] = {128.0f / 255.0f, 16.0f / 255.0f, 128.0f / 255.0f, 16.0f / 255.0f};
- D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(
- D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER,
- D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f);
- hr = D3D::device->CreateSamplerState(&samDesc, &m_samplerState);
- CHECK(SUCCEEDED(hr), "create yuyv decoder sampler state");
- D3D::SetDebugObjectName(m_samplerState, "yuyv decoder sampler state");
-}
-
-void Television::Shutdown()
-{
- SAFE_RELEASE(m_pShader);
- SAFE_RELEASE(m_yuyvTextureSRV);
- SAFE_RELEASE(m_yuyvTexture);
- SAFE_RELEASE(m_samplerState);
-}
-
-void Television::Submit(u32 xfbAddr, u32 stride, u32 width, u32 height)
-{
- m_curAddr = xfbAddr;
- m_curWidth = width;
- m_curHeight = height;
-
- // Load data from GameCube RAM to YUYV texture
- u8* yuyvSrc = Memory::GetPointer(xfbAddr);
- D3D11_BOX box = CD3D11_BOX(0, 0, 0, stride, height, 1);
- D3D::context->UpdateSubresource(m_yuyvTexture, 0, &box, yuyvSrc, 2 * stride, 2 * stride * height);
-}
-
-void Television::Render()
-{
- if (g_ActiveConfig.bUseRealXFB && g_ActiveConfig.bUseXFB)
- {
- // Use real XFB mode
- // TODO: If this is the lower field, render at a vertical offset of 1
- // line down. We could even consider implementing a deinterlacing
- // algorithm.
-
- D3D11_RECT sourceRc = CD3D11_RECT(0, 0, int(m_curWidth), int(m_curHeight));
-
- D3D::stateman->SetSampler(0, m_samplerState);
-
- D3D::drawShadedTexQuad(m_yuyvTextureSRV, &sourceRc, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, m_pShader,
- VertexShaderCache::GetSimpleVertexShader(),
- VertexShaderCache::GetSimpleInputLayout());
- }
- else if (g_ActiveConfig.bUseXFB)
- {
- // Use virtual XFB mode
-
- // TODO: Eventually, Television should render the Virtual XFB mode
- // display as well.
- }
-}
-}
diff --git a/Source/Core/VideoBackends/D3D/Television.h b/Source/Core/VideoBackends/D3D/Television.h
deleted file mode 100644
index 2ad29cdf10..0000000000
--- a/Source/Core/VideoBackends/D3D/Television.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2011 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "Common/CommonTypes.h"
-
-struct ID3D11Texture2D;
-struct ID3D11ShaderResourceView;
-struct ID3D11PixelShader;
-struct ID3D11SamplerState;
-
-namespace DX11
-{
-class Television
-{
-public:
- Television();
-
- void Init();
- void Shutdown();
-
- // Submit video data to be drawn. This will change the current state of the
- // TV. xfbAddr points to YUYV data stored in GameCube/Wii RAM, but the XFB
- // may be virtualized when rendering so the RAM may not actually be read.
- void Submit(u32 xfbAddr, u32 stride, u32 width, u32 height);
-
- // Render the current state of the TV.
- void Render();
-
-private:
- // Properties of last Submit call
- u32 m_curAddr;
- u32 m_curWidth;
- u32 m_curHeight;
-
- // Used for real XFB mode
-
- ID3D11Texture2D* m_yuyvTexture;
- ID3D11ShaderResourceView* m_yuyvTextureSRV;
- ID3D11PixelShader* m_pShader;
- ID3D11SamplerState* m_samplerState;
-};
-}
diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp
index ced41e2b13..4a0c9c29a5 100644
--- a/Source/Core/VideoBackends/D3D/main.cpp
+++ b/Source/Core/VideoBackends/D3D/main.cpp
@@ -78,6 +78,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsInternalResolutionFrameDumps = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
g_Config.backend_info.bSupportsST3CTextures = false;
+ g_Config.backend_info.bSupportsCopyToVram = true;
g_Config.backend_info.bSupportsBitfield = false;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
diff --git a/Source/Core/VideoBackends/Null/FramebufferManager.h b/Source/Core/VideoBackends/Null/FramebufferManager.h
index d68a4a7d1f..0419ee36f8 100644
--- a/Source/Core/VideoBackends/Null/FramebufferManager.h
+++ b/Source/Core/VideoBackends/Null/FramebufferManager.h
@@ -12,7 +12,6 @@
class XFBSource : public XFBSourceBase
{
public:
- void DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) override {}
void CopyEFB(float gamma) override {}
};
diff --git a/Source/Core/VideoBackends/Null/Render.cpp b/Source/Core/VideoBackends/Null/Render.cpp
index 084a7b49af..b1a88f7a80 100644
--- a/Source/Core/VideoBackends/Null/Render.cpp
+++ b/Source/Core/VideoBackends/Null/Render.cpp
@@ -36,7 +36,7 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
return result;
}
-void Renderer::SwapImpl(u32, u32, u32, u32, const EFBRectangle&, u64, float)
+void Renderer::SwapImpl(AbstractTexture*, const EFBRectangle&, u64, float)
{
UpdateActiveConfig();
}
diff --git a/Source/Core/VideoBackends/Null/Render.h b/Source/Core/VideoBackends/Null/Render.h
index 2187f147c0..2a21918f81 100644
--- a/Source/Core/VideoBackends/Null/Render.h
+++ b/Source/Core/VideoBackends/Null/Render.h
@@ -21,8 +21,7 @@ public:
void BBoxWrite(int index, u16 value) override {}
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
- void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
- u64 ticks, float gamma) override;
+ void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override;
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
index 91be73a9f3..77ef205f2a 100644
--- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
@@ -530,7 +530,7 @@ void FramebufferManager::ResolveEFBStencilTexture()
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight,
const EFBRectangle& sourceRc, float Gamma)
{
- u8* xfb_in_ram = Memory::GetPointer(xfbAddr);
+/* u8* xfb_in_ram = Memory::GetPointer(xfbAddr);
if (!xfb_in_ram)
{
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
@@ -539,7 +539,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight,
TargetRectangle targetRc = g_renderer->ConvertEFBRectangle(sourceRc);
TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram,
- sourceRc.GetWidth(), fbStride, fbHeight);
+ sourceRc.GetWidth(), fbStride, fbHeight);*/
}
GLuint FramebufferManager::GetResolvedFramebuffer()
@@ -615,11 +615,6 @@ XFBSource::~XFBSource()
glDeleteTextures(1, &texture);
}
-void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
-{
- TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
-}
-
void XFBSource::CopyEFB(float Gamma)
{
g_renderer->ResetAPIState();
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.h b/Source/Core/VideoBackends/OGL/FramebufferManager.h
index 62b2f5ce3c..1d3626af36 100644
--- a/Source/Core/VideoBackends/OGL/FramebufferManager.h
+++ b/Source/Core/VideoBackends/OGL/FramebufferManager.h
@@ -54,7 +54,6 @@ struct XFBSource : public XFBSourceBase
~XFBSource();
void CopyEFB(float Gamma) override;
- void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override;
const GLuint texture;
const int m_layers;
diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.cpp b/Source/Core/VideoBackends/OGL/PostProcessing.cpp
index f400bc56ef..08e0d36c6e 100644
--- a/Source/Core/VideoBackends/OGL/PostProcessing.cpp
+++ b/Source/Core/VideoBackends/OGL/PostProcessing.cpp
@@ -25,7 +25,7 @@ static const char s_vertex_shader[] = "out vec2 uv0;\n"
"void main(void) {\n"
" vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n"
" gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n"
- " uv0 = rawpos * src_rect.zw + src_rect.xy;\n"
+ " uv0 = vec2(mix(src_rect.xy, src_rect.zw, rawpos));\n"
"}\n";
OpenGLPostProcessing::OpenGLPostProcessing() : m_initialized(false)
@@ -52,8 +52,8 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle
glUniform4f(m_uniform_resolution, (float)src_width, (float)src_height, 1.0f / (float)src_width,
1.0f / (float)src_height);
- glUniform4f(m_uniform_src_rect, src.left / (float)src_width, src.bottom / (float)src_height,
- src.GetWidth() / (float)src_width, src.GetHeight() / (float)src_height);
+ glUniform4f(m_uniform_src_rect, src.left / (float)src_width, src.top / (float)src_height,
+ src.right / (float)src_width, src.bottom / (float)src_height);
glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed());
glUniform1i(m_uniform_layer, layer);
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index ccf89b45f2..d53ace17a5 100644
--- a/Source/Core/VideoBackends/OGL/Render.cpp
+++ b/Source/Core/VideoBackends/OGL/Render.cpp
@@ -66,7 +66,6 @@ static std::unique_ptr<RasterFont> s_raster_font;
static int s_MSAASamples = 1;
static u32 s_last_multisamples = 1;
static bool s_last_stereo_mode = false;
-static bool s_last_xfb_mode = false;
static bool s_vsync;
@@ -726,7 +725,6 @@ Renderer::Renderer()
s_MSAASamples = s_last_multisamples;
s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0;
- s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
// Handle VSync on/off
s_vsync = g_ActiveConfig.IsVSync();
@@ -1331,8 +1329,7 @@ void Renderer::SetBlendingState(const BlendingState& state)
}
// This function has the final picture. We adjust the aspect ratio here.
-void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
- const EFBRectangle& rc, u64 ticks, float Gamma)
+void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma)
{
if (g_ogl_config.bSupportsDebug)
{
@@ -1342,20 +1339,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
glDisable(GL_DEBUG_OUTPUT);
}
- if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
- {
- Core::Callback_VideoCopiedToXFB(false);
- return;
- }
+ auto* xfb_texture = static_cast<OGLTexture*>(texture);
- u32 xfbCount = 0;
- const XFBSourceBase* const* xfbSourceList =
- FramebufferManager::GetXFBSource(xfbAddr, fbStride, fbHeight, &xfbCount);
- if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0))
- {
- Core::Callback_VideoCopiedToXFB(false);
- return;
- }
+ TargetRectangle sourceRc = ConvertEFBRectangle(rc);
+ sourceRc.left = 0;
+ sourceRc.right = xfb_texture->config.width;
+ sourceRc.top = xfb_texture->config.height;
+ sourceRc.bottom = 0;
ResetAPIState();
@@ -1366,7 +1356,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
std::swap(flipped_trc.top, flipped_trc.bottom);
// Copy the framebuffer to screen.
- DrawFrame(0, flipped_trc, rc, xfbAddr, xfbSourceList, xfbCount, fbWidth, fbStride, fbHeight);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width, xfb_texture->config.height);
// The FlushFrameDump call here is necessary even after frame dumping is stopped.
// If left out, screenshots are "one frame" behind, as an extra frame is dumped and buffered.
@@ -1380,7 +1371,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
if (use_offscreen_buffer)
{
// DumpFrameUsingFBO resets GL_FRAMEBUFFER, so change back to the window for drawing OSD.
- DumpFrameUsingFBO(rc, xfbAddr, xfbSourceList, xfbCount, fbWidth, fbStride, fbHeight, ticks);
+ DumpFrameUsingFBO(sourceRc, ticks);
}
else
{
@@ -1391,24 +1382,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
// Finish up the current frame, print some stats
- SetWindowSize(fbStride, fbHeight);
+ SetWindowSize(xfb_texture->config.width, xfb_texture->config.height);
GLInterface->Update(); // just updates the render window position and the backbuffer size
- bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB;
-
- if (FramebufferManagerBase::LastXfbWidth() != fbStride ||
- FramebufferManagerBase::LastXfbHeight() != fbHeight)
- {
- xfbchanged = true;
- unsigned int const last_w =
- (fbStride < 1 || fbStride > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbStride;
- unsigned int const last_h =
- (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight;
- FramebufferManagerBase::SetLastXfbWidth(last_w);
- FramebufferManagerBase::SetLastXfbHeight(last_h);
- }
-
bool window_resized = false;
int window_width = static_cast<int>(std::max(GLInterface->GetBackBufferWidth(), 1u));
int window_height = static_cast<int>(std::max(GLInterface->GetBackBufferHeight(), 1u));
@@ -1428,9 +1405,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
stencil_buffer_enabled != BoundingBox::NeedsStencilBuffer() ||
s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0);
- if (xfbchanged || window_resized || fb_needs_update)
+ if (window_resized || fb_needs_update)
{
- s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
UpdateDrawRectangle();
}
if (fb_needs_update)
@@ -1523,110 +1499,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
ClearEFBCache();
}
-void Renderer::DrawFrame(GLuint framebuffer, const TargetRectangle& target_rc,
- const EFBRectangle& source_rc, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height)
-{
- if (g_ActiveConfig.bUseXFB)
- {
- if (g_ActiveConfig.bUseRealXFB)
- DrawRealXFB(framebuffer, target_rc, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
- else
- DrawVirtualXFB(framebuffer, target_rc, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride,
- fb_height);
- }
- else
- {
- DrawEFB(framebuffer, target_rc, source_rc);
- }
-}
-
void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc,
- const EFBRectangle& source_rc)
+ const TargetRectangle& source_rc)
{
- TargetRectangle scaled_source_rc = ConvertEFBRectangle(source_rc);
-
// for msaa mode, we must resolve the efb content to non-msaa
GLuint tex = FramebufferManager::ResolveAndGetRenderTarget(source_rc);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- BlitScreen(scaled_source_rc, target_rc, tex, m_target_width, m_target_height);
-}
-
-void Renderer::DrawVirtualXFB(GLuint framebuffer, const TargetRectangle& target_rc, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height)
-{
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-
- for (u32 i = 0; i < xfb_count; ++i)
- {
- const XFBSource* xfbSource = static_cast<const XFBSource*>(xfb_sources[i]);
-
- TargetRectangle draw_rc;
- TargetRectangle source_rc;
- source_rc.left = xfbSource->sourceRc.left;
- source_rc.right = xfbSource->sourceRc.right;
- source_rc.top = xfbSource->sourceRc.top;
- source_rc.bottom = xfbSource->sourceRc.bottom;
-
- // use virtual xfb with offset
- int xfbHeight = xfbSource->srcHeight;
- int xfbWidth = xfbSource->srcWidth;
- int hOffset = (static_cast<s32>(xfbSource->srcAddr) - static_cast<s32>(xfb_addr)) /
- (static_cast<s32>(fb_stride) * 2);
-
- draw_rc.top = target_rc.top - hOffset * target_rc.GetHeight() / static_cast<s32>(fb_height);
- draw_rc.bottom =
- target_rc.top - (hOffset + xfbHeight) * target_rc.GetHeight() / static_cast<s32>(fb_height);
- draw_rc.left =
- target_rc.left +
- (target_rc.GetWidth() - xfbWidth * target_rc.GetWidth() / static_cast<s32>(fb_stride)) / 2;
- draw_rc.right =
- target_rc.left +
- (target_rc.GetWidth() + xfbWidth * target_rc.GetWidth() / static_cast<s32>(fb_stride)) / 2;
-
- // The following code disables auto stretch. Kept for reference.
- // scale draw area for a 1 to 1 pixel mapping with the draw target
- // float h_scale = static_cast<float>(fb_width) / static_cast<float>(target_rc.GetWidth());
- // float v_scale = static_cast<float>(fb_height) / static_cast<float>(target_rc.GetHeight());
- // draw_rc.top *= v_scale;
- // draw_rc.bottom *= v_scale;
- // draw_rc.left *= h_scale;
- // draw_rc.right *= h_scale;
-
- source_rc.right -= Renderer::EFBToScaledX(fb_stride - fb_width);
-
- BlitScreen(source_rc, draw_rc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight);
- }
-}
-
-void Renderer::DrawRealXFB(GLuint framebuffer, const TargetRectangle& target_rc,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height)
-{
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-
- for (u32 i = 0; i < xfb_count; ++i)
- {
- const XFBSource* xfbSource = static_cast<const XFBSource*>(xfb_sources[i]);
-
- TargetRectangle source_rc;
- source_rc.left = xfbSource->sourceRc.left;
- source_rc.right = xfbSource->sourceRc.right;
- source_rc.top = xfbSource->sourceRc.top;
- source_rc.bottom = xfbSource->sourceRc.bottom;
-
- source_rc.right -= fb_stride - fb_width;
-
- // RealXFB doesn't call ConvertEFBRectangle for sourceRc, therefore it is still assuming a top-
- // left origin. The top offset is always zero (see FramebufferManagerBase::GetRealXFBSource).
- source_rc.top = source_rc.bottom;
- source_rc.bottom = 0;
-
- TargetRectangle draw_rc = target_rc;
- BlitScreen(source_rc, draw_rc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight);
- }
+ BlitScreen(source_rc, target_rc, tex, m_target_width, m_target_height);
}
void Renderer::FlushFrameDump()
@@ -1683,9 +1562,7 @@ void Renderer::DumpFrame(const TargetRectangle& flipped_trc, u64 ticks)
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
-void Renderer::DumpFrameUsingFBO(const EFBRectangle& source_rc, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count,
- u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks)
+void Renderer::DumpFrameUsingFBO(const TargetRectangle& source_rc, u64 ticks)
{
// This needs to be converted to the GL bottom-up window coordinate system.
TargetRectangle render_rc = CalculateFrameDumpDrawRectangle();
@@ -1705,8 +1582,7 @@ void Renderer::DumpFrameUsingFBO(const EFBRectangle& source_rc, u32 xfb_addr,
// Render the frame into the frame dump render texture. Disable alpha writes in case the
// post-processing shader writes a non-1.0 value.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
- DrawFrame(m_frame_dump_render_framebuffer, render_rc, source_rc, xfb_addr, xfb_sources, xfb_count,
- fb_width, fb_stride, fb_height);
+ DrawEFB(m_frame_dump_render_framebuffer, render_rc, source_rc);
// Copy frame to output buffer. This assumes that GL_FRAMEBUFFER has been set.
DumpFrame(render_rc, ticks);
diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h
index 8efea70bec..a130e9c770 100644
--- a/Source/Core/VideoBackends/OGL/Render.h
+++ b/Source/Core/VideoBackends/OGL/Render.h
@@ -98,8 +98,7 @@ public:
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
- void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
- u64 ticks, float Gamma) override;
+ void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override;
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override;
@@ -112,27 +111,14 @@ private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc,
const TargetRectangle& targetPixelRc, const void* data);
- // Draw either the EFB, or specified XFB sources to the currently-bound framebuffer.
- void DrawFrame(GLuint framebuffer, const TargetRectangle& target_rc,
- const EFBRectangle& source_rc, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height);
- void DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, const EFBRectangle& source_rc);
- void DrawVirtualXFB(GLuint framebuffer, const TargetRectangle& target_rc, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height);
- void DrawRealXFB(GLuint framebuffer, const TargetRectangle& target_rc,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height);
+ void DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, const TargetRectangle& source_rc);
void BlitScreen(TargetRectangle src, TargetRectangle dst, GLuint src_texture, int src_width,
int src_height);
void FlushFrameDump();
void DumpFrame(const TargetRectangle& flipped_trc, u64 ticks);
- void DumpFrameUsingFBO(const EFBRectangle& source_rc, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height, u64 ticks);
+ void DumpFrameUsingFBO(const TargetRectangle& source_rc, u64 ticks);
// Frame dumping framebuffer, we render to this, then read it back
void PrepareFrameDumpRenderTexture(u32 width, u32 height);
diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp
index 4b3a7a5daf..f5ccbcd64c 100644
--- a/Source/Core/VideoBackends/OGL/main.cpp
+++ b/Source/Core/VideoBackends/OGL/main.cpp
@@ -91,6 +91,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsReversedDepthRange = true;
g_Config.backend_info.bSupportsMultithreading = false;
g_Config.backend_info.bSupportsInternalResolutionFrameDumps = true;
+ g_Config.backend_info.bSupportsCopyToVram = true;
// TODO: There is a bug here, if texel buffers are not supported the graphics options
// will show the option when it is not supported. The only way around this would be
diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp
index 9f6af90c0d..411839c852 100644
--- a/Source/Core/VideoBackends/Software/EfbInterface.cpp
+++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp
@@ -520,15 +520,6 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe
// Scanline buffer, leave room for borders
yuv444 scanline[EFB_WIDTH + 2];
- // our internal yuv444 type is not normalized, so black is {0, 0, 0} instead of {16, 128, 128}
- yuv444 black;
- black.Y = 0;
- black.U = 0;
- black.V = 0;
-
- scanline[0] = black; // black border at start
- scanline[right + 1] = black; // black border at end
-
for (u16 y = sourceRc.top; y < sourceRc.bottom; y++)
{
// Get a scanline of YUV pixels in 4:4:4 format
@@ -538,6 +529,10 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe
scanline[i] = GetColorYUV(x, y);
}
+ // Flipper clamps the border colors
+ scanline[0] = scanline[1];
+ scanline[right + 1] = scanline[right];
+
// And Downsample them to 4:2:2
for (int i = 1, x = left; x < right; i += 2, x += 2)
{
@@ -562,26 +557,7 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe
// main memory or doing a yuyv conversion
void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)
{
- if (fbWidth * fbHeight > MAX_XFB_WIDTH * MAX_XFB_HEIGHT)
- {
- ERROR_LOG(VIDEO, "Framebuffer is too large: %ix%i", fbWidth, fbHeight);
- return;
- }
-
- size_t textureAddress = 0;
- const int left = sourceRc.left;
- const int right = sourceRc.right;
-
- for (u16 y = sourceRc.top; y < sourceRc.bottom; y++)
- {
- for (u16 x = left; x < right; x++)
- {
- const u32 color = Common::swap32(GetColor(x, y) | 0xFF);
-
- std::memcpy(&texture[textureAddress], &color, sizeof(u32));
- textureAddress += sizeof(u32);
- }
- }
+ // TODO: Upload directly to texture cache.
}
bool ZCompare(u16 x, u16 y, u32 z)
diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp
index 9d42ff5790..52b2fb02cd 100644
--- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp
+++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp
@@ -9,6 +9,7 @@
#include "Common/Logging/Log.h"
#include "VideoBackends/Software/SWOGLWindow.h"
+#include "VideoCommon/AbstractTexture.h"
std::unique_ptr<SWOGLWindow> SWOGLWindow::s_instance;
@@ -53,9 +54,9 @@ void SWOGLWindow::Prepare()
std::string frag_shader = "in vec2 TexCoord;\n"
"out vec4 ColorOut;\n"
- "uniform sampler2D Texture;\n"
+ "uniform sampler2DArray samp;\n"
"void main() {\n"
- " ColorOut = texture(Texture, TexCoord);\n"
+ " ColorOut = texture(samp, vec3(TexCoord, 0.0));\n"
"}\n";
std::string vertex_shader = "out vec2 TexCoord;\n"
@@ -74,12 +75,9 @@ void SWOGLWindow::Prepare()
glUseProgram(m_image_program);
- glUniform1i(glGetUniformLocation(m_image_program, "Texture"), 0);
+ glUniform1i(glGetUniformLocation(m_image_program, "samp"), 0);
- glGenTextures(1, &m_image_texture);
- glBindTexture(GL_TEXTURE_2D, m_image_texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
glGenVertexArrays(1, &m_image_vao);
}
@@ -89,23 +87,19 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color)
m_text.push_back({text, x, y, color});
}
-void SWOGLWindow::ShowImage(const u8* data, int stride, int width, int height, float aspect)
+void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect)
{
- GLInterface->MakeCurrent();
- GLInterface->Update();
- Prepare();
+ GLInterface->Update(); // just updates the render window position and the backbuffer size
GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth();
GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight();
glViewport(0, 0, glWidth, glHeight);
- glBindTexture(GL_TEXTURE_2D, m_image_texture);
+ image->Bind(0);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / 4);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, data);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glUseProgram(m_image_program);
@@ -119,7 +113,6 @@ void SWOGLWindow::ShowImage(const u8* data, int stride, int width, int height, f
m_text.clear();
GLInterface->Swap();
- GLInterface->ClearCurrent();
}
int SWOGLWindow::PeekMessages()
diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h
index 110642b3f8..3b5d623846 100644
--- a/Source/Core/VideoBackends/Software/SWOGLWindow.h
+++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h
@@ -10,17 +10,20 @@
#include "Common/CommonTypes.h"
+class AbstractTexture;
+
class SWOGLWindow
{
public:
static void Init(void* window_handle);
static void Shutdown();
+ void Prepare();
// Will be printed on the *next* image
void PrintText(const std::string& text, int x, int y, u32 color);
// Image to show, will be swapped immediately
- void ShowImage(const u8* data, int stride, int width, int height, float aspect);
+ void ShowImage(AbstractTexture* image, float aspect);
int PeekMessages();
@@ -28,7 +31,6 @@ public:
private:
SWOGLWindow() {}
- void Prepare();
struct TextData
{
@@ -40,5 +42,5 @@ private:
bool m_init{false};
- u32 m_image_program, m_image_texture, m_image_vao;
+ u32 m_image_program, m_image_vao;
};
diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp
index dc378cbede..9074a429b9 100644
--- a/Source/Core/VideoBackends/Software/SWRenderer.cpp
+++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp
@@ -23,26 +23,13 @@
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
-static u8* s_xfbColorTexture[2];
-static int s_currentColorTexture = 0;
-
SWRenderer::SWRenderer()
: ::Renderer(static_cast<int>(MAX_XFB_WIDTH), static_cast<int>(MAX_XFB_HEIGHT))
{
}
-SWRenderer::~SWRenderer()
-{
- delete[] s_xfbColorTexture[0];
- delete[] s_xfbColorTexture[1];
-}
-
void SWRenderer::Init()
{
- s_xfbColorTexture[0] = new u8[MAX_XFB_WIDTH * MAX_XFB_HEIGHT * 4];
- s_xfbColorTexture[1] = new u8[MAX_XFB_WIDTH * MAX_XFB_HEIGHT * 4];
-
- s_currentColorTexture = 0;
}
void SWRenderer::Shutdown()
@@ -55,80 +42,16 @@ void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 colo
SWOGLWindow::s_instance->PrintText(pstr, left, top, color);
}
-u8* SWRenderer::GetNextColorTexture()
-{
- return s_xfbColorTexture[!s_currentColorTexture];
-}
-
-u8* SWRenderer::GetCurrentColorTexture()
-{
- return s_xfbColorTexture[s_currentColorTexture];
-}
-
-void SWRenderer::SwapColorTexture()
-{
- s_currentColorTexture = !s_currentColorTexture;
-}
-
-void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed* xfb, u32 fbWidth, u32 fbHeight)
-{
- if (fbWidth * fbHeight > MAX_XFB_WIDTH * MAX_XFB_HEIGHT)
- {
- ERROR_LOG(VIDEO, "Framebuffer is too large: %ix%i", fbWidth, fbHeight);
- return;
- }
-
- u32 offset = 0;
- u8* TexturePointer = GetNextColorTexture();
-
- for (u16 y = 0; y < fbHeight; y++)
- {
- for (u16 x = 0; x < fbWidth; x += 2)
- {
- // We do this one color sample (aka 2 RGB pixles) at a time
- int Y1 = xfb[x].Y - 16;
- int Y2 = xfb[x + 1].Y - 16;
- int U = int(xfb[x].UV) - 128;
- int V = int(xfb[x + 1].UV) - 128;
-
- // We do the inverse BT.601 conversion for YCbCr to RGB
- // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion
- TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255);
- TexturePointer[offset++] =
- MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255);
- TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255);
- TexturePointer[offset++] = 255;
-
- TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255);
- TexturePointer[offset++] =
- MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255);
- TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255);
- TexturePointer[offset++] = 255;
- }
- xfb += fbWidth;
- }
- SwapColorTexture();
-}
-
// Called on the GPU thread
-void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
- const EFBRectangle& rc, u64 ticks, float Gamma)
+void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma)
{
- if (g_ActiveConfig.bUseXFB)
- {
- EfbInterface::yuv422_packed* xfb = (EfbInterface::yuv422_packed*)Memory::GetPointer(xfbAddr);
- UpdateColorTexture(xfb, fbWidth, fbHeight);
- }
- else
- {
- EfbInterface::BypassXFB(GetCurrentColorTexture(), fbWidth, fbHeight, rc, Gamma);
- }
+ SWOGLWindow::s_instance->ShowImage(texture, 1.0);
// Save screenshot
if (IsFrameDumping())
{
AVIDump::Frame state = AVIDump::FetchState(ticks);
- DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, state);
+ //DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, state);
FinishFrameData();
}
@@ -136,15 +59,9 @@ void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
DrawDebugText();
- SWOGLWindow::s_instance->ShowImage(GetCurrentColorTexture(), fbWidth * 4, fbWidth, fbHeight, 1.0);
+ SWOGLWindow::s_instance->ShowImage(texture, 1.0);
UpdateActiveConfig();
-
- // virtual XFB is not supported
- if (g_ActiveConfig.bUseXFB)
- {
- Config::SetCurrent(Config::GFX_USE_REAL_XFB, true);
- }
}
u32 SWRenderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
diff --git a/Source/Core/VideoBackends/Software/SWRenderer.h b/Source/Core/VideoBackends/Software/SWRenderer.h
index b19b9841fd..e30e490bd7 100644
--- a/Source/Core/VideoBackends/Software/SWRenderer.h
+++ b/Source/Core/VideoBackends/Software/SWRenderer.h
@@ -14,16 +14,10 @@ class SWRenderer : public Renderer
{
public:
SWRenderer();
- ~SWRenderer() override;
static void Init();
static void Shutdown();
- static u8* GetNextColorTexture();
- static u8* GetCurrentColorTexture();
- void SwapColorTexture();
- void UpdateColorTexture(EfbInterface::yuv422_packed* xfb, u32 fbWidth, u32 fbHeight);
-
void RenderText(const std::string& pstr, int left, int top, u32 color) override;
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
@@ -32,8 +26,7 @@ public:
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
- void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
- u64 ticks, float Gamma) override;
+ void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override;
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
u32 color, u32 z) override;
diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp
index dff26e6d86..26a649b010 100644
--- a/Source/Core/VideoBackends/Software/SWmain.cpp
+++ b/Source/Core/VideoBackends/Software/SWmain.cpp
@@ -8,16 +8,17 @@
#include <utility>
#include "Common/CommonTypes.h"
+#include "Common/GL/GLInterfaceBase.h"
#include "VideoBackends/Software/Clipper.h"
#include "VideoBackends/Software/DebugUtil.h"
-#include "VideoBackends/Software/EfbCopy.h"
#include "VideoBackends/Software/EfbInterface.h"
#include "VideoBackends/Software/Rasterizer.h"
#include "VideoBackends/Software/SWOGLWindow.h"
#include "VideoBackends/Software/SWRenderer.h"
#include "VideoBackends/Software/SWTexture.h"
#include "VideoBackends/Software/SWVertexLoader.h"
+#include "VideoBackends/Software/TextureCache.h"
#include "VideoBackends/Software/VideoBackend.h"
#include "VideoCommon/FramebufferManagerBase.h"
@@ -46,58 +47,6 @@ public:
bool IsFlushed() const override { return true; }
};
-class TextureCache : public TextureCacheBase
-{
-public:
- bool CompileShaders() override { return true; }
- void DeleteShaders() override {}
- void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette,
- TLUTFormat format) override
- {
- }
- void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
- u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
- bool scale_by_half) override
- {
- EfbCopy::CopyEfb();
- }
-
-private:
- std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override
- {
- return std::make_unique<SWTexture>(config);
- }
-
- void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
- bool scale_by_half, unsigned int cbuf_id, const float* colmat) override
- {
- EfbCopy::CopyEfb();
- }
-};
-
-class XFBSource : public XFBSourceBase
-{
- void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override {}
- void CopyEFB(float Gamma) override {}
-};
-
-class FramebufferManager : public FramebufferManagerBase
-{
- std::unique_ptr<XFBSourceBase> CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers) override
- {
- return std::make_unique<XFBSource>();
- }
-
- std::pair<u32, u32> GetTargetSize() const override { return std::make_pair(0, 0); }
- void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,
- float Gamma = 1.0f) override
- {
- EfbCopy::CopyEfb();
- }
-};
-
std::string VideoSoftware::GetName() const
{
return "Software Renderer";
@@ -123,6 +72,7 @@ void VideoSoftware::InitBackendInfo()
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
g_Config.backend_info.bSupportsST3CTextures = false;
g_Config.backend_info.bSupportsBPTCTextures = false;
+ g_Config.backend_info.bSupportsCopyToVram = false;
// aamodes
g_Config.backend_info.AAModes = {1};
@@ -169,12 +119,14 @@ void VideoSoftware::Video_Cleanup()
// This is called after Video_Initialize() from the Core
void VideoSoftware::Video_Prepare()
{
+ GLInterface->MakeCurrent();
+ SWOGLWindow::s_instance->Prepare();
+
g_renderer = std::make_unique<SWRenderer>();
g_vertex_manager = std::make_unique<SWVertexLoader>();
g_perf_query = std::make_unique<PerfQuery>();
g_texture_cache = std::make_unique<TextureCache>();
SWRenderer::Init();
- g_framebuffer_manager = std::make_unique<FramebufferManager>();
}
unsigned int VideoSoftware::PeekMessages()
diff --git a/Source/Core/VideoBackends/Software/Software.vcxproj b/Source/Core/VideoBackends/Software/Software.vcxproj
index bf13233d67..36d833ba2c 100644
--- a/Source/Core/VideoBackends/Software/Software.vcxproj
+++ b/Source/Core/VideoBackends/Software/Software.vcxproj
@@ -65,6 +65,7 @@
<ClInclude Include="SWTexture.h" />
<ClInclude Include="SWVertexLoader.h" />
<ClInclude Include="Tev.h" />
+ <ClInclude Include="TextureCache.h" />
<ClInclude Include="TextureEncoder.h" />
<ClInclude Include="TextureSampler.h" />
<ClInclude Include="TransformUnit.h" />
diff --git a/Source/Core/VideoBackends/Software/TextureCache.h b/Source/Core/VideoBackends/Software/TextureCache.h
new file mode 100644
index 0000000000..82c2ce9f55
--- /dev/null
+++ b/Source/Core/VideoBackends/Software/TextureCache.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <memory>
+
+#include "VideoBackends/Software/EfbCopy.h"
+#include "VideoBackends/Software/SWTexture.h"
+#include "VideoCommon/TextureCacheBase.h"
+
+namespace SW
+{
+
+class TextureCache : public TextureCacheBase
+{
+public:
+ bool CompileShaders() override { return true; }
+ void DeleteShaders() override {}
+ void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette,
+ TLUTFormat format) override
+ {
+ }
+ void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
+ u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
+ bool scale_by_half) override
+ {
+ EfbCopy::CopyEfb();
+ }
+
+private:
+ std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override
+ {
+ return std::make_unique<SWTexture>(config);
+ }
+
+ void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
+ bool scale_by_half, unsigned int cbuf_id, const float* colmat) override
+ {
+ EfbCopy::CopyEfb();
+ }
+};
+
+} // namespace SW
diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
index 53351e0325..c23c19b544 100644
--- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
@@ -89,11 +89,6 @@ MultisamplingState FramebufferManager::GetEFBMultisamplingState() const
return ms;
}
-std::pair<u32, u32> FramebufferManager::GetTargetSize() const
-{
- return std::make_pair(GetEFBWidth(), GetEFBHeight());
-}
-
bool FramebufferManager::Initialize()
{
if (!CreateEFBRenderPass())
@@ -1450,15 +1445,6 @@ VKTexture* XFBSource::GetTexture() const
return static_cast<VKTexture*>(m_texture.get());
}
-void XFBSource::DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height)
-{
- // Guest memory -> GPU EFB Textures
- const u8* src_ptr = Memory::GetPointer(xfb_addr);
- _assert_(src_ptr);
- TextureCache::GetInstance()->GetTextureConverter()->DecodeYUYVTextureFromMemory(
- static_cast<VKTexture*>(m_texture.get()), src_ptr, fb_width, fb_width * 2, fb_height);
-}
-
void XFBSource::CopyEFB(float gamma)
{
// Pending/batched EFB pokes should be included in the copied image.
diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h
index ca7065c3bb..3f2a251662 100644
--- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h
+++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h
@@ -43,7 +43,6 @@ public:
u32 GetEFBLayers() const;
VkSampleCountFlagBits GetEFBSamples() const;
MultisamplingState GetEFBMultisamplingState() const;
- std::pair<u32, u32> GetTargetSize() const override;
std::unique_ptr<XFBSourceBase> CreateXFBSource(unsigned int target_width,
unsigned int target_height,
@@ -178,8 +177,6 @@ public:
~XFBSource();
VKTexture* GetTexture() const;
- // Guest -> GPU EFB Textures
- void DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) override;
// Used for virtual XFB
void CopyEFB(float gamma) override;
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index 3a4907b88c..be442476ad 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -41,6 +41,7 @@
#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VideoBackendBase.h"
+#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/XFMemory.h"
@@ -485,27 +486,19 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
BindEFBToStateTracker();
}
-void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
- const EFBRectangle& rc, u64 ticks, float gamma)
+void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma)
{
// Pending/batched EFB pokes should be included in the final image.
FramebufferManager::GetInstance()->FlushEFBPokes();
// Check that we actually have an image to render in XFB-on modes.
- if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
+ if (!m_xfb_written)
{
Core::Callback_VideoCopiedToXFB(false);
- return;
- }
- u32 xfb_count = 0;
- const XFBSourceBase* const* xfb_sources =
- FramebufferManager::GetXFBSource(xfb_addr, fb_stride, fb_height, &xfb_count);
- if (g_ActiveConfig.VirtualXFBEnabled() && (!xfb_sources || xfb_count == 0))
- {
- Core::Callback_VideoCopiedToXFB(false);
- return;
}
+ auto* xfb_texture = static_cast<VKTexture*>(texture);
+
// End the current render pass.
StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->OnEndFrame();
@@ -514,14 +507,6 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
// are determined by guest state. Currently, the only way to catch these is to update every frame.
UpdateDrawRectangle();
- // Scale the source rectangle to the internal resolution when XFB is disabled.
- TargetRectangle scaled_efb_rect = Renderer::ConvertEFBRectangle(rc);
-
- // If MSAA is enabled, and we're not using XFB, we need to resolve the EFB framebuffer before
- // rendering the final image to the screen, or dumping the frame. This is because we can't resolve
- // an image within a render pass, which will have already started by the time it is used.
- TransitionBuffersForSwap(scaled_efb_rect, xfb_sources, xfb_count);
-
// Render the frame dump image if enabled.
if (IsFrameDumping())
{
@@ -529,8 +514,8 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
if (!m_frame_dumping_active)
StartFrameDumping();
- DrawFrameDump(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height,
- ticks);
+ /* DrawFrameDump(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height,
+ ticks);*/
}
else
{
@@ -547,7 +532,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
// Draw to the screen if we have a swap chain.
if (m_swap_chain)
{
- DrawScreen(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
+ DrawScreen(xfb_texture);
// Submit the current command buffer, signaling rendering finished semaphore when it's done
// Because this final command buffer is rendering to the swap chain, we need to wait for
@@ -581,15 +566,12 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
// Handle host window resizes.
CheckForSurfaceChange();
- // Handle output size changes from the guest.
- // There is a downside to doing this here is that if the game changes its XFB source area,
- // the changes will be delayed by one frame. For the moment it has to be done here because
- // this can cause a target size change, which would result in a black frame if done earlier.
- CheckForTargetResize(fb_width, fb_stride, fb_height);
+ if (CalculateTargetSize())
+ ResizeEFBTextures();
// Update the window size based on the frame that was just rendered.
// Due to depending on guest state, we need to call this every frame.
- SetWindowSize(static_cast<int>(fb_stride), static_cast<int>(fb_height));
+ SetWindowSize(xfb_texture->config.width, xfb_texture->config.height);
// Clean up stale textures.
TextureCache::GetInstance()->Cleanup(frameCount);
@@ -714,9 +696,7 @@ void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& targ
}
}
-void Renderer::DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height)
+void Renderer::DrawScreen(VKTexture* xfb_texture)
{
VkResult res;
if (!g_command_buffer_mgr->CheckLastPresentFail())
@@ -767,9 +747,9 @@ void Renderer::DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &info,
VK_SUBPASS_CONTENTS_INLINE);
- // Draw guest buffers (EFB or XFB)
- DrawFrame(m_swap_chain->GetRenderPass(), GetTargetRectangle(), scaled_efb_rect, xfb_addr,
- xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
+ // Draw
+ TargetRectangle source_rc = xfb_texture->config.Rect();
+ BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), source_rc, xfb_texture->GetRawTexIdentifier());
// Draw OSD
Util::SetViewportAndScissor(g_command_buffer_mgr->GetCurrentCommandBuffer(), 0, 0,
@@ -1055,7 +1035,7 @@ void Renderer::DestroyFrameDumpResources()
void Renderer::CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height)
{
- if (FramebufferManagerBase::LastXfbWidth() == fb_stride &&
+ /*if (FramebufferManagerBase::LastXfbWidth() == fb_stride &&
FramebufferManagerBase::LastXfbHeight() == fb_height)
{
return;
@@ -1068,7 +1048,7 @@ void Renderer::CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height)
// Changing the XFB source area may alter the target size.
if (CalculateTargetSize())
- ResizeEFBTextures();
+ ResizeEFBTextures();*/
}
void Renderer::CheckForSurfaceChange()
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h
index 5a367f2bcd..b9d746582c 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.h
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.h
@@ -23,6 +23,7 @@ class SwapChain;
class StagingTexture2D;
class Texture2D;
class RasterFont;
+class VKTexture;
class Renderer : public ::Renderer
{
@@ -43,8 +44,7 @@ public:
void BBoxWrite(int index, u16 value) override;
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
- void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
- u64 ticks, float gamma) override;
+ void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override;
void ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable,
u32 color, u32 z) override;
@@ -106,9 +106,7 @@ private:
u32 fb_stride, u32 fb_height);
// Draw the frame, as well as the OSD to the swap chain.
- void DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height);
+ void DrawScreen(VKTexture* xfb_texture);
// Draw the frame only to the screenshot buffer.
bool DrawFrameDump(const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
index e2f44b73be..3edd507b23 100644
--- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
+++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
@@ -246,6 +246,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config)
config->backend_info.bSupportsST3CTextures = false; // Dependent on features.
config->backend_info.bSupportsBPTCTextures = false; // Dependent on features.
config->backend_info.bSupportsReversedDepthRange = false; // No support yet due to driver bugs.
+ config->backend_info.bSupportsCopyToVram = true; // Assumed support.
}
void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list)