diff --git a/Source/Core/VideoBackends/D3D/CMakeLists.txt b/Source/Core/VideoBackends/D3D/CMakeLists.txt
index 953f8737e5..3811ce6a0d 100644
--- a/Source/Core/VideoBackends/D3D/CMakeLists.txt
+++ b/Source/Core/VideoBackends/D3D/CMakeLists.txt
@@ -38,8 +38,6 @@ set(SRCS
VertexShaderCache.cpp
VertexShaderCache.h
VideoBackend.h
- XFBEncoder.cpp
- XFBEncoder.h
)
set(LIBS
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj
index ff63898039..50c8ea0fcd 100644
--- a/Source/Core/VideoBackends/D3D/D3D.vcxproj
+++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj
@@ -55,7 +55,6 @@
-
@@ -76,7 +75,6 @@
-
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
index e3138ff28f..f544ae67db 100644
--- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
+++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
@@ -57,9 +57,6 @@
Render
-
- Render
-
Render
@@ -114,9 +111,6 @@
Render
-
- Render
-
Render
diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
index 3ecd3119f8..4bd5a3fd60 100644
--- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
@@ -16,12 +16,10 @@
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/Render.h"
#include "VideoBackends/D3D/VertexShaderCache.h"
-#include "VideoBackends/D3D/XFBEncoder.h"
#include "VideoCommon/VideoConfig.h"
namespace DX11
{
-static XFBEncoder s_xfbEncoder;
static bool s_integer_efb_render_target = false;
FramebufferManager::Efb FramebufferManager::m_efb;
@@ -282,15 +280,11 @@ FramebufferManager::FramebufferManager(int target_width, int target_height)
m_efb.resolved_color_tex = nullptr;
m_efb.resolved_depth_tex = nullptr;
}
-
- s_xfbEncoder.Init();
s_integer_efb_render_target = false;
}
FramebufferManager::~FramebufferManager()
{
- s_xfbEncoder.Shutdown();
-
SAFE_RELEASE(m_efb.color_tex);
SAFE_RELEASE(m_efb.color_int_rtv);
SAFE_RELEASE(m_efb.color_temp_tex);
@@ -304,52 +298,4 @@ FramebufferManager::~FramebufferManager()
SAFE_RELEASE(m_efb.resolved_depth_tex);
}
-void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight,
- const EFBRectangle& sourceRc, float Gamma)
-{
- u8* dst = Memory::GetPointer(xfbAddr);
-
- // The destination stride can differ from the copy region width, in which case the pixels
- // outside the copy region should not be written to.
- s_xfbEncoder.Encode(dst, static_cast(sourceRc.GetWidth()), fbHeight, sourceRc, Gamma);
-}
-
-std::unique_ptr FramebufferManager::CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers)
-{
- return std::make_unique(
- D3DTexture2D::Create(target_width, target_height,
- (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
- D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, layers),
- layers);
-}
-
-std::pair FramebufferManager::GetTargetSize() const
-{
- return std::make_pair(m_target_width, m_target_height);
-}
-
-void XFBSource::CopyEFB(float Gamma)
-{
- g_renderer->ResetAPIState(); // reset any game specific settings
-
- // 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::SetPointCopySampler();
-
- D3D::drawShadedTexQuad(
- FramebufferManager::GetEFBColorTexture()->GetSRV(), &rect, g_renderer->GetTargetWidth(),
- g_renderer->GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(true),
- VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
- GeometryShaderCache::GetCopyGeometryShader(), Gamma);
-
- FramebufferManager::BindEFBRenderTarget();
- g_renderer->RestoreAPIState();
-}
-
} // namespace DX11
diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.h b/Source/Core/VideoBackends/D3D/FramebufferManager.h
index 96e76118ee..f8767a2c5d 100644
--- a/Source/Core/VideoBackends/D3D/FramebufferManager.h
+++ b/Source/Core/VideoBackends/D3D/FramebufferManager.h
@@ -46,16 +46,6 @@ namespace DX11
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize.
-struct XFBSource : public XFBSourceBase
-{
- XFBSource(D3DTexture2D* _tex, int slices) : tex(_tex), m_slices(slices) {}
- ~XFBSource() { tex->Release(); }
- void CopyEFB(float Gamma) override;
-
- D3DTexture2D* const tex;
- const int m_slices;
-};
-
class FramebufferManager : public FramebufferManagerBase
{
public:
@@ -79,14 +69,6 @@ public:
static void BindEFBRenderTarget(bool bind_depth = true);
private:
- std::unique_ptr CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers) override;
- std::pair GetTargetSize() const override;
-
- void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,
- float Gamma) override;
-
static struct Efb
{
D3DTexture2D* color_tex;
diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp
index e49dc4053a..18aec69490 100644
--- a/Source/Core/VideoBackends/D3D/Render.cpp
+++ b/Source/Core/VideoBackends/D3D/Render.cpp
@@ -610,11 +610,6 @@ void Renderer::SetBlendingState(const BlendingState& state)
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma)
{
- if (!m_xfb_written)
- {
- Core::Callback_VideoCopiedToXFB(false);
- }
-
ResetAPIState();
// Prepare to copy the XFBs to our backbuffer
diff --git a/Source/Core/VideoBackends/D3D/XFBEncoder.cpp b/Source/Core/VideoBackends/D3D/XFBEncoder.cpp
deleted file mode 100644
index 696c5c35e0..0000000000
--- a/Source/Core/VideoBackends/D3D/XFBEncoder.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-// Copyright 2011 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include "VideoBackends/D3D/XFBEncoder.h"
-#include "Common/CommonTypes.h"
-#include "Common/Logging/Log.h"
-#include "Common/MsgHandler.h"
-#include "VideoBackends/D3D/D3DBase.h"
-#include "VideoBackends/D3D/D3DBlob.h"
-#include "VideoBackends/D3D/D3DShader.h"
-#include "VideoBackends/D3D/D3DState.h"
-#include "VideoBackends/D3D/FramebufferManager.h"
-#include "VideoBackends/D3D/Render.h"
-
-namespace DX11
-{
-union XFBEncodeParams
-{
- struct
- {
- FLOAT Width; // Width and height of encoded XFB in luma pixels
- FLOAT Height;
- FLOAT TexLeft; // Normalized tex coordinates of XFB source area in EFB texture
- FLOAT TexTop;
- FLOAT TexRight;
- FLOAT TexBottom;
- FLOAT Gamma;
- };
- // Constant buffers must be a multiple of 16 bytes in size
- u8 pad[32]; // Pad to the next multiple of 16
-};
-
-static const char XFB_ENCODE_VS[] =
- "// dolphin-emu XFB encoder vertex shader\n"
-
- "cbuffer cbParams : register(b0)\n"
- "{\n"
- "struct\n" // Should match XFBEncodeParams above
- "{\n"
- "float Width;\n"
- "float Height;\n"
- "float TexLeft;\n"
- "float TexTop;\n"
- "float TexRight;\n"
- "float TexBottom;\n"
- "float Gamma;\n"
- "} Params;\n"
- "}\n"
-
- "struct Output\n"
- "{\n"
- "float4 Pos : SV_Position;\n"
- "float2 Coord : ENCODECOORD;\n"
- "};\n"
-
- "Output main(in float2 Pos : POSITION)\n"
- "{\n"
- "Output result;\n"
- "result.Pos = float4(2*Pos.x-1, -2*Pos.y+1, 0, 1);\n"
- "result.Coord = Pos * float2(floor(Params.Width/2), Params.Height);\n"
- "return result;\n"
- "}\n";
-
-static const char XFB_ENCODE_PS[] =
- "// dolphin-emu XFB encoder pixel shader\n"
-
- "cbuffer cbParams : register(b0)\n"
- "{\n"
- "struct\n" // Should match XFBEncodeParams above
- "{\n"
- "float Width;\n"
- "float Height;\n"
- "float TexLeft;\n"
- "float TexTop;\n"
- "float TexRight;\n"
- "float TexBottom;\n"
- "float Gamma;\n"
- "} Params;\n"
- "}\n"
-
- "Texture2DArray EFBTexture : register(t0);\n"
- "sampler EFBSampler : register(s0);\n"
-
- // GameCube/Wii uses the BT.601 standard algorithm for converting to YCbCr; see
- //
- "static const float3x4 RGB_TO_YCBCR = float3x4(\n"
- "0.257, 0.504, 0.098, 16.0/255.0,\n"
- "-0.148, -0.291, 0.439, 128.0/255.0,\n"
- "0.439, -0.368, -0.071, 128.0/255.0\n"
- ");\n"
-
- "float3 SampleEFB(float2 coord)\n"
- "{\n"
- "float2 texCoord = lerp(float2(Params.TexLeft,Params.TexTop), "
- "float2(Params.TexRight,Params.TexBottom), coord / float2(Params.Width,Params.Height));\n"
- "return EFBTexture.Sample(EFBSampler, float3(texCoord, 0.0)).rgb;\n"
- "}\n"
-
- "void main(out float4 ocol0 : SV_Target, in float4 Pos : SV_Position, in float2 Coord : "
- "ENCODECOORD)\n"
- "{\n"
- // Multiplying X by 2, moves pixel centers from (x+0.5) to (2x+1) instead of (2x+0.5), so
- // subtract 0.5 to compensate
- "float2 baseCoord = Coord * float2(2,1) - float2(0.5,0);\n"
- // FIXME: Shall we apply gamma here, or apply it below to the Y components?
- // Be careful if you apply it to Y! The Y components are in the range (16..235) / 255.
- "float3 sampleL = pow(abs(SampleEFB(baseCoord+float2(-1,0))), Params.Gamma);\n" // Left
- "float3 sampleM = pow(abs(SampleEFB(baseCoord)), Params.Gamma);\n" // Middle
- "float3 sampleR = pow(abs(SampleEFB(baseCoord+float2(1,0))), Params.Gamma);\n" // Right
-
- "float3 yuvL = mul(RGB_TO_YCBCR, float4(sampleL,1));\n"
- "float3 yuvM = mul(RGB_TO_YCBCR, float4(sampleM,1));\n"
- "float3 yuvR = mul(RGB_TO_YCBCR, float4(sampleR,1));\n"
-
- // The Y components correspond to two EFB pixels, while the U and V are
- // made from a blend of three EFB pixels.
- "float y0 = yuvM.r;\n"
- "float y1 = yuvR.r;\n"
- "float u0 = 0.25*yuvL.g + 0.5*yuvM.g + 0.25*yuvR.g;\n"
- "float v0 = 0.25*yuvL.b + 0.5*yuvM.b + 0.25*yuvR.b;\n"
-
- "ocol0 = float4(y0, u0, y1, v0);\n"
- "}\n";
-
-static const D3D11_INPUT_ELEMENT_DESC QUAD_LAYOUT_DESC[] = {
- {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}};
-
-static const struct QuadVertex
-{
- float posX;
- float posY;
-} QUAD_VERTS[4] = {{0, 0}, {1, 0}, {0, 1}, {1, 1}};
-
-XFBEncoder::XFBEncoder()
- : m_out(nullptr), m_outRTV(nullptr), m_outStage(nullptr), m_encodeParams(nullptr),
- m_quad(nullptr), m_vShader(nullptr), m_quadLayout(nullptr), m_pShader(nullptr),
- m_xfbEncodeBlendState(nullptr), m_xfbEncodeDepthState(nullptr), m_xfbEncodeRastState(nullptr),
- m_efbSampler(nullptr)
-{
-}
-
-void XFBEncoder::Init()
-{
- HRESULT hr;
-
- // Create output texture
-
- // The pixel shader can generate one YUYV entry per pixel. One YUYV entry
- // is created for every two EFB pixels.
- D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, MAX_XFB_WIDTH / 2,
- MAX_XFB_HEIGHT, 1, 1, D3D11_BIND_RENDER_TARGET);
- hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_out);
- CHECK(SUCCEEDED(hr), "create xfb encoder output texture");
- D3D::SetDebugObjectName(m_out, "xfb encoder output texture");
-
- // Create output render target view
-
- D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(
- m_out, D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R8G8B8A8_UNORM);
- hr = D3D::device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV);
- CHECK(SUCCEEDED(hr), "create xfb encoder output texture rtv");
- D3D::SetDebugObjectName(m_outRTV, "xfb encoder output rtv");
-
- // Create output staging buffer
-
- t2dd.Usage = D3D11_USAGE_STAGING;
- t2dd.BindFlags = 0;
- t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_outStage);
- CHECK(SUCCEEDED(hr), "create xfb encoder output staging buffer");
- D3D::SetDebugObjectName(m_outStage, "xfb encoder output staging buffer");
-
- // Create constant buffer for uploading params to shaders
-
- D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(XFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER);
- hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encodeParams);
- CHECK(SUCCEEDED(hr), "create xfb encode params buffer");
- D3D::SetDebugObjectName(m_encodeParams, "xfb encoder params buffer");
-
- // Create vertex quad
-
- bd = CD3D11_BUFFER_DESC(sizeof(QUAD_VERTS), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE);
- D3D11_SUBRESOURCE_DATA srd = {QUAD_VERTS, 0, 0};
-
- hr = D3D::device->CreateBuffer(&bd, &srd, &m_quad);
- CHECK(SUCCEEDED(hr), "create xfb encode quad vertex buffer");
- D3D::SetDebugObjectName(m_quad, "xfb encoder quad vertex buffer");
-
- // Create vertex shader
-
- D3DBlob* bytecode = nullptr;
- if (!D3D::CompileVertexShader(XFB_ENCODE_VS, &bytecode))
- {
- ERROR_LOG(VIDEO, "XFB encode vertex shader failed to compile");
- return;
- }
-
- hr = D3D::device->CreateVertexShader(bytecode->Data(), bytecode->Size(), nullptr, &m_vShader);
- CHECK(SUCCEEDED(hr), "create xfb encode vertex shader");
- D3D::SetDebugObjectName(m_vShader, "xfb encoder vertex shader");
-
- // Create input layout for vertex quad using bytecode from vertex shader
-
- hr = D3D::device->CreateInputLayout(QUAD_LAYOUT_DESC,
- sizeof(QUAD_LAYOUT_DESC) / sizeof(D3D11_INPUT_ELEMENT_DESC),
- bytecode->Data(), bytecode->Size(), &m_quadLayout);
- CHECK(SUCCEEDED(hr), "create xfb encode quad vertex layout");
- D3D::SetDebugObjectName(m_quadLayout, "xfb encoder quad layout");
-
- bytecode->Release();
-
- // Create pixel shader
-
- m_pShader = D3D::CompileAndCreatePixelShader(XFB_ENCODE_PS);
- if (!m_pShader)
- {
- ERROR_LOG(VIDEO, "XFB encode pixel shader failed to compile");
- return;
- }
- D3D::SetDebugObjectName(m_pShader, "xfb encoder pixel shader");
-
- // Create blend state
-
- D3D11_BLEND_DESC bld = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
- hr = D3D::device->CreateBlendState(&bld, &m_xfbEncodeBlendState);
- CHECK(SUCCEEDED(hr), "create xfb encode blend state");
- D3D::SetDebugObjectName(m_xfbEncodeBlendState, "xfb encoder blend state");
-
- // Create depth state
-
- D3D11_DEPTH_STENCIL_DESC dsd = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
- dsd.DepthEnable = FALSE;
- hr = D3D::device->CreateDepthStencilState(&dsd, &m_xfbEncodeDepthState);
- CHECK(SUCCEEDED(hr), "create xfb encode depth state");
- D3D::SetDebugObjectName(m_xfbEncodeDepthState, "xfb encoder depth state");
-
- // Create rasterizer state
-
- D3D11_RASTERIZER_DESC rd = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT());
- rd.CullMode = D3D11_CULL_NONE;
- rd.DepthClipEnable = FALSE;
- hr = D3D::device->CreateRasterizerState(&rd, &m_xfbEncodeRastState);
- CHECK(SUCCEEDED(hr), "create xfb encode rasterizer state");
- D3D::SetDebugObjectName(m_xfbEncodeRastState, "xfb encoder rast state");
-
- // Create EFB texture sampler
-
- D3D11_SAMPLER_DESC sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
- sd.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
- hr = D3D::device->CreateSamplerState(&sd, &m_efbSampler);
- CHECK(SUCCEEDED(hr), "create xfb encode texture sampler");
- D3D::SetDebugObjectName(m_efbSampler, "xfb encoder texture sampler");
-}
-
-void XFBEncoder::Shutdown()
-{
- SAFE_RELEASE(m_efbSampler);
- SAFE_RELEASE(m_xfbEncodeRastState);
- SAFE_RELEASE(m_xfbEncodeDepthState);
- SAFE_RELEASE(m_xfbEncodeBlendState);
- SAFE_RELEASE(m_pShader);
- SAFE_RELEASE(m_quadLayout);
- SAFE_RELEASE(m_vShader);
- SAFE_RELEASE(m_quad);
- SAFE_RELEASE(m_encodeParams);
- SAFE_RELEASE(m_outStage);
- SAFE_RELEASE(m_outRTV);
- SAFE_RELEASE(m_out);
-}
-
-void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma)
-{
- HRESULT hr;
-
- // Reset API
-
- g_renderer->ResetAPIState();
-
- // Set up all the state for XFB encoding
-
- D3D::stateman->SetPixelShader(m_pShader);
- D3D::stateman->SetVertexShader(m_vShader);
- D3D::stateman->SetGeometryShader(nullptr);
-
- D3D::stateman->PushBlendState(m_xfbEncodeBlendState);
- D3D::stateman->PushDepthState(m_xfbEncodeDepthState);
- D3D::stateman->PushRasterizerState(m_xfbEncodeRastState);
-
- D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width / 2), FLOAT(height));
- D3D::context->RSSetViewports(1, &vp);
-
- D3D::stateman->SetInputLayout(m_quadLayout);
- D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
- UINT stride = sizeof(QuadVertex);
- UINT offset = 0;
- D3D::stateman->SetVertexBuffer(m_quad, stride, offset);
-
- TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect);
-
- XFBEncodeParams params = {0};
- params.Width = FLOAT(width);
- params.Height = FLOAT(height);
- params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetTargetWidth();
- params.TexTop = FLOAT(targetRect.top) / g_renderer->GetTargetHeight();
- params.TexRight = FLOAT(targetRect.right) / g_renderer->GetTargetWidth();
- params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetTargetHeight();
- params.Gamma = gamma;
- D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0);
-
- D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr);
-
- ID3D11ShaderResourceView* pEFB = FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
-
- D3D::stateman->SetVertexConstants(m_encodeParams);
- D3D::stateman->SetPixelConstants(m_encodeParams);
- D3D::stateman->SetTexture(0, pEFB);
- D3D::stateman->SetSampler(0, m_efbSampler);
-
- // Encode!
-
- D3D::stateman->Apply();
- D3D::context->Draw(4, 0);
-
- // Copy to staging buffer
-
- D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, width / 2, height, 1);
- D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
-
- // Clean up state
-
- D3D::context->OMSetRenderTargets(0, nullptr, nullptr);
-
- D3D::stateman->SetSampler(0, nullptr);
- D3D::stateman->SetTexture(0, nullptr);
- D3D::stateman->SetPixelConstants(nullptr);
- D3D::stateman->SetVertexConstants(nullptr);
-
- D3D::stateman->SetPixelShader(nullptr);
- D3D::stateman->SetVertexShader(nullptr);
-
- D3D::stateman->PopRasterizerState();
- D3D::stateman->PopDepthState();
- D3D::stateman->PopBlendState();
-
- // Transfer staging buffer to GameCube/Wii RAM
-
- D3D11_MAPPED_SUBRESOURCE map = {0};
- hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map);
- CHECK(SUCCEEDED(hr), "map staging buffer");
-
- u8* src = (u8*)map.pData;
- for (unsigned int y = 0; y < height; ++y)
- {
- memcpy(dst, src, 2 * width);
- dst += bpmem.copyMipMapStrideChannels * 32;
- src += map.RowPitch;
- }
-
- D3D::context->Unmap(m_outStage, 0);
-
- // Restore API
- g_renderer->RestoreAPIState();
- D3D::stateman->Apply(); // force unbind efb texture as shader resource
- FramebufferManager::BindEFBRenderTarget();
-}
-}
diff --git a/Source/Core/VideoBackends/D3D/XFBEncoder.h b/Source/Core/VideoBackends/D3D/XFBEncoder.h
deleted file mode 100644
index 91da877b8b..0000000000
--- a/Source/Core/VideoBackends/D3D/XFBEncoder.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2011 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "VideoCommon/VideoCommon.h"
-
-struct ID3D11Texture2D;
-struct ID3D11RenderTargetView;
-struct ID3D11Buffer;
-struct ID3D11VertexShader;
-struct ID3D11PixelShader;
-struct ID3D11InputLayout;
-struct ID3D11BlendState;
-struct ID3D11DepthStencilState;
-struct ID3D11RasterizerState;
-struct ID3D11SamplerState;
-
-namespace DX11
-{
-class XFBEncoder
-{
-public:
- XFBEncoder();
-
- void Init();
- void Shutdown();
-
- void Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma);
-
-private:
- ID3D11Texture2D* m_out;
- ID3D11RenderTargetView* m_outRTV;
- ID3D11Texture2D* m_outStage;
- ID3D11Buffer* m_encodeParams;
- ID3D11Buffer* m_quad;
- ID3D11VertexShader* m_vShader;
- ID3D11InputLayout* m_quadLayout;
- ID3D11PixelShader* m_pShader;
- ID3D11BlendState* m_xfbEncodeBlendState;
- ID3D11DepthStencilState* m_xfbEncodeDepthState;
- ID3D11RasterizerState* m_xfbEncodeRastState;
- ID3D11SamplerState* m_efbSampler;
-};
-}
diff --git a/Source/Core/VideoBackends/Null/FramebufferManager.h b/Source/Core/VideoBackends/Null/FramebufferManager.h
deleted file mode 100644
index 0419ee36f8..0000000000
--- a/Source/Core/VideoBackends/Null/FramebufferManager.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2015 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include
-
-#include "Common/CommonTypes.h"
-#include "VideoCommon/FramebufferManagerBase.h"
-
-class XFBSource : public XFBSourceBase
-{
-public:
- void CopyEFB(float gamma) override {}
-};
-
-class FramebufferManager : public FramebufferManagerBase
-{
-public:
- std::unique_ptr CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers) override
- {
- return std::make_unique();
- }
-
- std::pair GetTargetSize() const override { return std::make_pair(0, 0); }
- void CopyToRealXFB(u32 xfb_addr, u32 fb_stride, u32 fb_height, const EFBRectangle& source_rc,
- float gamma = 1.0f) override
- {
- }
-};
diff --git a/Source/Core/VideoBackends/Null/Null.vcxproj b/Source/Core/VideoBackends/Null/Null.vcxproj
index 178575ef81..664488035e 100644
--- a/Source/Core/VideoBackends/Null/Null.vcxproj
+++ b/Source/Core/VideoBackends/Null/Null.vcxproj
@@ -43,7 +43,6 @@
-
diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp
index 2a52fe7172..1bb8d6248e 100644
--- a/Source/Core/VideoBackends/Null/NullBackend.cpp
+++ b/Source/Core/VideoBackends/Null/NullBackend.cpp
@@ -7,7 +7,6 @@
// This backend tries not to do anything in the backend,
// but everything in VideoCommon.
-#include "VideoBackends/Null/FramebufferManager.h"
#include "VideoBackends/Null/PerfQuery.h"
#include "VideoBackends/Null/Render.h"
#include "VideoBackends/Null/ShaderCache.h"
@@ -15,6 +14,7 @@
#include "VideoBackends/Null/VertexManager.h"
#include "VideoBackends/Null/VideoBackend.h"
+#include "VideoCommon/FramebufferManagerBase.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
@@ -68,7 +68,7 @@ void VideoBackend::Video_Prepare()
g_renderer = std::make_unique();
g_vertex_manager = std::make_unique();
g_perf_query = std::make_unique();
- g_framebuffer_manager = std::make_unique();
+ g_framebuffer_manager = std::make_unique();
g_texture_cache = std::make_unique();
VertexShaderCache::s_instance = std::make_unique();
GeometryShaderCache::s_instance = std::make_unique();
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
index 77ef205f2a..a670a47111 100644
--- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp
@@ -33,7 +33,6 @@ bool FramebufferManager::m_enable_stencil_buffer;
GLenum FramebufferManager::m_textureType;
std::vector FramebufferManager::m_efbFramebuffer;
-GLuint FramebufferManager::m_xfbFramebuffer;
GLuint FramebufferManager::m_efbColor;
GLuint FramebufferManager::m_efbDepth;
GLuint FramebufferManager::m_efbColorSwap; // for hot swap when reinterpreting EFB pixel formats
@@ -110,7 +109,6 @@ bool FramebufferManager::HasStencilBuffer()
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples,
bool enable_stencil_buffer)
{
- m_xfbFramebuffer = 0;
m_efbColor = 0;
m_efbDepth = 0;
m_efbColorSwap = 0;
@@ -189,9 +187,6 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
CreateTexture(m_textureType, depth_internal_format, depth_pixel_format, depth_data_type);
m_efbColorSwap = CreateTexture(m_textureType, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
- // Create XFB framebuffer; targets will be created elsewhere.
- glGenFramebuffers(1, &m_xfbFramebuffer);
-
// Bind target textures to EFB framebuffer.
glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data());
BindLayeredTexture(m_efbColor, m_efbFramebuffer, GL_COLOR_ATTACHMENT0, m_textureType);
@@ -419,9 +414,6 @@ FramebufferManager::~FramebufferManager()
m_efbFramebuffer.clear();
m_resolvedFramebuffer.clear();
- glDeleteFramebuffers(1, &m_xfbFramebuffer);
- m_xfbFramebuffer = 0;
-
glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture;
glDeleteTextures(2, glObj);
@@ -527,21 +519,6 @@ void FramebufferManager::ResolveEFBStencilTexture()
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]);
}
-void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight,
- const EFBRectangle& sourceRc, float Gamma)
-{
-/* u8* xfb_in_ram = Memory::GetPointer(xfbAddr);
- if (!xfb_in_ram)
- {
- WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
- return;
- }
-
- TargetRectangle targetRc = g_renderer->ConvertEFBRectangle(sourceRc);
- TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram,
- sourceRc.GetWidth(), fbStride, fbHeight);*/
-}
-
GLuint FramebufferManager::GetResolvedFramebuffer()
{
if (m_msaaSamples <= 1)
@@ -610,56 +587,6 @@ void FramebufferManager::ReinterpretPixelData(unsigned int convtype)
g_renderer->RestoreAPIState();
}
-XFBSource::~XFBSource()
-{
- glDeleteTextures(1, &texture);
-}
-
-void XFBSource::CopyEFB(float Gamma)
-{
- g_renderer->ResetAPIState();
-
- // Copy EFB data to XFB and restore render target again
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
-
- for (int i = 0; i < m_layers; i++)
- {
- // Bind EFB and texture layer
- glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer(i));
- glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, i);
-
- glBlitFramebuffer(0, 0, texWidth, texHeight, 0, 0, texWidth, texHeight, GL_COLOR_BUFFER_BIT,
- GL_NEAREST);
- }
-
- // Return to EFB.
- FramebufferManager::SetFramebuffer(0);
-
- g_renderer->RestoreAPIState();
-}
-
-std::unique_ptr FramebufferManager::CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers)
-{
- GLuint texture;
-
- glGenTextures(1, &texture);
-
- glActiveTexture(GL_TEXTURE9);
- glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, target_width, target_height, layers, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, nullptr);
-
- return std::make_unique(texture, layers);
-}
-
-std::pair FramebufferManager::GetTargetSize() const
-{
- return std::make_pair(m_targetWidth, m_targetHeight);
-}
-
void FramebufferManager::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points)
{
g_renderer->ResetAPIState();
diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.h b/Source/Core/VideoBackends/OGL/FramebufferManager.h
index 1d3626af36..f68556bf90 100644
--- a/Source/Core/VideoBackends/OGL/FramebufferManager.h
+++ b/Source/Core/VideoBackends/OGL/FramebufferManager.h
@@ -48,17 +48,6 @@
namespace OGL
{
-struct XFBSource : public XFBSourceBase
-{
- XFBSource(GLuint tex, int layers) : texture(tex), m_layers(layers) {}
- ~XFBSource();
-
- void CopyEFB(float Gamma) override;
-
- const GLuint texture;
- const int m_layers;
-};
-
class FramebufferManager : public FramebufferManagerBase
{
public:
@@ -76,7 +65,6 @@ public:
{
return (layer < m_EFBLayers) ? m_efbFramebuffer[layer] : m_efbFramebuffer.back();
}
- static GLuint GetXFBFramebuffer() { return m_xfbFramebuffer; }
// Resolved framebuffer is only used in MSAA mode.
static GLuint GetResolvedFramebuffer();
static void SetFramebuffer(GLuint fb);
@@ -108,13 +96,6 @@ private:
GLenum data_type);
void BindLayeredTexture(GLuint texture, const std::vector& framebuffers,
GLenum attachment, GLenum texture_type);
- std::unique_ptr CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers) override;
- std::pair GetTargetSize() const override;
-
- void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,
- float Gamma) override;
static int m_targetWidth;
static int m_targetHeight;
@@ -122,7 +103,6 @@ private:
static GLenum m_textureType;
static std::vector m_efbFramebuffer;
- static GLuint m_xfbFramebuffer;
static GLuint m_efbColor;
static GLuint m_efbDepth;
static GLuint
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index e426b97ef6..655b69cb4e 100644
--- a/Source/Core/VideoBackends/OGL/Render.cpp
+++ b/Source/Core/VideoBackends/OGL/Render.cpp
@@ -790,12 +790,7 @@ Renderer::Renderer()
ClearEFBCache();
}
-Renderer::~Renderer()
-{
- FlushFrameDump();
- //FinishFrameData();
- DestroyFrameDumpResources();
-}
+Renderer::~Renderer() = default;
void Renderer::Shutdown()
{
@@ -1360,27 +1355,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti
glBindFramebuffer(GL_FRAMEBUFFER, 0);
BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), xfb_texture->GetConfig().width, xfb_texture->GetConfig().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.
- /*FlushFrameDump();
- if (IsFrameDumping())
- {
- // Currently, we only use the off-screen buffer as a frame dump source if full-resolution
- // frame dumping is enabled, saving the need for an extra copy. In the future, this could
- // be extended to be used for surfaceless contexts as well.
- bool use_offscreen_buffer = g_ActiveConfig.bInternalResolutionFrameDumps;
- if (use_offscreen_buffer)
- {
- // DumpFrameUsingFBO resets GL_FRAMEBUFFER, so change back to the window for drawing OSD.
- DumpFrameUsingFBO(sourceRc, ticks);
- }
- else
- {
- // GL_READ_FRAMEBUFFER is set by GL_FRAMEBUFFER in DrawFrame -> Draw{EFB,VirtualXFB,RealXFB}.
- DumpFrame(flipped_trc, ticks);
- }
- }*/
-
// Finish up the current frame, print some stats
SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height);
@@ -1509,134 +1483,6 @@ void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc,
BlitScreen(source_rc, target_rc, tex, m_target_width, m_target_height);
}
-void Renderer::FlushFrameDump()
-{
- /*if (!m_last_frame_exported)
- return;
-
- FinishFrameData();
- glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]);
- m_frame_pbo_is_mapped[0] = true;
- void* data = glMapBufferRange(
- GL_PIXEL_PACK_BUFFER, 0, m_last_frame_width[0] * m_last_frame_height[0] * 4, GL_MAP_READ_BIT);
- DumpFrameData(reinterpret_cast(data), m_last_frame_width[0], m_last_frame_height[0],
- m_last_frame_width[0] * 4, m_last_frame_state, true);
- glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
- m_last_frame_exported = false;*/
-}
-
-void Renderer::DumpFrame(const TargetRectangle& flipped_trc, u64 ticks)
-{
- if (!m_frame_dumping_pbo[0])
- {
- glGenBuffers(2, m_frame_dumping_pbo.data());
- glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]);
- }
- else
- {
- FlushFrameDump();
- std::swap(m_frame_dumping_pbo[0], m_frame_dumping_pbo[1]);
- std::swap(m_frame_pbo_is_mapped[0], m_frame_pbo_is_mapped[1]);
- std::swap(m_last_frame_width[0], m_last_frame_width[1]);
- std::swap(m_last_frame_height[0], m_last_frame_height[1]);
- glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]);
- if (m_frame_pbo_is_mapped[0])
- glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
- m_frame_pbo_is_mapped[0] = false;
- }
-
- if (flipped_trc.GetWidth() != m_last_frame_width[0] ||
- flipped_trc.GetHeight() != m_last_frame_height[0])
- {
- m_last_frame_width[0] = flipped_trc.GetWidth();
- m_last_frame_height[0] = flipped_trc.GetHeight();
- glBufferData(GL_PIXEL_PACK_BUFFER, m_last_frame_width[0] * m_last_frame_height[0] * 4, nullptr,
- GL_STREAM_READ);
- }
-
- m_last_frame_state = AVIDump::FetchState(ticks);
- m_last_frame_exported = true;
-
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(flipped_trc.left, flipped_trc.bottom, m_last_frame_width[0], m_last_frame_height[0],
- GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-}
-
-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();
- std::swap(render_rc.top, render_rc.bottom);
-
- // Ensure the render texture meets the size requirements of the draw area.
- u32 render_width = static_cast(render_rc.GetWidth());
- u32 render_height = static_cast(render_rc.GetHeight());
- PrepareFrameDumpRenderTexture(render_width, render_height);
-
- // Ensure the alpha channel of the render texture is blank. The frame dump backend expects
- // that the alpha is set to 1.0 for all pixels.
- glBindFramebuffer(GL_FRAMEBUFFER, m_frame_dump_render_framebuffer);
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- // 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);
- 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);
-
- // Restore state after drawing. This isn't the game state, it's the state set by ResetAPIState.
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-void Renderer::PrepareFrameDumpRenderTexture(u32 width, u32 height)
-{
- // Ensure framebuffer exists (we lazily allocate it in case frame dumping isn't used).
- // Or, resize texture if it isn't large enough to accommodate the current frame.
- if (m_frame_dump_render_texture != 0 && m_frame_dump_render_framebuffer != 0 &&
- m_frame_dump_render_texture_width >= width && m_frame_dump_render_texture_height >= height)
- {
- return;
- }
-
- // Recreate texture objects.
- if (m_frame_dump_render_texture != 0)
- glDeleteTextures(1, &m_frame_dump_render_texture);
- if (m_frame_dump_render_framebuffer != 0)
- glDeleteFramebuffers(1, &m_frame_dump_render_framebuffer);
-
- glGenTextures(1, &m_frame_dump_render_texture);
- glActiveTexture(GL_TEXTURE9);
- glBindTexture(GL_TEXTURE_2D, m_frame_dump_render_texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
-
- glGenFramebuffers(1, &m_frame_dump_render_framebuffer);
- FramebufferManager::SetFramebuffer(m_frame_dump_render_framebuffer);
- FramebufferManager::FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- m_frame_dump_render_texture, 0);
-
- m_frame_dump_render_texture_width = width;
- m_frame_dump_render_texture_height = height;
- OGLTexture::SetStage();
-}
-
-void Renderer::DestroyFrameDumpResources()
-{
- if (m_frame_dump_render_framebuffer)
- glDeleteFramebuffers(1, &m_frame_dump_render_framebuffer);
- if (m_frame_dump_render_texture)
- glDeleteTextures(1, &m_frame_dump_render_texture);
- if (m_frame_dumping_pbo[0])
- glDeleteBuffers(2, m_frame_dumping_pbo.data());
-}
-
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
void Renderer::ResetAPIState()
{
diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h
index d71ad15bd1..78d680fbd2 100644
--- a/Source/Core/VideoBackends/OGL/Render.h
+++ b/Source/Core/VideoBackends/OGL/Render.h
@@ -4,7 +4,6 @@
#pragma once
-#include
#include
#include "Common/GL/GLUtil.h"
@@ -116,25 +115,5 @@ private:
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 TargetRectangle& source_rc, u64 ticks);
-
- // Frame dumping framebuffer, we render to this, then read it back
- void PrepareFrameDumpRenderTexture(u32 width, u32 height);
- void DestroyFrameDumpResources();
- GLuint m_frame_dump_render_texture = 0;
- GLuint m_frame_dump_render_framebuffer = 0;
- u32 m_frame_dump_render_texture_width = 0;
- u32 m_frame_dump_render_texture_height = 0;
-
- // avi dumping state to delay one frame
- std::array m_frame_dumping_pbo = {};
- std::array m_frame_pbo_is_mapped = {};
- std::array m_last_frame_width = {};
- std::array m_last_frame_height = {};
- bool m_last_frame_exported = false;
- AVIDump::Frame m_last_frame_state;
};
}
diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp
index 1fb55c8d24..a2460bf935 100644
--- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp
+++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp
@@ -41,11 +41,6 @@ static GLuint s_dstTexture = 0; // for encoding to RAM
const int renderBufferWidth = EFB_WIDTH * 4;
const int renderBufferHeight = 1024;
-static SHADER s_rgbToYuyvProgram;
-static int s_rgbToYuyvUniform_loc;
-
-static SHADER s_yuyvToRgbProgram;
-
struct EncodingProgram
{
SHADER program;
@@ -56,87 +51,6 @@ static std::map s_encoding_programs;
static GLuint s_PBO = 0; // for readback with different strides
-static void CreatePrograms()
-{
- /* TODO: Accuracy Improvements
- *
- * This shader doesn't really match what the GameCube does internally in the
- * copy pipeline.
- * 1. It uses OpenGL's built in filtering when yscaling, someone could work
- * out how the copypipeline does it's filtering and implement it correctly
- * in this shader.
- * 2. Deflickering isn't implemented, a futher filtering over 3 lines.
- * Isn't really needed on non-interlaced monitors (and would lower quality;
- * But hey, accuracy!)
- * 3. Flipper's YUYV conversion implements a 3 pixel horizontal blur on the
- * UV channels, centering the U channel on the Left pixel and the V channel
- * on the Right pixel.
- * The current implementation Centers both UV channels at the same place
- * inbetween the two Pixels, and only blurs over these two pixels.
- */
- // Output is BGRA because that is slightly faster than RGBA.
- const char* VProgramRgbToYuyv =
- "out vec2 uv0;\n"
- "uniform vec4 copy_position;\n" // left, top, right, bottom
- "SAMPLER_BINDING(9) uniform sampler2DArray samp9;\n"
- "void main()\n"
- "{\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 = mix(copy_position.xy, copy_position.zw, rawpos) / vec2(textureSize(samp9, 0).xy);\n"
- "}\n";
- const char* FProgramRgbToYuyv =
- "SAMPLER_BINDING(9) uniform sampler2DArray samp9;\n"
- "in vec2 uv0;\n"
- "out vec4 ocol0;\n"
- "void main()\n"
- "{\n"
- " vec3 c0 = texture(samp9, vec3(uv0 - dFdx(uv0) * 0.25, 0.0)).rgb;\n"
- " vec3 c1 = texture(samp9, vec3(uv0 + dFdx(uv0) * 0.25, 0.0)).rgb;\n"
- " vec3 c01 = (c0 + c1) * 0.5;\n"
- " vec3 y_const = vec3(0.257,0.504,0.098);\n"
- " vec3 u_const = vec3(-0.148,-0.291,0.439);\n"
- " vec3 v_const = vec3(0.439,-0.368,-0.071);\n"
- " vec4 const3 = vec4(0.0625,0.5,0.0625,0.5);\n"
- " ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + "
- "const3;\n"
- "}\n";
- ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgramRgbToYuyv, FProgramRgbToYuyv);
- s_rgbToYuyvUniform_loc = glGetUniformLocation(s_rgbToYuyvProgram.glprogid, "copy_position");
-
- /* TODO: Accuracy Improvements
- *
- * The YVYU to RGB conversion here matches the RGB to YUYV done above, but
- * if a game modifies or adds images to the XFB then it should be using the
- * same algorithm as the flipper, and could result in slight color inaccuracies
- * when run back through this shader.
- */
- const char* VProgramYuyvToRgb = "void main()\n"
- "{\n"
- " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n"
- " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n"
- "}\n";
- const char* FProgramYuyvToRgb = "SAMPLER_BINDING(9) uniform sampler2D samp9;\n"
- "in vec2 uv0;\n"
- "out vec4 ocol0;\n"
- "void main()\n"
- "{\n"
- " ivec2 uv = ivec2(gl_FragCoord.xy);\n"
- // We switch top/bottom here. TODO: move this to screen blit.
- " ivec2 ts = textureSize(samp9, 0);\n"
- " vec4 c0 = texelFetch(samp9, ivec2(uv.x>>1, ts.y-uv.y-1), 0);\n"
- " float y = mix(c0.r, c0.b, (uv.x & 1) == 1);\n"
- " float yComp = 1.164 * (y - 0.0625);\n"
- " float uComp = c0.g - 0.5;\n"
- " float vComp = c0.a - 0.5;\n"
- " ocol0 = vec4(yComp + (1.596 * vComp),\n"
- " yComp - (0.813 * vComp) - (0.391 * uComp),\n"
- " yComp + (2.018 * uComp),\n"
- " 1.0);\n"
- "}\n";
- ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgramYuyvToRgb, FProgramYuyvToRgb);
-}
-
static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params)
{
auto iter = s_encoding_programs.find(params);
@@ -191,8 +105,6 @@ void Init()
FramebufferManager::SetFramebuffer(0);
glGenBuffers(1, &s_PBO);
-
- CreatePrograms();
}
void Shutdown()
@@ -202,9 +114,6 @@ void Shutdown()
glDeleteBuffers(1, &s_PBO);
glDeleteFramebuffers(2, s_texConvFrameBuffer);
- s_rgbToYuyvProgram.Destroy();
- s_yuyvToRgbProgram.Destroy();
-
for (auto& program : s_encoding_programs)
program.second.program.Destroy();
s_encoding_programs.clear();
@@ -297,64 +206,6 @@ void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 nativ
g_renderer->RestoreAPIState();
}
-void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth,
- u32 dstStride, u32 dstHeight)
-{
- g_renderer->ResetAPIState();
-
- s_rgbToYuyvProgram.Bind();
-
- glUniform4f(s_rgbToYuyvUniform_loc, static_cast(sourceRc.left),
- static_cast(sourceRc.top), static_cast(sourceRc.right),
- static_cast(sourceRc.bottom));
-
- // We enable linear filtering, because the GameCube does filtering in the vertical direction when
- // yscale is enabled.
- // Otherwise we get jaggies when a game uses yscaling (most PAL games)
- EncodeToRamUsingShader(srcTexture, destAddr, dstWidth * 2, dstHeight, dstStride, true, 1.0f);
- FramebufferManager::SetFramebuffer(0);
- OGLTexture::DisableStage(0);
- g_renderer->RestoreAPIState();
-}
-
-// Should be scale free.
-void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
-{
- u8* srcAddr = Memory::GetPointer(xfbAddr);
- if (!srcAddr)
- {
- WARN_LOG(VIDEO, "Tried to decode from invalid memory address");
- return;
- }
-
- g_renderer->ResetAPIState(); // reset any game specific settings
-
- OpenGL_BindAttributelessVAO();
-
- // switch to texture converter frame buffer
- // attach destTexture as color destination
- FramebufferManager::SetFramebuffer(s_texConvFrameBuffer[1]);
- FramebufferManager::FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_ARRAY,
- destTexture, 0);
-
- // activate source texture
- // set srcAddr as data for source texture
- glActiveTexture(GL_TEXTURE9);
- glBindTexture(GL_TEXTURE_2D, s_srcTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, srcWidth / 2, srcHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- srcAddr);
- g_sampler_cache->BindNearestSampler(9);
-
- glViewport(0, 0, srcWidth, srcHeight);
- s_yuyvToRgbProgram.Bind();
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- FramebufferManager::SetFramebuffer(0);
-
- g_renderer->RestoreAPIState();
-}
-
} // namespace
} // namespace OGL
diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.h b/Source/Core/VideoBackends/OGL/TextureConverter.h
index 3b535752a3..baed715a7e 100644
--- a/Source/Core/VideoBackends/OGL/TextureConverter.h
+++ b/Source/Core/VideoBackends/OGL/TextureConverter.h
@@ -20,11 +20,6 @@ namespace TextureConverter
void Init();
void Shutdown();
-void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth,
- u32 dstStride, u32 dstHeight);
-
-void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
-
// returns size of the encoded data (in bytes)
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
index c23c19b544..305f0343f7 100644
--- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
@@ -1377,93 +1377,4 @@ void FramebufferManager::DestroyPokeShaders()
}
}
-std::unique_ptr FramebufferManager::CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers)
-{
- TextureConfig config;
- config.width = target_width;
- config.height = target_height;
- config.layers = layers;
- config.rendertarget = true;
- auto texture = TextureCache::GetInstance()->CreateTexture(config);
- if (!texture)
- {
- PanicAlert("Failed to create texture for XFB source");
- return nullptr;
- }
-
- return std::make_unique(std::move(texture));
-}
-
-void FramebufferManager::CopyToRealXFB(u32 xfb_addr, u32 fb_stride, u32 fb_height,
- const EFBRectangle& source_rc, float gamma)
-{
- // Pending/batched EFB pokes should be included in the copied image.
- FlushEFBPokes();
-
- // Schedule early command-buffer execution.
- StateTracker::GetInstance()->EndRenderPass();
- StateTracker::GetInstance()->OnReadback();
-
- // GPU EFB textures -> Guest memory
- u8* xfb_ptr = Memory::GetPointer(xfb_addr);
- _assert_(xfb_ptr);
-
- // source_rc is in native coordinates, so scale it to the internal resolution.
- TargetRectangle scaled_rc = g_renderer->ConvertEFBRectangle(source_rc);
- VkRect2D scaled_rc_vk = {
- {scaled_rc.left, scaled_rc.top},
- {static_cast(scaled_rc.GetWidth()), static_cast(scaled_rc.GetHeight())}};
- Texture2D* src_texture = ResolveEFBColorTexture(scaled_rc_vk);
-
- // The destination stride can differ from the copy region width, in which case the pixels
- // outside the copy region should not be written to.
- TextureCache::GetInstance()->GetTextureConverter()->EncodeTextureToMemoryYUYV(
- xfb_ptr, static_cast(source_rc.GetWidth()), fb_stride, fb_height, src_texture,
- scaled_rc);
-
- // If we sourced directly from the EFB framebuffer, restore it to a color attachment.
- if (src_texture == m_efb_color_texture.get())
- {
- src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- }
-}
-
-XFBSource::XFBSource(std::unique_ptr texture)
- : XFBSourceBase(), m_texture(std::move(texture))
-{
-}
-
-XFBSource::~XFBSource()
-{
-}
-
-VKTexture* XFBSource::GetTexture() const
-{
- return static_cast(m_texture.get());
-}
-
-void XFBSource::CopyEFB(float gamma)
-{
- // Pending/batched EFB pokes should be included in the copied image.
- FramebufferManager::GetInstance()->FlushEFBPokes();
-
- // Virtual XFB, copy EFB at native resolution to m_texture
- MathUtil::Rectangle rect(0, 0, static_cast(texWidth), static_cast(texHeight));
- VkRect2D vk_rect = {{rect.left, rect.top},
- {static_cast(rect.GetWidth()), static_cast(rect.GetHeight())}};
-
- Texture2D* src_texture = FramebufferManager::GetInstance()->ResolveEFBColorTexture(vk_rect);
- static_cast(m_texture.get())->CopyRectangleFromTexture(src_texture, rect, rect);
-
- // If we sourced directly from the EFB framebuffer, restore it to a color attachment.
- if (src_texture == FramebufferManager::GetInstance()->GetEFBColorTexture())
- {
- src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- }
-}
-
} // namespace Vulkan
diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h
index 3f2a251662..0c1a160728 100644
--- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h
+++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h
@@ -44,14 +44,6 @@ public:
VkSampleCountFlagBits GetEFBSamples() const;
MultisamplingState GetEFBMultisamplingState() const;
- std::unique_ptr CreateXFBSource(unsigned int target_width,
- unsigned int target_height,
- unsigned int layers) override;
-
- // GPU EFB textures -> Guest
- void CopyToRealXFB(u32 xfb_addr, u32 fb_stride, u32 fb_height, const EFBRectangle& source_rc,
- float gamma = 1.0f) override;
-
void ResizeEFBTextures();
// Recompile shaders, use when MSAA mode changes.
@@ -168,21 +160,4 @@ private:
VkShaderModule m_poke_fragment_shader = VK_NULL_HANDLE;
};
-// The XFB source class simply wraps a texture cache entry.
-// All the required functionality is provided by TextureCache.
-class XFBSource final : public XFBSourceBase
-{
-public:
- explicit XFBSource(std::unique_ptr texture);
- ~XFBSource();
-
- VKTexture* GetTexture() const;
-
- // Used for virtual XFB
- void CopyEFB(float gamma) override;
-
-private:
- std::unique_ptr m_texture;
-};
-
} // namespace Vulkan
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index ce77fb68fd..af0bfba451 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -61,11 +61,6 @@ Renderer::~Renderer()
{
UpdateActiveConfig();
- // Ensure all frames are written to frame dump at shutdown.
- if (m_frame_dumping_active)
- EndFrameDumping();
-
- DestroyFrameDumpResources();
DestroyShaders();
DestroySemaphores();
}
@@ -491,12 +486,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti
// 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)
- {
- Core::Callback_VideoCopiedToXFB(false);
- }
-
auto* xfb_texture = static_cast(texture);
// End the current render pass.
@@ -563,90 +552,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti
g_shader_cache->RetrieveAsyncShaders();
}
-void Renderer::TransitionBuffersForSwap(const TargetRectangle& scaled_rect,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count)
-{
- VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
-
- // Drawing XFB sources, so transition all of them.
- // Don't need the EFB, so leave it as-is.
- for (u32 i = 0; i < xfb_count; i++)
- {
- const XFBSource* xfb_source = static_cast(xfb_sources[i]);
- xfb_source->GetTexture()->GetRawTexIdentifier()->TransitionToLayout(
- command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- }
-}
-
-void Renderer::DrawFrame(VkRenderPass render_pass, const TargetRectangle& target_rect,
- 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::DrawEFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
- const TargetRectangle& scaled_efb_rect)
-{
- // Transition the EFB render target to a shader resource.
- Texture2D* efb_color_texture =
- g_ActiveConfig.iMultisamples > 1 ?
- FramebufferManager::GetInstance()->GetResolvedEFBColorTexture() :
- FramebufferManager::GetInstance()->GetEFBColorTexture();
-
- // Copy EFB -> backbuffer
- BlitScreen(render_pass, target_rect, scaled_efb_rect, efb_color_texture);
-}
-
-void Renderer::DrawVirtualXFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
- u32 xfb_addr, const XFBSourceBase* const* xfb_sources, u32 xfb_count,
- u32 fb_width, u32 fb_stride, u32 fb_height)
-{
- for (u32 i = 0; i < xfb_count; ++i)
- {
- const XFBSource* xfb_source = static_cast(xfb_sources[i]);
- TargetRectangle source_rect = xfb_source->sourceRc;
- TargetRectangle draw_rect;
-
- int xfb_width = static_cast(xfb_source->srcWidth);
- int xfb_height = static_cast(xfb_source->srcHeight);
- int h_offset = (static_cast(xfb_source->srcAddr) - static_cast(xfb_addr)) /
- (static_cast(fb_stride) * 2);
- draw_rect.top =
- target_rect.top + h_offset * target_rect.GetHeight() / static_cast(fb_height);
- draw_rect.bottom =
- target_rect.top +
- (h_offset + xfb_height) * target_rect.GetHeight() / static_cast(fb_height);
- draw_rect.left = target_rect.left +
- (target_rect.GetWidth() -
- xfb_width * target_rect.GetWidth() / static_cast(fb_stride)) /
- 2;
- draw_rect.right = target_rect.left +
- (target_rect.GetWidth() +
- xfb_width * target_rect.GetWidth() / static_cast(fb_stride)) /
- 2;
-
- source_rect.right -= Renderer::EFBToScaledX(fb_stride - fb_width);
- BlitScreen(render_pass, draw_rect, source_rect,
- xfb_source->GetTexture()->GetRawTexIdentifier());
- }
-}
-
-void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height)
-{
- for (u32 i = 0; i < xfb_count; ++i)
- {
- const XFBSource* xfb_source = static_cast(xfb_sources[i]);
- TargetRectangle source_rect = xfb_source->sourceRc;
- TargetRectangle draw_rect = target_rect;
- source_rect.right -= fb_stride - fb_width;
- BlitScreen(render_pass, draw_rect, source_rect,
- xfb_source->GetTexture()->GetRawTexIdentifier());
- }
-}
-
void Renderer::DrawScreen(VKTexture* xfb_texture)
{
VkResult res;
@@ -718,173 +623,6 @@ void Renderer::DrawScreen(VKTexture* xfb_texture)
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
}
-bool Renderer::DrawFrameDump(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, u64 ticks)
-{
- TargetRectangle target_rect = CalculateFrameDumpDrawRectangle();
- u32 width = std::max(1u, static_cast(target_rect.GetWidth()));
- u32 height = std::max(1u, static_cast(target_rect.GetHeight()));
- if (!ResizeFrameDumpBuffer(width, height))
- return false;
-
- // If there was a previous frame dumped, we'll still be in TRANSFER_SRC layout.
- m_frame_dump_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
- VkClearRect clear_rect = {{{0, 0}, {width, height}}, 0, 1};
- VkClearAttachment clear_attachment = {VK_IMAGE_ASPECT_COLOR_BIT, 0, clear_value};
- VkRenderPassBeginInfo info = {
- VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- nullptr,
- FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass(),
- m_frame_dump_framebuffer,
- {{0, 0}, {width, height}},
- 1,
- &clear_value};
- vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &info,
- VK_SUBPASS_CONTENTS_INLINE);
- vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), 1, &clear_attachment, 1,
- &clear_rect);
- DrawFrame(FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass(), target_rect,
- scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
- vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer());
-
- // Prepare the readback texture for copying.
- StagingTexture2D* readback_texture = PrepareFrameDumpImage(width, height, ticks);
- if (!readback_texture)
- return false;
-
- // Queue a copy to the current frame dump buffer. It will be written to the frame dump later.
- m_frame_dump_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
- readback_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- m_frame_dump_render_texture->GetImage(),
- VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, width, height, 0, 0);
- return true;
-}
-
-void Renderer::StartFrameDumping()
-{
- _assert_(!m_frame_dumping_active);
-
- // Register fence callback so that we know when frames are ready to be written to the dump.
- // This is done by clearing the fence pointer, so WriteFrameDumpFrame doesn't have to wait.
- auto queued_callback = [](VkCommandBuffer, VkFence) {};
- auto signaled_callback = std::bind(&Renderer::OnFrameDumpImageReady, this, std::placeholders::_1);
-
- // We use the array pointer as a key here, that way if Renderer needed fence callbacks in
- // the future it could be used without conflicting.
- // We're not interested in when fences are submitted, so the first callback is a no-op.
- g_command_buffer_mgr->AddFencePointCallback(
- m_frame_dump_images.data(), std::move(queued_callback), std::move(signaled_callback));
- m_frame_dumping_active = true;
-}
-
-void Renderer::EndFrameDumping()
-{
- _assert_(m_frame_dumping_active);
-
- // Write any pending frames to the frame dump.
- FlushFrameDump();
-
- // Remove the fence callback that we registered earlier, one less function that needs to be
- // called when preparing a command buffer.
- g_command_buffer_mgr->RemoveFencePointCallback(m_frame_dump_images.data());
- m_frame_dumping_active = false;
-}
-
-void Renderer::OnFrameDumpImageReady(VkFence fence)
-{
- for (FrameDumpImage& frame : m_frame_dump_images)
- {
- // fence being a null handle means that we don't have to wait to re-use this image.
- if (frame.fence == fence)
- frame.fence = VK_NULL_HANDLE;
- }
-}
-
-void Renderer::WriteFrameDumpImage(size_t index)
-{
- /*FrameDumpImage& frame = m_frame_dump_images[index];
- _assert_(frame.pending);
-
- // Check fence has been signaled.
- // The callback here should set fence to null.
- if (frame.fence != VK_NULL_HANDLE)
- {
- g_command_buffer_mgr->WaitForFence(frame.fence);
- _assert_(frame.fence == VK_NULL_HANDLE);
- }
-
- // Copy the now-populated image data to the output file.
- DumpFrameData(reinterpret_cast(frame.readback_texture->GetMapPointer()),
- static_cast(frame.readback_texture->GetWidth()),
- static_cast(frame.readback_texture->GetHeight()),
- static_cast(frame.readback_texture->GetRowStride()), frame.dump_state);
-
- frame.pending = false;*/
-}
-
-StagingTexture2D* Renderer::PrepareFrameDumpImage(u32 width, u32 height, u64 ticks)
-{
- // Ensure the last frame that was sent to the frame dump has completed encoding before we send
- // the next image to it.
- //FinishFrameData();
-
- // If the last image hasn't been written to the frame dump yet, write it now.
- // This is necessary so that the worker thread is no more than one frame behind, and the pointer
- // (which is actually the buffer) is safe for us to re-use next time.
- if (m_frame_dump_images[m_current_frame_dump_image].pending)
- WriteFrameDumpImage(m_current_frame_dump_image);
-
- // Move to the next image buffer
- m_current_frame_dump_image = (m_current_frame_dump_image + 1) % FRAME_DUMP_BUFFERED_FRAMES;
- FrameDumpImage& image = m_frame_dump_images[m_current_frame_dump_image];
-
- // Ensure the dimensions of the readback texture are sufficient.
- if (!image.readback_texture || width != image.readback_texture->GetWidth() ||
- height != image.readback_texture->GetHeight())
- {
- // Allocate a new readback texture.
- // The reset() call is here so that the memory is released before allocating the new texture.
- image.readback_texture.reset();
- image.readback_texture = StagingTexture2D::Create(STAGING_BUFFER_TYPE_READBACK, width, height,
- EFB_COLOR_TEXTURE_FORMAT);
-
- if (!image.readback_texture || !image.readback_texture->Map())
- {
- // Not actually fatal, just means we can't dump this frame.
- PanicAlert("Failed to allocate frame dump readback texture.");
- image.readback_texture.reset();
- return nullptr;
- }
- }
-
- // The copy happens immediately after this function returns, so flag this frame as pending.
- image.fence = g_command_buffer_mgr->GetCurrentCommandBufferFence();
- image.dump_state = AVIDump::FetchState(ticks);
- image.pending = true;
- return image.readback_texture.get();
-}
-
-void Renderer::FlushFrameDump()
-{
- // We must write frames in order, so this is why we use a counter rather than a range.
- for (size_t i = 0; i < FRAME_DUMP_BUFFERED_FRAMES; i++)
- {
- if (m_frame_dump_images[m_current_frame_dump_image].pending)
- WriteFrameDumpImage(m_current_frame_dump_image);
-
- m_current_frame_dump_image = (m_current_frame_dump_image + 1) % FRAME_DUMP_BUFFERED_FRAMES;
- }
-
- // Since everything has been written now, may as well start at index zero.
- // count-1 here because the index is incremented before usage.
- m_current_frame_dump_image = FRAME_DUMP_BUFFERED_FRAMES - 1;
-}
-
void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_rect,
const TargetRectangle& src_rect, const Texture2D* src_tex)
{
@@ -908,100 +646,6 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r
}
}
-bool Renderer::ResizeFrameDumpBuffer(u32 new_width, u32 new_height)
-{
- if (m_frame_dump_render_texture && m_frame_dump_render_texture->GetWidth() == new_width &&
- m_frame_dump_render_texture->GetHeight() == new_height)
- {
- return true;
- }
-
- // Ensure all previous frames have been dumped, since we are destroying a framebuffer
- // that may still be in use.
- FlushFrameDump();
-
- if (m_frame_dump_framebuffer != VK_NULL_HANDLE)
- {
- vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_frame_dump_framebuffer, nullptr);
- m_frame_dump_framebuffer = VK_NULL_HANDLE;
- }
-
- m_frame_dump_render_texture =
- Texture2D::Create(new_width, new_height, 1, 1, EFB_COLOR_TEXTURE_FORMAT,
- VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
-
- if (!m_frame_dump_render_texture)
- {
- WARN_LOG(VIDEO, "Failed to resize frame dump render texture");
- m_frame_dump_render_texture.reset();
- return false;
- }
-
- VkImageView attachment = m_frame_dump_render_texture->GetView();
- VkFramebufferCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- info.renderPass = FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass();
- info.attachmentCount = 1;
- info.pAttachments = &attachment;
- info.width = new_width;
- info.height = new_height;
- info.layers = 1;
-
- VkResult res =
- vkCreateFramebuffer(g_vulkan_context->GetDevice(), &info, nullptr, &m_frame_dump_framebuffer);
- if (res != VK_SUCCESS)
- {
- WARN_LOG(VIDEO, "Failed to create frame dump framebuffer");
- m_frame_dump_render_texture.reset();
- return false;
- }
-
- // Render pass expects texture is in transfer src to start with.
- m_frame_dump_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
-
- return true;
-}
-
-void Renderer::DestroyFrameDumpResources()
-{
- if (m_frame_dump_framebuffer != VK_NULL_HANDLE)
- {
- vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_frame_dump_framebuffer, nullptr);
- m_frame_dump_framebuffer = VK_NULL_HANDLE;
- }
-
- m_frame_dump_render_texture.reset();
-
- for (FrameDumpImage& image : m_frame_dump_images)
- {
- image.readback_texture.reset();
- image.fence = VK_NULL_HANDLE;
- image.dump_state = {};
- image.pending = false;
- }
- m_current_frame_dump_image = FRAME_DUMP_BUFFERED_FRAMES - 1;
-}
-
-void Renderer::CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height)
-{
- /*if (FramebufferManagerBase::LastXfbWidth() == fb_stride &&
- FramebufferManagerBase::LastXfbHeight() == fb_height)
- {
- return;
- }
-
- u32 new_width = (fb_stride < 1 || fb_stride > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fb_stride;
- u32 new_height = (fb_height < 1 || fb_height > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fb_height;
- FramebufferManagerBase::SetLastXfbWidth(new_width);
- FramebufferManagerBase::SetLastXfbHeight(new_height);
-
- // Changing the XFB source area may alter the target size.
- if (CalculateTargetSize())
- ResizeEFBTextures();*/
-}
-
void Renderer::CheckForSurfaceChange()
{
if (!m_surface_needs_change.IsSet())
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h
index b9d746582c..a94d44138b 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.h
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.h
@@ -72,7 +72,6 @@ private:
void BeginFrame();
- void CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height);
void CheckForSurfaceChange();
void CheckForConfigChanges();
@@ -86,61 +85,13 @@ private:
bool CompileShaders();
void DestroyShaders();
- // Transitions EFB/XFB buffers to SHADER_READ_ONLY, ready for presenting/dumping.
- // If MSAA is enabled, and XFB is disabled, also resolves the EFB buffer.
- void TransitionBuffersForSwap(const TargetRectangle& scaled_rect,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count);
-
- // Draw either the EFB, or specified XFB sources to the currently-bound framebuffer.
- void DrawFrame(VkRenderPass render_pass, const TargetRectangle& target_rect,
- 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 DrawEFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
- const TargetRectangle& scaled_efb_rect);
- void DrawVirtualXFB(VkRenderPass render_pass, const TargetRectangle& target_rect, u32 xfb_addr,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height);
- void DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
- const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
- u32 fb_stride, u32 fb_height);
-
// Draw the frame, as well as the OSD to the swap chain.
void DrawScreen(VKTexture* xfb_texture);
- // Draw the frame only to the screenshot buffer.
- bool DrawFrameDump(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, u64 ticks);
-
- // Sets up renderer state to permit framedumping.
- // Ideally we would have EndFrameDumping be a virtual method of Renderer, but due to various
- // design issues it would have to end up being called in the destructor, which won't work.
- void StartFrameDumping();
- void EndFrameDumping();
-
- // Fence callback so that we know when frames are ready to be written to the dump.
- // This is done by clearing the fence pointer, so WriteFrameDumpFrame doesn't have to wait.
- void OnFrameDumpImageReady(VkFence fence);
-
- // Writes the specified buffered frame to the frame dump.
- // NOTE: Assumes that frame.ticks and frame.pending are valid.
- void WriteFrameDumpImage(size_t index);
-
- // If there is a pending frame in this buffer, writes it to the frame dump.
- // Ensures that the specified readback buffer meets the size requirements of the current frame.
- StagingTexture2D* PrepareFrameDumpImage(u32 width, u32 height, u64 ticks);
-
- // Ensures all buffered frames are written to frame dump.
- void FlushFrameDump();
-
// Copies/scales an image to the currently-bound framebuffer.
void BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_rect,
const TargetRectangle& src_rect, const Texture2D* src_tex);
- bool ResizeFrameDumpBuffer(u32 new_width, u32 new_height);
- void DestroyFrameDumpResources();
-
VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE;
VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE;
@@ -153,22 +104,5 @@ private:
// Shaders used for clear/blit.
VkShaderModule m_clear_fragment_shader = VK_NULL_HANDLE;
-
- // Texture used for screenshot/frame dumping
- std::unique_ptr m_frame_dump_render_texture;
- VkFramebuffer m_frame_dump_framebuffer = VK_NULL_HANDLE;
-
- // Readback resources for frame dumping
- static const size_t FRAME_DUMP_BUFFERED_FRAMES = 2;
- struct FrameDumpImage
- {
- std::unique_ptr readback_texture;
- VkFence fence = VK_NULL_HANDLE;
- AVIDump::Frame dump_state = {};
- bool pending = false;
- };
- std::array m_frame_dump_images;
- size_t m_current_frame_dump_image = FRAME_DUMP_BUFFERED_FRAMES - 1;
- bool m_frame_dumping_active = false;
};
}
diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp
index d749cb7bcf..5e95cff805 100644
--- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp
+++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp
@@ -14,145 +14,7 @@
std::unique_ptr g_framebuffer_manager;
-std::unique_ptr
- FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode
-FramebufferManagerBase::VirtualXFBListType
- FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
-std::array
- FramebufferManagerBase::m_overlappingXFBArray;
-
unsigned int FramebufferManagerBase::m_EFBLayers = 1;
-FramebufferManagerBase::FramebufferManagerBase()
-{
- // Can't hurt
- m_overlappingXFBArray.fill(nullptr);
-}
+FramebufferManagerBase::~FramebufferManagerBase() = default;
-FramebufferManagerBase::~FramebufferManagerBase()
-{
- // Necessary, as these are static members
- // (they really shouldn't be and should be refactored at some point).
- m_virtualXFBList.clear();
- m_realXFBSource.reset();
-}
-
-void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight,
- const EFBRectangle& sourceRc, float Gamma)
-{
-}
-
-void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight,
- const EFBRectangle& sourceRc, float Gamma)
-{
- if (!g_framebuffer_manager)
- return;
-
- VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, sourceRc.GetWidth(), fbHeight);
-
- if (m_virtualXFBList.end() == vxfb)
- {
- if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB)
- {
- // create a new Virtual XFB and place it at the front of the list
- m_virtualXFBList.emplace_front();
- vxfb = m_virtualXFBList.begin();
- }
- else
- {
- // Replace the last virtual XFB
- --vxfb;
- }
- }
- // else // replace existing virtual XFB
-
- // move this Virtual XFB to the front of the list.
- if (m_virtualXFBList.begin() != vxfb)
- m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb);
-
- u32 target_width, target_height;
- std::tie(target_width, target_height) = g_framebuffer_manager->GetTargetSize();
-
- // recreate if needed
- if (vxfb->xfbSource &&
- (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height))
- vxfb->xfbSource.reset();
-
- if (!vxfb->xfbSource)
- {
- vxfb->xfbSource =
- g_framebuffer_manager->CreateXFBSource(target_width, target_height, m_EFBLayers);
- if (!vxfb->xfbSource)
- return;
-
- vxfb->xfbSource->texWidth = target_width;
- vxfb->xfbSource->texHeight = target_height;
- }
-
- vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr;
- vxfb->xfbSource->srcWidth = vxfb->xfbWidth = sourceRc.GetWidth();
- vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
-
- vxfb->xfbSource->sourceRc = g_renderer->ConvertEFBRectangle(sourceRc);
-
- // keep stale XFB data from being used
- ReplaceVirtualXFB();
-
- // Copy EFB data to XFB and restore render target again
- vxfb->xfbSource->CopyEFB(Gamma);
-}
-
-FramebufferManagerBase::VirtualXFBListType::iterator
-FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
-{
- const u32 srcLower = xfbAddr;
- const u32 srcUpper = xfbAddr + 2 * width * height;
-
- return std::find_if(m_virtualXFBList.begin(), m_virtualXFBList.end(),
- [srcLower, srcUpper](const VirtualXFB& xfb) {
- const u32 dstLower = xfb.xfbAddr;
- const u32 dstUpper = xfb.xfbAddr + 2 * xfb.xfbWidth * xfb.xfbHeight;
-
- return dstLower >= srcLower && dstUpper <= srcUpper;
- });
-}
-
-void FramebufferManagerBase::ReplaceVirtualXFB()
-{
- VirtualXFBListType::iterator it = m_virtualXFBList.begin();
-
- const s32 srcLower = it->xfbAddr;
- const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
- const s32 lineSize = 2 * it->xfbWidth;
-
- ++it;
-
- for (; it != m_virtualXFBList.end(); ++it)
- {
- s32 dstLower = it->xfbAddr;
- s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
-
- if (dstLower >= srcLower && dstUpper <= srcUpper)
- {
- // Invalidate the data
- it->xfbAddr = 0;
- it->xfbHeight = 0;
- it->xfbWidth = 0;
- }
- else if (AddressRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
- {
- s32 upperOverlap = (srcUpper - dstLower) / lineSize;
- s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
-
- if (upperOverlap > 0 && lowerOverlap < 0)
- {
- it->xfbAddr += lineSize * upperOverlap;
- it->xfbHeight -= upperOverlap;
- }
- else if (lowerOverlap > 0)
- {
- it->xfbHeight -= lowerOverlap;
- }
- }
- }
-}
diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.h b/Source/Core/VideoCommon/FramebufferManagerBase.h
index b0ba40b1a0..2d725fa346 100644
--- a/Source/Core/VideoCommon/FramebufferManagerBase.h
+++ b/Source/Core/VideoCommon/FramebufferManagerBase.h
@@ -17,76 +17,16 @@ inline bool AddressRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
return !((aLower >= bUpper) || (bLower >= aUpper));
}
-struct XFBSourceBase
-{
- virtual ~XFBSourceBase() {}
-
- virtual void CopyEFB(float Gamma) = 0;
-
- u32 srcAddr;
- u32 srcWidth;
- u32 srcHeight;
-
- unsigned int texWidth;
- unsigned int texHeight;
-
- // TODO: only used by OGL
- TargetRectangle sourceRc;
-};
-
class FramebufferManagerBase
{
public:
- enum
- {
- // There may be multiple XFBs in GameCube RAM. This is the maximum number to
- // virtualize.
- MAX_VIRTUAL_XFB = 8
- };
-
- FramebufferManagerBase();
virtual ~FramebufferManagerBase();
- static void CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,
- float Gamma);
-
static unsigned int GetEFBLayers() { return m_EFBLayers; }
- virtual std::pair GetTargetSize() const = 0;
protected:
- struct VirtualXFB
- {
- VirtualXFB() {}
- // Address and size in GameCube RAM
- u32 xfbAddr = 0;
- u32 xfbWidth = 0;
- u32 xfbHeight = 0;
-
- std::unique_ptr xfbSource;
- };
-
- typedef std::list VirtualXFBListType;
static unsigned int m_EFBLayers;
-
-private:
- virtual std::unique_ptr
- CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) = 0;
-
- static VirtualXFBListType::iterator FindVirtualXFB(u32 xfbAddr, u32 width, u32 height);
-
- static void ReplaceVirtualXFB();
-
- // TODO: merge these virtual funcs, they are nearly all the same
- virtual void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,
- float Gamma = 1.0f) = 0;
- static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,
- float Gamma = 1.0f);
-
- static std::unique_ptr m_realXFBSource; // Only used in Real XFB mode
- static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
-
- static std::array m_overlappingXFBArray;
};
extern std::unique_ptr g_framebuffer_manager;
diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp
index 0a3648c9ea..4bc8911b08 100644
--- a/Source/Core/VideoCommon/RenderBase.cpp
+++ b/Source/Core/VideoCommon/RenderBase.cpp
@@ -112,8 +112,6 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStri
if (!fbStride || !fbHeight)
return;
-
- m_xfb_written = true;
}
unsigned int Renderer::GetEFBScale() const
@@ -412,34 +410,6 @@ std::tuple Renderer::ScaleToDisplayAspectRatio(const int width,
return std::make_tuple(scaled_width, scaled_height);
}
-TargetRectangle Renderer::CalculateFrameDumpDrawRectangle() const
-{
- // No point including any borders in the frame dump image, since they'd have to be cropped anyway.
- TargetRectangle rc;
- rc.left = 0;
- rc.top = 0;
-
- // If full-resolution frame dumping is disabled, just use the window draw rectangle.
- if (!g_ActiveConfig.bInternalResolutionFrameDumps)
- {
- // But still remove the borders, since the caller expects this.
- rc.right = m_target_rectangle.GetWidth();
- rc.bottom = m_target_rectangle.GetHeight();
- return rc;
- }
-
- // Grab the dimensions of the EFB textures, we scale either of these depending on the ratio.
- u32 efb_width, efb_height;
- std::tie(efb_width, efb_height) = g_framebuffer_manager->GetTargetSize();
-
- float draw_width, draw_height;
- std::tie(draw_width, draw_height) = ScaleToDisplayAspectRatio(efb_width, efb_height);
-
- rc.right = static_cast(std::ceil(draw_width));
- rc.bottom = static_cast(std::ceil(draw_height));
- return rc;
-}
-
void Renderer::UpdateDrawRectangle()
{
// The rendering window size
@@ -693,7 +663,6 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const
stats.ResetFrame();
Core::Callback_VideoCopiedToXFB(update_frame_count);
- m_xfb_written = false;
}
bool Renderer::IsFrameDumping()
diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h
index 1d776a97d1..f2063e8228 100644
--- a/Source/Core/VideoCommon/RenderBase.h
+++ b/Source/Core/VideoCommon/RenderBase.h
@@ -96,7 +96,6 @@ public:
float CalculateDrawAspectRatio() const;
std::tuple ScaleToDisplayAspectRatio(int width, int height) const;
- TargetRectangle CalculateFrameDumpDrawRectangle() const;
void UpdateDrawRectangle();
// Use this to convert a single target rectangle to two stereo rectangles
@@ -167,7 +166,6 @@ protected:
int m_backbuffer_width = 0;
int m_backbuffer_height = 0;
TargetRectangle m_target_rectangle = {};
- bool m_xfb_written = false;
FPSCounter m_fps_counter;