From 79387dddb24ddf035b70cd9379a42368dcd49e93 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 29 May 2017 17:02:09 -0500 Subject: [PATCH 01/40] Add support for hybrid XFB --- Source/Core/VideoBackends/D3D/D3D.vcxproj | 2 - .../VideoBackends/D3D/D3D.vcxproj.filters | 6 - .../VideoBackends/D3D/FramebufferManager.cpp | 6 - .../VideoBackends/D3D/FramebufferManager.h | 1 - .../VideoBackends/D3D/PSTextureEncoder.cpp | 5 +- Source/Core/VideoBackends/D3D/Render.cpp | 107 +--------- Source/Core/VideoBackends/D3D/Render.h | 3 +- Source/Core/VideoBackends/D3D/Television.cpp | 166 --------------- Source/Core/VideoBackends/D3D/Television.h | 45 ---- Source/Core/VideoBackends/D3D/main.cpp | 1 + .../VideoBackends/Null/FramebufferManager.h | 1 - Source/Core/VideoBackends/Null/Render.cpp | 2 +- Source/Core/VideoBackends/Null/Render.h | 3 +- .../VideoBackends/OGL/FramebufferManager.cpp | 9 +- .../VideoBackends/OGL/FramebufferManager.h | 1 - .../Core/VideoBackends/OGL/PostProcessing.cpp | 6 +- Source/Core/VideoBackends/OGL/Render.cpp | 156 ++------------ Source/Core/VideoBackends/OGL/Render.h | 20 +- Source/Core/VideoBackends/OGL/main.cpp | 1 + .../VideoBackends/Software/EfbInterface.cpp | 34 +-- .../VideoBackends/Software/SWOGLWindow.cpp | 27 +-- .../Core/VideoBackends/Software/SWOGLWindow.h | 8 +- .../VideoBackends/Software/SWRenderer.cpp | 91 +------- .../Core/VideoBackends/Software/SWRenderer.h | 9 +- Source/Core/VideoBackends/Software/SWmain.cpp | 60 +----- .../VideoBackends/Software/Software.vcxproj | 1 + .../VideoBackends/Software/TextureCache.h | 41 ++++ .../Vulkan/FramebufferManager.cpp | 14 -- .../VideoBackends/Vulkan/FramebufferManager.h | 3 - Source/Core/VideoBackends/Vulkan/Renderer.cpp | 54 ++--- Source/Core/VideoBackends/Vulkan/Renderer.h | 8 +- .../VideoBackends/Vulkan/VulkanContext.cpp | 1 + Source/Core/VideoCommon/BPStructs.cpp | 12 +- .../VideoCommon/FramebufferManagerBase.cpp | 98 --------- .../Core/VideoCommon/FramebufferManagerBase.h | 18 -- Source/Core/VideoCommon/RenderBase.cpp | 35 ++- Source/Core/VideoCommon/RenderBase.h | 4 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 201 +++++++++++------- Source/Core/VideoCommon/TextureCacheBase.h | 14 +- .../VideoCommon/TextureConversionShader.cpp | 27 +++ Source/Core/VideoCommon/TextureDecoder.h | 10 + .../VideoCommon/TextureDecoder_Common.cpp | 39 +++- .../Core/VideoCommon/TextureDecoder_x64.cpp | 32 +++ Source/Core/VideoCommon/VideoCommon.h | 2 + Source/Core/VideoCommon/VideoConfig.h | 1 + 45 files changed, 400 insertions(+), 985 deletions(-) delete mode 100644 Source/Core/VideoBackends/D3D/Television.cpp delete mode 100644 Source/Core/VideoBackends/D3D/Television.h create mode 100644 Source/Core/VideoBackends/Software/TextureCache.h 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 @@ - @@ -73,7 +72,6 @@ - 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 @@ Render - - Render - Render @@ -108,9 +105,6 @@ Render - - Render - Render 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 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 s_clear_blend_states{}; static std::array 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(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(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(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 - -#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 - // - - "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 fill(MAX_XFB_SIZE); - for (size_t i = 0; i < MAX_XFB_SIZE / sizeof(u32); ++i) - reinterpret_cast(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 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(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(std::max(GLInterface->GetBackBufferWidth(), 1u)); int window_height = static_cast(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(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(xfbSource->srcAddr) - static_cast(xfb_addr)) / - (static_cast(fb_stride) * 2); - - draw_rc.top = target_rc.top - hOffset * target_rc.GetHeight() / static_cast(fb_height); - draw_rc.bottom = - target_rc.top - (hOffset + xfbHeight) * target_rc.GetHeight() / static_cast(fb_height); - draw_rc.left = - target_rc.left + - (target_rc.GetWidth() - xfbWidth * target_rc.GetWidth() / static_cast(fb_stride)) / 2; - draw_rc.right = - target_rc.left + - (target_rc.GetWidth() + xfbWidth * target_rc.GetWidth() / static_cast(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(fb_width) / static_cast(target_rc.GetWidth()); - // float v_scale = static_cast(fb_height) / static_cast(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(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::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(MAX_XFB_WIDTH), static_cast(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 #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 CreateTexture(const TextureConfig& config) override - { - return std::make_unique(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 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 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(); g_vertex_manager = std::make_unique(); g_perf_query = std::make_unique(); g_texture_cache = std::make_unique(); SWRenderer::Init(); - g_framebuffer_manager = std::make_unique(); } 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 @@ + 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 + +#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 CreateTexture(const TextureConfig& config) override + { + return std::make_unique(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 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(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(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 GetTargetSize() const override; std::unique_ptr 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(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(fb_stride), static_cast(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) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 5605284092..977cc46b3e 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -250,16 +250,18 @@ static void BPWritten(const BPCmd& bp) float num_xfb_lines = 1.0f + bpmem.copyTexSrcWH.y * yScale; u32 height = static_cast(num_xfb_lines); - if (height > MAX_XFB_HEIGHT) - { - INFO_LOG(VIDEO, "Tried to scale EFB to too many XFB lines: %d (%f)", height, num_xfb_lines); - height = MAX_XFB_HEIGHT; - } DEBUG_LOG(VIDEO, "RenderToXFB: destAddr: %08x | srcRect {%d %d %d %d} | fbWidth: %u | " "fbStride: %u | fbHeight: %u", destAddr, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, bpmem.copyTexSrcWH.x + 1, destStride, height); + + bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24; + g_texture_cache->CopyRenderTargetToTexture(destAddr, EFBCopyFormat::XFB, destStride, + is_depth_copy, srcRect, false, + false); + + // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); } diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index dd2cc88735..4bcb5e6567 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -21,9 +21,6 @@ FramebufferManagerBase::VirtualXFBListType std::array FramebufferManagerBase::m_overlappingXFBArray; -unsigned int FramebufferManagerBase::s_last_xfb_width = 1; -unsigned int FramebufferManagerBase::s_last_xfb_height = 1; - unsigned int FramebufferManagerBase::m_EFBLayers = 1; FramebufferManagerBase::FramebufferManagerBase() @@ -40,85 +37,6 @@ FramebufferManagerBase::~FramebufferManagerBase() m_realXFBSource.reset(); } -const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, - u32 fbHeight, u32* xfbCountP) -{ - if (!g_ActiveConfig.bUseXFB) - return nullptr; - - if (g_ActiveConfig.bUseRealXFB) - return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCountP); - else - return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCountP); -} - -const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, - u32 fbHeight, u32* xfbCountP) -{ - *xfbCountP = 1; - - // recreate if needed - if (m_realXFBSource && - (m_realXFBSource->texWidth != fbWidth || m_realXFBSource->texHeight != fbHeight)) - m_realXFBSource.reset(); - - if (!m_realXFBSource && g_framebuffer_manager) - m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight, 1); - - if (!m_realXFBSource) - return nullptr; - - m_realXFBSource->srcAddr = xfbAddr; - - m_realXFBSource->srcWidth = MAX_XFB_WIDTH; - m_realXFBSource->srcHeight = MAX_XFB_HEIGHT; - - m_realXFBSource->texWidth = fbWidth; - m_realXFBSource->texHeight = fbHeight; - - m_realXFBSource->sourceRc.left = 0; - m_realXFBSource->sourceRc.top = 0; - m_realXFBSource->sourceRc.right = fbWidth; - m_realXFBSource->sourceRc.bottom = fbHeight; - - // Decode YUYV data from GameCube RAM - m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight); - - m_overlappingXFBArray[0] = m_realXFBSource.get(); - return &m_overlappingXFBArray[0]; -} - -const XFBSourceBase* const* -FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCountP) -{ - u32 xfbCount = 0; - - if (m_virtualXFBList.empty()) // no Virtual XFBs available - return nullptr; - - u32 srcLower = xfbAddr; - u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight; - - VirtualXFBListType::reverse_iterator it = m_virtualXFBList.rbegin(), - vlend = m_virtualXFBList.rend(); - for (; it != vlend; ++it) - { - VirtualXFB* vxfb = &*it; - - u32 dstLower = vxfb->xfbAddr; - u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight; - - if (AddressRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) - { - m_overlappingXFBArray[xfbCount] = vxfb->xfbSource.get(); - ++xfbCount; - } - } - - *xfbCountP = xfbCount; - return &m_overlappingXFBArray[0]; -} - void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { @@ -247,19 +165,3 @@ void FramebufferManagerBase::ReplaceVirtualXFB() } } } - -int FramebufferManagerBase::ScaleToVirtualXfbWidth(int x, const TargetRectangle& target_rectangle) -{ - if (g_ActiveConfig.RealXFBEnabled()) - return x; - - return x * target_rectangle.GetWidth() / s_last_xfb_width; -} - -int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y, const TargetRectangle& target_rectangle) -{ - if (g_ActiveConfig.RealXFBEnabled()) - return y; - - return y * target_rectangle.GetHeight() / s_last_xfb_height; -} diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.h b/Source/Core/VideoCommon/FramebufferManagerBase.h index c780a3fa21..b0ba40b1a0 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/FramebufferManagerBase.h @@ -20,7 +20,6 @@ inline bool AddressRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) struct XFBSourceBase { virtual ~XFBSourceBase() {} - virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0; virtual void CopyEFB(float Gamma) = 0; @@ -50,15 +49,6 @@ public: static void CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma); - static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, - u32* xfbCount); - - static void SetLastXfbWidth(unsigned int width) { s_last_xfb_width = width; } - static void SetLastXfbHeight(unsigned int height) { s_last_xfb_height = height; } - static unsigned int LastXfbWidth() { return s_last_xfb_width; } - static unsigned int LastXfbHeight() { return s_last_xfb_height; } - static int ScaleToVirtualXfbWidth(int x, const TargetRectangle& target_rectangle); - static int ScaleToVirtualXfbHeight(int y, const TargetRectangle& target_rectangle); static unsigned int GetEFBLayers() { return m_EFBLayers; } virtual std::pair GetTargetSize() const = 0; @@ -93,18 +83,10 @@ private: static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma = 1.0f); - static const XFBSourceBase* const* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, - u32* xfbCount); - static const XFBSourceBase* const* GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, - u32* xfbCount); - 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; - - static unsigned int s_last_xfb_width; - static unsigned int s_last_xfb_height; }; extern std::unique_ptr g_framebuffer_manager; diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 63e3f5f5ed..2af607dd64 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -84,9 +84,6 @@ static float AspectToWidescreen(float aspect) Renderer::Renderer(int backbuffer_width, int backbuffer_height) : m_backbuffer_width(backbuffer_width), m_backbuffer_height(backbuffer_height) { - FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH); - FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT); - UpdateActiveConfig(); UpdateDrawRectangle(); CalculateTargetSize(); @@ -116,19 +113,6 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStri return; m_xfb_written = true; - - if (g_ActiveConfig.bUseXFB) - { - FramebufferManagerBase::CopyToXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); - } - else - { - // The timing is not predictable here. So try to use the XFB path to dump frames. - u64 ticks = CoreTiming::GetTicks(); - - // below div two to convert from bytes to pixels - it expects width, not stride - Swap(xfbAddr, fbStride / 2, fbStride / 2, fbHeight, sourceRc, ticks, Gamma); - } } unsigned int Renderer::GetEFBScale() const @@ -433,9 +417,7 @@ TargetRectangle Renderer::CalculateFrameDumpDrawRectangle() const rc.top = 0; // If full-resolution frame dumping is disabled, just use the window draw rectangle. - // Also do this if RealXFB is enabled, since the image has been downscaled for the XFB copy - // anyway, and there's no point writing an upscaled frame with no filtering. - if (!g_ActiveConfig.bInternalResolutionFrameDumps || g_ActiveConfig.RealXFBEnabled()) + if (!g_ActiveConfig.bInternalResolutionFrameDumps) { // But still remove the borders, since the caller expects this. rc.right = m_target_rectangle.GetWidth(); @@ -663,8 +645,19 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_aspect_wide = flush_count_anamorphic > 0.75 * flush_total; } - // TODO: merge more generic parts into VideoCommon - SwapImpl(xfbAddr, fbWidth, fbStride, fbHeight, rc, ticks, Gamma); + if (xfbAddr && fbWidth && fbStride && fbHeight) + { + constexpr int force_safe_texture_cache_hash = 0; + // Get the current XFB from texture cache + auto* xfb_entry = g_texture_cache->GetTexture(xfbAddr, fbWidth, fbHeight, TextureFormat::XFB, + force_safe_texture_cache_hash); + + // TODO, check if xfb_entry is a duplicate of the previous frame and skip SwapImpl + + + // TODO: merge more generic parts into VideoCommon + g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, Gamma); + } if (m_xfb_written) m_fps_counter.Update(); diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 30f16c35a0..9de7c6393b 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -32,6 +32,7 @@ #include "VideoCommon/RenderState.h" #include "VideoCommon/VideoCommon.h" +class AbstractTexture; class PostProcessingShaderImplementation; enum class EFBAccessType; @@ -132,8 +133,7 @@ public: // Finish up the current frame, print some stats void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks, float Gamma = 1.0f); - virtual void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, - const EFBRectangle& rc, u64 ticks, float Gamma = 1.0f) = 0; + virtual void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma = 1.0f) = 0; PEControl::PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; } void StorePixelFormat(PEControl::PixelFormat new_format) { m_prev_efb_format = new_format; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 0c0d0e4e36..fb30575a95 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -238,7 +238,8 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTForma if (!decoded_entry) return nullptr; - decoded_entry->SetGeneralParameters(entry->addr, entry->size_in_bytes, entry->format); + decoded_entry->SetGeneralParameters(entry->addr, entry->size_in_bytes, entry->format, + entry->should_force_safe_hashing); decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); decoded_entry->SetHashes(entry->base_hash, entry->hash); decoded_entry->frameCount = FRAMECOUNT_INVALID; @@ -462,20 +463,6 @@ static u32 CalculateLevelSize(u32 level_0_size, u32 level) return std::max(level_0_size >> level, 1u); } -// Used by TextureCacheBase::Load -TextureCacheBase::TCacheEntry* TextureCacheBase::ReturnEntry(unsigned int stage, TCacheEntry* entry) -{ - entry->frameCount = FRAMECOUNT_INVALID; - bound_textures[stage] = entry; - - GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); - - // We need to keep track of invalided textures until they have actually been replaced or re-loaded - valid_bind_points.set(stage); - - return entry; -} - void TextureCacheBase::BindTextures() { for (size_t i = 0; i < bound_textures.size(); ++i) @@ -625,7 +612,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) // if this stage was not invalidated by changes to texture registers, keep the current texture if (IsValidBindPoint(stage) && bound_textures[stage]) { - return ReturnEntry(stage, bound_textures[stage]); + return bound_textures[stage]; } const FourTexUnits& tex = bpmem.tex[stage >> 2]; @@ -639,7 +626,35 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) const bool use_mipmaps = SamplerCommon::AreBpTexMode0MipmapsEnabled(tex.texMode0[id]); u32 tex_levels = use_mipmaps ? ((tex.texMode1[id].max_lod + 0xf) / 0x10 + 1) : 1; const bool from_tmem = tex.texImage1[id].image_type != 0; + const u32 tmem_address_even = from_tmem ? tex.texImage1[id].tmem_even * TMEM_LINE_SIZE : 0; + const u32 tmem_address_odd = from_tmem ? tex.texImage2[id].tmem_odd * TMEM_LINE_SIZE : 0; + auto entry = GetTexture(address, width, height, texformat, + g_ActiveConfig.iSafeTextureCache_ColorSamples, tlutaddr, tlutfmt, + use_mipmaps, tex_levels, from_tmem, tmem_address_even, + tmem_address_odd); + + if (!entry) + return nullptr; + + entry->frameCount = FRAMECOUNT_INVALID; + bound_textures[stage] = entry; + + GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); + + // We need to keep track of invalided textures until they have actually been replaced or re-loaded + valid_bind_points.set(stage); + + return entry; +} + +TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, + const TextureFormat texformat, + const int textureCacheSafetyColorSampleSize, u32 tlutaddr, + TLUTFormat tlutfmt, bool use_mipmaps, + u32 tex_levels, bool from_tmem, u32 tmem_address_even, + u32 tmem_address_odd) +{ // TexelSizeInNibbles(format) * width * height / 16; const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat); const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat); @@ -683,9 +698,12 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); } + // TODO: the texture cache lookup is based on address, but a texture from tmem has no reason + // to have a unique and valid address. This could result in a regular texture and a tmem + // texture aliasing onto the same texture cache entry. const u8* src_data; if (from_tmem) - src_data = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE]; + src_data = &texMem[tmem_address_even]; else src_data = Memory::GetPointer(address); @@ -704,13 +722,13 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) // TODO: This doesn't hash GB tiles for preloaded RGBA8 textures (instead, it's hashing more data // from the low tmem bank than it should) - base_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); + base_hash = GetHash64(src_data, texture_size, textureCacheSafetyColorSampleSize); u32 palette_size = 0; if (isPaletteTexture) { palette_size = TexDecoder_GetPaletteSize(texformat); full_hash = base_hash ^ GetHash64(&texMem[tlutaddr], palette_size, - g_ActiveConfig.iSafeTextureCache_ColorSamples); + textureCacheSafetyColorSampleSize); } else { @@ -789,7 +807,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) // texture formats. I'm not sure what effect checking width/height/levels // would have. if (!isPaletteTexture || !g_Config.backend_info.bSupportsPaletteConversion) - return ReturnEntry(stage, entry); + return entry; // Note that we found an unconverted EFB copy, then continue. We'll // perform the conversion later. Currently, we only convert EFB copies to @@ -816,7 +834,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) { entry = DoPartialTextureUpdates(iter->second, &texMem[tlutaddr], tlutfmt); - return ReturnEntry(stage, entry); + return entry; } } @@ -841,7 +859,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) if (decoded_entry) { - return ReturnEntry(stage, decoded_entry); + return decoded_entry; } } @@ -851,9 +869,9 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) // textures cause unnecessary slowdowns // Example: Tales of Symphonia (GC) uses over 500 small textures in menus, but only around 70 // different ones - if (g_ActiveConfig.iSafeTextureCache_ColorSamples == 0 || + if (textureCacheSafetyColorSampleSize == 0 || std::max(texture_size, palette_size) <= - (u32)g_ActiveConfig.iSafeTextureCache_ColorSamples * 8) + (u32)textureCacheSafetyColorSampleSize * 8) { auto hash_range = textures_by_hash.equal_range(full_hash); TexHashCache::iterator hash_iter = hash_range.first; @@ -866,7 +884,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) { entry = DoPartialTextureUpdates(hash_iter->second, &texMem[tlutaddr], tlutfmt); - return ReturnEntry(stage, entry); + return entry; } ++hash_iter; } @@ -936,64 +954,66 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) // Initialized to null because only software loading uses this buffer u8* dst_buffer = nullptr; - if (!hires_tex && decode_on_gpu) + if (!hires_tex) { - u32 row_stride = bytes_per_block * (expandedWidth / bsw); - g_texture_cache->DecodeTextureOnGPU(entry, 0, src_data, texture_size, texformat, width, height, - expandedWidth, expandedHeight, row_stride, tlut, tlutfmt); - } - else if (!hires_tex) - { - size_t decoded_texture_size = expandedWidth * sizeof(u32) * expandedHeight; - - // Allocate memory for all levels at once - size_t total_texture_size = decoded_texture_size; - - // For the downsample, we need 2 buffers; 1 is 1/4 of the original texture, the other 1/16 - size_t mip_downsample_buffer_size = decoded_texture_size * 5 / 16; - - size_t prev_level_size = decoded_texture_size; - for (u32 i = 1; i < tex_levels; ++i) + if (decode_on_gpu) { - prev_level_size /= 4; - total_texture_size += prev_level_size; - } - - // Add space for the downsampling at the end - total_texture_size += mip_downsample_buffer_size; - - CheckTempSize(total_texture_size); - dst_buffer = temp; - - if (!(texformat == TextureFormat::RGBA8 && from_tmem)) - { - TexDecoder_Decode(dst_buffer, src_data, expandedWidth, expandedHeight, texformat, tlut, - tlutfmt); + u32 row_stride = bytes_per_block * (expandedWidth / bsw); + g_texture_cache->DecodeTextureOnGPU( + entry, 0, src_data, texture_size, texformat, width, height, + expandedWidth, expandedHeight, row_stride, tlut, tlutfmt); } else { - u8* src_data_gb = - &texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE]; - TexDecoder_DecodeRGBA8FromTmem(dst_buffer, src_data, src_data_gb, expandedWidth, - expandedHeight); + size_t decoded_texture_size = expandedWidth * sizeof(u32) * expandedHeight; + + // Allocate memory for all levels at once + size_t total_texture_size = decoded_texture_size; + + // For the downsample, we need 2 buffers; 1 is 1/4 of the original texture, the other 1/16 + size_t mip_downsample_buffer_size = decoded_texture_size * 5 / 16; + + size_t prev_level_size = decoded_texture_size; + for (u32 i = 1; i < tex_levels; ++i) + { + prev_level_size /= 4; + total_texture_size += prev_level_size; + } + + // Add space for the downsampling at the end + total_texture_size += mip_downsample_buffer_size; + + CheckTempSize(total_texture_size); + dst_buffer = temp; + if (!(texformat == TextureFormat::RGBA8 && from_tmem)) + { + TexDecoder_Decode(dst_buffer, src_data, expandedWidth, expandedHeight, texformat, tlut, + tlutfmt); + } + else + { + u8* src_data_gb = + &texMem[tmem_address_odd]; + TexDecoder_DecodeRGBA8FromTmem(dst_buffer, src_data, src_data_gb, expandedWidth, expandedHeight); + } + + entry->texture->Load(0, width, height, expandedWidth, dst_buffer, decoded_texture_size); + + arbitrary_mip_detector.AddLevel(width, height, expandedWidth, dst_buffer); + + dst_buffer += decoded_texture_size; } - - entry->texture->Load(0, width, height, expandedWidth, dst_buffer, decoded_texture_size); - - arbitrary_mip_detector.AddLevel(width, height, expandedWidth, dst_buffer); - - dst_buffer += decoded_texture_size; } iter = textures_by_address.emplace(address, entry); - if (g_ActiveConfig.iSafeTextureCache_ColorSamples == 0 || + if (textureCacheSafetyColorSampleSize == 0 || std::max(texture_size, palette_size) <= - (u32)g_ActiveConfig.iSafeTextureCache_ColorSamples * 8) + (u32)textureCacheSafetyColorSampleSize * 8) { entry->textures_by_hash_iter = textures_by_hash.emplace(full_hash, entry); } - entry->SetGeneralParameters(address, texture_size, full_format); + entry->SetGeneralParameters(address, texture_size, full_format, false); entry->SetDimensions(nativeW, nativeH, tex_levels); entry->SetHashes(base_hash, full_hash); entry->is_efb_copy = false; @@ -1025,9 +1045,8 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) const u8* ptr_odd = nullptr; if (from_tmem) { - ptr_even = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE + - texture_size]; - ptr_odd = &texMem[bpmem.tex[stage / 4].texImage2[stage % 4].tmem_odd * TMEM_LINE_SIZE]; + ptr_even = &texMem[tmem_address_even + texture_size]; + ptr_odd = &texMem[tmem_address_odd]; } for (u32 level = 1; level != texLevels; ++level) @@ -1081,7 +1100,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) entry = DoPartialTextureUpdates(iter->second, &texMem[tlutaddr], tlutfmt); - return ReturnEntry(stage, entry); + return entry; } void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, @@ -1159,6 +1178,10 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF unsigned int cbufid = UINT_MAX; PEControl::PixelFormat srcFormat = bpmem.zcontrol.pixel_format; bool efbHasAlpha = srcFormat == PEControl::RGBA6_Z24; + + bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam; + bool copy_to_vram = g_ActiveConfig.backend_info.bSupportsCopyToVram; + bool is_xfb_copy = false; if (is_depth_copy) { @@ -1388,6 +1411,15 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF } break; + case EFBCopyFormat::XFB: // XFB copy, we just pretend it's an RGBX copy + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 30; // just re-use the RGBX8 cbufid from above + copy_to_ram = g_ActiveConfig.bUseRealXFB; + is_xfb_copy = true; + break; + default: ERROR_LOG(VIDEO, "Unknown copy color format: 0x%X", static_cast(dstFormat)); colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; @@ -1430,9 +1462,6 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF const u32 bytes_per_row = num_blocks_x * bytes_per_block; const u32 covered_range = num_blocks_y * dstStride; - bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam; - bool copy_to_vram = true; - if (copy_to_ram) { EFBCopyParams format(srcFormat, dstFormat, is_depth_copy, isIntensity); @@ -1524,7 +1553,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF if (entry) { - entry->SetGeneralParameters(dstAddr, 0, baseFormat); + entry->SetGeneralParameters(dstAddr, 0, baseFormat, is_xfb_copy); entry->SetDimensions(tex_w, tex_h, 1); entry->frameCount = FRAMECOUNT_INVALID; @@ -1537,7 +1566,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF u64 hash = entry->CalculateHash(); entry->SetHashes(hash, hash); - if (g_ActiveConfig.bDumpEFBTarget) + if (g_ActiveConfig.bDumpEFBTarget && !is_xfb_copy) { static int count = 0; entry->texture->Save(StringFromFormat("%sefb_frame_%i.png", @@ -1699,12 +1728,22 @@ void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) size_in_bytes = memory_stride * NumBlocksY(); } +int TextureCacheBase::TCacheEntry::HashSampleSize() const +{ + if (should_force_safe_hashing) + { + return 0; + } + + return g_ActiveConfig.iSafeTextureCache_ColorSamples; +} + u64 TextureCacheBase::TCacheEntry::CalculateHash() const { u8* ptr = Memory::GetPointer(addr); if (memory_stride == BytesPerRow()) { - return GetHash64(ptr, size_in_bytes, g_ActiveConfig.iSafeTextureCache_ColorSamples); + return GetHash64(ptr, size_in_bytes, HashSampleSize()); } else { @@ -1712,11 +1751,11 @@ u64 TextureCacheBase::TCacheEntry::CalculateHash() const u64 temp_hash = size_in_bytes; u32 samples_per_row = 0; - if (g_ActiveConfig.iSafeTextureCache_ColorSamples != 0) + if (HashSampleSize() != 0) { // Hash at least 4 samples per row to avoid hashing in a bad pattern, like just on the left // side of the efb copy - samples_per_row = std::max(g_ActiveConfig.iSafeTextureCache_ColorSamples / blocks, 4u); + samples_per_row = std::max(HashSampleSize() / blocks, 4u); } for (u32 i = 0; i < blocks; i++) diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 6b69caf036..40c1779fbb 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -84,6 +84,7 @@ public: bool tmem_only = false; // indicates that this texture only exists in the tmem cache bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary // content, aren't just downscaled + bool should_force_safe_hashing = false; // for XFB unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view @@ -105,11 +106,12 @@ public: ~TCacheEntry(); - void SetGeneralParameters(u32 _addr, u32 _size, TextureAndTLUTFormat _format) + void SetGeneralParameters(u32 _addr, u32 _size, TextureAndTLUTFormat _format, bool force_safe_hashing) { addr = _addr; size_in_bytes = _size; format = _format; + should_force_safe_hashing = force_safe_hashing; } void SetDimensions(unsigned int _native_width, unsigned int _native_height, @@ -145,6 +147,7 @@ public: u64 CalculateHash() const; + int HashSampleSize() const; u32 GetWidth() const { return texture->GetConfig().width; } u32 GetHeight() const { return texture->GetConfig().height; } u32 GetNumLevels() const { return texture->GetConfig().levels; } @@ -172,7 +175,12 @@ public: TCacheEntry* Load(const u32 stage); static void InvalidateAllBindPoints() { valid_bind_points.reset(); } static bool IsValidBindPoint(u32 i) { return valid_bind_points.test(i); } - void BindTextures(); + TCacheEntry* GetTexture(u32 address, u32 width, u32 height, const TextureFormat texformat, + const int textureCacheSafetyColorSampleSize, u32 tlutaddr = 0, + TLUTFormat tlutfmt = TLUTFormat::IA8, bool use_mipmaps = false, + u32 tex_levels = 1, bool from_tmem = false, u32 tmem_address_even = 0, + u32 tmem_address_odd = 0); + virtual void BindTextures(); void CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); @@ -248,8 +256,6 @@ private: // Removes and unlinks texture from texture cache and returns it to the pool TexAddrCache::iterator InvalidateTexture(TexAddrCache::iterator t_iter); - TCacheEntry* ReturnEntry(unsigned int stage, TCacheEntry* entry); - TexAddrCache textures_by_address; TexHashCache textures_by_hash; TexPool texture_pool; diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index ab1b284b78..74e50cd27f 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -49,6 +49,8 @@ u16 GetEncodedSampleCount(EFBCopyFormat format) case EFBCopyFormat::RG8: case EFBCopyFormat::GB8: return 2; + case EFBCopyFormat::XFB: + return 2; default: PanicAlert("Invalid EFB Copy Format (0x%X)! (GetEncodedSampleCount)", static_cast(format)); return 1; @@ -656,6 +658,28 @@ static void WriteZ24Encoder(char*& p, APIType ApiType, const EFBCopyParams& para WriteEncoderEnd(p); } +static void WriteXFBEncoder(char*& p, APIType ApiType, const EFBCopyParams& params) +{ + WriteSwizzler(p, EFBCopyFormat::XFB, ApiType); + + WRITE(p, " float3 y_const = float3(0.257, 0.504, 0.098);\n"); + WRITE(p, " float3 u_const = float3(-0.148, -0.291, 0.439);\n"); + WRITE(p, " float3 v_const = float3(0.439, -0.368, -0.071);\n"); + WRITE(p, " float3 color0;\n"); + WRITE(p, " float3 color1;\n"); + + WriteSampleColor(p, "rgb", "color0", 0, ApiType, params); + WriteSampleColor(p, "rgb", "color1", 1, ApiType, params); + WRITE(p, " float3 average = (color0 + color1) * 0.5;\n"); + + WRITE(p, " ocol0.b = dot(color0, y_const) + 0.0625;\n"); + WRITE(p, " ocol0.g = dot(average, u_const) + 0.5;\n"); + WRITE(p, " ocol0.r = dot(color1, y_const) + 0.0625;\n"); + WRITE(p, " ocol0.a = dot(average, v_const) + 0.5;\n"); + + WriteEncoderEnd(p); +} + const char* GenerateEncodingShader(const EFBCopyParams& params, APIType api_type) { text[sizeof(text) - 1] = 0x7C; // canary @@ -728,6 +752,9 @@ const char* GenerateEncodingShader(const EFBCopyParams& params, APIType api_type else WriteCC8Encoder(p, "gb", api_type, params); break; + case EFBCopyFormat::XFB: + WriteXFBEncoder(p, api_type, params); + break; default: PanicAlert("Invalid EFB Copy Format (0x%X)! (GenerateEncodingShader)", static_cast(params.copy_format)); diff --git a/Source/Core/VideoCommon/TextureDecoder.h b/Source/Core/VideoCommon/TextureDecoder.h index 1a33fbfcf8..2a270eacd1 100644 --- a/Source/Core/VideoCommon/TextureDecoder.h +++ b/Source/Core/VideoCommon/TextureDecoder.h @@ -28,6 +28,11 @@ enum class TextureFormat C8 = 0x9, C14X2 = 0xA, CMPR = 0xE, + + // Special texture format used to represent YUVY xfb copies. + // They aren't really textures, but they share so much hardware and usecases that it makes sense + // to emulate them as part of texture cache. + XFB = 0xF, }; static inline bool IsColorIndexed(TextureFormat format) @@ -73,6 +78,11 @@ enum class EFBCopyFormat B8 = 0xA, // B8, Z8L RG8 = 0xB, // RG8, Z16R (Note: G and R are reversed) GB8 = 0xC, // GB8, Z16L + + // Special texture format used to represent YUVY xfb copies. + // They aren't really textures, but they share so much hardware and usecases that it makes sense + // to emulate them as part of texture cache. + XFB = 0xF, }; enum class TLUTFormat diff --git a/Source/Core/VideoCommon/TextureDecoder_Common.cpp b/Source/Core/VideoCommon/TextureDecoder_Common.cpp index 52debad57b..90be3d8dc7 100644 --- a/Source/Core/VideoCommon/TextureDecoder_Common.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_Common.cpp @@ -3,9 +3,11 @@ // Refer to the license.txt file included. #include +#include #include #include "Common/CommonTypes.h" +#include "Common/MathUtil.h" #include "Common/MsgHandler.h" #include "Common/Swap.h" @@ -46,6 +48,9 @@ int TexDecoder_GetTexelSizeInNibbles(TextureFormat format) // Compressed format case TextureFormat::CMPR: return 1; + // Special formats + case TextureFormat::XFB: + return 4; default: PanicAlert("Invalid Texture Format (0x%X)! (GetTexelSizeInNibbles)", static_cast(format)); return 1; @@ -82,6 +87,9 @@ int TexDecoder_GetBlockWidthInTexels(TextureFormat format) // Compressed format case TextureFormat::CMPR: return 8; + // Special formats + case TextureFormat::XFB: + return 16; default: PanicAlert("Invalid Texture Format (0x%X)! (GetBlockWidthInTexels)", static_cast(format)); return 8; @@ -113,6 +121,9 @@ int TexDecoder_GetBlockHeightInTexels(TextureFormat format) // Compressed format case TextureFormat::CMPR: return 8; + // Special formats + case TextureFormat::XFB: + return 1; default: PanicAlert("Invalid Texture Format (0x%X)! (GetBlockHeightInTexels)", static_cast(format)); return 4; @@ -144,6 +155,9 @@ int TexDecoder_GetEFBCopyBlockWidthInTexels(EFBCopyFormat format) // 32-bit formats case EFBCopyFormat::RGBA8: return 4; + // Special formats + case EFBCopyFormat::XFB: + return 16; default: PanicAlert("Invalid EFB Copy Format (0x%X)! (GetEFBCopyBlockWidthInTexels)", static_cast(format)); @@ -176,6 +190,9 @@ int TexDecoder_GetEFBCopyBlockHeightInTexels(EFBCopyFormat format) // 32-bit formats case EFBCopyFormat::RGBA8: return 4; + // Special formats + case EFBCopyFormat::XFB: + return 1; default: PanicAlert("Invalid EFB Copy Format (0x%X)! (GetEFBCopyBlockHeightInTexels)", static_cast(format)); @@ -226,6 +243,8 @@ TextureFormat TexDecoder_GetEFBCopyBaseFormat(EFBCopyFormat format) return TextureFormat::RGB5A3; case EFBCopyFormat::RGBA8: return TextureFormat::RGBA8; + case EFBCopyFormat::XFB: + return TextureFormat::XFB; default: PanicAlert("Invalid EFB Copy Format (0x%X)! (GetEFBCopyBaseFormat)", static_cast(format)); return static_cast(format); @@ -247,7 +266,7 @@ static const char* texfmt[] = { "0x1C", "0x1D", "0x1E", "0x1F", // pixel + copy "CR4", "0x21", "CRA4", "CRA8", "0x24", "0x25", "CYUVA8", "CA8", "CR8", "CG8", "CB8", "CRG8", - "CGB8", "0x2D", "0x2E", "0x2F", + "CGB8", "0x2D", "0x2E", "XFB", // Z + copy "CZ4", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "CZ8M", "CZ8L", "0x3B", "CZ16L", "0x3D", "0x3E", "0x3F", @@ -619,6 +638,24 @@ void TexDecoder_DecodeTexel(u8* dst, const u8* src, int s, int t, int imageWidth *((u32*)dst) = color; } break; + case TextureFormat::XFB: + { + // TODO: I should kind of like... ACTUALLY TEST THIS!!!!! + size_t offset = (t * imageWidth + (s & (~1))) * 2; + + // We do this one color sample (aka 2 RGB pixles) at a time + int Y = int((s & 1) == 0 ? src[offset] : src[offset + 2]) - 16; + int U = int(src[offset + 1]) - 128; + int V = int(src[offset + 3]) - 128; + + // We do the inverse BT.601 conversion for YCbCr to RGB + // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion + u8 R = MathUtil::Clamp(int(1.164f * Y + 1.596f * V), 0, 255); + u8 G = MathUtil::Clamp(int(1.164f * Y - 0.392f * U - 0.813f * V), 0, 255); + u8 B = MathUtil::Clamp(int(1.164f * Y + 2.017f * U), 0, 255); + dst[t * imageWidth + s] = 0xff000000 | B << 16 | G << 8 | R; + } + break; } } diff --git a/Source/Core/VideoCommon/TextureDecoder_x64.cpp b/Source/Core/VideoCommon/TextureDecoder_x64.cpp index 135fc60629..b31d3692f0 100644 --- a/Source/Core/VideoCommon/TextureDecoder_x64.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_x64.cpp @@ -9,6 +9,7 @@ #include "Common/CPUDetect.h" #include "Common/CommonTypes.h" #include "Common/Intrinsics.h" +#include "Common/MathUtil.h" #include "Common/MsgHandler.h" #include "Common/Swap.h" @@ -1485,6 +1486,37 @@ void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, Text case TextureFormat::CMPR: TexDecoder_DecodeImpl_CMPR(dst, src, width, height, texformat, tlut, tlutfmt, Wsteps4, Wsteps8); break; + + case TextureFormat::XFB: + { + for (int y = 0; y < height; y += 1) + { + for (int x = 0; x < width; x += 2) + { + size_t offset = static_cast((y * width + x) * 2); + + // We do this one color sample (aka 2 RGB pixles) at a time + int Y1 = int(src[offset]) - 16; + int U = int(src[offset + 1]) - 128; + int Y2 = int(src[offset + 2]) - 16; + int V = int(src[offset + 3]) - 128; + + // We do the inverse BT.601 conversion for YCbCr to RGB + // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion + u8 R1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255)); + u8 G1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); + u8 B1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255)); + + u8 R2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255)); + u8 G2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); + u8 B2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255)); + + dst[y * width + x] = 0xff000000 | B1 << 16 | G1 << 8 | R1; + dst[y * width + x + 1] = 0xff000000 | B2 << 16 | G2 << 8 | R2; + } + } + } + break; default: PanicAlert("Invalid Texture Format (0x%X)! (_TexDecoder_DecodeImpl)", diff --git a/Source/Core/VideoCommon/VideoCommon.h b/Source/Core/VideoCommon/VideoCommon.h index e25b2b66a5..5a397084f1 100644 --- a/Source/Core/VideoCommon/VideoCommon.h +++ b/Source/Core/VideoCommon/VideoCommon.h @@ -55,6 +55,8 @@ struct TargetRectangle : public MathUtil::Rectangle return (RECT*)this; } #endif + TargetRectangle(const MathUtil::Rectangle &other) : MathUtil::Rectangle(other) {} + TargetRectangle() = default; }; #ifdef _WIN32 diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index c49fe90456..ea5c64896c 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -221,6 +221,7 @@ struct VideoConfig final bool bSupportsInternalResolutionFrameDumps; bool bSupportsGPUTextureDecoding; bool bSupportsST3CTextures; + bool bSupportsCopyToVram; bool bSupportsBitfield; // Needed by UberShaders, so must stay in VideoCommon bool bSupportsDynamicSamplerIndexing; // Needed by UberShaders, so must stay in VideoCommon bool bSupportsBPTCTextures; From a9f0d1783bdf00e6610d314c48d8c16cf9439a1f Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 30 May 2017 23:44:03 -0500 Subject: [PATCH 02/40] Support frame and video dumping from VideoCommon --- Source/Core/VideoBackends/D3D/DXTexture.cpp | 75 ++++++++++------ Source/Core/VideoBackends/D3D/DXTexture.h | 7 +- Source/Core/VideoBackends/D3D/Render.cpp | 23 ----- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 88 +++++++++++++----- Source/Core/VideoBackends/OGL/OGLTexture.h | 9 +- Source/Core/VideoBackends/OGL/Render.cpp | 11 +-- Source/Core/VideoBackends/OGL/Render.h | 1 + .../VideoBackends/Software/SWRenderer.cpp | 8 -- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 23 +---- .../Core/VideoBackends/Vulkan/VKTexture.cpp | 52 +++++------ Source/Core/VideoBackends/Vulkan/VKTexture.h | 7 +- Source/Core/VideoCommon/AbstractTexture.cpp | 89 ++++++++++++++++++- Source/Core/VideoCommon/AbstractTexture.h | 21 ++++- Source/Core/VideoCommon/RenderBase.cpp | 32 ++++--- Source/Core/VideoCommon/RenderBase.h | 14 +-- Source/Core/VideoCommon/VideoCommon.vcxproj | 2 +- .../VideoCommon/VideoCommon.vcxproj.filters | 2 +- 17 files changed, 306 insertions(+), 158 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index 1ac52e76b2..e4bc024568 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -80,6 +80,7 @@ DXTexture::DXTexture(const TextureConfig& tex_config) : AbstractTexture(tex_conf DXTexture::~DXTexture() { m_texture->Release(); + SAFE_RELEASE(m_staging_texture); } D3DTexture2D* DXTexture::GetRawTexIdentifier() const @@ -92,48 +93,72 @@ void DXTexture::Bind(unsigned int stage) D3D::stateman->SetTexture(stage, m_texture->GetSRV()); } -bool DXTexture::Save(const std::string& filename, unsigned int level) +std::optional DXTexture::MapFullImpl() { - // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 - // framebuffer, and saving that). TextureCache does not call Save for custom textures - // anyway, so this is fine for now. - _assert_(m_config.format == AbstractTextureFormat::RGBA8); + CD3D11_TEXTURE2D_DESC staging_texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, m_config.width, + m_config.height, 1, 1, 0, D3D11_USAGE_STAGING, + D3D11_CPU_ACCESS_READ); - // Create a staging/readback texture with the dimensions of the specified mip level. - u32 mip_width = std::max(m_config.width >> level, 1u); - u32 mip_height = std::max(m_config.height >> level, 1u); - CD3D11_TEXTURE2D_DESC staging_texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, mip_width, mip_height, 1, - 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ); - - ID3D11Texture2D* staging_texture; - HRESULT hr = D3D::device->CreateTexture2D(&staging_texture_desc, nullptr, &staging_texture); + HRESULT hr = D3D::device->CreateTexture2D(&staging_texture_desc, nullptr, &m_staging_texture); if (FAILED(hr)) { WARN_LOG(VIDEO, "Failed to create texture dumping readback texture: %X", static_cast(hr)); - return false; + return {}; } - // Copy the selected mip level to the staging texture. - CD3D11_BOX src_box(0, 0, 0, mip_width, mip_height, 1); - D3D::context->CopySubresourceRegion(staging_texture, 0, 0, 0, 0, m_texture->GetTex(), + // Copy the selected data to the staging texture + D3D::context->CopyResource(m_staging_texture, m_texture->GetTex()); + + // Map the staging texture to client memory, and encode it as a .png image. + D3D11_MAPPED_SUBRESOURCE map; + hr = D3D::context->Map(m_staging_texture, 0, D3D11_MAP_READ, 0, &map); + if (FAILED(hr)) + { + WARN_LOG(VIDEO, "Failed to map texture dumping readback texture: %X", static_cast(hr)); + return {}; + } + + return AbstractTexture::RawTextureInfo{reinterpret_cast(map.pData), map.RowPitch, + m_config.width, m_config.height}; +} + +std::optional DXTexture::MapRegionImpl(u32 level, u32 x, u32 y, + u32 width, u32 height) +{ + CD3D11_TEXTURE2D_DESC staging_texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, 0, + D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ); + + HRESULT hr = D3D::device->CreateTexture2D(&staging_texture_desc, nullptr, &m_staging_texture); + if (FAILED(hr)) + { + WARN_LOG(VIDEO, "Failed to create texture dumping readback texture: %X", static_cast(hr)); + return {}; + } + + // Copy the selected data to the staging texture + CD3D11_BOX src_box(x, y, 0, width, height, 1); + D3D::context->CopySubresourceRegion(m_staging_texture, 0, 0, 0, 0, m_texture->GetTex(), D3D11CalcSubresource(level, 0, m_config.levels), &src_box); // Map the staging texture to client memory, and encode it as a .png image. D3D11_MAPPED_SUBRESOURCE map; - hr = D3D::context->Map(staging_texture, 0, D3D11_MAP_READ, 0, &map); + hr = D3D::context->Map(m_staging_texture, 0, D3D11_MAP_READ, 0, &map); if (FAILED(hr)) { WARN_LOG(VIDEO, "Failed to map texture dumping readback texture: %X", static_cast(hr)); - staging_texture->Release(); - return false; + return {}; } - bool encode_result = - TextureToPng(reinterpret_cast(map.pData), map.RowPitch, filename, mip_width, mip_height); - D3D::context->Unmap(staging_texture, 0); - staging_texture->Release(); + return AbstractTexture::RawTextureInfo{reinterpret_cast(map.pData), map.RowPitch, + m_config.width, m_config.height}; +} - return encode_result; +void DXTexture::Unmap() +{ + if (!m_staging_texture) + return; + + D3D::context->Unmap(m_staging_texture, 0); } void DXTexture::CopyRectangleFromTexture(const AbstractTexture* source, diff --git a/Source/Core/VideoBackends/D3D/DXTexture.h b/Source/Core/VideoBackends/D3D/DXTexture.h index a57c104fa0..8dfffd38d5 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.h +++ b/Source/Core/VideoBackends/D3D/DXTexture.h @@ -19,7 +19,7 @@ public: ~DXTexture(); void Bind(unsigned int stage) override; - bool Save(const std::string& filename, unsigned int level) override; + void Unmap() override; void CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle& srcrect, @@ -30,7 +30,12 @@ public: D3DTexture2D* GetRawTexIdentifier() const; private: + std::optional MapFullImpl() override; + std::optional MapRegionImpl(u32 level, u32 x, u32 y, u32 width, + u32 height) override; + D3DTexture2D* m_texture; + ID3D11Texture2D* m_staging_texture = nullptr; }; } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 55d9267b46..4dddd6784d 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -659,29 +659,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width, xfb_texture->config.height, Gamma); - // Dump frames - if (IsFrameDumping()) - { - if (!s_screenshot_texture) - CreateScreenshotTexture(); - - D3D11_BOX source_box = GetScreenshotSourceBox(targetRc); - unsigned int source_width = source_box.right - source_box.left; - unsigned int source_height = source_box.bottom - source_box.top; - D3D::context->CopySubresourceRegion(s_screenshot_texture, 0, 0, 0, 0, - D3D::GetBackBuffer()->GetTex(), 0, &source_box); - - D3D11_MAPPED_SUBRESOURCE map; - D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); - - AVIDump::Frame state = AVIDump::FetchState(ticks); - DumpFrameData(reinterpret_cast(map.pData), source_width, source_height, map.RowPitch, - state); - FinishFrameData(); - - D3D::context->Unmap(s_screenshot_texture, 0); - } - // Reset viewport for drawing text D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetBackbufferWidth(), (float)GetBackbufferHeight()); diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 8569e9b8b0..659cc9764b 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -66,22 +66,6 @@ GLenum GetGLTypeForTextureFormat(AbstractTextureFormat format) } } // Anonymous namespace -bool SaveTexture(const std::string& filename, u32 textarget, u32 tex, int virtual_width, - int virtual_height, unsigned int level) -{ - if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL) - return false; - int width = std::max(virtual_width >> level, 1); - int height = std::max(virtual_height >> level, 1); - std::vector data(width * height * 4); - glActiveTexture(GL_TEXTURE9); - glBindTexture(textarget, tex); - glGetTexImage(textarget, level, GL_RGBA, GL_UNSIGNED_BYTE, data.data()); - OGLTexture::SetStage(); - - return TextureToPng(data.data(), width * 4, filename, width, height, true); -} - OGLTexture::OGLTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config) { glGenTextures(1, &m_texId); @@ -164,15 +148,73 @@ void OGLTexture::Bind(unsigned int stage) } } -bool OGLTexture::Save(const std::string& filename, unsigned int level) +std::optional OGLTexture::MapFullImpl() { - // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 - // framebuffer, and saving that). TextureCache does not call Save for custom textures - // anyway, so this is fine for now. - _assert_(m_config.format == AbstractTextureFormat::RGBA8); + if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL) + return {}; - return SaveTexture(filename, GL_TEXTURE_2D_ARRAY, m_texId, m_config.width, m_config.height, - level); + m_staging_data.reserve(m_config.width * m_config.height * 4); + glActiveTexture(GL_TEXTURE9); + + glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId); + glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_staging_data.data()); + OGLTexture::SetStage(); + return AbstractTexture::RawTextureInfo{reinterpret_cast(m_staging_data.data()), + m_config.width * 4, m_config.width, m_config.height}; +} + +std::optional OGLTexture::MapRegionImpl(u32 level, u32 x, u32 y, + u32 width, u32 height) +{ + if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL) + return {}; + m_staging_data.reserve(m_config.width * m_config.height * 4); + glActiveTexture(GL_TEXTURE9); + glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId); + if (g_ogl_config.bSupportTextureSubImage) + { + glGetTextureSubImage(GL_TEXTURE_2D_ARRAY, level, GLint(x), GLint(y), 0, GLsizei(width), + GLsizei(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, GLsizei(width * height * 4), + m_staging_data.data()); + } + else + { + MapRegionSlow(level, x, y, width, height); + } + OGLTexture::SetStage(); + return AbstractTexture::RawTextureInfo{m_staging_data.data(), width * 4, width, height}; +} + +void OGLTexture::MapRegionSlow(u32 level, u32 x, u32 y, u32 width, u32 height) +{ + glActiveTexture(GL_TEXTURE9); + + glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId); + glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_staging_data.data()); + + // Now copy the region out of the staging data + + const u32 partial_stride = width * 4; + + std::vector partial_data; + partial_data.resize(partial_stride * height); + + const u32 staging_stride = m_config.width * 4; + const u32 x_offset = x * 4; + + auto staging_location = m_staging_data.begin() + staging_stride * y; + auto partial_location = partial_data.begin(); + + for (size_t i = 0; i < height; ++i) + { + auto starting_location = staging_location + x_offset; + std::copy(starting_location, starting_location + partial_stride, partial_location); + staging_location += staging_stride; + partial_location += partial_stride; + } + + // Now swap the region back in for the staging data + m_staging_data.swap(partial_data); } void OGLTexture::CopyRectangleFromTexture(const AbstractTexture* source, diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.h b/Source/Core/VideoBackends/OGL/OGLTexture.h index 029afe272f..91cb09bbca 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.h +++ b/Source/Core/VideoBackends/OGL/OGLTexture.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "Common/GL/GLUtil.h" #include "VideoCommon/AbstractTexture.h" @@ -17,7 +19,6 @@ public: ~OGLTexture(); void Bind(unsigned int stage) override; - bool Save(const std::string& filename, unsigned int level) override; void CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle& srcrect, @@ -32,8 +33,14 @@ public: static void SetStage(); private: + std::optional MapFullImpl() override; + std::optional MapRegionImpl(u32 level, u32 x, u32 y, u32 width, + u32 height) override; + void MapRegionSlow(u32 level, u32 x, u32 y, u32 width, u32 height); + GLuint m_texId; GLuint m_framebuffer = 0; + std::vector m_staging_data; }; } // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index d53ace17a5..e6c90d8c7e 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -460,6 +460,7 @@ Renderer::Renderer() GLExtensions::Supports("GL_EXT_copy_image") || GLExtensions::Supports("GL_OES_copy_image")) && !DriverDetails::HasBug(DriverDetails::BUG_BROKEN_COPYIMAGE); + g_ogl_config.bSupportTextureSubImage = GLExtensions::Supports("ARB_get_texture_sub_image"); // Desktop OpenGL supports the binding layout if it supports 420pack // OpenGL ES 3.1 supports it implicitly without an extension @@ -792,7 +793,7 @@ Renderer::Renderer() Renderer::~Renderer() { FlushFrameDump(); - FinishFrameData(); + //FinishFrameData(); DestroyFrameDumpResources(); } @@ -1361,7 +1362,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // 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(); + /*FlushFrameDump(); if (IsFrameDumping()) { // Currently, we only use the off-screen buffer as a frame dump source if full-resolution @@ -1378,7 +1379,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // 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 @@ -1510,7 +1511,7 @@ void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, void Renderer::FlushFrameDump() { - if (!m_last_frame_exported) + /*if (!m_last_frame_exported) return; FinishFrameData(); @@ -1521,7 +1522,7 @@ void Renderer::FlushFrameDump() 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; + m_last_frame_exported = false;*/ } void Renderer::DumpFrame(const TargetRectangle& flipped_trc, u64 ticks) diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index a130e9c770..d71ad15bd1 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -59,6 +59,7 @@ struct VideoConfig bool bSupportsImageLoadStore; bool bSupportsAniso; bool bSupportsBitfield; + bool bSupportTextureSubImage; const char* gl_vendor; const char* gl_renderer; diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 9074a429b9..26471629c8 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -47,14 +47,6 @@ void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 { SWOGLWindow::s_instance->ShowImage(texture, 1.0); - // Save screenshot - if (IsFrameDumping()) - { - AVIDump::Frame state = AVIDump::FetchState(ticks); - //DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, state); - FinishFrameData(); - } - OSD::DoCallbacks(OSD::CallbackType::OnFrame); DrawDebugText(); diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index be442476ad..020dd474f5 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -507,23 +507,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // are determined by guest state. Currently, the only way to catch these is to update every frame. UpdateDrawRectangle(); - // Render the frame dump image if enabled. - if (IsFrameDumping()) - { - // If we haven't dumped a single frame yet, set up frame dumping. - if (!m_frame_dumping_active) - StartFrameDumping(); - - /* DrawFrameDump(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height, - ticks);*/ - } - else - { - // If frame dumping was previously enabled, flush all frames and remove the fence callback. - if (m_frame_dumping_active) - EndFrameDumping(); - } - // Ensure the worker thread is not still submitting a previous command buffer. // In other words, the last frame has been submitted (otherwise the next call would // be a race, as the image may not have been consumed yet). @@ -856,7 +839,7 @@ void Renderer::OnFrameDumpImageReady(VkFence fence) void Renderer::WriteFrameDumpImage(size_t index) { - FrameDumpImage& frame = m_frame_dump_images[index]; + /*FrameDumpImage& frame = m_frame_dump_images[index]; _assert_(frame.pending); // Check fence has been signaled. @@ -873,14 +856,14 @@ void Renderer::WriteFrameDumpImage(size_t index) static_cast(frame.readback_texture->GetHeight()), static_cast(frame.readback_texture->GetRowStride()), frame.dump_state); - frame.pending = false; + 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(); + //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 diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp index 36292751b0..c06778be52 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp @@ -113,23 +113,17 @@ void VKTexture::Bind(unsigned int stage) StateTracker::GetInstance()->SetTexture(stage, m_texture->GetView()); } -bool VKTexture::Save(const std::string& filename, unsigned int level) +std::optional VKTexture::MapFullImpl() { - _assert_(level < m_config.levels); + // No support for optimization of full copy + return MapRegionImpl(0, 0, 0, m_config.width, m_config.height); +} - // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 - // framebuffer, and saving that). TextureCache does not call Save for custom textures - // anyway, so this is fine for now. - _assert_(m_config.format == AbstractTextureFormat::RGBA8); - - // Determine dimensions of image we want to save. - u32 level_width = std::max(1u, m_config.width >> level); - u32 level_height = std::max(1u, m_config.height >> level); - - // Use a temporary staging texture for the download. Certainly not optimal, - // but since we have to idle the GPU anyway it doesn't really matter. - std::unique_ptr staging_texture = StagingTexture2D::Create( - STAGING_BUFFER_TYPE_READBACK, level_width, level_height, TEXTURECACHE_TEXTURE_FORMAT); +std::optional VKTexture::MapRegionImpl(u32 level, u32 x, u32 y, + u32 width, u32 height) +{ + m_staging_texture = StagingTexture2D::Create(STAGING_BUFFER_TYPE_READBACK, width, height, + TEXTURECACHE_TEXTURE_FORMAT); // Transition image to transfer source, and invalidate the current state, // since we'll be executing the command buffer. @@ -138,9 +132,9 @@ bool VKTexture::Save(const std::string& filename, unsigned int level) StateTracker::GetInstance()->EndRenderPass(); // Copy to download buffer. - staging_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), - m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, - level_width, level_height, level, 0); + m_staging_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), + m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, x, y, width, + height, level, 0); // Restore original state of texture. m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), @@ -150,21 +144,23 @@ bool VKTexture::Save(const std::string& filename, unsigned int level) Util::ExecuteCurrentCommandsAndRestoreState(false, true); // Map the staging texture so we can copy the contents out. - if (!staging_texture->Map()) + if (!m_staging_texture->Map()) { PanicAlert("Failed to map staging texture"); - return false; + return {}; } - // Write texture out to file. - // It's okay to throw this texture away immediately, since we're done with it, and - // we blocked until the copy completed on the GPU anyway. - bool result = TextureToPng(reinterpret_cast(staging_texture->GetMapPointer()), - static_cast(staging_texture->GetRowStride()), filename, - level_width, level_height); + return AbstractTexture::RawTextureInfo{reinterpret_cast(m_staging_texture->GetMapPointer()), + static_cast(m_staging_texture->GetRowStride()), width, + height}; +} - staging_texture->Unmap(); - return result; +void VKTexture::Unmap() +{ + if (!m_staging_texture) + return; + + m_staging_texture->Unmap(); } void VKTexture::CopyTextureRectangle(const MathUtil::Rectangle& dst_rect, diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.h b/Source/Core/VideoBackends/Vulkan/VKTexture.h index 056f50c6e8..61ffae242c 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.h +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.h @@ -20,7 +20,7 @@ public: ~VKTexture(); void Bind(unsigned int stage) override; - bool Save(const std::string& filename, unsigned int level) override; + void Unmap() override; void CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle& srcrect, @@ -47,7 +47,12 @@ private: void ScaleTextureRectangle(const MathUtil::Rectangle& dst_rect, Texture2D* src_texture, const MathUtil::Rectangle& src_rect); + std::optional MapFullImpl() override; + std::optional MapRegionImpl(u32 level, u32 x, u32 y, u32 width, + u32 height) override; + std::unique_ptr m_texture; + std::unique_ptr m_staging_texture; VkFramebuffer m_framebuffer; }; diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp index 18f9c72064..0e92b6f7bd 100644 --- a/Source/Core/VideoCommon/AbstractTexture.cpp +++ b/Source/Core/VideoCommon/AbstractTexture.cpp @@ -4,9 +4,12 @@ #include -#include "VideoCommon/AbstractTexture.h" +#include "Common/Assert.h" -AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c) +#include "VideoCommon/AbstractTexture.h" +#include "VideoCommon/ImageWrite.h" + +AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c), m_currently_mapped(false) { } @@ -14,7 +17,87 @@ AbstractTexture::~AbstractTexture() = default; bool AbstractTexture::Save(const std::string& filename, unsigned int level) { - return false; + // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 + // framebuffer, and saving that). TextureCache does not call Save for custom textures + // anyway, so this is fine for now. + _assert_(m_config.format == AbstractTextureFormat::RGBA8); + + auto result = level == 0 ? Map() : Map(level); + + if (!result.has_value()) + { + return false; + } + + auto raw_data = result.value(); + return TextureToPng(raw_data.data, raw_data.stride, filename, raw_data.width, raw_data.height); +} + +std::optional AbstractTexture::Map() +{ + if (m_currently_mapped) + { + Unmap(); + m_currently_mapped = false; + } + auto result = MapFullImpl(); + + if (!result.has_value()) + { + m_currently_mapped = false; + return {}; + } + + m_currently_mapped = true; + return result; +} + +std::optional AbstractTexture::Map(u32 level, u32 x, u32 y, + u32 width, u32 height) +{ + _assert_(level < m_config.levels); + + u32 max_level_width = std::max(m_config.width >> level, 1u); + u32 max_level_height = std::max(m_config.height >> level, 1u); + + _assert_(width < max_level_width); + _assert_(height < max_level_height); + + auto result = MapRegionImpl(level, x, y, width, height); + + if (!result.has_value()) + { + m_currently_mapped = false; + return {}; + } + + m_currently_mapped = true; + return result; +} + +std::optional AbstractTexture::Map(u32 level) +{ + _assert_(level < m_config.levels); + + u32 level_width = std::max(m_config.width >> level, 1u); + u32 level_height = std::max(m_config.height >> level, 1u); + + return Map(level, 0, 0, level_width, level_height); +} + +void AbstractTexture::Unmap() +{ +} + +std::optional AbstractTexture::MapFullImpl() +{ + return {}; +} + +std::optional +AbstractTexture::MapRegionImpl(u32 level, u32 x, u32 y, u32 width, u32 height) +{ + return {}; } bool AbstractTexture::IsCompressedHostTextureFormat(AbstractTextureFormat format) diff --git a/Source/Core/VideoCommon/AbstractTexture.h b/Source/Core/VideoCommon/AbstractTexture.h index 94c082af70..612ca34758 100644 --- a/Source/Core/VideoCommon/AbstractTexture.h +++ b/Source/Core/VideoCommon/AbstractTexture.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "Common/CommonTypes.h" @@ -17,7 +18,20 @@ public: explicit AbstractTexture(const TextureConfig& c); virtual ~AbstractTexture(); virtual void Bind(unsigned int stage) = 0; - virtual bool Save(const std::string& filename, unsigned int level); + bool Save(const std::string& filename, unsigned int level); + + struct RawTextureInfo + { + const u8* data; + u32 stride; + u32 width; + u32 height; + }; + + std::optional Map(); + std::optional Map(u32 level, u32 x, u32 y, u32 width, u32 height); + std::optional Map(u32 level); + virtual void Unmap(); virtual void CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle& srcrect, @@ -31,5 +45,10 @@ public: const TextureConfig& GetConfig() const; protected: + virtual std::optional MapFullImpl(); + virtual std::optional MapRegionImpl(u32 level, u32 x, u32 y, u32 width, + u32 height); + bool m_currently_mapped = false; + const TextureConfig m_config; }; diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 2af607dd64..95217f443b 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -43,6 +43,7 @@ #include "Core/Host.h" #include "Core/Movie.h" +#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/AVIDump.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/CPMemory.h" @@ -645,6 +646,20 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_aspect_wide = flush_count_anamorphic > 0.75 * flush_total; } + // The FinishFrameData 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. + FinishFrameData(); + if (IsFrameDumping()) + { + auto result = m_last_xfb_texture->Map(); + if (result.has_value()) + { + auto raw_data = result.value(); + DumpFrameData(raw_data.data, raw_data.width, raw_data.height, raw_data.stride, + AVIDump::FetchState(ticks)); + } + } + if (xfbAddr && fbWidth && fbStride && fbHeight) { constexpr int force_safe_texture_cache_hash = 0; @@ -654,6 +669,9 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const // TODO, check if xfb_entry is a duplicate of the previous frame and skip SwapImpl + m_previous_xfb_texture = xfb_entry->texture.get(); + + m_last_xfb_texture = xfb_entry->texture.get(); // TODO: merge more generic parts into VideoCommon g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, Gamma); @@ -697,12 +715,9 @@ void Renderer::ShutdownFrameDumping() m_frame_dump_start.Set(); } -void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state, - bool swap_upside_down) +void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state) { - FinishFrameData(); - - m_frame_dump_config = FrameDumpConfig{data, w, h, stride, swap_upside_down, state}; + m_frame_dump_config = FrameDumpConfig{ m_last_xfb_texture, data, w, h, stride, state }; if (!m_frame_dump_thread_running.IsSet()) { @@ -723,6 +738,7 @@ void Renderer::FinishFrameData() m_frame_dump_done.Wait(); m_frame_dump_frame_running = false; + m_frame_dump_config.texture->Unmap(); } void Renderer::RunFrameDumps() @@ -749,12 +765,6 @@ void Renderer::RunFrameDumps() auto config = m_frame_dump_config; - if (config.upside_down) - { - config.data = config.data + (config.height - 1) * config.stride; - config.stride = -config.stride; - } - // Save screenshot if (m_screenshot_request.TestAndClear()) { diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 9de7c6393b..1d776a97d1 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -32,6 +32,7 @@ #include "VideoCommon/RenderState.h" #include "VideoCommon/VideoCommon.h" +class AbstractRawTexture; class AbstractTexture; class PostProcessingShaderImplementation; enum class EFBAccessType; @@ -152,11 +153,6 @@ protected: void CheckFifoRecording(); void RecordVideoMemory(); - bool IsFrameDumping(); - void DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state, - bool swap_upside_down = false); - void FinishFrameData(); - Common::Flag m_screenshot_request; Common::Event m_screenshot_completed; std::mutex m_screenshot_lock; @@ -205,14 +201,16 @@ private: bool m_frame_dump_frame_running = false; struct FrameDumpConfig { + AbstractTexture* texture; const u8* data; int width; int height; int stride; - bool upside_down; AVIDump::Frame state; } m_frame_dump_config; + AbstractTexture * m_last_xfb_texture; + // NOTE: The methods below are called on the framedumping thread. bool StartFrameDumpToAVI(const FrameDumpConfig& config); void DumpFrameToAVI(const FrameDumpConfig& config); @@ -220,6 +218,10 @@ private: std::string GetFrameDumpNextImageFileName() const; bool StartFrameDumpToImage(const FrameDumpConfig& config); void DumpFrameToImage(const FrameDumpConfig& config); + + bool IsFrameDumping(); + void DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state); + void FinishFrameData(); }; extern std::unique_ptr g_renderer; diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index d8c43256e1..6bdd57a9fd 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -180,4 +180,4 @@ - + \ No newline at end of file diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index 8e5b9fef31..7b3a5c6892 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -360,4 +360,4 @@ - + \ No newline at end of file From 198d3b69b43b19685b4d4bed0173ebf2b2db9f0a Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 2 Jun 2017 20:33:26 -0500 Subject: [PATCH 03/40] Add ability to dump xfb copies to texture for debugging purposes --- Source/Core/Core/Config/GraphicsSettings.cpp | 1 + Source/Core/Core/Config/GraphicsSettings.h | 1 + Source/Core/DolphinWX/VideoConfigDiag.cpp | 4 +++ Source/Core/VideoBackends/D3D/Render.cpp | 33 +++---------------- Source/Core/VideoBackends/OGL/Render.cpp | 8 ++--- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 4 +-- Source/Core/VideoCommon/TextureCacheBase.cpp | 13 ++++++-- .../VideoCommon/VideoCommon.vcxproj.filters | 6 ++++ Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 1 + 10 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index 0229e8d006..8874f4def4 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -45,6 +45,7 @@ const ConfigInfo GFX_CONVERT_HIRES_TEXTURES{{System::GFX, "Settings", "Con const ConfigInfo GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresTextures"}, false}; const ConfigInfo GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false}; +const ConfigInfo GFX_DUMP_XFB_TARGET{ { System::GFX, "Settings", "DumpXFBTarget" }, false }; const ConfigInfo GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false}; const ConfigInfo GFX_FREE_LOOK{{System::GFX, "Settings", "FreeLook"}, false}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index a50ee253c0..4fd874a4fe 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -37,6 +37,7 @@ extern const ConfigInfo GFX_HIRES_TEXTURES; extern const ConfigInfo GFX_CONVERT_HIRES_TEXTURES; extern const ConfigInfo GFX_CACHE_HIRES_TEXTURES; extern const ConfigInfo GFX_DUMP_EFB_TARGET; +extern const ConfigInfo GFX_DUMP_XFB_TARGET; extern const ConfigInfo GFX_DUMP_FRAMES_AS_IMAGES; extern const ConfigInfo GFX_FREE_LOOK; extern const ConfigInfo GFX_USE_FFV1; diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 08d2697514..051da17060 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -250,6 +250,8 @@ static wxString cache_hires_textures_desc = "more RAM but fixes possible stuttering.\n\nIf unsure, leave this unchecked."); static wxString dump_efb_desc = wxTRANSLATE( "Dump the contents of EFB copies to User/Dump/Textures/.\n\nIf unsure, leave this unchecked."); +static wxString dump_xfb_desc = wxTRANSLATE( + "Dump the contents of XFB copies to User/Dump/Textures/.\n\nIf unsure, leave this unchecked."); static wxString internal_resolution_frame_dumping_desc = wxTRANSLATE( "Create frame dumps and screenshots at the internal resolution of the renderer, rather than " "the size of the window it is displayed within. If the aspect ratio is widescreen, the output " @@ -890,6 +892,8 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) szr_utility->Add(CreateCheckBox(page_advanced, _("Dump EFB Target"), wxGetTranslation(dump_efb_desc), Config::GFX_DUMP_EFB_TARGET)); + szr_utility->Add(CreateCheckBox(page_advanced, _("Dump XFB Target"), + wxGetTranslation(dump_xfb_desc), Config::GFX_DUMP_XFB_TARGET)); szr_utility->Add(CreateCheckBox(page_advanced, _("Free Look"), wxGetTranslation(free_look_desc), Config::GFX_FREE_LOOK)); #if defined(HAVE_FFMPEG) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 4dddd6784d..e49dc4053a 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -181,31 +181,6 @@ static void TeardownDeviceObjects() s_gx_state_cache.Clear(); } -static void CreateScreenshotTexture() -{ - // We can't render anything outside of the backbuffer anyway, so use the backbuffer size as the - // screenshot buffer size. - // This texture is released to be recreated when the window is resized in Renderer::SwapImpl. - D3D11_TEXTURE2D_DESC scrtex_desc = CD3D11_TEXTURE2D_DESC( - DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, - D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); - HRESULT hr = D3D::device->CreateTexture2D(&scrtex_desc, nullptr, &s_screenshot_texture); - CHECK(hr == S_OK, "Create screenshot staging texture"); - D3D::SetDebugObjectName(s_screenshot_texture, "staging screenshot texture"); -} - -static D3D11_BOX GetScreenshotSourceBox(const TargetRectangle& targetRc) -{ - // Since the screenshot buffer is copied back to the CPU via Map(), we can't access pixels that - // fall outside the backbuffer bounds. Therefore, when crop is enabled and the target rect is - // off-screen to the top/left, we clamp the origin at zero, as well as the bottom/right - // coordinates at the backbuffer dimensions. This will result in a rectangle that can be - // smaller than the backbuffer, but never larger. - return CD3D11_BOX(std::max(targetRc.left, 0), std::max(targetRc.top, 0), 0, - std::min(D3D::GetBackBufferWidth(), (unsigned int)targetRc.right), - std::min(D3D::GetBackBufferHeight(), (unsigned int)targetRc.bottom), 1); -} - static void Create3DVisionTexture(int width, int height) { // Create a staging texture for 3D vision with signature information in the last row. @@ -654,10 +629,10 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // activate linear filtering for the buffer copies D3D::SetLinearCopySampler(); auto* xfb_texture = static_cast(texture); - TargetRectangle source_rc = xfb_texture->config.Rect(); + TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); - BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width, - xfb_texture->config.height, Gamma); + BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->GetConfig().width, + xfb_texture->GetConfig().height, Gamma); // Reset viewport for drawing text D3D11_VIEWPORT vp = @@ -676,7 +651,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti g_texture_cache->OnConfigChanged(g_ActiveConfig); VertexShaderCache::RetreiveAsyncShaders(); - SetWindowSize(xfb_texture->config.width, xfb_texture->config.height); + SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); const bool window_resized = CheckForResize(); const bool fullscreen = D3D::GetFullscreenState(); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index e6c90d8c7e..e426b97ef6 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1344,8 +1344,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti TargetRectangle sourceRc = ConvertEFBRectangle(rc); sourceRc.left = 0; - sourceRc.right = xfb_texture->config.width; - sourceRc.top = xfb_texture->config.height; + sourceRc.right = xfb_texture->GetConfig().width; + sourceRc.top = xfb_texture->GetConfig().height; sourceRc.bottom = 0; ResetAPIState(); @@ -1358,7 +1358,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // Copy the framebuffer to screen. glBindFramebuffer(GL_FRAMEBUFFER, 0); - BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width, xfb_texture->config.height); + 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. @@ -1383,7 +1383,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // Finish up the current frame, print some stats - SetWindowSize(xfb_texture->config.width, xfb_texture->config.height); + SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); GLInterface->Update(); // just updates the render window position and the backbuffer size diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 020dd474f5..43eb0a7ec3 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -554,7 +554,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // 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(xfb_texture->config.width, xfb_texture->config.height); + SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); // Clean up stale textures. TextureCache::GetInstance()->Cleanup(frameCount); @@ -731,7 +731,7 @@ void Renderer::DrawScreen(VKTexture* xfb_texture) VK_SUBPASS_CONTENTS_INLINE); // Draw - TargetRectangle source_rc = xfb_texture->config.Rect(); + TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), source_rc, xfb_texture->GetRawTexIdentifier()); // Draw OSD diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index fb30575a95..918e33bd64 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1568,10 +1568,19 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF if (g_ActiveConfig.bDumpEFBTarget && !is_xfb_copy) { - static int count = 0; + static int efb_count = 0; entry->texture->Save(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++), + efb_count++), + 0); + } + + if (g_ActiveConfig.bDumpXFBTarget && is_xfb_copy) + { + static int xfb_count = 0; + entry->texture->Save(StringFromFormat("%sxfb_frame_%i.png", + File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + xfb_count++), 0); } diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index 7b3a5c6892..815fd86bbb 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -173,6 +173,9 @@ Base + + Base + Shader Generators @@ -344,6 +347,9 @@ Base + + Base + Util diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 5dbc3ef196..8288ae8a1f 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -81,6 +81,7 @@ void VideoConfig::Refresh() bConvertHiresTextures = Config::Get(Config::GFX_CONVERT_HIRES_TEXTURES); bCacheHiresTextures = Config::Get(Config::GFX_CACHE_HIRES_TEXTURES); bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET); + bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET); bDumpFramesAsImages = Config::Get(Config::GFX_DUMP_FRAMES_AS_IMAGES); bFreeLook = Config::Get(Config::GFX_FREE_LOOK); bUseFFV1 = Config::Get(Config::GFX_USE_FFV1); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index ea5c64896c..4e0dc71b79 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -98,6 +98,7 @@ struct VideoConfig final bool bConvertHiresTextures; bool bCacheHiresTextures; bool bDumpEFBTarget; + bool bDumpXFBTarget; bool bDumpFramesAsImages; bool bUseFFV1; std::string sDumpCodec; From 65cd085f9bb80531f5739807afffe837c7d2ffc1 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 25 Jun 2017 22:23:47 -0500 Subject: [PATCH 04/40] Add new GUI option to skip XFBToRam and remove old XFB options --- Source/Core/Core/Analytics.cpp | 3 +- Source/Core/Core/Config/GraphicsSettings.cpp | 4 +- Source/Core/Core/Config/GraphicsSettings.h | 3 +- .../Core/ConfigLoaders/GameConfigLoader.cpp | 3 +- .../Core/ConfigLoaders/IsSettingSaveable.cpp | 3 +- .../Core/ConfigLoaders/MovieConfigLoader.cpp | 7 ++- Source/Core/Core/HotkeyManager.cpp | 1 + Source/Core/Core/HotkeyManager.h | 1 + Source/Core/Core/Movie.cpp | 3 +- Source/Core/Core/Movie.h | 5 +- .../Config/Graphics/HacksWidget.cpp | 40 ++++----------- .../DolphinQt2/Config/Graphics/HacksWidget.h | 6 +-- .../Graphics/SoftwareRendererWidget.cpp | 8 --- .../Config/Graphics/SoftwareRendererWidget.h | 1 - Source/Core/DolphinQt2/HotkeyScheduler.cpp | 2 + Source/Core/DolphinWX/Frame.cpp | 7 +++ .../DolphinWX/SoftwareVideoConfigDialog.cpp | 4 -- Source/Core/DolphinWX/VideoConfigDiag.cpp | 49 ++++--------------- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 38 +------------- .../VideoCommon/FramebufferManagerBase.cpp | 9 ---- Source/Core/VideoCommon/MainBase.cpp | 2 +- Source/Core/VideoCommon/RenderBase.cpp | 5 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- Source/Core/VideoCommon/VideoConfig.cpp | 10 +--- Source/Core/VideoCommon/VideoConfig.h | 5 +- 25 files changed, 51 insertions(+), 170 deletions(-) diff --git a/Source/Core/Core/Analytics.cpp b/Source/Core/Core/Analytics.cpp index fab7275112..0673b283b9 100644 --- a/Source/Core/Core/Analytics.cpp +++ b/Source/Core/Core/Analytics.cpp @@ -219,13 +219,12 @@ void DolphinAnalytics::MakePerGameBuilder() builder.AddData("cfg-gfx-multisamples", g_Config.iMultisamples); builder.AddData("cfg-gfx-ssaa", g_Config.bSSAA); builder.AddData("cfg-gfx-anisotropy", g_Config.iMaxAnisotropy); - builder.AddData("cfg-gfx-realxfb", g_Config.RealXFBEnabled()); - builder.AddData("cfg-gfx-virtualxfb", g_Config.VirtualXFBEnabled()); builder.AddData("cfg-gfx-vsync", g_Config.bVSync); builder.AddData("cfg-gfx-aspect-ratio", g_Config.iAspectRatio); builder.AddData("cfg-gfx-efb-access", g_Config.bEFBAccessEnable); builder.AddData("cfg-gfx-efb-copy-format-changes", g_Config.bEFBEmulateFormatChanges); builder.AddData("cfg-gfx-efb-copy-ram", !g_Config.bSkipEFBCopyToRam); + builder.AddData("cfg-gfx-xfb-copy-ram", !g_Config.bSkipXFBCopyToRam); builder.AddData("cfg-gfx-efb-copy-scaled", g_Config.bCopyEFBScaled); builder.AddData("cfg-gfx-internal-resolution", g_Config.iEFBScale); builder.AddData("cfg-gfx-tc-samples", g_Config.iSafeTextureCache_ColorSamples); diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index 8874f4def4..cc0aae44a2 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -26,8 +26,6 @@ const ConfigInfo GFX_ASPECT_RATIO{{System::GFX, "Settings", "AspectRatio"}, const ConfigInfo GFX_SUGGESTED_ASPECT_RATIO{{System::GFX, "Settings", "SuggestedAspectRatio"}, static_cast(ASPECT_AUTO)}; const ConfigInfo GFX_CROP{{System::GFX, "Settings", "Crop"}, false}; -const ConfigInfo GFX_USE_XFB{{System::GFX, "Settings", "UseXFB"}, false}; -const ConfigInfo GFX_USE_REAL_XFB{{System::GFX, "Settings", "UseRealXFB"}, false}; const ConfigInfo GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES{ {System::GFX, "Settings", "SafeTextureCacheColorSamples"}, 128}; const ConfigInfo GFX_SHOW_FPS{{System::GFX, "Settings", "ShowFPS"}, false}; @@ -133,6 +131,8 @@ const ConfigInfo GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION{ const ConfigInfo GFX_HACK_FORCE_PROGRESSIVE{{System::GFX, "Hacks", "ForceProgressive"}, true}; const ConfigInfo GFX_HACK_SKIP_EFB_COPY_TO_RAM{{System::GFX, "Hacks", "EFBToTextureEnable"}, true}; +const ConfigInfo GFX_HACK_SKIP_XFB_COPY_TO_RAM{{System::GFX, "Hacks", "XFBToTextureEnable"}, + true}; const ConfigInfo GFX_HACK_COPY_EFB_ENABLED{{System::GFX, "Hacks", "EFBScaledCopy"}, true}; const ConfigInfo GFX_HACK_EFB_EMULATE_FORMAT_CHANGES{ {System::GFX, "Hacks", "EFBEmulateFormatChanges"}, false}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index 4fd874a4fe..9ebc299379 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -23,8 +23,6 @@ extern const ConfigInfo GFX_WIDESCREEN_HACK; extern const ConfigInfo GFX_ASPECT_RATIO; extern const ConfigInfo GFX_SUGGESTED_ASPECT_RATIO; extern const ConfigInfo GFX_CROP; -extern const ConfigInfo GFX_USE_XFB; -extern const ConfigInfo GFX_USE_REAL_XFB; extern const ConfigInfo GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES; extern const ConfigInfo GFX_SHOW_FPS; extern const ConfigInfo GFX_SHOW_NETPLAY_PING; @@ -101,6 +99,7 @@ extern const ConfigInfo GFX_HACK_BBOX_ENABLE; extern const ConfigInfo GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION; extern const ConfigInfo GFX_HACK_FORCE_PROGRESSIVE; extern const ConfigInfo GFX_HACK_SKIP_EFB_COPY_TO_RAM; +extern const ConfigInfo GFX_HACK_SKIP_XFB_COPY_TO_RAM; extern const ConfigInfo GFX_HACK_COPY_EFB_ENABLED; extern const ConfigInfo GFX_HACK_EFB_EMULATE_FORMAT_CHANGES; extern const ConfigInfo GFX_HACK_VERTEX_ROUDING; diff --git a/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp index 17ffed0b94..e409757f53 100644 --- a/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp @@ -74,8 +74,6 @@ static const INIToLocationMap& GetINIToLocationMap() {{"Video_Settings", "AspectRatio"}, {Config::GFX_ASPECT_RATIO.location}}, {{"Video_Settings", "SuggestedAspectRatio"}, {Config::GFX_SUGGESTED_ASPECT_RATIO.location}}, {{"Video_Settings", "Crop"}, {Config::GFX_CROP.location}}, - {{"Video_Settings", "UseXFB"}, {Config::GFX_USE_XFB.location}}, - {{"Video_Settings", "UseRealXFB"}, {Config::GFX_USE_REAL_XFB.location}}, {{"Video_Settings", "SafeTextureCacheColorSamples"}, {Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES.location}}, {{"Video_Settings", "HiresTextures"}, {Config::GFX_HIRES_TEXTURES.location}}, @@ -109,6 +107,7 @@ static const INIToLocationMap& GetINIToLocationMap() {{"Video_Hacks", "BBoxEnable"}, {Config::GFX_HACK_BBOX_ENABLE.location}}, {{"Video_Hacks", "ForceProgressive"}, {Config::GFX_HACK_FORCE_PROGRESSIVE.location}}, {{"Video_Hacks", "EFBToTextureEnable"}, {Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location}}, + {{"Video_Hacks", "XFBToTextureEnable"}, {Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location}}, {{"Video_Hacks", "EFBScaledCopy"}, {Config::GFX_EFB_SCALE.location}}, {{"Video_Hacks", "EFBEmulateFormatChanges"}, {Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location}}, diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 0349fa6ed6..c38bec4e4d 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -28,7 +28,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) // Graphics.Settings Config::GFX_WIDESCREEN_HACK.location, Config::GFX_ASPECT_RATIO.location, - Config::GFX_CROP.location, Config::GFX_USE_XFB.location, Config::GFX_USE_REAL_XFB.location, + Config::GFX_CROP.location, Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES.location, Config::GFX_SHOW_FPS.location, Config::GFX_SHOW_NETPLAY_PING.location, Config::GFX_SHOW_NETPLAY_MESSAGES.location, Config::GFX_LOG_RENDER_TIME_TO_FILE.location, Config::GFX_OVERLAY_STATS.location, @@ -73,6 +73,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) Config::GFX_HACK_EFB_ACCESS_ENABLE.location, Config::GFX_HACK_BBOX_ENABLE.location, Config::GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION.location, Config::GFX_HACK_FORCE_PROGRESSIVE.location, Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location, + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location, Config::GFX_HACK_COPY_EFB_ENABLED.location, Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location, Config::GFX_HACK_VERTEX_ROUDING.location, diff --git a/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp index edfea3919e..de008d4046 100644 --- a/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp @@ -39,10 +39,10 @@ static void LoadFromDTM(Config::Layer* config_layer, Movie::DTMHeader* dtm) else config_layer->Set(Config::MAIN_GC_LANGUAGE, static_cast(dtm->language)); - config_layer->Set(Config::GFX_USE_XFB, dtm->bUseXFB); - config_layer->Set(Config::GFX_USE_REAL_XFB, dtm->bUseRealXFB); + config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable); config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam); + config_layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, dtm->bSkipXFBCopyToRam); config_layer->Set(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, dtm->bEFBEmulateFormatChanges); } @@ -62,10 +62,9 @@ void SaveToDTM(Movie::DTMHeader* dtm) else dtm->language = Config::Get(Config::MAIN_GC_LANGUAGE); - dtm->bUseXFB = Config::Get(Config::GFX_USE_XFB); - dtm->bUseRealXFB = Config::Get(Config::GFX_USE_REAL_XFB); dtm->bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE); dtm->bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); + dtm->bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); dtm->bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES); // This never used the regular config diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index ed586e1c7c..5b1627b53e 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -72,6 +72,7 @@ const std::string hotkey_labels[] = { _trans("Toggle Crop"), _trans("Toggle Aspect Ratio"), _trans("Toggle EFB Copies"), + _trans("Toggle XFB Copies"), _trans("Toggle Fog"), _trans("Toggle Texture Dumping"), _trans("Toggle Custom Textures"), diff --git a/Source/Core/Core/HotkeyManager.h b/Source/Core/Core/HotkeyManager.h index f9b4dabaf5..68f07545f4 100644 --- a/Source/Core/Core/HotkeyManager.h +++ b/Source/Core/Core/HotkeyManager.h @@ -70,6 +70,7 @@ enum Hotkey HK_TOGGLE_CROP, HK_TOGGLE_AR, HK_TOGGLE_EFBCOPIES, + HK_TOGGLE_XFBCOPIES, HK_TOGGLE_FOG, HK_TOGGLE_DUMPTEXTURES, HK_TOGGLE_TEXTURES, diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 3bdcc9b13d..ac135f086c 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -1367,9 +1367,8 @@ void SetGraphicsConfig() { g_Config.bEFBAccessEnable = tmpHeader.bEFBAccessEnable; g_Config.bSkipEFBCopyToRam = tmpHeader.bSkipEFBCopyToRam; + g_Config.bSkipXFBCopyToRam = tmpHeader.bSkipXFBCopyToRam; g_Config.bEFBEmulateFormatChanges = tmpHeader.bEFBEmulateFormatChanges; - g_Config.bUseXFB = tmpHeader.bUseXFB; - g_Config.bUseRealXFB = tmpHeader.bUseRealXFB; } // NOTE: EmuThread / Host Thread diff --git a/Source/Core/Core/Movie.h b/Source/Core/Core/Movie.h index 343790ccb3..c5b477b4bf 100644 --- a/Source/Core/Core/Movie.h +++ b/Source/Core/Core/Movie.h @@ -87,10 +87,9 @@ struct DTMHeader bool bEFBAccessEnable; bool bEFBCopyEnable; bool bSkipEFBCopyToRam; + bool bSkipXFBCopyToRam; bool bEFBCopyCacheEnable; bool bEFBEmulateFormatChanges; - bool bUseXFB; - bool bUseRealXFB; u8 memcards; // Memcards inserted (from least to most significant, the bits are slot A and B) bool bClearSave; // Create a new memory card when playing back a movie if true u8 bongos; // Bongos plugged in (from least to most significant, the bits are ports 1-4) @@ -98,7 +97,7 @@ struct DTMHeader bool bNetPlay; bool bPAL60; u8 language; - u8 reserved[11]; // Padding for any new config options + u8 reserved[12]; // Padding for any new config options u8 discChange[40]; // Name of iso file to switch to, for two disc games. u8 revision[20]; // Git hash u32 DSPiromHash; diff --git a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp index 3690a43161..723a177c2e 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp +++ b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp @@ -20,7 +20,6 @@ HacksWidget::HacksWidget(GraphicsWindow* parent) : GraphicsWidget(parent) CreateWidgets(); LoadSettings(); ConnectWidgets(); - OnXFBToggled(); AddDescriptions(); } @@ -68,13 +67,11 @@ void HacksWidget::CreateWidgets() auto* xfb_layout = new QGridLayout(); xfb_box->setLayout(xfb_layout); - m_disable_xfb = new GraphicsBool(tr("Disable"), Config::GFX_USE_XFB, true); - m_real_xfb = new GraphicsBoolEx(tr("Real"), Config::GFX_USE_REAL_XFB, false); - m_virtual_xfb = new GraphicsBoolEx(tr("Virtual"), Config::GFX_USE_REAL_XFB, true); + m_store_xfb_copies = new GraphicsBool(tr("Store XFB Copies to Texture Only"), + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); + + xfb_layout->addWidget(m_store_xfb_copies, 1, 0); - xfb_layout->addWidget(m_disable_xfb, 0, 0); - xfb_layout->addWidget(m_virtual_xfb, 0, 1); - xfb_layout->addWidget(m_real_xfb, 0, 2); // Other auto* other_box = new QGroupBox(tr("Other")); auto* other_layout = new QGridLayout(); @@ -101,16 +98,9 @@ void HacksWidget::CreateWidgets() void HacksWidget::ConnectWidgets() { - connect(m_disable_xfb, &QCheckBox::toggled, this, &HacksWidget::OnXFBToggled); connect(m_accuracy, &QSlider::valueChanged, [this](int) { SaveSettings(); }); } -void HacksWidget::OnXFBToggled() -{ - m_real_xfb->setEnabled(!m_disable_xfb->isChecked()); - m_virtual_xfb->setEnabled(!m_disable_xfb->isChecked()); -} - void HacksWidget::LoadSettings() { auto samples = Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES); @@ -179,20 +169,10 @@ void HacksWidget::AddDescriptions() "from RAM.\nLower accuracies cause in-game text to appear garbled in certain " "games.\n\nIf unsure, use the rightmost value."); - static const char* TR_DISABLE_XFB_DESCRIPTION = QT_TR_NOOP( - "Disable any XFB emulation.\nSpeeds up emulation a lot but causes heavy glitches in many " - "games " - "which rely on them (especially homebrew applications).\n\nIf unsure, leave this checked."); - static const char* TR_VIRTUAL_XFB_DESCRIPTION = QT_TR_NOOP( - "Emulate XFBs using GPU texture objects.\nFixes many games which don't work without XFB " - "emulation while not being as slow as real XFB emulation. However, it may still fail for " - "a lot " - "of other games (especially homebrew applications).\n\nIf unsure, leave this checked."); - - static const char* TR_REAL_XFB_DESCRIPTION = - QT_TR_NOOP("Emulate XFBs accurately.\nSlows down emulation a lot and prohibits " - "high-resolution rendering but is necessary to emulate a number of games " - "properly.\n\nIf unsure, check virtual XFB emulation instead."); + static const char* TR_STORE_XFB_TO_TEXTURE_DESCRIPTION = QT_TR_NOOP( + "Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " + "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to Texture\nDisabled = XFB Copies to RAM " + "(and Texture)\n\nIf unsure, leave this checked."); static const char* TR_GPU_DECODING_DESCRIPTION = QT_TR_NOOP("Enables texture decoding using the GPU instead of the CPU. This may result in " @@ -215,9 +195,7 @@ void HacksWidget::AddDescriptions() AddDescription(m_ignore_format_changes, TR_IGNORE_FORMAT_CHANGE_DESCRIPTION); AddDescription(m_store_efb_copies, TR_STORE_EFB_TO_TEXTURE_DESCRIPTION); AddDescription(m_accuracy, TR_ACCUARCY_DESCRIPTION); - AddDescription(m_disable_xfb, TR_DISABLE_XFB_DESCRIPTION); - AddDescription(m_virtual_xfb, TR_VIRTUAL_XFB_DESCRIPTION); - AddDescription(m_real_xfb, TR_REAL_XFB_DESCRIPTION); + AddDescription(m_store_xfb_copies, TR_STORE_XFB_TO_TEXTURE_DESCRIPTION); AddDescription(m_gpu_texture_decoding, TR_GPU_DECODING_DESCRIPTION); AddDescription(m_fast_depth_calculation, TR_FAST_DEPTH_CALC_DESCRIPTION); AddDescription(m_disable_bounding_box, TR_DISABLE_BOUNDINGBOX_DESCRIPTION); diff --git a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h index d652a10b3f..9e83e76415 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h +++ b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h @@ -21,8 +21,6 @@ private: void LoadSettings() override; void SaveSettings() override; - void OnXFBToggled(); - // EFB QCheckBox* m_skip_efb_cpu; QCheckBox* m_ignore_format_changes; @@ -33,9 +31,7 @@ private: QCheckBox* m_gpu_texture_decoding; // External Framebuffer - QCheckBox* m_disable_xfb; - QRadioButton* m_virtual_xfb; - QRadioButton* m_real_xfb; + QCheckBox* m_store_xfb_copies; // Other QCheckBox* m_fast_depth_calculation; diff --git a/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.cpp b/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.cpp index 65cd96b2c5..24e0d77836 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.cpp +++ b/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.cpp @@ -38,12 +38,10 @@ void SoftwareRendererWidget::CreateWidgets() auto* rendering_box = new QGroupBox(tr("Rendering")); auto* rendering_layout = new QGridLayout(); m_backend_combo = new QComboBox(); - m_bypass_xfb = new GraphicsBool(tr("Bypass XFB"), Config::GFX_USE_XFB, true); rendering_box->setLayout(rendering_layout); rendering_layout->addWidget(new QLabel(tr("Backend:")), 1, 1); rendering_layout->addWidget(m_backend_combo, 1, 2); - rendering_layout->addWidget(m_bypass_xfb, 2, 1); for (const auto& backend : g_available_video_backends) m_backend_combo->addItem(tr(backend->GetDisplayName().c_str())); @@ -156,11 +154,6 @@ void SoftwareRendererWidget::AddDescriptions() "backend, so for the best emulation experience it's recommended to try both and " "choose the one that's less problematic.\n\nIf unsure, select OpenGL."); - static const char* TR_BYPASS_XFB_DESCRIPTION = QT_TR_NOOP( - "Disable any XFB emulation.\nSpeeds up emulation a lot but causes heavy glitches in many " - "games " - "which rely on them (especially homebrew applications).\n\nIf unsure, leave this checked."); - static const char* TR_SHOW_STATISTICS_DESCRIPTION = QT_TR_NOOP("Show various rendering statistics.\n\nIf unsure, leave this unchecked."); @@ -169,7 +162,6 @@ void SoftwareRendererWidget::AddDescriptions() "this unchecked."); AddDescription(m_backend_combo, TR_BACKEND_DESCRIPTION); - AddDescription(m_bypass_xfb, TR_BYPASS_XFB_DESCRIPTION); AddDescription(m_enable_statistics, TR_SHOW_STATISTICS_DESCRIPTION); AddDescription(m_dump_textures, TR_DUMP_TEXTURES_DESCRIPTION); } diff --git a/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.h b/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.h index 61b6130d4c..19d0918a63 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.h +++ b/Source/Core/DolphinQt2/Config/Graphics/SoftwareRendererWidget.h @@ -29,7 +29,6 @@ private: void AddDescriptions(); QComboBox* m_backend_combo; - QCheckBox* m_bypass_xfb; QCheckBox* m_enable_statistics; QCheckBox* m_dump_textures; QCheckBox* m_dump_objects; diff --git a/Source/Core/DolphinQt2/HotkeyScheduler.cpp b/Source/Core/DolphinQt2/HotkeyScheduler.cpp index e3aa7750c9..f72075c489 100644 --- a/Source/Core/DolphinQt2/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt2/HotkeyScheduler.cpp @@ -224,6 +224,8 @@ void HotkeyScheduler::Run() g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; if (IsHotkey(HK_TOGGLE_EFBCOPIES)) g_Config.bSkipEFBCopyToRam = !g_Config.bSkipEFBCopyToRam; + if (IsHotkey(HK_TOGGLE_XFBCOPIES)) + g_Config.bSkipXFBCopyToRam = !g_Config.bSkipXFBCopyToRam; if (IsHotkey(HK_TOGGLE_FOG)) g_Config.bDisableFog = !g_Config.bDisableFog; if (IsHotkey(HK_TOGGLE_DUMPTEXTURES)) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 6a1c3a0c53..5732664293 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1484,6 +1484,13 @@ void CFrame::ParseHotkeys() Config::SetCurrent(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, !Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM)); } + if (IsHotkey(HK_TOGGLE_XFBCOPIES)) + { + OSDChoice = 6; + // Toggle XFB copies between XFB2RAM and XFB2Texture + Config::SetCurrent(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, + !Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM)); + } if (IsHotkey(HK_TOGGLE_FOG)) { OSDChoice = 4; diff --git a/Source/Core/DolphinWX/SoftwareVideoConfigDialog.cpp b/Source/Core/DolphinWX/SoftwareVideoConfigDialog.cpp index af1ab0485a..76601ca2a9 100644 --- a/Source/Core/DolphinWX/SoftwareVideoConfigDialog.cpp +++ b/Source/Core/DolphinWX/SoftwareVideoConfigDialog.cpp @@ -77,10 +77,6 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std label_backend->Disable(); choice_backend->Disable(); } - - // xfb - szr_rendering->Add( - new SettingCheckBox(page_general, _("Bypass XFB"), "", Config::GFX_USE_XFB, true)); } // - info diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 051da17060..c33227b98b 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -201,6 +201,10 @@ static wxString skip_efb_copy_to_ram_desc = wxTRANSLATE( "Stores EFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " "in a small number of games.\n\nEnabled = EFB Copies to Texture\nDisabled = EFB Copies to RAM " "(and Texture)\n\nIf unsure, leave this checked."); +static wxString skip_xfb_copy_to_ram_desc = wxTRANSLATE( + "Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " + "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to Texture\nDisabled = XFB Copies to RAM " + "(and Texture)\n\nIf unsure, leave this checked."); static wxString stc_desc = wxTRANSLATE("The \"Safe\" setting eliminates the likelihood of the GPU missing texture updates " "from RAM.\nLower accuracies cause in-game text to appear garbled in certain " @@ -229,17 +233,6 @@ static wxString show_netplay_messages_desc = static wxString texfmt_desc = wxTRANSLATE("Modify textures to show the format they're encoded in. Needs an emulation reset " "in most cases.\n\nIf unsure, leave this unchecked."); -static wxString xfb_desc = wxTRANSLATE( - "Disable any XFB emulation.\nSpeeds up emulation a lot but causes heavy glitches in many games " - "which rely on them (especially homebrew applications).\n\nIf unsure, leave this checked."); -static wxString xfb_virtual_desc = wxTRANSLATE( - "Emulate XFBs using GPU texture objects.\nFixes many games which don't work without XFB " - "emulation while not being as slow as real XFB emulation. However, it may still fail for a lot " - "of other games (especially homebrew applications).\n\nIf unsure, leave this checked."); -static wxString xfb_real_desc = - wxTRANSLATE("Emulate XFBs accurately.\nSlows down emulation a lot and prohibits " - "high-resolution rendering but is necessary to emulate a number of games " - "properly.\n\nIf unsure, check virtual XFB emulation instead."); static wxString dump_textures_desc = wxTRANSLATE("Dump decoded game textures to User/Dump/Textures//.\n\nIf unsure, leave " "this unchecked."); @@ -724,6 +717,11 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM), 0, wxLEFT | wxRIGHT, space5); szr_efb->AddSpacer(space5); + szr_efb->Add(CreateCheckBox(page_hacks, _("Store XFB Copies to Texture Only"), + wxGetTranslation(skip_xfb_copy_to_ram_desc), + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM), + 0, wxLEFT | wxRIGHT, space5); + szr_efb->AddSpacer(space5); szr_hacks->AddSpacer(space5); szr_hacks->Add(szr_efb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); @@ -782,31 +780,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) szr_hacks->Add(szr_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); } - // - XFB - { - wxStaticBoxSizer* const group_xfb = - new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("External Frame Buffer (XFB)")); - - SettingCheckBox* disable_xfb = CreateCheckBox( - page_hacks, _("Disable"), wxGetTranslation(xfb_desc), Config::GFX_USE_XFB, true); - virtual_xfb = CreateRadioButton(page_hacks, _("Virtual"), wxGetTranslation(xfb_virtual_desc), - Config::GFX_USE_REAL_XFB, true, wxRB_GROUP); - real_xfb = CreateRadioButton(page_hacks, _("Real"), wxGetTranslation(xfb_real_desc), - Config::GFX_USE_REAL_XFB); - - wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL); - szr->Add(disable_xfb, 0, wxALIGN_CENTER_VERTICAL); - szr->AddStretchSpacer(1); - szr->Add(virtual_xfb, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5); - szr->Add(real_xfb, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5); - - group_xfb->Add(szr, 1, wxEXPAND | wxLEFT | wxRIGHT, space5); - group_xfb->AddSpacer(space5); - - szr_hacks->AddSpacer(space5); - szr_hacks->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); - } // xfb - // - other hacks { wxGridSizer* const szr_other = new wxGridSizer(2, space5, space5); @@ -1112,10 +1085,6 @@ void VideoConfigDiag::OnUpdateUI(wxUpdateUIEvent& ev) choice_aamode->Enable(vconfig.backend_info.AAModes.size() > 1); text_aamode->Enable(vconfig.backend_info.AAModes.size() > 1); - // XFB - virtual_xfb->Enable(vconfig.bUseXFB); - real_xfb->Enable(vconfig.bUseXFB); - // custom textures cache_hires_textures->Enable(vconfig.bHiresTextures); diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 43eb0a7ec3..ce77fb68fd 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -568,31 +568,6 @@ void Renderer::TransitionBuffersForSwap(const TargetRectangle& scaled_rect, { VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); - if (!g_ActiveConfig.bUseXFB) - { - // Drawing EFB direct. - if (g_ActiveConfig.iMultisamples > 1) - { - // While the source rect can be out-of-range when drawing, the resolve rectangle must be - // within the bounds of the texture. - VkRect2D region = { - {scaled_rect.left, scaled_rect.top}, - {static_cast(scaled_rect.GetWidth()), static_cast(scaled_rect.GetHeight())}}; - region = Util::ClampRect2D(region, FramebufferManager::GetInstance()->GetEFBWidth(), - FramebufferManager::GetInstance()->GetEFBHeight()); - - Vulkan::Texture2D* rtex = FramebufferManager::GetInstance()->ResolveEFBColorTexture(region); - rtex->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } - else - { - FramebufferManager::GetInstance()->GetEFBColorTexture()->TransitionToLayout( - command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } - - return; - } - // 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++) @@ -608,13 +583,6 @@ void Renderer::DrawFrame(VkRenderPass render_pass, const TargetRectangle& target const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, u32 fb_stride, u32 fb_height) { - if (!g_ActiveConfig.bUseXFB) - DrawEFB(render_pass, target_rect, scaled_efb_rect); - else if (!g_ActiveConfig.bUseRealXFB) - DrawVirtualXFB(render_pass, target_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, - fb_height); - else - DrawRealXFB(render_pass, target_rect, xfb_sources, xfb_count, fb_width, fb_stride, fb_height); } void Renderer::DrawEFB(VkRenderPass render_pass, const TargetRectangle& target_rect, @@ -1107,8 +1075,6 @@ void Renderer::CheckForConfigChanges() int old_aspect_ratio = g_ActiveConfig.iAspectRatio; int old_efb_scale = g_ActiveConfig.iEFBScale; bool old_force_filtering = g_ActiveConfig.bForceFiltering; - bool old_use_xfb = g_ActiveConfig.bUseXFB; - bool old_use_realxfb = g_ActiveConfig.bUseRealXFB; // Copy g_Config to g_ActiveConfig. // NOTE: This can potentially race with the UI thread, however if it does, the changes will be @@ -1120,14 +1086,12 @@ void Renderer::CheckForConfigChanges() bool force_texture_filtering_changed = old_force_filtering != g_ActiveConfig.bForceFiltering; bool efb_scale_changed = old_efb_scale != g_ActiveConfig.iEFBScale; bool aspect_changed = old_aspect_ratio != g_ActiveConfig.iAspectRatio; - bool use_xfb_changed = old_use_xfb != g_ActiveConfig.bUseXFB; - bool use_realxfb_changed = old_use_realxfb != g_ActiveConfig.bUseRealXFB; // Update texture cache settings with any changed options. TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig); // Handle settings that can cause the target rectangle to change. - if (efb_scale_changed || aspect_changed || use_xfb_changed || use_realxfb_changed) + if (efb_scale_changed || aspect_changed) { if (CalculateTargetSize()) ResizeEFBTextures(); diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index 4bcb5e6567..d749cb7bcf 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -40,15 +40,6 @@ FramebufferManagerBase::~FramebufferManagerBase() void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { - if (g_ActiveConfig.bUseRealXFB) - { - if (g_framebuffer_manager) - g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); - } - else - { - CopyToVirtualXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); - } } void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index d442e7f0b8..652eb15969 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -49,7 +49,7 @@ void VideoBackendBase::Video_ExitLoop() void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, u64 ticks) { - if (m_initialized && g_ActiveConfig.bUseXFB && g_renderer) + if (m_initialized && g_renderer) { Fifo::SyncGPU(Fifo::SyncGPUReason::Swap); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 95217f443b..28e607f8cb 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -327,6 +327,7 @@ void Renderer::DrawDebugText() } const char* const efbcopy_text = g_ActiveConfig.bSkipEFBCopyToRam ? "to Texture" : "to RAM"; + const char* const xfbcopy_text = g_ActiveConfig.bSkipXFBCopyToRam ? "to Texture" : "to RAM"; // The rows const std::string lines[] = { @@ -338,6 +339,7 @@ void Renderer::DrawDebugText() "Speed Limit: Unlimited" : StringFromFormat("Speed Limit: %li%%", std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)), + std::string("Copy XFB: ") + xfbcopy_text, }; enum @@ -688,8 +690,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const // New frame stats.ResetFrame(); - Core::Callback_VideoCopiedToXFB(m_xfb_written || - (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); + Core::Callback_VideoCopiedToXFB(m_xfb_written || !g_ActiveConfig.bSkipXFBCopyToRam); m_xfb_written = false; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 918e33bd64..7e71e5a38a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1416,7 +1416,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 30; // just re-use the RGBX8 cbufid from above - copy_to_ram = g_ActiveConfig.bUseRealXFB; + copy_to_ram = !g_ActiveConfig.bSkipXFBCopyToRam; is_xfb_copy = true; break; diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 8288ae8a1f..a127e23b18 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -67,8 +67,6 @@ void VideoConfig::Refresh() else iAspectRatio = aspect_ratio; bCrop = Config::Get(Config::GFX_CROP); - bUseXFB = Config::Get(Config::GFX_USE_XFB); - bUseRealXFB = Config::Get(Config::GFX_USE_REAL_XFB); iSafeTextureCache_ColorSamples = Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES); bShowFPS = Config::Get(Config::GFX_SHOW_FPS); bShowNetPlayPing = Config::Get(Config::GFX_SHOW_NETPLAY_PING); @@ -138,6 +136,7 @@ void VideoConfig::Refresh() Config::Get(Config::GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION); bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE); bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); + bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); bCopyEFBScaled = Config::Get(Config::GFX_HACK_COPY_EFB_ENABLED); bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES); bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING); @@ -171,13 +170,6 @@ void VideoConfig::VerifyValidity() 10000); iStereoMode = 0; } - - if (bUseXFB && bUseRealXFB) - { - OSD::AddMessage("Stereoscopic 3D isn't supported with Real XFB, turning off stereoscopy.", - 10000); - iStereoMode = 0; - } } } diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 4e0dc71b79..71031eb192 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -65,8 +65,6 @@ struct VideoConfig final bool bWidescreenHack; int iAspectRatio; bool bCrop; // Aspect ratio controls. - bool bUseXFB; - bool bUseRealXFB; bool bShaderCache; // Enhancements @@ -119,6 +117,7 @@ struct VideoConfig final bool bEFBEmulateFormatChanges; bool bSkipEFBCopyToRam; + bool bSkipXFBCopyToRam; bool bCopyEFBScaled; int iSafeTextureCache_ColorSamples; ProjectionHackConfig phack; @@ -229,8 +228,6 @@ struct VideoConfig final } backend_info; // Utility - bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; } - bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; } bool MultisamplingEnabled() const { return iMultisamples > 1; } bool ExclusiveFullscreenEnabled() const { From 2cd9565b187806490a962f4d78e975e6fb9dc027 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 26 Jun 2017 12:06:50 -0500 Subject: [PATCH 05/40] Add an additional flag fo 'XFB Copy' --- .../VideoBackends/Vulkan/TextureConverter.cpp | 2 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 49 ++++++++++++++----- Source/Core/VideoCommon/TextureCacheBase.h | 5 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index 75b4a01f4c..e4d0e167f9 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -150,7 +150,7 @@ TextureConverter::GetCommandBufferForTextureConversion(const TextureCache::TCach // EFB copies can be used as paletted textures as well. For these, we can't assume them to be // contain the correct data before the frame begins (when the init command buffer is executed), // so we must convert them at the appropriate time, during the drawing command buffer. - if (src_entry->IsEfbCopy()) + if (src_entry->IsCopy()) { StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->SetPendingRebind(); diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 7e71e5a38a..ed5a071177 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -158,7 +158,7 @@ void TextureCacheBase::Cleanup(int _frameCount) } else if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) { - if (iter->second->IsEfbCopy()) + if (iter->second->IsCopy()) { // Only remove EFB copies when they wouldn't be used anymore(changed hash), because EFB // copies living on the @@ -243,7 +243,8 @@ TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTForma decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); decoded_entry->SetHashes(entry->base_hash, entry->hash); decoded_entry->frameCount = FRAMECOUNT_INVALID; - decoded_entry->is_efb_copy = false; + decoded_entry->should_force_safe_hashing = false; + decoded_entry->SetNotCopy(); decoded_entry->may_have_overlapping_textures = entry->may_have_overlapping_textures; ConvertTexture(decoded_entry, entry, palette, tlutfmt); @@ -307,7 +308,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale // EFB copies are excluded from these updates, until there's an example where a game would // benefit from updating. This would require more work to be done. - if (entry_to_update->IsEfbCopy()) + if (entry_to_update->IsCopy()) return entry_to_update; u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt); @@ -321,7 +322,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale while (iter.first != iter.second) { TCacheEntry* entry = iter.first->second; - if (entry != entry_to_update && entry->IsEfbCopy() && !entry->tmem_only && + if (entry != entry_to_update && entry->IsCopy() && !entry->tmem_only && entry->references.count(entry_to_update) == 0 && entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes) && entry->memory_stride == numBlocksX * block_size) @@ -793,7 +794,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid // Do not load strided EFB copies, they are not meant to be used directly. // Also do not directly load EFB copies, which were partly overwritten. - if (entry->IsEfbCopy() && entry->native_width == nativeW && entry->native_height == nativeH && + if (entry->IsCopy() && entry->native_width == nativeW && entry->native_height == nativeH && entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures) { // EFB copies have slightly different rules as EFB copy formats have different @@ -828,7 +829,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid else { // For normal textures, all texture parameters need to match - if (!entry->IsEfbCopy() && entry->hash == full_hash && entry->format == full_format && + if (!entry->IsCopy() && entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { @@ -844,7 +845,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid // Example: Sonic the Fighters (inside Sonic Gems Collection) // Skip EFB copies here, so they can be used for partial texture updates if (entry->frameCount != FRAMECOUNT_INVALID && entry->frameCount < temp_frameCount && - !entry->IsEfbCopy() && !(isPaletteTexture && entry->base_hash == base_hash)) + !entry->IsCopy() && !(isPaletteTexture && entry->base_hash == base_hash)) { temp_frameCount = entry->frameCount; oldest_entry = iter; @@ -1016,9 +1017,9 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid entry->SetGeneralParameters(address, texture_size, full_format, false); entry->SetDimensions(nativeW, nativeH, tex_levels); entry->SetHashes(base_hash, full_hash); - entry->is_efb_copy = false; entry->is_custom_tex = hires_tex != nullptr; entry->memory_stride = entry->BytesPerRow(); + entry->SetNotCopy(); std::string basename = ""; if (g_ActiveConfig.bDumpTextures && !hires_tex) @@ -1557,7 +1558,15 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF entry->SetDimensions(tex_w, tex_h, 1); entry->frameCount = FRAMECOUNT_INVALID; - entry->SetEfbCopy(dstStride); + if (is_xfb_copy) + { + entry->should_force_safe_hashing = is_xfb_copy; + entry->SetXfbCopy(dstStride); + } + else + { + entry->SetEfbCopy(dstStride); + } entry->may_have_overlapping_textures = false; entry->is_custom_tex = false; @@ -1727,9 +1736,10 @@ u32 TextureCacheBase::TCacheEntry::NumBlocksY() const return actualHeight / blockH; } -void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) +void TextureCacheBase::TCacheEntry::SetXfbCopy(u32 stride) { - is_efb_copy = true; + is_efb_copy = false; + is_xfb_copy = true; memory_stride = stride; _assert_msg_(VIDEO, memory_stride >= BytesPerRow(), "Memory stride is too small"); @@ -1737,6 +1747,23 @@ void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) size_in_bytes = memory_stride * NumBlocksY(); } +void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride) +{ + is_efb_copy = true; + is_xfb_copy = false; + memory_stride = stride; + + _assert_msg_(VIDEO, memory_stride >= BytesPerRow(), "Memory stride is too small"); + + size_in_bytes = memory_stride * NumBlocksY(); +} + +void TextureCacheBase::TCacheEntry::SetNotCopy() +{ + is_xfb_copy = false; + is_efb_copy = false; +} + int TextureCacheBase::TCacheEntry::HashSampleSize() const { if (should_force_safe_hashing) diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 40c1779fbb..53ab41a836 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -85,6 +85,7 @@ public: bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary // content, aren't just downscaled bool should_force_safe_hashing = false; // for XFB + bool is_xfb_copy = false; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view @@ -137,11 +138,15 @@ public: other_entry->references.emplace(this); } + void SetXfbCopy(u32 stride); void SetEfbCopy(u32 stride); + void SetNotCopy(); bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; bool IsEfbCopy() const { return is_efb_copy; } + bool IsCopy() const { return is_xfb_copy || is_efb_copy; } + u32 NumBlocksY() const; u32 BytesPerRow() const; From 5a372020ea989abb5dfaf10040d6e3fbd90c8001 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 26 Jun 2017 14:49:32 -0500 Subject: [PATCH 06/40] FifoPlayer: Generate fake VideoInterface updates --- Source/Core/Core/FifoPlayer/FifoDataFile.cpp | 5 +++ Source/Core/Core/FifoPlayer/FifoDataFile.h | 1 + Source/Core/Core/FifoPlayer/FifoPlayer.cpp | 10 +++++ Source/Core/Core/FifoPlayer/FifoPlayer.h | 2 + Source/Core/Core/HW/VideoInterface.cpp | 46 +++++++++++++++++++- Source/Core/Core/HW/VideoInterface.h | 3 ++ Source/Core/VideoCommon/BPStructs.cpp | 7 +++ 7 files changed, 72 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/FifoPlayer/FifoDataFile.cpp b/Source/Core/Core/FifoPlayer/FifoDataFile.cpp index af693688f8..9b3d03d69a 100644 --- a/Source/Core/Core/FifoPlayer/FifoDataFile.cpp +++ b/Source/Core/Core/FifoPlayer/FifoDataFile.cpp @@ -72,6 +72,11 @@ FifoDataFile::FifoDataFile() = default; FifoDataFile::~FifoDataFile() = default; +bool FifoDataFile::ShouldGenerateFakeVIUpdates() const +{ + return true; +} + bool FifoDataFile::HasBrokenEFBCopies() const { return m_Version < 2; diff --git a/Source/Core/Core/FifoPlayer/FifoDataFile.h b/Source/Core/Core/FifoPlayer/FifoDataFile.h index f57f2fcf4a..a3825ffd2c 100644 --- a/Source/Core/Core/FifoPlayer/FifoDataFile.h +++ b/Source/Core/Core/FifoPlayer/FifoDataFile.h @@ -60,6 +60,7 @@ public: void SetIsWii(bool isWii); bool GetIsWii() const; bool HasBrokenEFBCopies() const; + bool ShouldGenerateFakeVIUpdates() const; u32* GetBPMem() { return m_BPMem; } u32* GetCPMem() { return m_CPMem; } diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp index f84b783e68..32d0c0871c 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp @@ -162,6 +162,16 @@ std::unique_ptr FifoPlayer::GetCPUCore() return std::make_unique(this); } +bool FifoPlayer::IsRunningWithFakeVideoInterfaceUpdates() const +{ + if (!m_File || m_File->GetFrameCount() == 0) + { + return false; + } + + return m_File->ShouldGenerateFakeVIUpdates(); +} + u32 FifoPlayer::GetFrameObjectCount() const { if (m_CurrentFrame < m_FrameInfo.size()) diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.h b/Source/Core/Core/FifoPlayer/FifoPlayer.h index b291415ead..b2db00cb0f 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.h +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.h @@ -94,6 +94,8 @@ public: void SetFrameWrittenCallback(CallbackFunc callback) { m_FrameWrittenCb = callback; } static FifoPlayer& GetInstance(); + bool IsRunningWithFakeVideoInterfaceUpdates() const; + private: class CPUCore; diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp index d02a9be81d..c8ec4a3d0b 100644 --- a/Source/Core/Core/HW/VideoInterface.cpp +++ b/Source/Core/Core/HW/VideoInterface.cpp @@ -18,6 +18,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/CoreTiming.h" +#include "Core/FifoPlayer/FifoPlayer.h" #include "Core/HW/MMIO.h" #include "Core/HW/ProcessorInterface.h" #include "Core/HW/SI/SI.h" @@ -549,8 +550,9 @@ float GetAspectRatio() // 5. Calculate the final ratio and scale to 4:3 float ratio = horizontal_active_ratio / vertical_active_ratio; - if (std::isnormal( - ratio)) // Check we have a sane ratio and haven't propagated any infs/nans/zeros + bool running_fifo_log = FifoPlayer::GetInstance().IsRunningWithFakeVideoInterfaceUpdates(); + if (std::isnormal(ratio) && // Check we have a sane ratio without any infs/nans/zeros + !running_fifo_log) // we don't know the correct ratio for fifos return ratio * (4.0f / 3.0f); // Scale to 4:3 else return (4.0f / 3.0f); // VI isn't initialized correctly, just return 4:3 instead @@ -775,4 +777,44 @@ void Update(u64 ticks) UpdateInterrupts(); } +// Create a fake VI mode for a fifolog +void FakeVIUpdate(u32 xfb_address, u32 fb_width, u32 fb_height) +{ + u32 fb_stride = fb_width; + + bool interlaced = fb_height > 480 / 2; + if (interlaced) + { + fb_height = fb_height / 2; + fb_stride = fb_stride * 2; + } + + m_XFBInfoTop.POFF = 1; + m_XFBInfoBottom.POFF = 1; + m_VerticalTimingRegister.ACV = fb_height; + m_VerticalTimingRegister.EQU = 6; + m_VBlankTimingOdd.PRB = 502 - fb_height * 2; + m_VBlankTimingOdd.PSB = 5; + m_VBlankTimingEven.PRB = 503 - fb_height * 2; + m_VBlankTimingEven.PSB = 4; + m_PictureConfiguration.WPL = fb_width / 16; + m_PictureConfiguration.STD = fb_stride / 16; + + UpdateParameters(); + + u32 total_halflines = GetHalfLinesPerEvenField() + GetHalfLinesPerOddField(); + + if ((s_half_line_count - s_even_field_first_hl) % total_halflines < + (s_half_line_count - s_odd_field_first_hl) % total_halflines) + { + // Even/Bottom field is next. + m_XFBInfoBottom.FBB = interlaced ? (xfb_address + fb_width * 2) >> 5 : xfb_address >> 5; + } + else + { + // Odd/Top field is next + m_XFBInfoTop.FBB = (xfb_address >> 5); + } +} + } // namespace diff --git a/Source/Core/Core/HW/VideoInterface.h b/Source/Core/Core/HW/VideoInterface.h index 6d5a07edf9..7f0ebf8400 100644 --- a/Source/Core/Core/HW/VideoInterface.h +++ b/Source/Core/Core/HW/VideoInterface.h @@ -373,4 +373,7 @@ u32 GetTicksPerField(); // result by 1.33333.. float GetAspectRatio(); +// Create a fake VI mode for a fifolog +void FakeVIUpdate(u32 xfb_address, u32 fb_width, u32 fb_height); + } // namespace VideoInterface diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 977cc46b3e..e721831481 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -12,8 +12,10 @@ #include "Common/StringUtil.h" #include "Common/Thread.h" #include "Core/ConfigManager.h" +#include "Core/FifoPlayer/FifoPlayer.h" #include "Core/FifoPlayer/FifoRecorder.h" #include "Core/HW/Memmap.h" +#include "Core/HW/VideoInterface.h" #include "VideoCommon/BPFunctions.h" #include "VideoCommon/BPMemory.h" @@ -263,6 +265,11 @@ static void BPWritten(const BPCmd& bp) // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); + + if (FifoPlayer::GetInstance().IsRunningWithFakeVideoInterfaceUpdates()) + { + VideoInterface::FakeVIUpdate(destAddr, srcRect.GetWidth(), height); + } } // Clear the rectangular region after copying it. From b285188de1a38565b9718bdac7fe698ee870d914 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 2 Jul 2017 21:24:20 -0500 Subject: [PATCH 07/40] Video Backends: Implement vertical scaling for xfb copies. This fixes the display of PAL games that run in 50hz mode. --- .../VideoBackends/D3D/PSTextureEncoder.cpp | 7 ++++-- .../VideoBackends/OGL/TextureConverter.cpp | 11 ++++++---- .../VideoBackends/Vulkan/TextureConverter.cpp | 22 +++++++++++++++---- Source/Core/VideoCommon/BPStructs.cpp | 4 ++-- Source/Core/VideoCommon/RenderBase.cpp | 11 +++++----- Source/Core/VideoCommon/TextureCacheBase.cpp | 20 +++++++++-------- Source/Core/VideoCommon/TextureCacheBase.h | 15 ++++++++----- .../VideoCommon/TextureConversionShader.cpp | 9 ++++++-- 8 files changed, 65 insertions(+), 34 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 7c05215948..2aafb299bf 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -26,6 +26,8 @@ struct EFBEncodeParams s32 SrcTop; u32 DestWidth; u32 ScaleFactor; + float y_scale; + u32 padding[3]; }; PSTextureEncoder::PSTextureEncoder() @@ -45,7 +47,7 @@ void PSTextureEncoder::Init() // 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, 1, 1, D3D11_BIND_RENDER_TARGET); + 1024, 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"); @@ -127,6 +129,7 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_w encode_params.SrcTop = src_rect.top; encode_params.DestWidth = native_width; encode_params.ScaleFactor = scale_by_half ? 2 : 1; + encode_params.y_scale = params.y_scale; D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &encode_params, 0, 0); D3D::stateman->SetPixelConstants(m_encodeParams); @@ -134,7 +137,7 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, u32 native_w // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more // complex down filtering to average all pixels and produce the correct result. // Also, box filtering won't be correct for anything other than 1x IR - if (scale_by_half || g_renderer->GetEFBScale() != 1) + if (scale_by_half || g_renderer->GetEFBScale() != 1 || params.y_scale > 1.0f) D3D::SetLinearCopySampler(); else D3D::SetPointCopySampler(); diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp index 67f1bcc28e..1fb55c8d24 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp @@ -50,6 +50,7 @@ struct EncodingProgram { SHADER program; GLint copy_position_uniform; + GLint y_scale_uniform; }; static std::map s_encoding_programs; @@ -166,6 +167,7 @@ static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params) PanicAlert("Failed to compile texture encoding shader."); program.copy_position_uniform = glGetUniformLocation(program.program.glprogid, "position"); + program.y_scale_uniform = glGetUniformLocation(program.program.glprogid, "y_scale"); return s_encoding_programs.emplace(params, program).first->second; } @@ -217,7 +219,7 @@ void Shutdown() // dst_line_size, writeStride in bytes static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line_size, - u32 dstHeight, u32 writeStride, bool linearFilter) + u32 dstHeight, u32 writeStride, bool linearFilter, float y_scale) { // switch to texture converter frame buffer // attach render buffer as color destination @@ -233,7 +235,7 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more // complex down filtering to average all pixels and produce the correct result. // Also, box filtering won't be correct for anything other than 1x IR - if (linearFilter || g_renderer->GetEFBScale() != 1) + if (linearFilter || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f) g_sampler_cache->BindLinearSampler(9); else g_sampler_cache->BindNearestSampler(9); @@ -282,13 +284,14 @@ void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 nativ texconv_shader.program.Bind(); glUniform4i(texconv_shader.copy_position_uniform, src_rect.left, src_rect.top, native_width, scale_by_half ? 2 : 1); + glUniform1f(texconv_shader.y_scale_uniform, params.y_scale); const GLuint read_texture = params.depth ? FramebufferManager::ResolveAndGetDepthTarget(src_rect) : FramebufferManager::ResolveAndGetRenderTarget(src_rect); EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, memory_stride, - scale_by_half && !params.depth); + scale_by_half && !params.depth, params.y_scale); FramebufferManager::SetFramebuffer(0); g_renderer->RestoreAPIState(); @@ -308,7 +311,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des // 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); + EncodeToRamUsingShader(srcTexture, destAddr, dstWidth * 2, dstHeight, dstStride, true, 1.0f); FramebufferManager::SetFramebuffer(0); OGLTexture::DisableStage(0); g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index e4d0e167f9..75f274f917 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -5,6 +5,7 @@ #include "VideoBackends/Vulkan/TextureConverter.h" #include +#include #include #include #include @@ -32,6 +33,14 @@ namespace Vulkan { + namespace + { + struct EFBEncodeParams + { + std::array position_uniform; + float y_scale; + }; + } TextureConverter::TextureConverter() { } @@ -243,14 +252,19 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p VK_NULL_HANDLE, shader); // Uniform - int4 of left,top,native_width,scale - s32 position_uniform[4] = {src_rect.left, src_rect.top, static_cast(native_width), - scale_by_half ? 2 : 1}; - draw.SetPushConstants(position_uniform, sizeof(position_uniform)); + EFBEncodeParams encoder_params; + encoder_params.position_uniform[0] = src_rect.left; + encoder_params.position_uniform[1] = src_rect.top; + encoder_params.position_uniform[2] = static_cast(native_width); + encoder_params.position_uniform[3] = scale_by_half ? 2 : 1; + encoder_params.y_scale = params.y_scale; + draw.SetPushConstants(&encoder_params, sizeof(encoder_params)); // We also linear filtering for both box filtering and downsampling higher resolutions to 1x // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more // complex down filtering to average all pixels and produce the correct result. - bool linear_filter = (scale_by_half && !params.depth) || g_renderer->GetEFBScale() != 1; + bool linear_filter = (scale_by_half && !params.depth) || g_renderer->GetEFBScale() != 1 || + params.y_scale > 1.0f; draw.SetPSSampler(0, src_texture, linear_filter ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler()); diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index e721831481..183f7d4f20 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -232,7 +232,7 @@ static void BPWritten(const BPCmd& bp) bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24; g_texture_cache->CopyRenderTargetToTexture(destAddr, PE_copy.tp_realFormat(), destStride, is_depth_copy, srcRect, !!PE_copy.intensity_fmt, - !!PE_copy.half_scale); + !!PE_copy.half_scale, 1.0f); } else { @@ -261,7 +261,7 @@ static void BPWritten(const BPCmd& bp) bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24; g_texture_cache->CopyRenderTargetToTexture(destAddr, EFBCopyFormat::XFB, destStride, is_depth_copy, srcRect, false, - false); + false, yScale); // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 28e607f8cb..168aece684 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -668,15 +668,16 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const // Get the current XFB from texture cache auto* xfb_entry = g_texture_cache->GetTexture(xfbAddr, fbWidth, fbHeight, TextureFormat::XFB, force_safe_texture_cache_hash); - - // TODO, check if xfb_entry is a duplicate of the previous frame and skip SwapImpl - m_previous_xfb_texture = xfb_entry->texture.get(); + if (xfb_entry) + { + // TODO, check if xfb_entry is a duplicate of the previous frame and skip SwapImpl m_last_xfb_texture = xfb_entry->texture.get(); - // TODO: merge more generic parts into VideoCommon - g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, Gamma); + // TODO: merge more generic parts into VideoCommon + g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, Gamma); + } } if (m_xfb_written) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ed5a071177..beb5b584d8 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -376,7 +376,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x); u32 copy_height = - std::min(entry->native_height - src_y, entry_to_update->native_height - dst_y); + std::min((entry->native_height * entry->y_scale) - src_y, (entry_to_update->native_height * entry_to_update->y_scale) - dst_y); // If one of the textures is scaled, scale both with the current efb scaling factor if (entry_to_update->native_width != entry_to_update->GetWidth() || @@ -385,9 +385,9 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale { ScaleTextureCacheEntryTo(entry_to_update, g_renderer->EFBToScaledX(entry_to_update->native_width), - g_renderer->EFBToScaledY(entry_to_update->native_height)); + g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width), - g_renderer->EFBToScaledY(entry->native_height)); + g_renderer->EFBToScaledY(entry->native_height * entry->y_scale)); src_x = g_renderer->EFBToScaledX(src_x); src_y = g_renderer->EFBToScaledY(src_y); @@ -794,7 +794,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid // Do not load strided EFB copies, they are not meant to be used directly. // Also do not directly load EFB copies, which were partly overwritten. - if (entry->IsCopy() && entry->native_width == nativeW && entry->native_height == nativeH && + if (entry->IsCopy() && entry->native_width == nativeW && static_cast(entry->native_height * entry->y_scale) == nativeH && entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures) { // EFB copies have slightly different rules as EFB copy formats have different @@ -881,7 +881,8 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid TCacheEntry* entry = hash_iter->second; // All parameters, except the address, need to match here if (entry->format == full_format && entry->native_levels >= tex_levels && - entry->native_width == nativeW && entry->native_height == nativeH) + entry->native_width == nativeW && + static_cast(entry->native_height * entry->y_scale) == nativeH) { entry = DoPartialTextureUpdates(hash_iter->second, &texMem[tlutaddr], tlutfmt); @@ -1107,7 +1108,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf) + bool scaleByHalf, float y_scale) { // Emulation methods: // @@ -1451,7 +1452,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF const u32 blockW = TexDecoder_GetBlockWidthInTexels(baseFormat); // Round up source height to multiple of block size - u32 actualHeight = Common::AlignUp(tex_h, blockH); + u32 actualHeight = Common::AlignUp(static_cast(tex_h * y_scale), blockH); const u32 actualWidth = Common::AlignUp(tex_w, blockW); u32 num_blocks_y = actualHeight / blockH; @@ -1465,7 +1466,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF if (copy_to_ram) { - EFBCopyParams format(srcFormat, dstFormat, is_depth_copy, isIntensity); + EFBCopyParams format(srcFormat, dstFormat, is_depth_copy, isIntensity, y_scale); CopyEFB(dst, format, tex_w, bytes_per_row, num_blocks_y, dstStride, srcRect, scaleByHalf); } else @@ -1556,6 +1557,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF { entry->SetGeneralParameters(dstAddr, 0, baseFormat, is_xfb_copy); entry->SetDimensions(tex_w, tex_h, 1); + entry->y_scale = y_scale; entry->frameCount = FRAMECOUNT_INVALID; if (is_xfb_copy) @@ -1731,7 +1733,7 @@ u32 TextureCacheBase::TCacheEntry::NumBlocksY() const { u32 blockH = TexDecoder_GetBlockHeightInTexels(format.texfmt); // Round up source height to multiple of block size - u32 actualHeight = Common::AlignUp(native_height, blockH); + u32 actualHeight = Common::AlignUp(static_cast(native_height * y_scale), blockH); return actualHeight / blockH; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 53ab41a836..96b36b6eba 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -45,21 +45,22 @@ struct TextureAndTLUTFormat struct EFBCopyParams { EFBCopyParams(PEControl::PixelFormat efb_format_, EFBCopyFormat copy_format_, bool depth_, - bool yuv_) - : efb_format(efb_format_), copy_format(copy_format_), depth(depth_), yuv(yuv_) + bool yuv_, float y_scale_) + : efb_format(efb_format_), copy_format(copy_format_), depth(depth_), yuv(yuv_), y_scale(y_scale_) { } bool operator<(const EFBCopyParams& rhs) const { - return std::tie(efb_format, copy_format, depth, yuv) < - std::tie(rhs.efb_format, rhs.copy_format, rhs.depth, rhs.yuv); + return std::tie(efb_format, copy_format, depth, yuv, y_scale) < + std::tie(rhs.efb_format, rhs.copy_format, rhs.depth, rhs.yuv, rhs.y_scale); } PEControl::PixelFormat efb_format; EFBCopyFormat copy_format; bool depth; bool yuv; + float y_scale; }; class TextureCacheBase @@ -86,6 +87,7 @@ public: // content, aren't just downscaled bool should_force_safe_hashing = false; // for XFB bool is_xfb_copy = false; + float y_scale = 1.0f; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view @@ -188,7 +190,7 @@ public: virtual void BindTextures(); void CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf); + bool scaleByHalf, float y_scale); virtual void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette, TLUTFormat format) = 0; @@ -210,6 +212,8 @@ public: { } + void ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, u32 new_height); + protected: TextureCacheBase(); @@ -235,7 +239,6 @@ private: TCacheEntry* ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTFormat tlutfmt); - void ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, u32 new_height); TCacheEntry* DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* palette, TLUTFormat tlutfmt); diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 74e50cd27f..04b7bb3a01 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -64,9 +64,12 @@ static void WriteSwizzler(char*& p, EFBCopyFormat format, APIType ApiType) // left, top, of source rectangle within source texture // width of the destination rectangle, scale_factor (1 or 2) if (ApiType == APIType::Vulkan) - WRITE(p, "layout(std140, push_constant) uniform PCBlock { int4 position; } PC;\n"); + WRITE(p, "layout(std140, push_constant) uniform PCBlock { int4 position; float y_scale; } PC;\n"); else + { WRITE(p, "uniform int4 position;\n"); + WRITE(p, "uniform float y_scale;\n"); + } // Alpha channel in the copy is set to 1 the EFB format does not have an alpha channel. WRITE(p, "float4 RGBA8ToRGB8(float4 src)\n"); @@ -111,7 +114,8 @@ static void WriteSwizzler(char*& p, EFBCopyFormat format, APIType ApiType) WRITE(p, "{\n" " int2 sampleUv;\n" " int2 uv1 = int2(gl_FragCoord.xy);\n" - " int4 position = PC.position;\n"); + " int4 position = PC.position;\n" + " float y_scale = PC.y_scale;\n"); } else // D3D { @@ -150,6 +154,7 @@ static void WriteSwizzler(char*& p, EFBCopyFormat format, APIType ApiType) // pixel) WRITE(p, " uv0 += float2(position.xy);\n"); // move to copied rect WRITE(p, " uv0 /= float2(%d, %d);\n", EFB_WIDTH, EFB_HEIGHT); // normalize to [0:1] + WRITE(p, " uv0 /= float2(1, y_scale);\n"); // apply the y scaling if (ApiType == APIType::OpenGL) // ogl has to flip up and down { WRITE(p, " uv0.y = 1.0-uv0.y;\n"); From 081b92b8a7927fe699c5515cb1c90dcf8fe44179 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 5 Aug 2017 00:40:17 -0500 Subject: [PATCH 08/40] Video Common: Only update FPS when frame is renderered which yields more accurate results --- Source/Core/VideoCommon/RenderBase.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 168aece684..0a3648c9ea 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -662,6 +662,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const } } + bool update_frame_count = false; if (xfbAddr && fbWidth && fbStride && fbHeight) { constexpr int force_safe_texture_cache_hash = 0; @@ -677,12 +678,12 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const // TODO: merge more generic parts into VideoCommon g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, Gamma); + + m_fps_counter.Update(); + update_frame_count = true; } } - if (m_xfb_written) - m_fps_counter.Update(); - frameCount++; GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true); @@ -691,7 +692,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const // New frame stats.ResetFrame(); - Core::Callback_VideoCopiedToXFB(m_xfb_written || !g_ActiveConfig.bSkipXFBCopyToRam); + Core::Callback_VideoCopiedToXFB(update_frame_count); m_xfb_written = false; } From 33bc286baaafe31b2b564dd5d5574307cbd9e921 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 6 Aug 2017 23:05:42 -0500 Subject: [PATCH 09/40] Remove old XFB logic --- Source/Core/VideoBackends/D3D/CMakeLists.txt | 2 - Source/Core/VideoBackends/D3D/D3D.vcxproj | 2 - .../VideoBackends/D3D/D3D.vcxproj.filters | 6 - .../VideoBackends/D3D/FramebufferManager.cpp | 54 --- .../VideoBackends/D3D/FramebufferManager.h | 18 - Source/Core/VideoBackends/D3D/Render.cpp | 5 - Source/Core/VideoBackends/D3D/XFBEncoder.cpp | 367 ------------------ Source/Core/VideoBackends/D3D/XFBEncoder.h | 46 --- .../VideoBackends/Null/FramebufferManager.h | 33 -- Source/Core/VideoBackends/Null/Null.vcxproj | 1 - .../Core/VideoBackends/Null/NullBackend.cpp | 4 +- .../VideoBackends/OGL/FramebufferManager.cpp | 73 ---- .../VideoBackends/OGL/FramebufferManager.h | 20 - Source/Core/VideoBackends/OGL/Render.cpp | 156 +------- Source/Core/VideoBackends/OGL/Render.h | 21 - .../VideoBackends/OGL/TextureConverter.cpp | 149 ------- .../Core/VideoBackends/OGL/TextureConverter.h | 5 - .../Vulkan/FramebufferManager.cpp | 89 ----- .../VideoBackends/Vulkan/FramebufferManager.h | 25 -- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 356 ----------------- Source/Core/VideoBackends/Vulkan/Renderer.h | 66 ---- .../VideoCommon/FramebufferManagerBase.cpp | 140 +------ .../Core/VideoCommon/FramebufferManagerBase.h | 60 --- Source/Core/VideoCommon/RenderBase.cpp | 31 -- Source/Core/VideoCommon/RenderBase.h | 2 - 25 files changed, 4 insertions(+), 1727 deletions(-) delete mode 100644 Source/Core/VideoBackends/D3D/XFBEncoder.cpp delete mode 100644 Source/Core/VideoBackends/D3D/XFBEncoder.h delete mode 100644 Source/Core/VideoBackends/Null/FramebufferManager.h 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; From 4d13f69dc146bff6e9f1debf4f51d38e6b1e19db Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 6 Aug 2017 23:06:03 -0500 Subject: [PATCH 10/40] Remove TODOs --- Source/Core/VideoBackends/Software/EfbInterface.cpp | 7 ------- Source/Core/VideoBackends/Software/EfbInterface.h | 1 - Source/Core/VideoCommon/TextureDecoder_Common.cpp | 1 - 3 files changed, 9 deletions(-) diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index 411839c852..d80bd02f5b 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -553,13 +553,6 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe } } -// Like CopyToXFB, but we copy directly into the OpenGL color texture without going via GameCube -// main memory or doing a yuyv conversion -void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) -{ - // TODO: Upload directly to texture cache. -} - bool ZCompare(u16 x, u16 y, u32 z) { u32 offset = GetDepthOffset(x, y); diff --git a/Source/Core/VideoBackends/Software/EfbInterface.h b/Source/Core/VideoBackends/Software/EfbInterface.h index 244e1fc3cf..1e246db38f 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.h +++ b/Source/Core/VideoBackends/Software/EfbInterface.h @@ -59,7 +59,6 @@ u8* GetPixelPointer(u16 x, u16 y, bool depth); void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma); -void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma); extern u32 perf_values[PQ_NUM_MEMBERS]; inline void IncPerfCounterQuadCount(PerfQueryType type) diff --git a/Source/Core/VideoCommon/TextureDecoder_Common.cpp b/Source/Core/VideoCommon/TextureDecoder_Common.cpp index 90be3d8dc7..4351a819c0 100644 --- a/Source/Core/VideoCommon/TextureDecoder_Common.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_Common.cpp @@ -640,7 +640,6 @@ void TexDecoder_DecodeTexel(u8* dst, const u8* src, int s, int t, int imageWidth break; case TextureFormat::XFB: { - // TODO: I should kind of like... ACTUALLY TEST THIS!!!!! size_t offset = (t * imageWidth + (s & (~1))) * 2; // We do this one color sample (aka 2 RGB pixles) at a time From 76b775d5be1f9228c648b8edc1f7bb9533acb471 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 8 Aug 2017 00:09:25 -0500 Subject: [PATCH 11/40] Video Common: Add XFB decoding via the GPU --- .../Core/VideoBackends/OGL/TextureCache.cpp | 1 + .../VideoBackends/Vulkan/TextureConverter.cpp | 20 ++++++++++++- .../VideoBackends/Vulkan/TextureConverter.h | 1 + .../VideoCommon/TextureConversionShader.cpp | 29 +++++++++++++++++++ .../VideoCommon/TextureConversionShader.h | 1 + 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index df4bcb7f00..997b53f74b 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -391,6 +391,7 @@ void TextureCache::CreateTextureDecodingResources() GL_R8UI, // BUFFER_FORMAT_R8_UINT GL_R16UI, // BUFFER_FORMAT_R16_UINT GL_RG32UI, // BUFFER_FORMAT_R32G32_UINT + GL_RGBA8UI, // BUFFER_FORMAT_RGBA8_UINT }; glGenTextures(TextureConversionShader::BUFFER_FORMAT_COUNT, diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index 75f274f917..b646a59fa8 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -61,6 +61,8 @@ TextureConverter::~TextureConverter() vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_r32g32_uint, nullptr); if (m_texel_buffer_view_rgba8_unorm != VK_NULL_HANDLE) vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_rgba8_unorm, nullptr); + if (m_texel_buffer_view_rgba8_uint != VK_NULL_HANDLE) + vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_rgba8_uint, nullptr); if (m_encoding_render_pass != VK_NULL_HANDLE) vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_encoding_render_pass, nullptr); @@ -487,11 +489,22 @@ void TextureConverter::DecodeTexture(VkCommandBuffer command_buffer, // Copy/commit upload buffer. u32 texel_buffer_offset = static_cast(m_texel_buffer->GetCurrentOffset()); + + Util::BufferMemoryBarrier(g_command_buffer_mgr->GetCurrentCommandBuffer(), + m_texel_buffer->GetBuffer(), VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_HOST_WRITE_BIT, texel_buffer_offset, total_upload_size, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT); + std::memcpy(m_texel_buffer->GetCurrentHostPointer(), data, data_size); if (has_palette) std::memcpy(m_texel_buffer->GetCurrentHostPointer() + palette_offset, palette, palette_size); m_texel_buffer->CommitMemory(total_upload_size); + Util::BufferMemoryBarrier(g_command_buffer_mgr->GetCurrentCommandBuffer(), + m_texel_buffer->GetBuffer(), VK_ACCESS_HOST_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, texel_buffer_offset, total_upload_size, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + // Determine uniforms. PushConstants constants = { {width, height}, @@ -513,6 +526,9 @@ void TextureConverter::DecodeTexture(VkCommandBuffer command_buffer, case TextureConversionShader::BUFFER_FORMAT_R32G32_UINT: data_view = m_texel_buffer_view_r32g32_uint; break; + case TextureConversionShader::BUFFER_FORMAT_RGBA8_UINT: + data_view = m_texel_buffer_view_rgba8_uint; + break; default: break; } @@ -564,10 +580,12 @@ bool TextureConverter::CreateTexelBuffer() m_texel_buffer_view_r16_uint = CreateTexelBufferView(VK_FORMAT_R16_UINT); m_texel_buffer_view_r32g32_uint = CreateTexelBufferView(VK_FORMAT_R32G32_UINT); m_texel_buffer_view_rgba8_unorm = CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UNORM); + m_texel_buffer_view_rgba8_uint= CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UINT); return m_texel_buffer_view_r8_uint != VK_NULL_HANDLE && m_texel_buffer_view_r16_uint != VK_NULL_HANDLE && m_texel_buffer_view_r32g32_uint != VK_NULL_HANDLE && - m_texel_buffer_view_rgba8_unorm != VK_NULL_HANDLE; + m_texel_buffer_view_rgba8_unorm != VK_NULL_HANDLE && + m_texel_buffer_view_rgba8_uint != VK_NULL_HANDLE; } VkBufferView TextureConverter::CreateTexelBufferView(VkFormat format) const diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.h b/Source/Core/VideoBackends/Vulkan/TextureConverter.h index 2465691901..1a62590019 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.h +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.h @@ -97,6 +97,7 @@ private: VkBufferView m_texel_buffer_view_r8_uint = VK_NULL_HANDLE; VkBufferView m_texel_buffer_view_r16_uint = VK_NULL_HANDLE; VkBufferView m_texel_buffer_view_r32g32_uint = VK_NULL_HANDLE; + VkBufferView m_texel_buffer_view_rgba8_uint = VK_NULL_HANDLE; VkBufferView m_texel_buffer_view_rgba8_unorm = VK_NULL_HANDLE; size_t m_texel_buffer_size = 0; diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 04b7bb3a01..1f608651ca 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -1262,12 +1262,41 @@ static const std::map s_decoding_shader_info{ vec4 norm_color = GetPaletteColorNormalized(index); imageStore(output_image, ivec3(ivec2(coords), 0), norm_color); } + )"}}, + + // We do the inverse BT.601 conversion for YCbCr to RGB + // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion + { TextureFormat::XFB, + { BUFFER_FORMAT_RGBA8_UINT, 0, 8, 8, false, + R"( + layout(local_size_x = 8, local_size_y = 8) in; + + void main() + { + uvec2 uv = gl_GlobalInvocationID.xy; + int buffer_pos = int(u_src_offset + (uv.y * u_src_row_stride) + (uv.x / 2)); + vec4 yuyv = texelFetch(s_input_buffer, buffer_pos); + + float y = mix(yuyv.r, yuyv.b, (uv.x & 1u) == 1u); + + float yComp = 1.164 * (y - 16); + float uComp = yuyv.g - 128; + float vComp = yuyv.a - 128; + + vec4 rgb = vec4(yComp + (1.596 * vComp), + yComp - (0.813 * vComp) - (0.391 * uComp), + yComp + (2.018 * uComp), + 255.0); + vec4 rgba_norm = rgb / 255.0; + imageStore(output_image, ivec3(ivec2(uv), 0), rgba_norm); + } )"}}}; static const std::array s_buffer_bytes_per_texel = {{ 1, // BUFFER_FORMAT_R8_UINT 2, // BUFFER_FORMAT_R16_UINT 8, // BUFFER_FORMAT_R32G32_UINT + 4, // BUFFER_FORMAT_RGBA8_UINT }}; const DecodingShaderInfo* GetDecodingShaderInfo(TextureFormat format) diff --git a/Source/Core/VideoCommon/TextureConversionShader.h b/Source/Core/VideoCommon/TextureConversionShader.h index 9b1feb8b45..2680cd3c5b 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.h +++ b/Source/Core/VideoCommon/TextureConversionShader.h @@ -27,6 +27,7 @@ enum BufferFormat BUFFER_FORMAT_R8_UINT, BUFFER_FORMAT_R16_UINT, BUFFER_FORMAT_R32G32_UINT, + BUFFER_FORMAT_RGBA8_UINT, BUFFER_FORMAT_COUNT }; From e33ab4117d68aae9a7406ca4738e9c429200bf17 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 12 Aug 2017 19:51:33 -0500 Subject: [PATCH 12/40] Video Common: Make auto IR work with HybridXFB --- Source/Core/VideoCommon/RenderBase.cpp | 8 ++++++-- Source/Core/VideoCommon/RenderBase.h | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 4bc8911b08..d0bebe363c 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -150,8 +150,8 @@ bool Renderer::CalculateTargetSize() if (g_ActiveConfig.iEFBScale == EFB_SCALE_AUTO_INTEGRAL) { // Set a scale based on the window size - int width = FramebufferManagerBase::ScaleToVirtualXfbWidth(EFB_WIDTH, m_target_rectangle); - int height = FramebufferManagerBase::ScaleToVirtualXfbHeight(EFB_HEIGHT, m_target_rectangle); + int width = EFB_WIDTH * m_target_rectangle.GetWidth() / m_last_xfb_width; + int height = EFB_HEIGHT * m_target_rectangle.GetWidth() / m_last_xfb_height; m_efb_scale = std::max((width - 1) / EFB_WIDTH + 1, (height - 1) / EFB_HEIGHT + 1); } else @@ -652,6 +652,10 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_fps_counter.Update(); update_frame_count = true; } + + // Update our last xfb values + m_last_xfb_width = (fbStride < 1 || fbStride > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbStride; + m_last_xfb_height = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight; } frameCount++; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index f2063e8228..07fd1424cd 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -209,6 +209,10 @@ private: AbstractTexture * m_last_xfb_texture; + // Note: Only used for auto-ir + u32 m_last_xfb_width = MAX_XFB_WIDTH; + u32 m_last_xfb_height = MAX_XFB_HEIGHT; + // NOTE: The methods below are called on the framedumping thread. bool StartFrameDumpToAVI(const FrameDumpConfig& config); void DumpFrameToAVI(const FrameDumpConfig& config); From a71bc9ebbf34ba815da8f38b55933abc25f32379 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 12 Aug 2017 22:35:41 -0500 Subject: [PATCH 13/40] Move XFB UI option to be under XFB group --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index c33227b98b..ef888a0dca 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -717,11 +717,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM), 0, wxLEFT | wxRIGHT, space5); szr_efb->AddSpacer(space5); - szr_efb->Add(CreateCheckBox(page_hacks, _("Store XFB Copies to Texture Only"), - wxGetTranslation(skip_xfb_copy_to_ram_desc), - Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM), - 0, wxLEFT | wxRIGHT, space5); - szr_efb->AddSpacer(space5); szr_hacks->AddSpacer(space5); szr_hacks->Add(szr_efb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); @@ -780,6 +775,21 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) szr_hacks->Add(szr_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); } + // - XFB + { + wxStaticBoxSizer* const group_xfb = + new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("External Frame Buffer (XFB)")); + + group_xfb->Add(CreateCheckBox(page_hacks, _("Store XFB Copies to Texture Only"), + wxGetTranslation(skip_xfb_copy_to_ram_desc), + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM), + 0, wxLEFT | wxRIGHT, space5); + group_xfb->AddSpacer(space5); + + szr_hacks->AddSpacer(space5); + szr_hacks->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); + } // xfb + // - other hacks { wxGridSizer* const szr_other = new wxGridSizer(2, space5, space5); From 7f0834c91992c3726f1ba36f32f85b97aaa1ece2 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 12 Aug 2017 23:10:21 -0500 Subject: [PATCH 14/40] Add 'immediate xfb' which reduces xfb latency at the cost of graphical errors --- Source/Core/Core/Analytics.cpp | 1 + Source/Core/Core/Config/GraphicsSettings.cpp | 1 + Source/Core/Core/Config/GraphicsSettings.h | 1 + Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp | 1 + .../Core/Core/ConfigLoaders/IsSettingSaveable.cpp | 1 + .../Core/Core/ConfigLoaders/MovieConfigLoader.cpp | 2 ++ Source/Core/Core/HotkeyManager.cpp | 1 + Source/Core/Core/HotkeyManager.h | 1 + Source/Core/Core/Movie.cpp | 1 + Source/Core/Core/Movie.h | 3 ++- .../Core/DolphinQt2/Config/Graphics/HacksWidget.cpp | 8 ++++++++ .../Core/DolphinQt2/Config/Graphics/HacksWidget.h | 1 + Source/Core/DolphinQt2/HotkeyScheduler.cpp | 2 ++ Source/Core/DolphinWX/Frame.cpp | 7 +++++++ Source/Core/DolphinWX/VideoConfigDiag.cpp | 10 ++++++++++ Source/Core/VideoCommon/BPStructs.cpp | 13 +++++++++++-- Source/Core/VideoCommon/MainBase.cpp | 2 +- Source/Core/VideoCommon/RenderBase.cpp | 3 +-- Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 1 + 20 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Analytics.cpp b/Source/Core/Core/Analytics.cpp index 0673b283b9..0a079c3e1f 100644 --- a/Source/Core/Core/Analytics.cpp +++ b/Source/Core/Core/Analytics.cpp @@ -225,6 +225,7 @@ void DolphinAnalytics::MakePerGameBuilder() builder.AddData("cfg-gfx-efb-copy-format-changes", g_Config.bEFBEmulateFormatChanges); builder.AddData("cfg-gfx-efb-copy-ram", !g_Config.bSkipEFBCopyToRam); builder.AddData("cfg-gfx-xfb-copy-ram", !g_Config.bSkipXFBCopyToRam); + builder.AddData("cfg-gfx-immediate-xfb", !g_Config.bImmediateXFB); builder.AddData("cfg-gfx-efb-copy-scaled", g_Config.bCopyEFBScaled); builder.AddData("cfg-gfx-internal-resolution", g_Config.iEFBScale); builder.AddData("cfg-gfx-tc-samples", g_Config.iSafeTextureCache_ColorSamples); diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index cc0aae44a2..d4b85972f6 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -133,6 +133,7 @@ const ConfigInfo GFX_HACK_SKIP_EFB_COPY_TO_RAM{{System::GFX, "Hacks", "EFB true}; const ConfigInfo GFX_HACK_SKIP_XFB_COPY_TO_RAM{{System::GFX, "Hacks", "XFBToTextureEnable"}, true}; +const ConfigInfo GFX_HACK_IMMEDIATE_XFB{{System::GFX, "Hacks", "ImmediateXFBEnable"}, false}; const ConfigInfo GFX_HACK_COPY_EFB_ENABLED{{System::GFX, "Hacks", "EFBScaledCopy"}, true}; const ConfigInfo GFX_HACK_EFB_EMULATE_FORMAT_CHANGES{ {System::GFX, "Hacks", "EFBEmulateFormatChanges"}, false}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index 9ebc299379..34a68e9489 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -100,6 +100,7 @@ extern const ConfigInfo GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION; extern const ConfigInfo GFX_HACK_FORCE_PROGRESSIVE; extern const ConfigInfo GFX_HACK_SKIP_EFB_COPY_TO_RAM; extern const ConfigInfo GFX_HACK_SKIP_XFB_COPY_TO_RAM; +extern const ConfigInfo GFX_HACK_IMMEDIATE_XFB; extern const ConfigInfo GFX_HACK_COPY_EFB_ENABLED; extern const ConfigInfo GFX_HACK_EFB_EMULATE_FORMAT_CHANGES; extern const ConfigInfo GFX_HACK_VERTEX_ROUDING; diff --git a/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp index e409757f53..e6ec7c97bc 100644 --- a/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp @@ -108,6 +108,7 @@ static const INIToLocationMap& GetINIToLocationMap() {{"Video_Hacks", "ForceProgressive"}, {Config::GFX_HACK_FORCE_PROGRESSIVE.location}}, {{"Video_Hacks", "EFBToTextureEnable"}, {Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location}}, {{"Video_Hacks", "XFBToTextureEnable"}, {Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location}}, + {{"Video_Hacks", "ImmediateXFBEnable"}, {Config::GFX_HACK_IMMEDIATE_XFB.location}}, {{"Video_Hacks", "EFBScaledCopy"}, {Config::GFX_EFB_SCALE.location}}, {{"Video_Hacks", "EFBEmulateFormatChanges"}, {Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location}}, diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index c38bec4e4d..0f5f783e5b 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -74,6 +74,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) Config::GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION.location, Config::GFX_HACK_FORCE_PROGRESSIVE.location, Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location, Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location, + Config::GFX_HACK_IMMEDIATE_XFB.location, Config::GFX_HACK_COPY_EFB_ENABLED.location, Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location, Config::GFX_HACK_VERTEX_ROUDING.location, diff --git a/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp index de008d4046..046bcf6631 100644 --- a/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp @@ -43,6 +43,7 @@ static void LoadFromDTM(Config::Layer* config_layer, Movie::DTMHeader* dtm) config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable); config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam); config_layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, dtm->bSkipXFBCopyToRam); + config_layer->Set(Config::GFX_HACK_IMMEDIATE_XFB, dtm->bImmediateXFB); config_layer->Set(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, dtm->bEFBEmulateFormatChanges); } @@ -65,6 +66,7 @@ void SaveToDTM(Movie::DTMHeader* dtm) dtm->bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE); dtm->bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); dtm->bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); + dtm->bImmediateXFB = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB); dtm->bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES); // This never used the regular config diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index 5b1627b53e..d989627ad1 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -73,6 +73,7 @@ const std::string hotkey_labels[] = { _trans("Toggle Aspect Ratio"), _trans("Toggle EFB Copies"), _trans("Toggle XFB Copies"), + _trans("Toggle XFB Immediate Mode"), _trans("Toggle Fog"), _trans("Toggle Texture Dumping"), _trans("Toggle Custom Textures"), diff --git a/Source/Core/Core/HotkeyManager.h b/Source/Core/Core/HotkeyManager.h index 68f07545f4..f8cc2bdc66 100644 --- a/Source/Core/Core/HotkeyManager.h +++ b/Source/Core/Core/HotkeyManager.h @@ -71,6 +71,7 @@ enum Hotkey HK_TOGGLE_AR, HK_TOGGLE_EFBCOPIES, HK_TOGGLE_XFBCOPIES, + HK_TOGGLE_IMMEDIATE_XFB, HK_TOGGLE_FOG, HK_TOGGLE_DUMPTEXTURES, HK_TOGGLE_TEXTURES, diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index ac135f086c..75bf23ee43 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -1368,6 +1368,7 @@ void SetGraphicsConfig() g_Config.bEFBAccessEnable = tmpHeader.bEFBAccessEnable; g_Config.bSkipEFBCopyToRam = tmpHeader.bSkipEFBCopyToRam; g_Config.bSkipXFBCopyToRam = tmpHeader.bSkipXFBCopyToRam; + g_Config.bImmediateXFB = tmpHeader.bImmediateXFB; g_Config.bEFBEmulateFormatChanges = tmpHeader.bEFBEmulateFormatChanges; } diff --git a/Source/Core/Core/Movie.h b/Source/Core/Core/Movie.h index c5b477b4bf..e369c5891a 100644 --- a/Source/Core/Core/Movie.h +++ b/Source/Core/Core/Movie.h @@ -88,6 +88,7 @@ struct DTMHeader bool bEFBCopyEnable; bool bSkipEFBCopyToRam; bool bSkipXFBCopyToRam; + bool bImmediateXFB; bool bEFBCopyCacheEnable; bool bEFBEmulateFormatChanges; u8 memcards; // Memcards inserted (from least to most significant, the bits are slot A and B) @@ -97,7 +98,7 @@ struct DTMHeader bool bNetPlay; bool bPAL60; u8 language; - u8 reserved[12]; // Padding for any new config options + u8 reserved[11]; // Padding for any new config options u8 discChange[40]; // Name of iso file to switch to, for two disc games. u8 revision[20]; // Git hash u32 DSPiromHash; diff --git a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp index 723a177c2e..ec2e4809c5 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp +++ b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp @@ -69,6 +69,8 @@ void HacksWidget::CreateWidgets() m_store_xfb_copies = new GraphicsBool(tr("Store XFB Copies to Texture Only"), Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); + m_immediate_xfb = new GraphicsBool(tr("Immediately Present XFB"), + Config::GFX_HACK_IMMEDIATE_XFB); xfb_layout->addWidget(m_store_xfb_copies, 1, 0); @@ -174,6 +176,11 @@ void HacksWidget::AddDescriptions() "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to Texture\nDisabled = XFB Copies to RAM " "(and Texture)\n\nIf unsure, leave this checked."); + static const char* TR_IMMEDIATE_XFB_DESCRIPTION = QT_TR_NOOP( + "Displays the XFB copies as soon as they are created, without waiting for scanout. Can cause graphical defects " + "in some games if the game doesn't expect all XFB copies to be displayed. However, turning this setting on reduces latency." + "\n\nIf unsure, leave this unchecked."); + static const char* TR_GPU_DECODING_DESCRIPTION = QT_TR_NOOP("Enables texture decoding using the GPU instead of the CPU. This may result in " "performance gains in some scenarios, or on systems where the CPU is the " @@ -196,6 +203,7 @@ void HacksWidget::AddDescriptions() AddDescription(m_store_efb_copies, TR_STORE_EFB_TO_TEXTURE_DESCRIPTION); AddDescription(m_accuracy, TR_ACCUARCY_DESCRIPTION); AddDescription(m_store_xfb_copies, TR_STORE_XFB_TO_TEXTURE_DESCRIPTION); + AddDescription(m_immediate_xfb, TR_STORE_XFB_TO_TEXTURE_DESCRIPTION); AddDescription(m_gpu_texture_decoding, TR_GPU_DECODING_DESCRIPTION); AddDescription(m_fast_depth_calculation, TR_FAST_DEPTH_CALC_DESCRIPTION); AddDescription(m_disable_bounding_box, TR_DISABLE_BOUNDINGBOX_DESCRIPTION); diff --git a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h index 9e83e76415..d612a6adf4 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h +++ b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.h @@ -32,6 +32,7 @@ private: // External Framebuffer QCheckBox* m_store_xfb_copies; + QCheckBox* m_immediate_xfb; // Other QCheckBox* m_fast_depth_calculation; diff --git a/Source/Core/DolphinQt2/HotkeyScheduler.cpp b/Source/Core/DolphinQt2/HotkeyScheduler.cpp index f72075c489..547e4676de 100644 --- a/Source/Core/DolphinQt2/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt2/HotkeyScheduler.cpp @@ -226,6 +226,8 @@ void HotkeyScheduler::Run() g_Config.bSkipEFBCopyToRam = !g_Config.bSkipEFBCopyToRam; if (IsHotkey(HK_TOGGLE_XFBCOPIES)) g_Config.bSkipXFBCopyToRam = !g_Config.bSkipXFBCopyToRam; + if (IsHotkey(HK_TOGGLE_IMMEDIATE_XFB)) + g_Config.bImmediateXFB = !g_Config.bImmediateXFB; if (IsHotkey(HK_TOGGLE_FOG)) g_Config.bDisableFog = !g_Config.bDisableFog; if (IsHotkey(HK_TOGGLE_DUMPTEXTURES)) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 5732664293..97c0f38ec9 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1491,6 +1491,13 @@ void CFrame::ParseHotkeys() Config::SetCurrent(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, !Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM)); } + if (IsHotkey(HK_TOGGLE_IMMEDIATE_XFB)) + { + OSDChoice = 6; + // Toggle immediate present of xfb + Config::SetCurrent(Config::GFX_HACK_IMMEDIATE_XFB, + !Config::Get(Config::GFX_HACK_IMMEDIATE_XFB)); + } if (IsHotkey(HK_TOGGLE_FOG)) { OSDChoice = 4; diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index ef888a0dca..07dcfb9cd2 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -205,6 +205,10 @@ static wxString skip_xfb_copy_to_ram_desc = wxTRANSLATE( "Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to Texture\nDisabled = XFB Copies to RAM " "(and Texture)\n\nIf unsure, leave this checked."); +static wxString immediate_xfb_desc = wxTRANSLATE( + "Displays the XFB copies as soon as they are created, without waiting for scanout. Can cause graphical defects " + "in some games if the game doesn't expect all XFB copies to be displayed. However, turning this setting on reduces latency." + "\n\nIf unsure, leave this unchecked."); static wxString stc_desc = wxTRANSLATE("The \"Safe\" setting eliminates the likelihood of the GPU missing texture updates " "from RAM.\nLower accuracies cause in-game text to appear garbled in certain " @@ -786,6 +790,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) 0, wxLEFT | wxRIGHT, space5); group_xfb->AddSpacer(space5); + group_xfb->Add(CreateCheckBox(page_hacks, _("Immediately Present XFB"), + wxGetTranslation(immediate_xfb_desc), + Config::GFX_HACK_IMMEDIATE_XFB), + 0, wxLEFT | wxRIGHT, space5); + group_xfb->AddSpacer(space5); + szr_hacks->AddSpacer(space5); szr_hacks->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); } // xfb diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 183f7d4f20..22e808fe90 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -12,6 +12,7 @@ #include "Common/StringUtil.h" #include "Common/Thread.h" #include "Core/ConfigManager.h" +#include "Core/CoreTiming.h" #include "Core/FifoPlayer/FifoPlayer.h" #include "Core/FifoPlayer/FifoRecorder.h" #include "Core/HW/Memmap.h" @@ -266,9 +267,17 @@ static void BPWritten(const BPCmd& bp) // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); - if (FifoPlayer::GetInstance().IsRunningWithFakeVideoInterfaceUpdates()) + if (g_ActiveConfig.bImmediateXFB) { - VideoInterface::FakeVIUpdate(destAddr, srcRect.GetWidth(), height); + // below div two to convert from bytes to pixels - it expects width, not stride + g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, false, srcRect, CoreTiming::GetTicks(), s_gammaLUT[PE_copy.gamma]); + } + else + { + if (FifoPlayer::GetInstance().IsRunningWithFakeVideoInterfaceUpdates()) + { + VideoInterface::FakeVIUpdate(destAddr, srcRect.GetWidth(), height); + } } } diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index 652eb15969..38d37113e2 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -49,7 +49,7 @@ void VideoBackendBase::Video_ExitLoop() void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, u64 ticks) { - if (m_initialized && g_renderer) + if (m_initialized && g_renderer && !g_ActiveConfig.bImmediateXFB) { Fifo::SyncGPU(Fifo::SyncGPUReason::Swap); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index d0bebe363c..d438951944 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -37,7 +37,6 @@ #include "Core/Config/SYSCONFSettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" -#include "Core/CoreTiming.h" #include "Core/FifoPlayer/FifoRecorder.h" #include "Core/HW/VideoInterface.h" #include "Core/Host.h" @@ -337,7 +336,7 @@ void Renderer::DrawDebugText() "Speed Limit: Unlimited" : StringFromFormat("Speed Limit: %li%%", std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)), - std::string("Copy XFB: ") + xfbcopy_text, + std::string("Copy XFB: ") + xfbcopy_text + (g_ActiveConfig.bImmediateXFB ? " (Immediate)" : ""), }; enum diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index a127e23b18..1f6e5a38c7 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -137,6 +137,7 @@ void VideoConfig::Refresh() bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE); bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); + bImmediateXFB = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB); bCopyEFBScaled = Config::Get(Config::GFX_HACK_COPY_EFB_ENABLED); bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES); bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 71031eb192..b22d568032 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -118,6 +118,7 @@ struct VideoConfig final bool bEFBEmulateFormatChanges; bool bSkipEFBCopyToRam; bool bSkipXFBCopyToRam; + bool bImmediateXFB; bool bCopyEFBScaled; int iSafeTextureCache_ColorSamples; ProjectionHackConfig phack; From 2295d60fdc95af80af03174753b7389a44896fc1 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 14 Aug 2017 23:07:39 -0500 Subject: [PATCH 15/40] VideoCommon: Output gamma now comes from the xfb copy --- Source/Core/VideoCommon/BPStructs.cpp | 6 +++--- Source/Core/VideoCommon/RenderBase.cpp | 4 ++-- Source/Core/VideoCommon/RenderBase.h | 3 +-- Source/Core/VideoCommon/TextureCacheBase.cpp | 3 ++- Source/Core/VideoCommon/TextureCacheBase.h | 3 ++- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 22e808fe90..bdba7468a8 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -233,7 +233,7 @@ static void BPWritten(const BPCmd& bp) bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24; g_texture_cache->CopyRenderTargetToTexture(destAddr, PE_copy.tp_realFormat(), destStride, is_depth_copy, srcRect, !!PE_copy.intensity_fmt, - !!PE_copy.half_scale, 1.0f); + !!PE_copy.half_scale, 1.0f, 1.0f); } else { @@ -262,7 +262,7 @@ static void BPWritten(const BPCmd& bp) bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24; g_texture_cache->CopyRenderTargetToTexture(destAddr, EFBCopyFormat::XFB, destStride, is_depth_copy, srcRect, false, - false, yScale); + false, yScale, s_gammaLUT[PE_copy.gamma]); // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); @@ -270,7 +270,7 @@ static void BPWritten(const BPCmd& bp) if (g_ActiveConfig.bImmediateXFB) { // below div two to convert from bytes to pixels - it expects width, not stride - g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, false, srcRect, CoreTiming::GetTicks(), s_gammaLUT[PE_copy.gamma]); + g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, false, srcRect, CoreTiming::GetTicks()); } else { diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index d438951944..67721caabc 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -599,7 +599,7 @@ void Renderer::RecordVideoMemory() } void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, - u64 ticks, float Gamma) + u64 ticks) { // Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode. if (!SConfig::GetInstance().bWii) @@ -646,7 +646,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_last_xfb_texture = xfb_entry->texture.get(); // TODO: merge more generic parts into VideoCommon - g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, Gamma); + g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, xfb_entry->gamma); m_fps_counter.Update(); update_frame_count = true; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 07fd1424cd..75b6b12509 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -131,8 +131,7 @@ public: virtual void BBoxWrite(int index, u16 value) = 0; // Finish up the current frame, print some stats - void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks, - float Gamma = 1.0f); + void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks); virtual void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma = 1.0f) = 0; PEControl::PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index beb5b584d8..c6df251723 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1108,7 +1108,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf, float y_scale) + bool scaleByHalf, float y_scale, float gamma) { // Emulation methods: // @@ -1558,6 +1558,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF entry->SetGeneralParameters(dstAddr, 0, baseFormat, is_xfb_copy); entry->SetDimensions(tex_w, tex_h, 1); entry->y_scale = y_scale; + entry->gamma = gamma; entry->frameCount = FRAMECOUNT_INVALID; if (is_xfb_copy) diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 96b36b6eba..76eb1b58db 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -88,6 +88,7 @@ public: bool should_force_safe_hashing = false; // for XFB bool is_xfb_copy = false; float y_scale = 1.0f; + float gamma = 1.0f; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view @@ -190,7 +191,7 @@ public: virtual void BindTextures(); void CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf, float y_scale); + bool scaleByHalf, float y_scale, float gamma); virtual void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette, TLUTFormat format) = 0; From c58010404df570edffd948302e8bfe6c539c698d Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 20 Aug 2017 01:32:18 -0500 Subject: [PATCH 16/40] Update all inis to remove old XFB settings. Also update Krome Studios games to use 'Immediate XFB' and Rogue Squadron games to disable 'Immediate XFB'. --- Data/Sys/GameSettings/DLS.ini | 3 +-- Data/Sys/GameSettings/E5Z.ini | 5 +++-- Data/Sys/GameSettings/E62.ini | 5 +++-- Data/Sys/GameSettings/E63.ini | 5 +++-- Data/Sys/GameSettings/E6V.ini | 5 +++-- Data/Sys/GameSettings/E6W.ini | 5 +++-- Data/Sys/GameSettings/E6X.ini | 5 +++-- Data/Sys/GameSettings/G2V.ini | 7 ++++--- Data/Sys/GameSettings/G4C.ini | 7 ++++--- Data/Sys/GameSettings/G5N.ini | 5 +++-- Data/Sys/GameSettings/G6Q.ini | 7 ++++--- Data/Sys/GameSettings/GAP.ini | 7 ++++--- Data/Sys/GameSettings/GAU.ini | 5 +++-- Data/Sys/GameSettings/GAY.ini | 5 +++-- Data/Sys/GameSettings/GBH.ini | 7 ++++--- Data/Sys/GameSettings/GBL.ini | 7 ++++--- Data/Sys/GameSettings/GBM.ini | 7 ++++--- Data/Sys/GameSettings/GBV.ini | 7 ++++--- Data/Sys/GameSettings/GBW.ini | 7 ++++--- Data/Sys/GameSettings/GC2.ini | 7 ++++--- Data/Sys/GameSettings/GCE.ini | 6 +++--- Data/Sys/GameSettings/GCN.ini | 5 +++-- Data/Sys/GameSettings/GCP.ini | 6 ++---- Data/Sys/GameSettings/GDD.ini | 7 ++++--- Data/Sys/GameSettings/GDG.ini | 7 ++++--- Data/Sys/GameSettings/GDS.ini | 7 ++++--- Data/Sys/GameSettings/GDT.ini | 7 ++++--- Data/Sys/GameSettings/GE3.ini | 5 +++-- Data/Sys/GameSettings/GEO.ini | 5 +++-- Data/Sys/GameSettings/GF4.ini | 5 +++-- Data/Sys/GameSettings/GFD.ini | 5 +++-- Data/Sys/GameSettings/GFF.ini | 7 ++++--- Data/Sys/GameSettings/GFG.ini | 7 ++++--- Data/Sys/GameSettings/GGE.ini | 5 ++--- Data/Sys/GameSettings/GGN.ini | 7 ++++--- Data/Sys/GameSettings/GGR.ini | 7 ++++--- Data/Sys/GameSettings/GGV.ini | 6 +++--- Data/Sys/GameSettings/GGY.ini | 8 ++++---- Data/Sys/GameSettings/GH2.ini | 5 +++-- Data/Sys/GameSettings/GHN.ini | 7 ++++--- Data/Sys/GameSettings/GHQ.ini | 5 +++-- Data/Sys/GameSettings/GHS.ini | 7 ++++--- Data/Sys/GameSettings/GHY.ini | 6 +++--- Data/Sys/GameSettings/GIQ.ini | 7 ++++--- Data/Sys/GameSettings/GIZ.ini | 5 +++-- Data/Sys/GameSettings/GJB.ini | 7 ++++--- Data/Sys/GameSettings/GJN.ini | 7 ++++--- Data/Sys/GameSettings/GK4.ini | 4 +--- Data/Sys/GameSettings/GKB.ini | 3 +-- Data/Sys/GameSettings/GKH.ini | 5 +++-- Data/Sys/GameSettings/GKS.ini | 7 ++++--- Data/Sys/GameSettings/GKZ.ini | 7 ++++--- Data/Sys/GameSettings/GLG.ini | 7 ++++--- Data/Sys/GameSettings/GLR.ini | 3 +-- Data/Sys/GameSettings/GLS.ini | 6 +++--- Data/Sys/GameSettings/GM3.ini | 7 ++++--- Data/Sys/GameSettings/GMD.ini | 7 ++++--- Data/Sys/GameSettings/GMH.ini | 7 ++++--- Data/Sys/GameSettings/GMI.ini | 5 +++-- Data/Sys/GameSettings/GMN.ini | 7 ++++--- Data/Sys/GameSettings/GMX.ini | 7 ++++--- Data/Sys/GameSettings/GN4.ini | 7 ++++--- Data/Sys/GameSettings/GN7.ini | 7 ++++--- Data/Sys/GameSettings/GNC.ini | 7 ++++--- Data/Sys/GameSettings/GNE.ini | 7 ++++--- Data/Sys/GameSettings/GNJ.ini | 7 ++++--- Data/Sys/GameSettings/GNN.ini | 7 ++++--- Data/Sys/GameSettings/GO2.ini | 7 ++++--- Data/Sys/GameSettings/GP2.ini | 7 ++++--- Data/Sys/GameSettings/GPE.ini | 7 ++++--- Data/Sys/GameSettings/GPK.ini | 7 ++++--- Data/Sys/GameSettings/GPS.ini | 7 ++++--- Data/Sys/GameSettings/GPT.ini | 6 +++--- Data/Sys/GameSettings/GQX.ini | 7 ++++--- Data/Sys/GameSettings/GRB.ini | 7 ++++--- Data/Sys/GameSettings/GRH.ini | 5 +++-- Data/Sys/GameSettings/GRK.ini | 5 +++-- Data/Sys/GameSettings/GRQ.ini | 7 ++++--- Data/Sys/GameSettings/GRS.ini | 5 +++-- Data/Sys/GameSettings/GRU.ini | 7 ++++--- Data/Sys/GameSettings/GRY.ini | 7 ++++--- Data/Sys/GameSettings/GS2.ini | 7 ++++--- Data/Sys/GameSettings/GSM.ini | 7 ++++--- Data/Sys/GameSettings/GSO.ini | 5 +++-- Data/Sys/GameSettings/GSQ.ini | 6 +++--- Data/Sys/GameSettings/GSS.ini | 7 ++++--- Data/Sys/GameSettings/GST.ini | 5 +++-- Data/Sys/GameSettings/GSW.ini | 3 +-- Data/Sys/GameSettings/GT3.ini | 7 ++++--- Data/Sys/GameSettings/GT6.ini | 4 +--- Data/Sys/GameSettings/GT7.ini | 8 ++++---- Data/Sys/GameSettings/GTR.ini | 6 +++--- Data/Sys/GameSettings/GTW.ini | 7 ++++--- Data/Sys/GameSettings/GTZ.ini | 7 ++++--- Data/Sys/GameSettings/GUT.ini | 3 +-- Data/Sys/GameSettings/GUZ.ini | 7 ++++--- Data/Sys/GameSettings/GVC.ini | 7 ++++--- Data/Sys/GameSettings/GVJ.ini | 7 ++++--- Data/Sys/GameSettings/GVO.ini | 7 ++++--- Data/Sys/GameSettings/GW7.ini | 5 +++-- Data/Sys/GameSettings/GWY.ini | 3 +-- Data/Sys/GameSettings/GX3.ini | 6 +++--- Data/Sys/GameSettings/GXM.ini | 7 ++++--- Data/Sys/GameSettings/GYT.ini | 5 +++-- Data/Sys/GameSettings/GZP.ini | 7 ++++--- Data/Sys/GameSettings/HAT.ini | 5 +++-- Data/Sys/GameSettings/HCL.ini | 5 +++-- Data/Sys/GameSettings/HCS.ini | 5 +++-- Data/Sys/GameSettings/L.ini | 5 +++-- Data/Sys/GameSettings/MAK.ini | 5 +++-- Data/Sys/GameSettings/MB3.ini | 5 +++-- Data/Sys/GameSettings/MBA.ini | 5 +++-- Data/Sys/GameSettings/MCD.ini | 5 +++-- Data/Sys/GameSettings/MCS.ini | 5 +++-- Data/Sys/GameSettings/MCV.ini | 5 +++-- Data/Sys/GameSettings/MCW.ini | 5 +++-- Data/Sys/GameSettings/MCY.ini | 5 +++-- Data/Sys/GameSettings/MCZ.ini | 5 +++-- Data/Sys/GameSettings/R2G.ini | 3 +-- Data/Sys/GameSettings/R3A.ini | 5 ++--- Data/Sys/GameSettings/R3B.ini | 5 +++-- Data/Sys/GameSettings/R3D.ini | 5 +++-- Data/Sys/GameSettings/R4F.ini | 6 +++--- Data/Sys/GameSettings/R7G.ini | 5 +++-- Data/Sys/GameSettings/R8L.ini | 7 ++++--- Data/Sys/GameSettings/RBO.ini | 5 +++-- Data/Sys/GameSettings/RBR.ini | 5 +++-- Data/Sys/GameSettings/RCL.ini | 7 ++++--- Data/Sys/GameSettings/RG6.ini | 5 +++-- Data/Sys/GameSettings/RGW.ini | 5 +++-- Data/Sys/GameSettings/RH8.ini | 7 ++++--- Data/Sys/GameSettings/RIZ.ini | 5 +++-- Data/Sys/GameSettings/RJ2.ini | 5 +++-- Data/Sys/GameSettings/RLJ.ini | 7 ++++--- Data/Sys/GameSettings/RLS.ini | 5 +++-- Data/Sys/GameSettings/RMH.ini | 4 +--- Data/Sys/GameSettings/RMO.ini | 5 +++-- Data/Sys/GameSettings/RNO.ini | 4 +--- Data/Sys/GameSettings/RO3.ini | 5 +++-- Data/Sys/GameSettings/RO9.ini | 5 +++-- Data/Sys/GameSettings/RRZ.ini | 5 +++-- Data/Sys/GameSettings/RSX.ini | 5 ++--- Data/Sys/GameSettings/RT3.ini | 4 ++-- Data/Sys/GameSettings/RTZ.ini | 5 +++-- Data/Sys/GameSettings/RXX.ini | 4 +--- Data/Sys/GameSettings/RZO.ini | 5 +++-- Data/Sys/GameSettings/S72.ini | 3 +-- Data/Sys/GameSettings/SBX.ini | 5 +++-- Data/Sys/GameSettings/SDM.ini | 3 +-- Data/Sys/GameSettings/SFI.ini | 7 ++++--- Data/Sys/GameSettings/SG8.ini | 3 +-- Data/Sys/GameSettings/SHW.ini | 7 ++++--- Data/Sys/GameSettings/SJE.ini | 5 +++-- Data/Sys/GameSettings/SKA.ini | 5 +++-- Data/Sys/GameSettings/SKC.ini | 5 +++-- Data/Sys/GameSettings/SKG.ini | 5 +++-- Data/Sys/GameSettings/SKJ.ini | 6 +++--- Data/Sys/GameSettings/SKO.ini | 5 +++-- Data/Sys/GameSettings/SKV.ini | 5 +++-- Data/Sys/GameSettings/SLW.ini | 5 +++-- Data/Sys/GameSettings/SMF.ini | 4 ++-- Data/Sys/GameSettings/SNY.ini | 5 +++-- Data/Sys/GameSettings/SOS.ini | 5 +++-- Data/Sys/GameSettings/SPR.ini | 5 +++-- Data/Sys/GameSettings/SSR.ini | 5 +++-- Data/Sys/GameSettings/SST.ini | 5 +++-- Data/Sys/GameSettings/SSZ.ini | 4 ++-- Data/Sys/GameSettings/SU7.ini | 4 ++-- Data/Sys/GameSettings/SUK.ini | 5 +++-- Data/Sys/GameSettings/SVV.ini | 5 +++-- Data/Sys/GameSettings/SVZ.ini | 5 +++-- Data/Sys/GameSettings/SX7.ini | 5 +++-- Data/Sys/GameSettings/W3M.ini | 5 +++-- Data/Sys/GameSettings/WA2.ini | 5 +++-- Data/Sys/GameSettings/WB2.ini | 4 ++-- Data/Sys/GameSettings/WB3.ini | 4 ++-- Data/Sys/GameSettings/WB6.ini | 4 ++-- Data/Sys/GameSettings/WB7.ini | 5 +++-- Data/Sys/GameSettings/WBX.ini | 4 ++-- Data/Sys/GameSettings/WBY.ini | 4 ++-- Data/Sys/GameSettings/WBZ.ini | 4 ++-- Data/Sys/GameSettings/WC6.ini | 5 +++-- Data/Sys/GameSettings/WCH.ini | 5 +++-- Data/Sys/GameSettings/WDO.ini | 5 +++-- Data/Sys/GameSettings/WFH.ini | 5 +++-- Data/Sys/GameSettings/WFU.ini | 4 ++-- Data/Sys/GameSettings/WGG.ini | 5 +++-- Data/Sys/GameSettings/WGL.ini | 5 +++-- Data/Sys/GameSettings/WHF.ini | 5 +++-- Data/Sys/GameSettings/WHP.ini | 5 +++-- Data/Sys/GameSettings/WHU.ini | 5 +++-- Data/Sys/GameSettings/WIB.ini | 5 +++-- Data/Sys/GameSettings/WJA.ini | 5 +++-- Data/Sys/GameSettings/WKD.ini | 5 +++-- Data/Sys/GameSettings/WLE.ini | 5 +++-- Data/Sys/GameSettings/WLN.ini | 5 +++-- Data/Sys/GameSettings/WLZ.ini | 7 ++++--- Data/Sys/GameSettings/WMA.ini | 5 +++-- Data/Sys/GameSettings/WMB.ini | 7 ++++--- Data/Sys/GameSettings/WMG.ini | 5 +++-- Data/Sys/GameSettings/WOY.ini | 4 ++-- Data/Sys/GameSettings/WP4.ini | 5 +++-- Data/Sys/GameSettings/WPU.ini | 5 +++-- Data/Sys/GameSettings/WR9.ini | 4 ++-- Data/Sys/GameSettings/WRX.ini | 5 +++-- Data/Sys/GameSettings/WSR.ini | 5 +++-- Data/Sys/GameSettings/WTE.ini | 3 +-- Data/Sys/GameSettings/WTU.ini | 5 +++-- Data/Sys/GameSettings/WTX.ini | 5 +++-- Data/Sys/GameSettings/WWA.ini | 5 +++-- Data/Sys/GameSettings/WXR.ini | 5 +++-- 211 files changed, 653 insertions(+), 513 deletions(-) diff --git a/Data/Sys/GameSettings/DLS.ini b/Data/Sys/GameSettings/DLS.ini index a09d5bb36e..6bc49ef098 100644 --- a/Data/Sys/GameSettings/DLS.ini +++ b/Data/Sys/GameSettings/DLS.ini @@ -21,8 +21,7 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/E5Z.ini b/Data/Sys/GameSettings/E5Z.ini index 1ddc86b65e..64955cf58d 100644 --- a/Data/Sys/GameSettings/E5Z.ini +++ b/Data/Sys/GameSettings/E5Z.ini @@ -19,5 +19,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/E62.ini b/Data/Sys/GameSettings/E62.ini index 29b4a6367c..61d1196d31 100644 --- a/Data/Sys/GameSettings/E62.ini +++ b/Data/Sys/GameSettings/E62.ini @@ -19,5 +19,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/E63.ini b/Data/Sys/GameSettings/E63.ini index 35c80facef..1ceb75d4fe 100644 --- a/Data/Sys/GameSettings/E63.ini +++ b/Data/Sys/GameSettings/E63.ini @@ -19,5 +19,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/E6V.ini b/Data/Sys/GameSettings/E6V.ini index 463925de6f..dc86ffff18 100644 --- a/Data/Sys/GameSettings/E6V.ini +++ b/Data/Sys/GameSettings/E6V.ini @@ -19,5 +19,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/E6W.ini b/Data/Sys/GameSettings/E6W.ini index 686673c761..6a12607d84 100644 --- a/Data/Sys/GameSettings/E6W.ini +++ b/Data/Sys/GameSettings/E6W.ini @@ -19,5 +19,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/E6X.ini b/Data/Sys/GameSettings/E6X.ini index 489f7f9fe0..09341815d7 100644 --- a/Data/Sys/GameSettings/E6X.ini +++ b/Data/Sys/GameSettings/E6X.ini @@ -19,5 +19,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/G2V.ini b/Data/Sys/GameSettings/G2V.ini index 50c1ea4f81..7588a8dc0e 100644 --- a/Data/Sys/GameSettings/G2V.ini +++ b/Data/Sys/GameSettings/G2V.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs xfb real for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs xfb real for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/G4C.ini b/Data/Sys/GameSettings/G4C.ini index 586343f201..fd164730ef 100644 --- a/Data/Sys/GameSettings/G4C.ini +++ b/Data/Sys/GameSettings/G4C.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/G5N.ini b/Data/Sys/GameSettings/G5N.ini index e2568001ed..b6dd7db4df 100644 --- a/Data/Sys/GameSettings/G5N.ini +++ b/Data/Sys/GameSettings/G5N.ini @@ -19,5 +19,6 @@ EmulationIssues = [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/G6Q.ini b/Data/Sys/GameSettings/G6Q.ini index eea3b597c5..209851ce54 100644 --- a/Data/Sys/GameSettings/G6Q.ini +++ b/Data/Sys/GameSettings/G6Q.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -19,5 +19,6 @@ EmulationIssues = Needs real xfb for the videos to display. [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GAP.ini b/Data/Sys/GameSettings/GAP.ini index 65b1084a22..d35b493fb1 100644 --- a/Data/Sys/GameSettings/GAP.ini +++ b/Data/Sys/GameSettings/GAP.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GAU.ini b/Data/Sys/GameSettings/GAU.ini index d509c75328..e3cd010311 100644 --- a/Data/Sys/GameSettings/GAU.ini +++ b/Data/Sys/GameSettings/GAU.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GAY.ini b/Data/Sys/GameSettings/GAY.ini index 4188b18c99..a2b9d3c413 100644 --- a/Data/Sys/GameSettings/GAY.ini +++ b/Data/Sys/GameSettings/GAY.ini @@ -19,5 +19,6 @@ EmulationIssues = [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GBH.ini b/Data/Sys/GameSettings/GBH.ini index 67565ec87b..2a0450c2aa 100644 --- a/Data/Sys/GameSettings/GBH.ini +++ b/Data/Sys/GameSettings/GBH.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GBL.ini b/Data/Sys/GameSettings/GBL.ini index d3f0c34701..4438dfc546 100644 --- a/Data/Sys/GameSettings/GBL.ini +++ b/Data/Sys/GameSettings/GBL.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GBM.ini b/Data/Sys/GameSettings/GBM.ini index 78a39d3282..a90d449dc1 100644 --- a/Data/Sys/GameSettings/GBM.ini +++ b/Data/Sys/GameSettings/GBM.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GBV.ini b/Data/Sys/GameSettings/GBV.ini index 0b99af1684..4d18173c3a 100644 --- a/Data/Sys/GameSettings/GBV.ini +++ b/Data/Sys/GameSettings/GBV.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs Real xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs Real xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False \ No newline at end of file diff --git a/Data/Sys/GameSettings/GBW.ini b/Data/Sys/GameSettings/GBW.ini index 8c0a6a2b42..9c64d9baa2 100644 --- a/Data/Sys/GameSettings/GBW.ini +++ b/Data/Sys/GameSettings/GBW.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GC2.ini b/Data/Sys/GameSettings/GC2.ini index f2aee2ee90..dc240690a2 100644 --- a/Data/Sys/GameSettings/GC2.ini +++ b/Data/Sys/GameSettings/GC2.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real Xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real Xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GCE.ini b/Data/Sys/GameSettings/GCE.ini index 0be75c5dbe..2e97b23de4 100644 --- a/Data/Sys/GameSettings/GCE.ini +++ b/Data/Sys/GameSettings/GCE.ini @@ -2,9 +2,9 @@ [Core] [EmuState] EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GCN.ini b/Data/Sys/GameSettings/GCN.ini index e9674c67d6..7fbb0299dc 100644 --- a/Data/Sys/GameSettings/GCN.ini +++ b/Data/Sys/GameSettings/GCN.ini @@ -17,6 +17,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GCP.ini b/Data/Sys/GameSettings/GCP.ini index 4564e9e8e4..8bdfec5167 100644 --- a/Data/Sys/GameSettings/GCP.ini +++ b/Data/Sys/GameSettings/GCP.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to appear. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,8 +18,6 @@ EmulationIssues = Needs real xfb for videos to appear. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True [Video_Hacks] - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GDD.ini b/Data/Sys/GameSettings/GDD.ini index b14da616cc..0ec8444a80 100644 --- a/Data/Sys/GameSettings/GDD.ini +++ b/Data/Sys/GameSettings/GDD.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GDG.ini b/Data/Sys/GameSettings/GDG.ini index 67abb45b12..b653bac936 100644 --- a/Data/Sys/GameSettings/GDG.ini +++ b/Data/Sys/GameSettings/GDG.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GDS.ini b/Data/Sys/GameSettings/GDS.ini index 019439a672..a07cf2b8df 100644 --- a/Data/Sys/GameSettings/GDS.ini +++ b/Data/Sys/GameSettings/GDS.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GDT.ini b/Data/Sys/GameSettings/GDT.ini index 53139ac043..8b75c322d7 100644 --- a/Data/Sys/GameSettings/GDT.ini +++ b/Data/Sys/GameSettings/GDT.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GE3.ini b/Data/Sys/GameSettings/GE3.ini index 90445bdd7c..a3a6e02263 100644 --- a/Data/Sys/GameSettings/GE3.ini +++ b/Data/Sys/GameSettings/GE3.ini @@ -19,5 +19,6 @@ EmulationIssues = [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GEO.ini b/Data/Sys/GameSettings/GEO.ini index d5500775e1..000bd30fa1 100644 --- a/Data/Sys/GameSettings/GEO.ini +++ b/Data/Sys/GameSettings/GEO.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GF4.ini b/Data/Sys/GameSettings/GF4.ini index be08f7ce94..3cbbea2c38 100644 --- a/Data/Sys/GameSettings/GF4.ini +++ b/Data/Sys/GameSettings/GF4.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GFD.ini b/Data/Sys/GameSettings/GFD.ini index c3c6e3c8f3..60b32a18e7 100644 --- a/Data/Sys/GameSettings/GFD.ini +++ b/Data/Sys/GameSettings/GFD.ini @@ -18,6 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GFF.ini b/Data/Sys/GameSettings/GFF.ini index a1e615e488..ae9fffcbfc 100644 --- a/Data/Sys/GameSettings/GFF.ini +++ b/Data/Sys/GameSettings/GFF.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GFG.ini b/Data/Sys/GameSettings/GFG.ini index 7e3d551cb4..71b48a9d88 100644 --- a/Data/Sys/GameSettings/GFG.ini +++ b/Data/Sys/GameSettings/GFG.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GGE.ini b/Data/Sys/GameSettings/GGE.ini index 89757688e3..e62c7e68a8 100644 --- a/Data/Sys/GameSettings/GGE.ini +++ b/Data/Sys/GameSettings/GGE.ini @@ -18,9 +18,8 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] -EFBAccessEnable = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GGN.ini b/Data/Sys/GameSettings/GGN.ini index 7dd5e59180..4b0dee79ba 100644 --- a/Data/Sys/GameSettings/GGN.ini +++ b/Data/Sys/GameSettings/GGN.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GGR.ini b/Data/Sys/GameSettings/GGR.ini index d49f71d43c..adaa6b4337 100644 --- a/Data/Sys/GameSettings/GGR.ini +++ b/Data/Sys/GameSettings/GGR.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs Real Xfb to show videos. Graphic glitches. +EmulationIssues = Graphic glitches. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb to show videos. Graphic glitches. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GGV.ini b/Data/Sys/GameSettings/GGV.ini index 3b518fd6b2..bfe9386122 100644 --- a/Data/Sys/GameSettings/GGV.ini +++ b/Data/Sys/GameSettings/GGV.ini @@ -2,10 +2,10 @@ [Core] [EmuState] EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnFrame] [ActionReplay] [Gecko] [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GGY.ini b/Data/Sys/GameSettings/GGY.ini index d93df192a0..b84a2d72c1 100644 --- a/Data/Sys/GameSettings/GGY.ini +++ b/Data/Sys/GameSettings/GGY.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs Real XFB for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,8 +18,8 @@ EmulationIssues = Needs Real XFB for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True - SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False + diff --git a/Data/Sys/GameSettings/GH2.ini b/Data/Sys/GameSettings/GH2.ini index 401a60f466..8f4a2c07c2 100644 --- a/Data/Sys/GameSettings/GH2.ini +++ b/Data/Sys/GameSettings/GH2.ini @@ -18,6 +18,7 @@ EmulationIssues = The game is slow. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GHN.ini b/Data/Sys/GameSettings/GHN.ini index 3ea3566e47..ea53e8fd32 100644 --- a/Data/Sys/GameSettings/GHN.ini +++ b/Data/Sys/GameSettings/GHN.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GHQ.ini b/Data/Sys/GameSettings/GHQ.ini index 2dab6952d0..57862fa744 100644 --- a/Data/Sys/GameSettings/GHQ.ini +++ b/Data/Sys/GameSettings/GHQ.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GHS.ini b/Data/Sys/GameSettings/GHS.ini index 0b528777a4..36b8a6bb05 100644 --- a/Data/Sys/GameSettings/GHS.ini +++ b/Data/Sys/GameSettings/GHS.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GHY.ini b/Data/Sys/GameSettings/GHY.ini index e600336082..334e0e1aff 100644 --- a/Data/Sys/GameSettings/GHY.ini +++ b/Data/Sys/GameSettings/GHY.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs Real Xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,6 @@ EmulationIssues = Needs Real Xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GIQ.ini b/Data/Sys/GameSettings/GIQ.ini index abf68cfd75..e90c36e580 100644 --- a/Data/Sys/GameSettings/GIQ.ini +++ b/Data/Sys/GameSettings/GIQ.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real XFB for videos to show up. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,6 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GIZ.ini b/Data/Sys/GameSettings/GIZ.ini index 33b2329807..da39ea083c 100644 --- a/Data/Sys/GameSettings/GIZ.ini +++ b/Data/Sys/GameSettings/GIZ.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GJB.ini b/Data/Sys/GameSettings/GJB.ini index c51995a177..3af361a955 100644 --- a/Data/Sys/GameSettings/GJB.ini +++ b/Data/Sys/GameSettings/GJB.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 5 -EmulationIssues = Videos need Real XFB to show up. Graphic glitches / unstable during videos. +EmulationIssues = Graphic glitches / unstable during videos. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -19,6 +19,7 @@ EmulationIssues = Videos need Real XFB to show up. Graphic glitches / unstable d [Video_Settings] SafeTextureCacheColorSamples = 512 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GJN.ini b/Data/Sys/GameSettings/GJN.ini index 122aed90ea..9ec0d2572b 100644 --- a/Data/Sys/GameSettings/GJN.ini +++ b/Data/Sys/GameSettings/GJN.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GK4.ini b/Data/Sys/GameSettings/GK4.ini index db8893c112..c00292742e 100644 --- a/Data/Sys/GameSettings/GK4.ini +++ b/Data/Sys/GameSettings/GK4.ini @@ -18,9 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GKB.ini b/Data/Sys/GameSettings/GKB.ini index d001e896bc..f3741dc6b4 100644 --- a/Data/Sys/GameSettings/GKB.ini +++ b/Data/Sys/GameSettings/GKB.ini @@ -19,9 +19,8 @@ EmulationIssues = # Add action replay cheats here. [Video_Hacks] +ImmediateXFBEnable = False EFBAccessEnable = False EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = False diff --git a/Data/Sys/GameSettings/GKH.ini b/Data/Sys/GameSettings/GKH.ini index 2b6b9db60d..569903f419 100644 --- a/Data/Sys/GameSettings/GKH.ini +++ b/Data/Sys/GameSettings/GKH.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GKS.ini b/Data/Sys/GameSettings/GKS.ini index 3a795191fb..804d80b8bf 100644 --- a/Data/Sys/GameSettings/GKS.ini +++ b/Data/Sys/GameSettings/GKS.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to work. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to work. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GKZ.ini b/Data/Sys/GameSettings/GKZ.ini index eb607d56a7..943b66eb26 100644 --- a/Data/Sys/GameSettings/GKZ.ini +++ b/Data/Sys/GameSettings/GKZ.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to work. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GLG.ini b/Data/Sys/GameSettings/GLG.ini index a59d0d1343..174dd7b34a 100644 --- a/Data/Sys/GameSettings/GLG.ini +++ b/Data/Sys/GameSettings/GLG.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to work. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to work. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GLR.ini b/Data/Sys/GameSettings/GLR.ini index 45cfeeb4bb..7be194dc62 100644 --- a/Data/Sys/GameSettings/GLR.ini +++ b/Data/Sys/GameSettings/GLR.ini @@ -21,8 +21,7 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GLS.ini b/Data/Sys/GameSettings/GLS.ini index 5c20c7ede5..3ae3ec6259 100644 --- a/Data/Sys/GameSettings/GLS.ini +++ b/Data/Sys/GameSettings/GLS.ini @@ -7,7 +7,7 @@ SyncGPU = 1 [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -19,6 +19,6 @@ EmulationIssues = Needs Real Xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GM3.ini b/Data/Sys/GameSettings/GM3.ini index 5575cdf448..fff6ce4402 100644 --- a/Data/Sys/GameSettings/GM3.ini +++ b/Data/Sys/GameSettings/GM3.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GMD.ini b/Data/Sys/GameSettings/GMD.ini index babc65013f..851b80fb80 100644 --- a/Data/Sys/GameSettings/GMD.ini +++ b/Data/Sys/GameSettings/GMD.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GMH.ini b/Data/Sys/GameSettings/GMH.ini index 5636422e69..1f2cee41dd 100644 --- a/Data/Sys/GameSettings/GMH.ini +++ b/Data/Sys/GameSettings/GMH.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real Xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real Xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GMI.ini b/Data/Sys/GameSettings/GMI.ini index 544def3258..ca0a14994a 100644 --- a/Data/Sys/GameSettings/GMI.ini +++ b/Data/Sys/GameSettings/GMI.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GMN.ini b/Data/Sys/GameSettings/GMN.ini index 847e98d75b..85463db2cd 100644 --- a/Data/Sys/GameSettings/GMN.ini +++ b/Data/Sys/GameSettings/GMN.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Videos require real XFB. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Videos require real XFB. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GMX.ini b/Data/Sys/GameSettings/GMX.ini index 2c5fcc2acc..0c5f5f6621 100644 --- a/Data/Sys/GameSettings/GMX.ini +++ b/Data/Sys/GameSettings/GMX.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -21,5 +21,6 @@ EmulationIssues = Needs real xfb for the videos to display. EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GN4.ini b/Data/Sys/GameSettings/GN4.ini index 581de39978..c71cf370ba 100644 --- a/Data/Sys/GameSettings/GN4.ini +++ b/Data/Sys/GameSettings/GN4.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GN7.ini b/Data/Sys/GameSettings/GN7.ini index 77b593397b..f380040c97 100644 --- a/Data/Sys/GameSettings/GN7.ini +++ b/Data/Sys/GameSettings/GN7.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GNC.ini b/Data/Sys/GameSettings/GNC.ini index d45006d38c..ab094e97fd 100644 --- a/Data/Sys/GameSettings/GNC.ini +++ b/Data/Sys/GameSettings/GNC.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GNE.ini b/Data/Sys/GameSettings/GNE.ini index b52b2a132a..b9565ca919 100644 --- a/Data/Sys/GameSettings/GNE.ini +++ b/Data/Sys/GameSettings/GNE.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GNJ.ini b/Data/Sys/GameSettings/GNJ.ini index ab86f8dd64..c5e42f0c52 100644 --- a/Data/Sys/GameSettings/GNJ.ini +++ b/Data/Sys/GameSettings/GNJ.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GNN.ini b/Data/Sys/GameSettings/GNN.ini index af5742f5b2..aa5e02b19d 100644 --- a/Data/Sys/GameSettings/GNN.ini +++ b/Data/Sys/GameSettings/GNN.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -19,5 +19,6 @@ EmulationIssues = Needs real xfb for the videos to display. [Video_Settings] SafeTextureCacheColorSamples = 512 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GO2.ini b/Data/Sys/GameSettings/GO2.ini index 5ee098ab53..d052a4f48e 100644 --- a/Data/Sys/GameSettings/GO2.ini +++ b/Data/Sys/GameSettings/GO2.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -20,5 +20,6 @@ EmulationIssues = Needs Real Xfb for the videos to display. [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GP2.ini b/Data/Sys/GameSettings/GP2.ini index 7bf6171a40..3475a9b04e 100644 --- a/Data/Sys/GameSettings/GP2.ini +++ b/Data/Sys/GameSettings/GP2.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for the videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GPE.ini b/Data/Sys/GameSettings/GPE.ini index 165f1440c2..db9b095b9a 100644 --- a/Data/Sys/GameSettings/GPE.ini +++ b/Data/Sys/GameSettings/GPE.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = requires real XFB to avoid flickering +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = requires real XFB to avoid flickering # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GPK.ini b/Data/Sys/GameSettings/GPK.ini index dade44324b..1950e7c7b9 100644 --- a/Data/Sys/GameSettings/GPK.ini +++ b/Data/Sys/GameSettings/GPK.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GPS.ini b/Data/Sys/GameSettings/GPS.ini index 9ac18749d2..12d15ea70b 100644 --- a/Data/Sys/GameSettings/GPS.ini +++ b/Data/Sys/GameSettings/GPS.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for the videos to display. D3D11 has issues. +EmulationIssues = D3D11 has issues. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,7 +18,8 @@ EmulationIssues = Needs Real Xfb for the videos to display. D3D11 has issues. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False + diff --git a/Data/Sys/GameSettings/GPT.ini b/Data/Sys/GameSettings/GPT.ini index 7c5c0593be..41cac59526 100644 --- a/Data/Sys/GameSettings/GPT.ini +++ b/Data/Sys/GameSettings/GPT.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,6 @@ EmulationIssues = Needs Real Xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GQX.ini b/Data/Sys/GameSettings/GQX.ini index 881b29b8e2..f8c6bf748e 100644 --- a/Data/Sys/GameSettings/GQX.ini +++ b/Data/Sys/GameSettings/GQX.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GRB.ini b/Data/Sys/GameSettings/GRB.ini index 4f13032ea7..e8444e076b 100644 --- a/Data/Sys/GameSettings/GRB.ini +++ b/Data/Sys/GameSettings/GRB.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GRH.ini b/Data/Sys/GameSettings/GRH.ini index 235f5209b9..21b104dec0 100644 --- a/Data/Sys/GameSettings/GRH.ini +++ b/Data/Sys/GameSettings/GRH.ini @@ -17,6 +17,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GRK.ini b/Data/Sys/GameSettings/GRK.ini index caa550db50..7b8309d3c1 100644 --- a/Data/Sys/GameSettings/GRK.ini +++ b/Data/Sys/GameSettings/GRK.ini @@ -18,7 +18,8 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False + diff --git a/Data/Sys/GameSettings/GRQ.ini b/Data/Sys/GameSettings/GRQ.ini index 2840f97730..f566192dfc 100644 --- a/Data/Sys/GameSettings/GRQ.ini +++ b/Data/Sys/GameSettings/GRQ.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs real XFB for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real XFB for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GRS.ini b/Data/Sys/GameSettings/GRS.ini index 26b57ec99b..f602657e36 100644 --- a/Data/Sys/GameSettings/GRS.ini +++ b/Data/Sys/GameSettings/GRS.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GRU.ini b/Data/Sys/GameSettings/GRU.ini index d4a9879f38..2272281d2a 100644 --- a/Data/Sys/GameSettings/GRU.ini +++ b/Data/Sys/GameSettings/GRU.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs Real XFB to display videos. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,6 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GRY.ini b/Data/Sys/GameSettings/GRY.ini index c10979b866..728964fcee 100644 --- a/Data/Sys/GameSettings/GRY.ini +++ b/Data/Sys/GameSettings/GRY.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real Xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GS2.ini b/Data/Sys/GameSettings/GS2.ini index 9856c2c65b..8d1b2a6243 100644 --- a/Data/Sys/GameSettings/GS2.ini +++ b/Data/Sys/GameSettings/GS2.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GSM.ini b/Data/Sys/GameSettings/GSM.ini index 3b317e640b..d13c7c4da1 100644 --- a/Data/Sys/GameSettings/GSM.ini +++ b/Data/Sys/GameSettings/GSM.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -20,5 +20,6 @@ EmulationIssues = Needs real xfb for the videos to display. [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GSO.ini b/Data/Sys/GameSettings/GSO.ini index 972933f1a1..36b396e3dc 100644 --- a/Data/Sys/GameSettings/GSO.ini +++ b/Data/Sys/GameSettings/GSO.ini @@ -18,7 +18,8 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False + diff --git a/Data/Sys/GameSettings/GSQ.ini b/Data/Sys/GameSettings/GSQ.ini index 98225298ff..1d47c09289 100644 --- a/Data/Sys/GameSettings/GSQ.ini +++ b/Data/Sys/GameSettings/GSQ.ini @@ -2,10 +2,10 @@ [Core] [EmuState] EmulationStateId = 3 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnFrame] [ActionReplay] [Gecko] [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GSS.ini b/Data/Sys/GameSettings/GSS.ini index 0a37f24396..46683704d1 100644 --- a/Data/Sys/GameSettings/GSS.ini +++ b/Data/Sys/GameSettings/GSS.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = EmulationStateId = 5 [OnLoad] @@ -18,6 +18,7 @@ EmulationStateId = 5 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GST.ini b/Data/Sys/GameSettings/GST.ini index cf5d656d07..06ccfcb415 100644 --- a/Data/Sys/GameSettings/GST.ini +++ b/Data/Sys/GameSettings/GST.ini @@ -17,5 +17,6 @@ EmulationStateId = 3 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GSW.ini b/Data/Sys/GameSettings/GSW.ini index f6aa412284..51783f24eb 100644 --- a/Data/Sys/GameSettings/GSW.ini +++ b/Data/Sys/GameSettings/GSW.ini @@ -21,9 +21,8 @@ EmulationStateId = 4 [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False EFBEmulateFormatChanges = True +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GT3.ini b/Data/Sys/GameSettings/GT3.ini index 87eb3bef3f..4d34cb2abb 100644 --- a/Data/Sys/GameSettings/GT3.ini +++ b/Data/Sys/GameSettings/GT3.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -20,5 +20,6 @@ EmulationIssues = Needs real xfb for the videos to display. [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GT6.ini b/Data/Sys/GameSettings/GT6.ini index 25e6998265..137f91035b 100644 --- a/Data/Sys/GameSettings/GT6.ini +++ b/Data/Sys/GameSettings/GT6.ini @@ -18,9 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBAccessEnable = False - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GT7.ini b/Data/Sys/GameSettings/GT7.ini index c59e054649..c95b2154e4 100644 --- a/Data/Sys/GameSettings/GT7.ini +++ b/Data/Sys/GameSettings/GT7.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Videos need real XFB to show up and loading screens show garbage. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,8 +18,8 @@ EmulationIssues = Videos need real XFB to show up and loading screens show garba # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True - SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False + diff --git a/Data/Sys/GameSettings/GTR.ini b/Data/Sys/GameSettings/GTR.ini index adf6912304..8e2f451cda 100644 --- a/Data/Sys/GameSettings/GTR.ini +++ b/Data/Sys/GameSettings/GTR.ini @@ -2,10 +2,10 @@ [Core] [EmuState] EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False [Gecko] diff --git a/Data/Sys/GameSettings/GTW.ini b/Data/Sys/GameSettings/GTW.ini index 9b50731724..d41bfcdee7 100644 --- a/Data/Sys/GameSettings/GTW.ini +++ b/Data/Sys/GameSettings/GTW.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GTZ.ini b/Data/Sys/GameSettings/GTZ.ini index b9ad4a7285..e06be5b4df 100644 --- a/Data/Sys/GameSettings/GTZ.ini +++ b/Data/Sys/GameSettings/GTZ.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real Xfb for videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real Xfb for videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GUT.ini b/Data/Sys/GameSettings/GUT.ini index 97997137e6..4757137fdb 100644 --- a/Data/Sys/GameSettings/GUT.ini +++ b/Data/Sys/GameSettings/GUT.ini @@ -19,8 +19,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Hacks] +ImmediateXFBEnable = False BBoxEnable = True [Video_Settings] -UseXFB = True -UseRealXFB = True diff --git a/Data/Sys/GameSettings/GUZ.ini b/Data/Sys/GameSettings/GUZ.ini index b26be53e53..63e0b72a43 100644 --- a/Data/Sys/GameSettings/GUZ.ini +++ b/Data/Sys/GameSettings/GUZ.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real XFB for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real XFB for videos to show up. # Add action replay cheats here. [Video_Settings] -UseRealXFB = True -UseXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GVC.ini b/Data/Sys/GameSettings/GVC.ini index dfaf95f58e..54f7b18922 100644 --- a/Data/Sys/GameSettings/GVC.ini +++ b/Data/Sys/GameSettings/GVC.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GVJ.ini b/Data/Sys/GameSettings/GVJ.ini index e472411799..70f24855c8 100644 --- a/Data/Sys/GameSettings/GVJ.ini +++ b/Data/Sys/GameSettings/GVJ.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GVO.ini b/Data/Sys/GameSettings/GVO.ini index 4bc7b884b6..6bf8c7a997 100644 --- a/Data/Sys/GameSettings/GVO.ini +++ b/Data/Sys/GameSettings/GVO.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GW7.ini b/Data/Sys/GameSettings/GW7.ini index 321afaaa94..45497fbd27 100644 --- a/Data/Sys/GameSettings/GW7.ini +++ b/Data/Sys/GameSettings/GW7.ini @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the video cutscenes to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GWY.ini b/Data/Sys/GameSettings/GWY.ini index 435a09bb36..0e29875e6b 100644 --- a/Data/Sys/GameSettings/GWY.ini +++ b/Data/Sys/GameSettings/GWY.ini @@ -21,9 +21,8 @@ EmulationIssues = Videos require real XFB. [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True SafeTextureCacheColorSamples = 512 [Video_Hacks] +ImmediateXFBEnable = False EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/GX3.ini b/Data/Sys/GameSettings/GX3.ini index cb945a6e63..d717bd981c 100644 --- a/Data/Sys/GameSettings/GX3.ini +++ b/Data/Sys/GameSettings/GX3.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 3 -EmulationIssues = Needs real xfb for the videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,6 @@ EmulationIssues = Needs real xfb for the videos to show up. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GXM.ini b/Data/Sys/GameSettings/GXM.ini index 5e92d676a2..0607f29d33 100644 --- a/Data/Sys/GameSettings/GXM.ini +++ b/Data/Sys/GameSettings/GXM.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GYT.ini b/Data/Sys/GameSettings/GYT.ini index 63e73f944e..97fa2b2dbc 100644 --- a/Data/Sys/GameSettings/GYT.ini +++ b/Data/Sys/GameSettings/GYT.ini @@ -23,5 +23,6 @@ EmulationIssues = EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GZP.ini b/Data/Sys/GameSettings/GZP.ini index e64360681e..4966225bbc 100644 --- a/Data/Sys/GameSettings/GZP.ini +++ b/Data/Sys/GameSettings/GZP.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/HAT.ini b/Data/Sys/GameSettings/HAT.ini index 4ff45b44fc..6ebeeac01b 100644 --- a/Data/Sys/GameSettings/HAT.ini +++ b/Data/Sys/GameSettings/HAT.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/HCL.ini b/Data/Sys/GameSettings/HCL.ini index 5fd4966ef5..9706a074e6 100644 --- a/Data/Sys/GameSettings/HCL.ini +++ b/Data/Sys/GameSettings/HCL.ini @@ -21,5 +21,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/HCS.ini b/Data/Sys/GameSettings/HCS.ini index 556f55760a..de4990d5e2 100644 --- a/Data/Sys/GameSettings/HCS.ini +++ b/Data/Sys/GameSettings/HCS.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/L.ini b/Data/Sys/GameSettings/L.ini index 5c9ae6ca7f..cae67b12b3 100644 --- a/Data/Sys/GameSettings/L.ini +++ b/Data/Sys/GameSettings/L.ini @@ -11,5 +11,6 @@ EmulationIssues = [Video_Settings] SuggestedAspectRatio = 2 SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MAK.ini b/Data/Sys/GameSettings/MAK.ini index 641a33f1fc..7a68d6d26f 100644 --- a/Data/Sys/GameSettings/MAK.ini +++ b/Data/Sys/GameSettings/MAK.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MB3.ini b/Data/Sys/GameSettings/MB3.ini index c2e607d744..7a078d2906 100644 --- a/Data/Sys/GameSettings/MB3.ini +++ b/Data/Sys/GameSettings/MB3.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MBA.ini b/Data/Sys/GameSettings/MBA.ini index 34186a48b2..d57bc43464 100644 --- a/Data/Sys/GameSettings/MBA.ini +++ b/Data/Sys/GameSettings/MBA.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MCD.ini b/Data/Sys/GameSettings/MCD.ini index ee31fcd189..826a23ca84 100644 --- a/Data/Sys/GameSettings/MCD.ini +++ b/Data/Sys/GameSettings/MCD.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MCS.ini b/Data/Sys/GameSettings/MCS.ini index 2c4b2380c9..85183c71f4 100644 --- a/Data/Sys/GameSettings/MCS.ini +++ b/Data/Sys/GameSettings/MCS.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MCV.ini b/Data/Sys/GameSettings/MCV.ini index 754c185e35..3a9cab1aab 100644 --- a/Data/Sys/GameSettings/MCV.ini +++ b/Data/Sys/GameSettings/MCV.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MCW.ini b/Data/Sys/GameSettings/MCW.ini index 233e3dd8fd..c761b9fb79 100644 --- a/Data/Sys/GameSettings/MCW.ini +++ b/Data/Sys/GameSettings/MCW.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MCY.ini b/Data/Sys/GameSettings/MCY.ini index cec1d19cbc..2043159c32 100644 --- a/Data/Sys/GameSettings/MCY.ini +++ b/Data/Sys/GameSettings/MCY.ini @@ -6,5 +6,6 @@ EmulationIssues = Use Opengl, D3D has issues. EmulationStateId = 4 [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/MCZ.ini b/Data/Sys/GameSettings/MCZ.ini index 42496fb872..19017725f6 100644 --- a/Data/Sys/GameSettings/MCZ.ini +++ b/Data/Sys/GameSettings/MCZ.ini @@ -7,5 +7,6 @@ EmulationStateId = 4 [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/R2G.ini b/Data/Sys/GameSettings/R2G.ini index 651c756bcb..ccfff8bfb2 100644 --- a/Data/Sys/GameSettings/R2G.ini +++ b/Data/Sys/GameSettings/R2G.ini @@ -18,9 +18,8 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBEmulateFormatChanges = True +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/R3A.ini b/Data/Sys/GameSettings/R3A.ini index 49d71e72e7..d75891f3db 100644 --- a/Data/Sys/GameSettings/R3A.ini +++ b/Data/Sys/GameSettings/R3A.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Requires Real XFB and EFB2RAM to fix various issues. +EmulationIssues = Requires EFB2RAM to fix various issues. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,8 +18,7 @@ EmulationIssues = Requires Real XFB and EFB2RAM to fix various issues. # Add action replay cheats here. [Video_Hacks] +ImmediateXFBEnable = False EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = True diff --git a/Data/Sys/GameSettings/R3B.ini b/Data/Sys/GameSettings/R3B.ini index 262f9f1d46..012cff5959 100644 --- a/Data/Sys/GameSettings/R3B.ini +++ b/Data/Sys/GameSettings/R3B.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/R3D.ini b/Data/Sys/GameSettings/R3D.ini index 190e8c5cca..02fbd2ae55 100644 --- a/Data/Sys/GameSettings/R3D.ini +++ b/Data/Sys/GameSettings/R3D.ini @@ -18,6 +18,7 @@ EmulationIssues = Automatic framelimit is problematic. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/R4F.ini b/Data/Sys/GameSettings/R4F.ini index 0ee28c12b7..84d1bea7f4 100644 --- a/Data/Sys/GameSettings/R4F.ini +++ b/Data/Sys/GameSettings/R4F.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Requires Real XFB and EFB2RAM to fix various issues. +EmulationIssues = Requires EFB2RAM to fix various issues. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,8 +18,8 @@ EmulationIssues = Requires Real XFB and EFB2RAM to fix various issues. # Add action replay cheats here. [Video_Hacks] +ImmediateXFBEnable = False EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = True + diff --git a/Data/Sys/GameSettings/R7G.ini b/Data/Sys/GameSettings/R7G.ini index 9d64cf36b1..04266c3bb8 100644 --- a/Data/Sys/GameSettings/R7G.ini +++ b/Data/Sys/GameSettings/R7G.ini @@ -19,6 +19,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/R8L.ini b/Data/Sys/GameSettings/R8L.ini index 04f958bf72..60520ccbaf 100644 --- a/Data/Sys/GameSettings/R8L.ini +++ b/Data/Sys/GameSettings/R8L.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs Real XFB in order to be playable. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs Real XFB in order to be playable. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RBO.ini b/Data/Sys/GameSettings/RBO.ini index 5fc9cd2dd6..e84e7dd048 100644 --- a/Data/Sys/GameSettings/RBO.ini +++ b/Data/Sys/GameSettings/RBO.ini @@ -18,9 +18,10 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Enhancements] MaxAnisotropy = 0 ForceFiltering = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RBR.ini b/Data/Sys/GameSettings/RBR.ini index 28bba3b1b4..22e5221dc7 100644 --- a/Data/Sys/GameSettings/RBR.ini +++ b/Data/Sys/GameSettings/RBR.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RCL.ini b/Data/Sys/GameSettings/RCL.ini index 0f8ebfc096..cb0a176b7f 100644 --- a/Data/Sys/GameSettings/RCL.ini +++ b/Data/Sys/GameSettings/RCL.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for the video cutscenes to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the video cutscenes to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RG6.ini b/Data/Sys/GameSettings/RG6.ini index 8cdb19157d..e068ac7053 100644 --- a/Data/Sys/GameSettings/RG6.ini +++ b/Data/Sys/GameSettings/RG6.ini @@ -18,9 +18,10 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Enhancements] MaxAnisotropy = 0 ForceFiltering = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RGW.ini b/Data/Sys/GameSettings/RGW.ini index 9ddb02d1e2..4164edd403 100644 --- a/Data/Sys/GameSettings/RGW.ini +++ b/Data/Sys/GameSettings/RGW.ini @@ -18,6 +18,7 @@ EmulationIssues = Efb to ram is needed for certain ingame functions but it will # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RH8.ini b/Data/Sys/GameSettings/RH8.ini index 9aef363f80..18f882d28e 100644 --- a/Data/Sys/GameSettings/RH8.ini +++ b/Data/Sys/GameSettings/RH8.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real Xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Needs real Xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RIZ.ini b/Data/Sys/GameSettings/RIZ.ini index 24bceefeb3..e4de9fd44b 100644 --- a/Data/Sys/GameSettings/RIZ.ini +++ b/Data/Sys/GameSettings/RIZ.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RJ2.ini b/Data/Sys/GameSettings/RJ2.ini index 848b521f61..f47696ebb3 100644 --- a/Data/Sys/GameSettings/RJ2.ini +++ b/Data/Sys/GameSettings/RJ2.ini @@ -18,10 +18,11 @@ EmulationIssues = Needs STC to prevent glitches and it runs slow. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 0 [Video_Enhancements] MaxAnisotropy = 0 ForceFiltering = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RLJ.ini b/Data/Sys/GameSettings/RLJ.ini index 6fd2ce5617..d2cf2e23fd 100644 --- a/Data/Sys/GameSettings/RLJ.ini +++ b/Data/Sys/GameSettings/RLJ.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 5 -EmulationIssues = Needs real xfb for the videos to display. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Needs real xfb for the videos to display. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RLS.ini b/Data/Sys/GameSettings/RLS.ini index d66ffe4512..e82d86acce 100644 --- a/Data/Sys/GameSettings/RLS.ini +++ b/Data/Sys/GameSettings/RLS.ini @@ -23,5 +23,6 @@ EmulationIssues = EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RMH.ini b/Data/Sys/GameSettings/RMH.ini index 2ab2870c99..e2fb0046a4 100644 --- a/Data/Sys/GameSettings/RMH.ini +++ b/Data/Sys/GameSettings/RMH.ini @@ -18,10 +18,8 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBAccessEnable = False EFBToTextureEnable = False - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RMO.ini b/Data/Sys/GameSettings/RMO.ini index c9968455ed..df2150a2fd 100644 --- a/Data/Sys/GameSettings/RMO.ini +++ b/Data/Sys/GameSettings/RMO.ini @@ -18,5 +18,6 @@ EmulationIssues = Flickers if XFB is disabled # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RNO.ini b/Data/Sys/GameSettings/RNO.ini index e1f56b62af..64ea06a808 100644 --- a/Data/Sys/GameSettings/RNO.ini +++ b/Data/Sys/GameSettings/RNO.ini @@ -18,9 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RO3.ini b/Data/Sys/GameSettings/RO3.ini index 5081bfca2f..c03ef4e497 100644 --- a/Data/Sys/GameSettings/RO3.ini +++ b/Data/Sys/GameSettings/RO3.ini @@ -18,6 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RO9.ini b/Data/Sys/GameSettings/RO9.ini index 8e32f7bfad..21e772708a 100644 --- a/Data/Sys/GameSettings/RO9.ini +++ b/Data/Sys/GameSettings/RO9.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RRZ.ini b/Data/Sys/GameSettings/RRZ.ini index 78d8f48d61..8cf6599aef 100644 --- a/Data/Sys/GameSettings/RRZ.ini +++ b/Data/Sys/GameSettings/RRZ.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RSX.ini b/Data/Sys/GameSettings/RSX.ini index b0b7eca79d..f1fd2c5075 100644 --- a/Data/Sys/GameSettings/RSX.ini +++ b/Data/Sys/GameSettings/RSX.ini @@ -18,9 +18,8 @@ EmulationIssues = Needs Wii nand dump (reconnect wiimote if necessary). EFB cpu # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] -EFBAccessEnable = True +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RT3.ini b/Data/Sys/GameSettings/RT3.ini index 16ebecc964..077b1e0213 100644 --- a/Data/Sys/GameSettings/RT3.ini +++ b/Data/Sys/GameSettings/RT3.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RTZ.ini b/Data/Sys/GameSettings/RTZ.ini index 7d5f9b9260..934b54d94a 100644 --- a/Data/Sys/GameSettings/RTZ.ini +++ b/Data/Sys/GameSettings/RTZ.ini @@ -18,6 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RXX.ini b/Data/Sys/GameSettings/RXX.ini index e503062656..7ec5df885d 100644 --- a/Data/Sys/GameSettings/RXX.ini +++ b/Data/Sys/GameSettings/RXX.ini @@ -18,9 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBEmulateFormatChanges = True - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RZO.ini b/Data/Sys/GameSettings/RZO.ini index a51e720995..8fc2994c7c 100644 --- a/Data/Sys/GameSettings/RZO.ini +++ b/Data/Sys/GameSettings/RZO.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/S72.ini b/Data/Sys/GameSettings/S72.ini index c45eb5a443..bbe6b9a798 100644 --- a/Data/Sys/GameSettings/S72.ini +++ b/Data/Sys/GameSettings/S72.ini @@ -18,9 +18,8 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 0 [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SBX.ini b/Data/Sys/GameSettings/SBX.ini index 2091f4b1a4..7ba6af51b2 100644 --- a/Data/Sys/GameSettings/SBX.ini +++ b/Data/Sys/GameSettings/SBX.ini @@ -20,5 +20,6 @@ EmulationIssues = Wiimote cursor misaligned [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SDM.ini b/Data/Sys/GameSettings/SDM.ini index 098d70b75d..19b1b1519a 100644 --- a/Data/Sys/GameSettings/SDM.ini +++ b/Data/Sys/GameSettings/SDM.ini @@ -18,8 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SFI.ini b/Data/Sys/GameSettings/SFI.ini index 5b3fb8ad81..535f7ae0be 100644 --- a/Data/Sys/GameSettings/SFI.ini +++ b/Data/Sys/GameSettings/SFI.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Needs real xfb for videos to show up. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -19,6 +19,7 @@ EmulationIssues = Needs real xfb for videos to show up. [Video_Settings] SafeTextureCacheColorSamples = 512 -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SG8.ini b/Data/Sys/GameSettings/SG8.ini index da8ca9a2f3..fe0847d40d 100644 --- a/Data/Sys/GameSettings/SG8.ini +++ b/Data/Sys/GameSettings/SG8.ini @@ -18,8 +18,7 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SHW.ini b/Data/Sys/GameSettings/SHW.ini index 8024cc335c..02585df754 100644 --- a/Data/Sys/GameSettings/SHW.ini +++ b/Data/Sys/GameSettings/SHW.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Requires Virtual XFB to prevent flickering. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,5 +18,6 @@ EmulationIssues = Requires Virtual XFB to prevent flickering. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SJE.ini b/Data/Sys/GameSettings/SJE.ini index d5fba19fc4..49e5f97412 100644 --- a/Data/Sys/GameSettings/SJE.ini +++ b/Data/Sys/GameSettings/SJE.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SKA.ini b/Data/Sys/GameSettings/SKA.ini index d5f2a80ecb..b719b2fb6d 100644 --- a/Data/Sys/GameSettings/SKA.ini +++ b/Data/Sys/GameSettings/SKA.ini @@ -18,5 +18,6 @@ EmulationIssues = Microphone input does not work because of missing IOS USB supp # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SKC.ini b/Data/Sys/GameSettings/SKC.ini index 56828ac2c6..7c61ba67f9 100644 --- a/Data/Sys/GameSettings/SKC.ini +++ b/Data/Sys/GameSettings/SKC.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SKG.ini b/Data/Sys/GameSettings/SKG.ini index d30782c678..435f8c3d07 100644 --- a/Data/Sys/GameSettings/SKG.ini +++ b/Data/Sys/GameSettings/SKG.ini @@ -18,5 +18,6 @@ EmulationIssues = Microphone input does not work because of missing IOS USB supp # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SKJ.ini b/Data/Sys/GameSettings/SKJ.ini index 41c21063d8..50e415b3aa 100644 --- a/Data/Sys/GameSettings/SKJ.ini +++ b/Data/Sys/GameSettings/SKJ.ini @@ -18,8 +18,8 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False - SafeTextureCacheColorSamples = 0 +[Video_Hacks] +ImmediateXFBEnable = False + diff --git a/Data/Sys/GameSettings/SKO.ini b/Data/Sys/GameSettings/SKO.ini index 26ac3e3d51..5cbd46cfe4 100644 --- a/Data/Sys/GameSettings/SKO.ini +++ b/Data/Sys/GameSettings/SKO.ini @@ -18,5 +18,6 @@ EmulationIssues = Microphone input does not work because of missing IOS USB supp # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SKV.ini b/Data/Sys/GameSettings/SKV.ini index 6a72f34012..5b6f648ceb 100644 --- a/Data/Sys/GameSettings/SKV.ini +++ b/Data/Sys/GameSettings/SKV.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SLW.ini b/Data/Sys/GameSettings/SLW.ini index 9fca2bf24f..4165513f3a 100644 --- a/Data/Sys/GameSettings/SLW.ini +++ b/Data/Sys/GameSettings/SLW.ini @@ -18,6 +18,7 @@ EmulationIssues = Needs Real Xfb for the pointer to appear. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SMF.ini b/Data/Sys/GameSettings/SMF.ini index 427cbf5ba1..a607627467 100644 --- a/Data/Sys/GameSettings/SMF.ini +++ b/Data/Sys/GameSettings/SMF.ini @@ -19,7 +19,7 @@ EmulationIssues = [Video_Settings] SafeTextureCacheColorSamples = 0 -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SNY.ini b/Data/Sys/GameSettings/SNY.ini index 951ba5b9e0..4297a659b6 100644 --- a/Data/Sys/GameSettings/SNY.ini +++ b/Data/Sys/GameSettings/SNY.ini @@ -13,5 +13,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SOS.ini b/Data/Sys/GameSettings/SOS.ini index e960e3bd14..558bfd3ada 100644 --- a/Data/Sys/GameSettings/SOS.ini +++ b/Data/Sys/GameSettings/SOS.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SPR.ini b/Data/Sys/GameSettings/SPR.ini index d5fa04c374..124e7dee8f 100644 --- a/Data/Sys/GameSettings/SPR.ini +++ b/Data/Sys/GameSettings/SPR.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SSR.ini b/Data/Sys/GameSettings/SSR.ini index 4cb29e0444..e66ac7198d 100644 --- a/Data/Sys/GameSettings/SSR.ini +++ b/Data/Sys/GameSettings/SSR.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SST.ini b/Data/Sys/GameSettings/SST.ini index b151d4df37..24b1b66ef5 100644 --- a/Data/Sys/GameSettings/SST.ini +++ b/Data/Sys/GameSettings/SST.ini @@ -20,5 +20,6 @@ EmulationIssues = [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SSZ.ini b/Data/Sys/GameSettings/SSZ.ini index 690ead5547..2c34e4fb48 100644 --- a/Data/Sys/GameSettings/SSZ.ini +++ b/Data/Sys/GameSettings/SSZ.ini @@ -18,6 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SU7.ini b/Data/Sys/GameSettings/SU7.ini index 83cc84cb5d..68d6e811c8 100644 --- a/Data/Sys/GameSettings/SU7.ini +++ b/Data/Sys/GameSettings/SU7.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SUK.ini b/Data/Sys/GameSettings/SUK.ini index c758320af7..097daa441b 100644 --- a/Data/Sys/GameSettings/SUK.ini +++ b/Data/Sys/GameSettings/SUK.ini @@ -18,6 +18,7 @@ EmulationIssues = Some minigames need XFB to work. # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SVV.ini b/Data/Sys/GameSettings/SVV.ini index 195c67747c..cf1a64aa90 100644 --- a/Data/Sys/GameSettings/SVV.ini +++ b/Data/Sys/GameSettings/SVV.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SVZ.ini b/Data/Sys/GameSettings/SVZ.ini index 542009dde9..011a7f5490 100644 --- a/Data/Sys/GameSettings/SVZ.ini +++ b/Data/Sys/GameSettings/SVZ.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SX7.ini b/Data/Sys/GameSettings/SX7.ini index 1dea6c236a..daa2f5d104 100644 --- a/Data/Sys/GameSettings/SX7.ini +++ b/Data/Sys/GameSettings/SX7.ini @@ -20,6 +20,7 @@ EmulationIssues = Sound issues. [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/W3M.ini b/Data/Sys/GameSettings/W3M.ini index 6c38776402..ac24006660 100644 --- a/Data/Sys/GameSettings/W3M.ini +++ b/Data/Sys/GameSettings/W3M.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WA2.ini b/Data/Sys/GameSettings/WA2.ini index 1576c436db..01fecf1fff 100644 --- a/Data/Sys/GameSettings/WA2.ini +++ b/Data/Sys/GameSettings/WA2.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WB2.ini b/Data/Sys/GameSettings/WB2.ini index 73d42c7487..e571663414 100644 --- a/Data/Sys/GameSettings/WB2.ini +++ b/Data/Sys/GameSettings/WB2.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WB3.ini b/Data/Sys/GameSettings/WB3.ini index 3fb79cab3d..85c7191caa 100644 --- a/Data/Sys/GameSettings/WB3.ini +++ b/Data/Sys/GameSettings/WB3.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WB6.ini b/Data/Sys/GameSettings/WB6.ini index 665409fb83..6a6d997713 100644 --- a/Data/Sys/GameSettings/WB6.ini +++ b/Data/Sys/GameSettings/WB6.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WB7.ini b/Data/Sys/GameSettings/WB7.ini index c9cd6b3135..3a65d0e4a6 100644 --- a/Data/Sys/GameSettings/WB7.ini +++ b/Data/Sys/GameSettings/WB7.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WBX.ini b/Data/Sys/GameSettings/WBX.ini index 7b5fa11937..ac0e1c0499 100644 --- a/Data/Sys/GameSettings/WBX.ini +++ b/Data/Sys/GameSettings/WBX.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WBY.ini b/Data/Sys/GameSettings/WBY.ini index 449f891eae..f29978c9dd 100644 --- a/Data/Sys/GameSettings/WBY.ini +++ b/Data/Sys/GameSettings/WBY.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WBZ.ini b/Data/Sys/GameSettings/WBZ.ini index c13698f6bf..7659e6521a 100644 --- a/Data/Sys/GameSettings/WBZ.ini +++ b/Data/Sys/GameSettings/WBZ.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WC6.ini b/Data/Sys/GameSettings/WC6.ini index 0aa9af9c51..889e49dc17 100644 --- a/Data/Sys/GameSettings/WC6.ini +++ b/Data/Sys/GameSettings/WC6.ini @@ -16,5 +16,6 @@ EmulationIssues = Disable PAL60 (EuRGB60) mode [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WCH.ini b/Data/Sys/GameSettings/WCH.ini index 1578143540..bde934a27f 100644 --- a/Data/Sys/GameSettings/WCH.ini +++ b/Data/Sys/GameSettings/WCH.ini @@ -15,5 +15,6 @@ EFBEmulateFormatChanges = True EFBToTextureEnable = False [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WDO.ini b/Data/Sys/GameSettings/WDO.ini index 52b66c0987..8bebc9138f 100644 --- a/Data/Sys/GameSettings/WDO.ini +++ b/Data/Sys/GameSettings/WDO.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WFH.ini b/Data/Sys/GameSettings/WFH.ini index b4dc6da328..ad96eb5bb3 100644 --- a/Data/Sys/GameSettings/WFH.ini +++ b/Data/Sys/GameSettings/WFH.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WFU.ini b/Data/Sys/GameSettings/WFU.ini index 3251d39c83..d3af396a23 100644 --- a/Data/Sys/GameSettings/WFU.ini +++ b/Data/Sys/GameSettings/WFU.ini @@ -6,5 +6,5 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WGG.ini b/Data/Sys/GameSettings/WGG.ini index 4b41cbfa90..56d98ddda3 100644 --- a/Data/Sys/GameSettings/WGG.ini +++ b/Data/Sys/GameSettings/WGG.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WGL.ini b/Data/Sys/GameSettings/WGL.ini index f75d30a080..d4e5e2ad5e 100644 --- a/Data/Sys/GameSettings/WGL.ini +++ b/Data/Sys/GameSettings/WGL.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WHF.ini b/Data/Sys/GameSettings/WHF.ini index 11be1d2ba1..753e49fbed 100644 --- a/Data/Sys/GameSettings/WHF.ini +++ b/Data/Sys/GameSettings/WHF.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WHP.ini b/Data/Sys/GameSettings/WHP.ini index 853f4b5b56..984a9ce4a4 100644 --- a/Data/Sys/GameSettings/WHP.ini +++ b/Data/Sys/GameSettings/WHP.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WHU.ini b/Data/Sys/GameSettings/WHU.ini index b6b526cf9e..6a5c991ff3 100644 --- a/Data/Sys/GameSettings/WHU.ini +++ b/Data/Sys/GameSettings/WHU.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WIB.ini b/Data/Sys/GameSettings/WIB.ini index 721747ff28..dffda3bc1e 100644 --- a/Data/Sys/GameSettings/WIB.ini +++ b/Data/Sys/GameSettings/WIB.ini @@ -20,5 +20,6 @@ EmulationIssues = Low FPS with OpenGL, crashes with Direct3D [Video] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WJA.ini b/Data/Sys/GameSettings/WJA.ini index 1a2e059f5f..11ba53818d 100644 --- a/Data/Sys/GameSettings/WJA.ini +++ b/Data/Sys/GameSettings/WJA.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WKD.ini b/Data/Sys/GameSettings/WKD.ini index 7ba6b434da..51418fd98f 100644 --- a/Data/Sys/GameSettings/WKD.ini +++ b/Data/Sys/GameSettings/WKD.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WLE.ini b/Data/Sys/GameSettings/WLE.ini index 40f63b3962..751bf2774b 100644 --- a/Data/Sys/GameSettings/WLE.ini +++ b/Data/Sys/GameSettings/WLE.ini @@ -11,5 +11,6 @@ EmulationIssues = [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WLN.ini b/Data/Sys/GameSettings/WLN.ini index b499ca3000..2dccbd4ec6 100644 --- a/Data/Sys/GameSettings/WLN.ini +++ b/Data/Sys/GameSettings/WLN.ini @@ -11,5 +11,6 @@ EmulationIssues = [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WLZ.ini b/Data/Sys/GameSettings/WLZ.ini index 309997c141..d97c32e269 100644 --- a/Data/Sys/GameSettings/WLZ.ini +++ b/Data/Sys/GameSettings/WLZ.ini @@ -5,7 +5,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationIssues = Needs real xfb. +EmulationIssues = EmulationStateId = 4 [OnLoad] @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WMA.ini b/Data/Sys/GameSettings/WMA.ini index 5eeb33f4b9..eb8b9d0ac5 100644 --- a/Data/Sys/GameSettings/WMA.ini +++ b/Data/Sys/GameSettings/WMA.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WMB.ini b/Data/Sys/GameSettings/WMB.ini index aaf9b2389a..9fd832d6cb 100644 --- a/Data/Sys/GameSettings/WMB.ini +++ b/Data/Sys/GameSettings/WMB.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Use OpenGL and Real XFB +EmulationIssues = Use OpenGL [OnLoad] # Add memory patches to be loaded once on boot here. @@ -18,6 +18,7 @@ EmulationIssues = Use OpenGL and Real XFB # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WMG.ini b/Data/Sys/GameSettings/WMG.ini index ec5ef25405..0ae83cf76b 100644 --- a/Data/Sys/GameSettings/WMG.ini +++ b/Data/Sys/GameSettings/WMG.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WOY.ini b/Data/Sys/GameSettings/WOY.ini index 3640cca17f..aba3460e7b 100644 --- a/Data/Sys/GameSettings/WOY.ini +++ b/Data/Sys/GameSettings/WOY.ini @@ -7,5 +7,5 @@ EmulationIssues = [ActionReplay] [Gecko] [Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WP4.ini b/Data/Sys/GameSettings/WP4.ini index 9091743774..2c0206a065 100644 --- a/Data/Sys/GameSettings/WP4.ini +++ b/Data/Sys/GameSettings/WP4.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WPU.ini b/Data/Sys/GameSettings/WPU.ini index 18395f85da..3e41efb681 100644 --- a/Data/Sys/GameSettings/WPU.ini +++ b/Data/Sys/GameSettings/WPU.ini @@ -6,6 +6,7 @@ EmulationIssues = [OnFrame] [ActionReplay] [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WR9.ini b/Data/Sys/GameSettings/WR9.ini index 2323587565..e979207f25 100644 --- a/Data/Sys/GameSettings/WR9.ini +++ b/Data/Sys/GameSettings/WR9.ini @@ -18,7 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WRX.ini b/Data/Sys/GameSettings/WRX.ini index 08fdc132de..465ca0be3d 100644 --- a/Data/Sys/GameSettings/WRX.ini +++ b/Data/Sys/GameSettings/WRX.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 512 + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WSR.ini b/Data/Sys/GameSettings/WSR.ini index 8162ab0bf9..f74ec24893 100644 --- a/Data/Sys/GameSettings/WSR.ini +++ b/Data/Sys/GameSettings/WSR.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WTE.ini b/Data/Sys/GameSettings/WTE.ini index f18126d2bf..2952f4e295 100644 --- a/Data/Sys/GameSettings/WTE.ini +++ b/Data/Sys/GameSettings/WTE.ini @@ -18,8 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WTU.ini b/Data/Sys/GameSettings/WTU.ini index cbc6150422..fbe9fb840e 100644 --- a/Data/Sys/GameSettings/WTU.ini +++ b/Data/Sys/GameSettings/WTU.ini @@ -18,5 +18,6 @@ EmulationStateId = 4 # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WTX.ini b/Data/Sys/GameSettings/WTX.ini index 0a49a0e8ac..f1fce49758 100644 --- a/Data/Sys/GameSettings/WTX.ini +++ b/Data/Sys/GameSettings/WTX.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = True + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WWA.ini b/Data/Sys/GameSettings/WWA.ini index c3640aeae1..78ca3e5a47 100644 --- a/Data/Sys/GameSettings/WWA.ini +++ b/Data/Sys/GameSettings/WWA.ini @@ -18,5 +18,6 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/WXR.ini b/Data/Sys/GameSettings/WXR.ini index 9888fef19d..873f7d5221 100644 --- a/Data/Sys/GameSettings/WXR.ini +++ b/Data/Sys/GameSettings/WXR.ini @@ -18,6 +18,7 @@ EmulationIssues = # Add action replay cheats here. [Video_Settings] -UseXFB = True -UseRealXFB = False SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +ImmediateXFBEnable = False From e6d85b0915681a3f8162d45468f2c488d6df8114 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 20 Aug 2017 14:24:37 -0500 Subject: [PATCH 17/40] Video Common: Avoid 'presenting' duplicate frames by detecting when swap hasn't changed since the last frame --- Source/Core/VideoCommon/RenderBase.cpp | 5 ++--- Source/Core/VideoCommon/RenderBase.h | 1 + Source/Core/VideoCommon/TextureCacheBase.cpp | 1 + Source/Core/VideoCommon/TextureCacheBase.h | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 67721caabc..00bb5d24fc 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -639,11 +639,10 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const auto* xfb_entry = g_texture_cache->GetTexture(xfbAddr, fbWidth, fbHeight, TextureFormat::XFB, force_safe_texture_cache_hash); - if (xfb_entry) + if (xfb_entry && xfb_entry->id != m_last_xfb_id) { - // TODO, check if xfb_entry is a duplicate of the previous frame and skip SwapImpl - m_last_xfb_texture = xfb_entry->texture.get(); + m_last_xfb_id = xfb_entry->id; // TODO: merge more generic parts into VideoCommon g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, xfb_entry->gamma); diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 75b6b12509..11a73536e5 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -207,6 +207,7 @@ private: } m_frame_dump_config; AbstractTexture * m_last_xfb_texture; + u64 m_last_xfb_id = 0; // Note: Only used for auto-ir u32 m_last_xfb_width = MAX_XFB_WIDTH; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index c6df251723..89fbb6ac59 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1611,6 +1611,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::AllocateCacheEntry(const Textur } TCacheEntry* cacheEntry = new TCacheEntry(std::move(texture)); cacheEntry->textures_by_hash_iter = textures_by_hash.end(); + cacheEntry->id = last_entry_id++; return cacheEntry; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 76eb1b58db..bec67c042a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -89,6 +89,7 @@ public: bool is_xfb_copy = false; float y_scale = 1.0f; float gamma = 1.0f; + u64 id; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view @@ -268,6 +269,7 @@ private: TexAddrCache textures_by_address; TexHashCache textures_by_hash; TexPool texture_pool; + u64 last_entry_id = 0; // Backup configuration values struct BackupConfig From 6e686f6ea10c486a6271a6ca7cd084e124776b5a Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 23 Aug 2017 21:46:23 -0500 Subject: [PATCH 18/40] Software Backend: Fix xfb output and add vertical scaling support --- .../Core/VideoBackends/Software/CopyRegion.h | 33 ++++++++ .../Core/VideoBackends/Software/EfbCopy.cpp | 59 -------------- Source/Core/VideoBackends/Software/EfbCopy.h | 3 - .../VideoBackends/Software/EfbInterface.cpp | 30 ++++--- .../VideoBackends/Software/EfbInterface.h | 3 +- .../VideoBackends/Software/SWOGLWindow.cpp | 23 ++++-- .../Core/VideoBackends/Software/SWOGLWindow.h | 2 +- .../VideoBackends/Software/SWRenderer.cpp | 2 - .../Core/VideoBackends/Software/SWTexture.cpp | 32 ++++++++ .../Core/VideoBackends/Software/SWTexture.h | 11 +++ .../VideoBackends/Software/Software.vcxproj | 1 + .../VideoBackends/Software/TextureCache.h | 9 ++- .../VideoBackends/Software/TextureEncoder.cpp | 81 +++++++++++++------ .../VideoBackends/Software/TextureEncoder.h | 7 +- 14 files changed, 179 insertions(+), 117 deletions(-) create mode 100644 Source/Core/VideoBackends/Software/CopyRegion.h diff --git a/Source/Core/VideoBackends/Software/CopyRegion.h b/Source/Core/VideoBackends/Software/CopyRegion.h new file mode 100644 index 0000000000..5f3c1bac83 --- /dev/null +++ b/Source/Core/VideoBackends/Software/CopyRegion.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Common/MathUtil.h" + +#include + +namespace SW +{ +// Modified from +// http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/ +template +void copy_region(const T* const source, const MathUtil::Rectangle& srcrect, T* destination, + const MathUtil::Rectangle& dstrect) +{ + double x_ratio = srcrect.GetWidth() / static_cast(dstrect.GetWidth()); + double y_ratio = srcrect.GetHeight() / static_cast(dstrect.GetHeight()); + for (int i = 0; i < dstrect.GetHeight(); i++) + { + for (int j = 0; j < dstrect.GetWidth(); j++) + { + int destination_x = j + dstrect.left; + int destination_y = i + dstrect.top; + int destination_offset = (destination_y * dstrect.GetWidth()) + destination_x; + + double src_x = std::round(destination_x*x_ratio) + srcrect.left; + double src_y = std::round(destination_y*y_ratio) + srcrect.top; + int src_offset = static_cast((src_y*srcrect.GetWidth()) + src_x); + + destination[destination_offset] = source[src_offset]; + } + } +} +} diff --git a/Source/Core/VideoBackends/Software/EfbCopy.cpp b/Source/Core/VideoBackends/Software/EfbCopy.cpp index 26afc6c779..7a69bb4881 100644 --- a/Source/Core/VideoBackends/Software/EfbCopy.cpp +++ b/Source/Core/VideoBackends/Software/EfbCopy.cpp @@ -12,29 +12,8 @@ #include "VideoCommon/BPMemory.h" #include "VideoCommon/Fifo.h" -static const float s_gammaLUT[] = {1.0f, 1.7f, 2.2f, 1.0f}; - namespace EfbCopy { -static void CopyToXfb(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, - float Gamma) -{ - DEBUG_LOG(VIDEO, "xfbaddr: %x, fbwidth: %i, fbheight: %i, source: (%i, %i, %i, %i), Gamma %f", - xfbAddr, fbWidth, fbHeight, sourceRc.top, sourceRc.left, sourceRc.bottom, - sourceRc.right, Gamma); - - EfbInterface::yuv422_packed* xfb_in_ram = - (EfbInterface::yuv422_packed*)Memory::GetPointer(xfbAddr); - - EfbInterface::CopyToXFB(xfb_in_ram, fbWidth, fbHeight, sourceRc, Gamma); -} - -static void CopyToRam() -{ - u8* dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5); - - TextureEncoder::Encode(dest_ptr); -} void ClearEfb() { @@ -56,42 +35,4 @@ void ClearEfb() } } -void CopyEfb() -{ - EFBRectangle rc; - rc.left = (int)bpmem.copyTexSrcXY.x; - rc.top = (int)bpmem.copyTexSrcXY.y; - - // flipper represents the widths internally as last pixel minus starting pixel, so - // these are zero indexed. - rc.right = rc.left + (int)bpmem.copyTexSrcWH.x + 1; - rc.bottom = rc.top + (int)bpmem.copyTexSrcWH.y + 1; - - if (bpmem.triggerEFBCopy.copy_to_xfb) - { - float yScale; - if (bpmem.triggerEFBCopy.scale_invert) - yScale = 256.0f / (float)bpmem.dispcopyyscale; - else - yScale = (float)bpmem.dispcopyyscale / 256.0f; - - float xfbLines = ((bpmem.copyTexSrcWH.y + 1.0f) * yScale); - - if (yScale != 1.0) - WARN_LOG(VIDEO, "yScale of %f is currently unsupported", yScale); - - if ((u32)xfbLines > MAX_XFB_HEIGHT) - { - INFO_LOG(VIDEO, "Tried to scale EFB to too many XFB lines (%f)", xfbLines); - xfbLines = MAX_XFB_HEIGHT; - } - - CopyToXfb(bpmem.copyTexDest << 5, bpmem.copyMipMapStrideChannels << 4, (u32)xfbLines, rc, - s_gammaLUT[bpmem.triggerEFBCopy.gamma]); - } - else - { - CopyToRam(); // FIXME: should use the rectangle we have already created above - } -} } diff --git a/Source/Core/VideoBackends/Software/EfbCopy.h b/Source/Core/VideoBackends/Software/EfbCopy.h index 95986c1dd5..a544b3245e 100644 --- a/Source/Core/VideoBackends/Software/EfbCopy.h +++ b/Source/Core/VideoBackends/Software/EfbCopy.h @@ -6,8 +6,5 @@ namespace EfbCopy { -// Copy the EFB to RAM as a texture format or XFB -void CopyEfb(); - void ClearEfb(); } diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index d80bd02f5b..2ca20b3997 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -7,11 +7,13 @@ #include #include #include +#include #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/Swap.h" +#include "VideoBackends/Software/CopyRegion.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/LookUpTables.h" #include "VideoCommon/PerfQueryBase.h" @@ -495,19 +497,16 @@ u8* GetPixelPointer(u16 x, u16 y, bool depth) return &efb[GetColorOffset(x, y)]; } -void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, - float Gamma) +void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale) { - // FIXME: We should do Gamma correction - if (!xfb_in_ram) { WARN_LOG(VIDEO, "Tried to copy to invalid XFB address"); return; } - int left = sourceRc.left; - int right = sourceRc.right; + int left = source_rect.left; + int right = source_rect.right; // this assumes copies will always start on an even (YU) pixel and the // copy always has an even width, which might not be true. @@ -520,7 +519,11 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe // Scanline buffer, leave room for borders yuv444 scanline[EFB_WIDTH + 2]; - for (u16 y = sourceRc.top; y < sourceRc.bottom; y++) + static std::vector source; + source.resize(EFB_WIDTH * EFB_HEIGHT); + yuv422_packed* src_ptr = &source[0]; + + for (float y = source_rect.top; y < source_rect.bottom; y++) { // Get a scanline of YUV pixels in 4:4:4 format @@ -537,20 +540,23 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe for (int i = 1, x = left; x < right; i += 2, x += 2) { // YU pixel - xfb_in_ram[x].Y = scanline[i].Y + 16; + src_ptr[x].Y = scanline[i].Y + 16; // we mix our color differences in 10 bit space so it will round more accurately // U[i] = 1/4 * U[i-1] + 1/2 * U[i] + 1/4 * U[i+1] - xfb_in_ram[x].UV = + src_ptr[x].UV = 128 + ((scanline[i - 1].U + (scanline[i].U << 1) + scanline[i + 1].U) >> 2); // YV pixel - xfb_in_ram[x + 1].Y = scanline[i + 1].Y + 16; + src_ptr[x + 1].Y = scanline[i + 1].Y + 16; // V[i] = 1/4 * V[i-1] + 1/2 * V[i] + 1/4 * V[i+1] - xfb_in_ram[x + 1].UV = + src_ptr[x + 1].UV = 128 + ((scanline[i].V + (scanline[i + 1].V << 1) + scanline[i + 2].V) >> 2); } - xfb_in_ram += fbWidth; + src_ptr += memory_stride; } + + // Apply y scaling and copy to the xfb memory location + SW::copy_region(source.data(), source_rect, xfb_in_ram, EFBRectangle{ source_rect.left, source_rect.top, source_rect.right, static_cast(static_cast(source_rect.bottom) * y_scale) }); } bool ZCompare(u16 x, u16 y, u32 z) diff --git a/Source/Core/VideoBackends/Software/EfbInterface.h b/Source/Core/VideoBackends/Software/EfbInterface.h index 1e246db38f..c13b21ac4a 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.h +++ b/Source/Core/VideoBackends/Software/EfbInterface.h @@ -57,8 +57,7 @@ u32 GetDepth(u16 x, u16 y); u8* GetPixelPointer(u16 x, u16 y, bool depth); -void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, - float Gamma); +void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale); extern u32 perf_values[PQ_NUM_MEMBERS]; inline void IncPerfCounterQuadCount(PerfQueryType type) diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 52b2fb02cd..372f15322e 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -9,7 +9,7 @@ #include "Common/Logging/Log.h" #include "VideoBackends/Software/SWOGLWindow.h" -#include "VideoCommon/AbstractTexture.h" +#include "VideoBackends/Software/SWTexture.h" std::unique_ptr SWOGLWindow::s_instance; @@ -54,9 +54,9 @@ void SWOGLWindow::Prepare() std::string frag_shader = "in vec2 TexCoord;\n" "out vec4 ColorOut;\n" - "uniform sampler2DArray samp;\n" + "uniform sampler2D samp;\n" "void main() {\n" - " ColorOut = texture(samp, vec3(TexCoord, 0.0));\n" + " ColorOut = texture(samp, TexCoord);\n" "}\n"; std::string vertex_shader = "out vec2 TexCoord;\n" @@ -76,8 +76,11 @@ void SWOGLWindow::Prepare() glUseProgram(m_image_program); glUniform1i(glGetUniformLocation(m_image_program, "samp"), 0); + glGenTextures(1, &m_image_texture); + glBindTexture(GL_TEXTURE_2D, m_image_texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glGenVertexArrays(1, &m_image_vao); } @@ -89,6 +92,7 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) { + SW::SWTexture * sw_image = static_cast(image); GLInterface->Update(); // just updates the render window position and the backbuffer size GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); @@ -96,10 +100,15 @@ void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) glViewport(0, 0, glWidth, glHeight); - image->Bind(0); + glActiveTexture(GL_TEXTURE9); + 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 + glPixelStorei(GL_UNPACK_ROW_LENGTH, sw_image->GetConfig().width); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(sw_image->GetConfig().width), + static_cast(sw_image->GetConfig().height), 0, GL_RGBA, GL_UNSIGNED_BYTE, + sw_image->GetData()); glUseProgram(m_image_program); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 3b5d623846..63f0bd82b7 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -42,5 +42,5 @@ private: bool m_init{false}; - u32 m_image_program, m_image_vao; + u32 m_image_program, m_image_texture, m_image_vao; }; diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 26471629c8..97311d0e1f 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -45,8 +45,6 @@ void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 colo // Called on the GPU thread void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) { - SWOGLWindow::s_instance->ShowImage(texture, 1.0); - OSD::DoCallbacks(OSD::CallbackType::OnFrame); DrawDebugText(); diff --git a/Source/Core/VideoBackends/Software/SWTexture.cpp b/Source/Core/VideoBackends/Software/SWTexture.cpp index 164c0d5314..e2752fe0c7 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.cpp +++ b/Source/Core/VideoBackends/Software/SWTexture.cpp @@ -4,8 +4,13 @@ #include "VideoBackends/Software/SWTexture.h" +#include + +#include "VideoBackends/Software/CopyRegion.h" + namespace SW { + SWTexture::SWTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config) { } @@ -18,11 +23,38 @@ void SWTexture::CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle& srcrect, const MathUtil::Rectangle& dstrect) { + const SWTexture * software_source_texture = static_cast(source); + + if (srcrect.GetWidth() == dstrect.GetWidth() && srcrect.GetHeight() == dstrect.GetHeight()) + { + m_data.assign(software_source_texture->GetData(), software_source_texture->GetData() + m_data.size()); + } + else + { + copy_region(software_source_texture->GetData(), srcrect, GetData(), dstrect); + } } void SWTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size) { + m_data.assign(buffer, buffer + buffer_size); +} + +const u8* SWTexture::GetData() const +{ + return m_data.data(); +} + +u8* SWTexture::GetData() +{ + return m_data.data(); +} + +std::optional SWTexture::MapFullImpl() +{ + return AbstractTexture::RawTextureInfo{ GetData(), + m_config.width * 4, m_config.width, m_config.height }; } } // namespace SW diff --git a/Source/Core/VideoBackends/Software/SWTexture.h b/Source/Core/VideoBackends/Software/SWTexture.h index 4d6189bb4f..7f130b39e9 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.h +++ b/Source/Core/VideoBackends/Software/SWTexture.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "Common/CommonTypes.h" #include "VideoCommon/AbstractTexture.h" @@ -23,6 +25,15 @@ public: const MathUtil::Rectangle& dstrect) override; void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size) override; + + const u8* GetData() const; + u8* GetData(); + +private: + + std::optional MapFullImpl() override; + + std::vector m_data; }; } // namespace SW diff --git a/Source/Core/VideoBackends/Software/Software.vcxproj b/Source/Core/VideoBackends/Software/Software.vcxproj index 36d833ba2c..9a1a992900 100644 --- a/Source/Core/VideoBackends/Software/Software.vcxproj +++ b/Source/Core/VideoBackends/Software/Software.vcxproj @@ -54,6 +54,7 @@ + diff --git a/Source/Core/VideoBackends/Software/TextureCache.h b/Source/Core/VideoBackends/Software/TextureCache.h index 82c2ce9f55..ec46101b70 100644 --- a/Source/Core/VideoBackends/Software/TextureCache.h +++ b/Source/Core/VideoBackends/Software/TextureCache.h @@ -1,9 +1,8 @@ #pragma once #include - -#include "VideoBackends/Software/EfbCopy.h" #include "VideoBackends/Software/SWTexture.h" +#include "VideoBackends/Software/TextureEncoder.h" #include "VideoCommon/TextureCacheBase.h" namespace SW @@ -22,7 +21,9 @@ public: u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half) override { - EfbCopy::CopyEfb(); + TextureEncoder::Encode(dst, params, native_width, bytes_per_row, + num_blocks_y, memory_stride, src_rect, + scale_by_half); } private: @@ -34,7 +35,7 @@ private: 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(); + // TODO: If we ever want to "fake" vram textures, we would need to implement this } }; diff --git a/Source/Core/VideoBackends/Software/TextureEncoder.cpp b/Source/Core/VideoBackends/Software/TextureEncoder.cpp index 6181d56dd4..bceb567524 100644 --- a/Source/Core/VideoBackends/Software/TextureEncoder.cpp +++ b/Source/Core/VideoBackends/Software/TextureEncoder.cpp @@ -14,6 +14,7 @@ #include "VideoCommon/BPMemory.h" #include "VideoCommon/LookUpTables.h" +#include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/TextureDecoder.h" namespace TextureEncoder @@ -1416,37 +1417,65 @@ static void EncodeZ24halfscale(u8* dst, const u8* src, EFBCopyFormat format) } } -void Encode(u8* dest_ptr) +namespace { - auto pixelformat = bpmem.zcontrol.pixel_format; - bool bFromZBuffer = pixelformat == PEControl::Z24; - bool bIsIntensityFmt = bpmem.triggerEFBCopy.intensity_fmt > 0; - EFBCopyFormat copyfmt = bpmem.triggerEFBCopy.tp_realFormat(); - - const u8* src = - EfbInterface::GetPixelPointer(bpmem.copyTexSrcXY.x, bpmem.copyTexSrcXY.y, bFromZBuffer); - - if (bpmem.triggerEFBCopy.half_scale) + void EncodeEfbCopy(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) { - if (pixelformat == PEControl::RGBA6_Z24) - EncodeRGBA6halfscale(dest_ptr, src, copyfmt, bIsIntensityFmt); - else if (pixelformat == PEControl::RGB8_Z24) - EncodeRGB8halfscale(dest_ptr, src, copyfmt, bIsIntensityFmt); - else if (pixelformat == PEControl::RGB565_Z16) // not supported - EncodeRGB8halfscale(dest_ptr, src, copyfmt, bIsIntensityFmt); - else if (pixelformat == PEControl::Z24) - EncodeZ24halfscale(dest_ptr, src, copyfmt); + const u8* src = + EfbInterface::GetPixelPointer(src_rect.left, src_rect.top, params.depth); + + if (scale_by_half) + { + switch (params.efb_format) + { + case PEControl::RGBA6_Z24: + EncodeRGBA6halfscale(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB8_Z24: + EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB565_Z16: + EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv); + break; + case PEControl::Z24: + EncodeZ24halfscale(dst, src, params.copy_format); + break; + } + } + else + { + switch (params.efb_format) + { + case PEControl::RGBA6_Z24: + EncodeRGBA6(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB8_Z24: + EncodeRGB8(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB565_Z16: + EncodeRGB8(dst, src, params.copy_format, params.yuv); + break; + case PEControl::Z24: + EncodeZ24(dst, src, params.copy_format); + break; + } + } + } +} + +void Encode(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) +{ + if (params.copy_format == EFBCopyFormat::XFB) + { + EfbInterface::EncodeXFB(reinterpret_cast(dst), native_width, src_rect, params.y_scale); } else { - if (pixelformat == PEControl::RGBA6_Z24) - EncodeRGBA6(dest_ptr, src, copyfmt, bIsIntensityFmt); - else if (pixelformat == PEControl::RGB8_Z24) - EncodeRGB8(dest_ptr, src, copyfmt, bIsIntensityFmt); - else if (pixelformat == PEControl::RGB565_Z16) // not supported - EncodeRGB8(dest_ptr, src, copyfmt, bIsIntensityFmt); - else if (pixelformat == PEControl::Z24) - EncodeZ24(dest_ptr, src, copyfmt); + EncodeEfbCopy(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, src_rect, scale_by_half); } } } diff --git a/Source/Core/VideoBackends/Software/TextureEncoder.h b/Source/Core/VideoBackends/Software/TextureEncoder.h index 32bc9d10cd..ca816b92bd 100644 --- a/Source/Core/VideoBackends/Software/TextureEncoder.h +++ b/Source/Core/VideoBackends/Software/TextureEncoder.h @@ -5,8 +5,13 @@ #pragma once #include "Common/CommonTypes.h" +#include "VideoCommon/VideoCommon.h" + +struct EFBCopyParams; namespace TextureEncoder { -void Encode(u8* dest_ptr); +void Encode(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); } From 1090549552c670d19239274e72787365d281aebb Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 23 Aug 2017 23:49:24 -0500 Subject: [PATCH 19/40] Software Backend: Force EFB/XFB to copy to ram --- Source/Core/VideoBackends/D3D/main.cpp | 1 + Source/Core/VideoBackends/OGL/main.cpp | 1 + Source/Core/VideoBackends/Software/SWmain.cpp | 1 + Source/Core/VideoBackends/Vulkan/VulkanContext.cpp | 1 + Source/Core/VideoCommon/TextureCacheBase.cpp | 4 ++-- Source/Core/VideoCommon/VideoConfig.h | 1 + 6 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 4a0c9c29a5..9597ac7d04 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -79,6 +79,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsGPUTextureDecoding = false; g_Config.backend_info.bSupportsST3CTextures = false; g_Config.backend_info.bSupportsCopyToVram = true; + g_Config.backend_info.bForceCopyToRam = false; g_Config.backend_info.bSupportsBitfield = false; g_Config.backend_info.bSupportsDynamicSamplerIndexing = false; g_Config.backend_info.bSupportsBPTCTextures = false; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index f5ccbcd64c..10d37de6bc 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -92,6 +92,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsMultithreading = false; g_Config.backend_info.bSupportsInternalResolutionFrameDumps = true; g_Config.backend_info.bSupportsCopyToVram = true; + g_Config.backend_info.bForceCopyToRam = false; // 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/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 26a649b010..c2bbafb420 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -73,6 +73,7 @@ void VideoSoftware::InitBackendInfo() g_Config.backend_info.bSupportsST3CTextures = false; g_Config.backend_info.bSupportsBPTCTextures = false; g_Config.backend_info.bSupportsCopyToVram = false; + g_Config.backend_info.bForceCopyToRam = true; // aamodes g_Config.backend_info.AAModes = {1}; diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index 3edd507b23..9d34174e90 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -247,6 +247,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config) 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. + config->backend_info.bForceCopyToRam = false; } void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 89fbb6ac59..3a86f4e94c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1181,7 +1181,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF PEControl::PixelFormat srcFormat = bpmem.zcontrol.pixel_format; bool efbHasAlpha = srcFormat == PEControl::RGBA6_Z24; - bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam; + bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam || g_ActiveConfig.backend_info.bForceCopyToRam; bool copy_to_vram = g_ActiveConfig.backend_info.bSupportsCopyToVram; bool is_xfb_copy = false; @@ -1418,7 +1418,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 30; // just re-use the RGBX8 cbufid from above - copy_to_ram = !g_ActiveConfig.bSkipXFBCopyToRam; + copy_to_ram = !g_ActiveConfig.bSkipXFBCopyToRam || g_ActiveConfig.backend_info.bForceCopyToRam; is_xfb_copy = true; break; diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index b22d568032..8779c785d6 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -223,6 +223,7 @@ struct VideoConfig final bool bSupportsGPUTextureDecoding; bool bSupportsST3CTextures; bool bSupportsCopyToVram; + bool bForceCopyToRam; // Needed by Software Renderer bool bSupportsBitfield; // Needed by UberShaders, so must stay in VideoCommon bool bSupportsDynamicSamplerIndexing; // Needed by UberShaders, so must stay in VideoCommon bool bSupportsBPTCTextures; From 65418a76f5588482133b8cb6995b5e5f6cb74f17 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 29 Aug 2017 00:24:25 -0500 Subject: [PATCH 20/40] Video Common: Use correct aspect ratio when saving screenshots / video --- Source/Core/VideoCommon/RenderBase.cpp | 53 +++++++++++++++++----- Source/Core/VideoCommon/RenderBase.h | 4 ++ Source/Core/VideoCommon/TextureCacheBase.h | 4 +- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 00bb5d24fc..b87ec7ded5 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -518,13 +518,26 @@ void Renderer::UpdateDrawRectangle() void Renderer::SetWindowSize(int width, int height) { - width = std::max(width, 1); - height = std::max(height, 1); - // Scale the window size by the EFB scale. if (g_ActiveConfig.iEFBScale != EFB_SCALE_AUTO_INTEGRAL) std::tie(width, height) = CalculateTargetScale(width, height); + std::tie(width, height) = CalculateOutputDimensions(width, height); + + // Track the last values of width/height to avoid sending a window resize event every frame. + if (width != m_last_window_request_width || height != m_last_window_request_height) + { + m_last_window_request_width = width; + m_last_window_request_height = height; + Host_RequestRenderWindowSize(width, height); + } +} + +std::tuple Renderer::CalculateOutputDimensions(int width, int height) +{ + width = std::max(width, 1); + height = std::max(height, 1); + float scaled_width, scaled_height; std::tie(scaled_width, scaled_height) = ScaleToDisplayAspectRatio(width, height); @@ -556,13 +569,7 @@ void Renderer::SetWindowSize(int width, int height) width -= width % 4; height -= height % 4; - // Track the last values of width/height to avoid sending a window resize event every frame. - if (width != m_last_window_request_width || height != m_last_window_request_height) - { - m_last_window_request_width = width; - m_last_window_request_height = height; - Host_RequestRenderWindowSize(width, height); - } + return std::make_tuple(width, height); } void Renderer::CheckFifoRecording() @@ -620,9 +627,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const // The FinishFrameData 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. FinishFrameData(); - if (IsFrameDumping()) + if (IsFrameDumping() && m_last_xfb_texture) { - auto result = m_last_xfb_texture->Map(); + UpdateFrameDumpTexture(horizontal_scale); + + auto result = m_dump_texture->Map(); if (result.has_value()) { auto raw_data = result.value(); @@ -679,6 +688,26 @@ bool Renderer::IsFrameDumping() return false; } +void Renderer::UpdateFrameDumpTexture(float horizontal_scale) +{ + int target_width, target_height; + std::tie(target_width, target_height) = CalculateOutputDimensions(m_last_xfb_texture->GetConfig().width, m_last_xfb_texture->GetConfig().height); + if (m_dump_texture == nullptr || + m_dump_texture->GetConfig().width != static_cast(target_width) || + m_dump_texture->GetConfig().height != static_cast(target_height)) + { + TextureConfig config; + config.width = target_width; + config.height = target_height; + config.rendertarget = true; + m_dump_texture = g_texture_cache->CreateTexture(config); + } + auto source_rect = m_last_xfb_texture->GetConfig().GetRect(); + source_rect.right /= horizontal_scale; + m_dump_texture->CopyRectangleFromTexture(m_last_xfb_texture, source_rect, + EFBRectangle{0, 0, target_width, target_height}); +} + void Renderer::ShutdownFrameDumping() { if (!m_frame_dump_thread_running.IsSet()) diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 11a73536e5..871939d7ab 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -181,6 +181,8 @@ protected: private: void RunFrameDumps(); void ShutdownFrameDumping(); + std::tuple CalculateOutputDimensions(int width, int height); + void UpdateFrameDumpTexture(float horizontal_scale); PEControl::PixelFormat m_prev_efb_format = PEControl::INVALID_FMT; unsigned int m_efb_scale = 1; @@ -209,6 +211,8 @@ private: AbstractTexture * m_last_xfb_texture; u64 m_last_xfb_id = 0; + std::unique_ptr m_dump_texture; + // Note: Only used for auto-ir u32 m_last_xfb_width = MAX_XFB_WIDTH; u32 m_last_xfb_height = MAX_XFB_HEIGHT; diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index bec67c042a..114127a8da 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -216,6 +216,8 @@ public: void ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, u32 new_height); + virtual std::unique_ptr CreateTexture(const TextureConfig& config) = 0; + protected: TextureCacheBase(); @@ -257,8 +259,6 @@ private: std::pair FindOverlappingTextures(u32 addr, u32 size_in_bytes); - virtual std::unique_ptr CreateTexture(const TextureConfig& config) = 0; - virtual void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half, unsigned int cbuf_id, const float* colmat) = 0; From 725d14e4c67ee5568b24595567b3b007d9e9e231 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 30 Aug 2017 00:15:08 -0500 Subject: [PATCH 21/40] Update game inis that need 'Immediate Mode' disabled due to having extra/incomplete frames in XFB. Also add new game inis: disable 'Immediate Mode' on Mushroom Men which needs XFB timing for its videos and disable 'Immediate Mode' on Go Vacation which also has extra/incomplete frames in some minigames. --- Data/Sys/GameSettings/G8M.ini | 1 + Data/Sys/GameSettings/GGS.ini | 2 ++ Data/Sys/GameSettings/GWL.ini | 3 +++ Data/Sys/GameSettings/R3M.ini | 2 +- Data/Sys/GameSettings/RBW.ini | 3 +++ Data/Sys/GameSettings/RED.ini | 2 ++ Data/Sys/GameSettings/RM9.ini | 23 +++++++++++++++++++++++ Data/Sys/GameSettings/SGV.ini | 21 +++++++++++++++++++++ 8 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 Data/Sys/GameSettings/RM9.ini create mode 100644 Data/Sys/GameSettings/SGV.ini diff --git a/Data/Sys/GameSettings/G8M.ini b/Data/Sys/GameSettings/G8M.ini index fdec5667ec..32779226bc 100644 --- a/Data/Sys/GameSettings/G8M.ini +++ b/Data/Sys/GameSettings/G8M.ini @@ -20,6 +20,7 @@ EmulationIssues = Needs Efb to Ram for BBox (proper graphics). [Video_Hacks] EFBToTextureEnable = False BBoxEnable = True +ImmediateXFBEnable = False [Video_Stereoscopy] StereoConvergence = 545 diff --git a/Data/Sys/GameSettings/GGS.ini b/Data/Sys/GameSettings/GGS.ini index b663c7b560..ddf5956832 100644 --- a/Data/Sys/GameSettings/GGS.ini +++ b/Data/Sys/GameSettings/GGS.ini @@ -20,3 +20,5 @@ EmulationIssues = [Video_Settings] SafeTextureCacheColorSamples = 512 +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/GWL.ini b/Data/Sys/GameSettings/GWL.ini index 37ed3483f9..0c82f15eb8 100644 --- a/Data/Sys/GameSettings/GWL.ini +++ b/Data/Sys/GameSettings/GWL.ini @@ -17,3 +17,6 @@ EmulationIssues = [ActionReplay] # Add action replay cheats here. + +[Video_Hacks] +ImmediateXFBEnable = False \ No newline at end of file diff --git a/Data/Sys/GameSettings/R3M.ini b/Data/Sys/GameSettings/R3M.ini index 733da1c50d..fdaa7e24e2 100644 --- a/Data/Sys/GameSettings/R3M.ini +++ b/Data/Sys/GameSettings/R3M.ini @@ -19,4 +19,4 @@ EmulationIssues = Disable PAL60 (EuRGB60) to avoid a black bar appearing. [Video_Hacks] EFBToTextureEnable = False - +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RBW.ini b/Data/Sys/GameSettings/RBW.ini index 208bd1031a..88524635d2 100644 --- a/Data/Sys/GameSettings/RBW.ini +++ b/Data/Sys/GameSettings/RBW.ini @@ -17,3 +17,6 @@ EmulationIssues = [ActionReplay] # Add action replay cheats here. + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RED.ini b/Data/Sys/GameSettings/RED.ini index 155b1cc5f7..3955ebdc58 100644 --- a/Data/Sys/GameSettings/RED.ini +++ b/Data/Sys/GameSettings/RED.ini @@ -17,3 +17,5 @@ EmulationIssues = Nunchuk doesn't work (both real and emulated). [ActionReplay] # Add action replay cheats here. +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/RM9.ini b/Data/Sys/GameSettings/RM9.ini new file mode 100644 index 0000000000..ca72c7fbe2 --- /dev/null +++ b/Data/Sys/GameSettings/RM9.ini @@ -0,0 +1,23 @@ +# RM9PGM, RM9EGM - Mushroom Men: The Spore Wars + +[Core] +# Values set here will override the main Dolphin settings. + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] + +[Video_Hacks] +ImmediateXFBEnable = False diff --git a/Data/Sys/GameSettings/SGV.ini b/Data/Sys/GameSettings/SGV.ini new file mode 100644 index 0000000000..ac1597be91 --- /dev/null +++ b/Data/Sys/GameSettings/SGV.ini @@ -0,0 +1,21 @@ +# SGVEAF, SGVPAF - Go Vacation + +[Core] +# Values set here will override the main Dolphin settings. + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Hacks] +ImmediateXFBEnable = False From 53684701fa1f9a787f8d089d864c5c1c97effa8c Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 2 Sep 2017 21:30:34 -0500 Subject: [PATCH 22/40] HybridXFB: Fix lint errors --- Source/Core/Core/Config/GraphicsSettings.cpp | 2 +- .../Core/ConfigLoaders/IsSettingSaveable.cpp | 25 ++--- .../Core/ConfigLoaders/MovieConfigLoader.cpp | 1 - Source/Core/Core/HW/VideoInterface.cpp | 4 +- .../Config/Graphics/HacksWidget.cpp | 18 +-- Source/Core/DolphinWX/Frame.cpp | 2 +- Source/Core/DolphinWX/VideoConfigDiag.cpp | 38 ++++--- Source/Core/VideoBackends/D3D/DXTexture.cpp | 2 +- .../VideoBackends/D3D/PSTextureEncoder.cpp | 4 +- Source/Core/VideoBackends/D3D/Render.cpp | 6 +- .../Core/VideoBackends/OGL/PostProcessing.cpp | 2 +- Source/Core/VideoBackends/OGL/Render.cpp | 3 +- Source/Core/VideoBackends/OGL/Render.h | 3 +- .../Core/VideoBackends/OGL/TextureCache.cpp | 8 +- .../Core/VideoBackends/Software/CopyRegion.h | 6 +- .../Core/VideoBackends/Software/EfbCopy.cpp | 2 - .../VideoBackends/Software/EfbInterface.cpp | 10 +- .../VideoBackends/Software/EfbInterface.h | 3 +- .../VideoBackends/Software/SWOGLWindow.cpp | 2 +- .../Core/VideoBackends/Software/SWOGLWindow.h | 1 - .../Core/VideoBackends/Software/SWTexture.cpp | 10 +- .../Core/VideoBackends/Software/SWTexture.h | 1 - .../VideoBackends/Software/TextureCache.h | 12 +- .../VideoBackends/Software/TextureEncoder.cpp | 104 +++++++++--------- .../VideoBackends/Software/TextureEncoder.h | 3 +- .../VideoBackends/Vulkan/TextureConverter.cpp | 22 ++-- .../Core/VideoBackends/Vulkan/VKTexture.cpp | 4 +- Source/Core/VideoCommon/BPStructs.cpp | 4 +- .../VideoCommon/FramebufferManagerBase.cpp | 1 - .../Core/VideoCommon/FramebufferManagerBase.h | 2 - Source/Core/VideoCommon/RenderBase.cpp | 10 +- Source/Core/VideoCommon/RenderBase.h | 2 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 54 ++++----- Source/Core/VideoCommon/TextureCacheBase.h | 9 +- .../VideoCommon/TextureConversionShader.cpp | 23 ++-- .../VideoCommon/TextureDecoder_Common.cpp | 2 +- .../Core/VideoCommon/TextureDecoder_x64.cpp | 2 +- Source/Core/VideoCommon/VideoCommon.h | 2 +- Source/Core/VideoCommon/VideoConfig.h | 2 +- 39 files changed, 207 insertions(+), 204 deletions(-) diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index d4b85972f6..f95e44a92a 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -43,7 +43,7 @@ const ConfigInfo GFX_CONVERT_HIRES_TEXTURES{{System::GFX, "Settings", "Con const ConfigInfo GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresTextures"}, false}; const ConfigInfo GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false}; -const ConfigInfo GFX_DUMP_XFB_TARGET{ { System::GFX, "Settings", "DumpXFBTarget" }, false }; +const ConfigInfo GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false}; const ConfigInfo GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false}; const ConfigInfo GFX_FREE_LOOK{{System::GFX, "Settings", "FreeLook"}, false}; diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 0f5f783e5b..84c6a82c35 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -28,17 +28,17 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) // Graphics.Settings Config::GFX_WIDESCREEN_HACK.location, Config::GFX_ASPECT_RATIO.location, - Config::GFX_CROP.location, - Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES.location, Config::GFX_SHOW_FPS.location, - Config::GFX_SHOW_NETPLAY_PING.location, Config::GFX_SHOW_NETPLAY_MESSAGES.location, - Config::GFX_LOG_RENDER_TIME_TO_FILE.location, Config::GFX_OVERLAY_STATS.location, - Config::GFX_OVERLAY_PROJ_STATS.location, Config::GFX_DUMP_TEXTURES.location, - Config::GFX_HIRES_TEXTURES.location, Config::GFX_CONVERT_HIRES_TEXTURES.location, - Config::GFX_CACHE_HIRES_TEXTURES.location, Config::GFX_DUMP_EFB_TARGET.location, - Config::GFX_DUMP_FRAMES_AS_IMAGES.location, Config::GFX_FREE_LOOK.location, - Config::GFX_USE_FFV1.location, Config::GFX_DUMP_FORMAT.location, - Config::GFX_DUMP_CODEC.location, Config::GFX_DUMP_PATH.location, - Config::GFX_BITRATE_KBPS.location, Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS.location, + Config::GFX_CROP.location, Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES.location, + Config::GFX_SHOW_FPS.location, Config::GFX_SHOW_NETPLAY_PING.location, + Config::GFX_SHOW_NETPLAY_MESSAGES.location, Config::GFX_LOG_RENDER_TIME_TO_FILE.location, + Config::GFX_OVERLAY_STATS.location, Config::GFX_OVERLAY_PROJ_STATS.location, + Config::GFX_DUMP_TEXTURES.location, Config::GFX_HIRES_TEXTURES.location, + Config::GFX_CONVERT_HIRES_TEXTURES.location, Config::GFX_CACHE_HIRES_TEXTURES.location, + Config::GFX_DUMP_EFB_TARGET.location, Config::GFX_DUMP_FRAMES_AS_IMAGES.location, + Config::GFX_FREE_LOOK.location, Config::GFX_USE_FFV1.location, + Config::GFX_DUMP_FORMAT.location, Config::GFX_DUMP_CODEC.location, + Config::GFX_DUMP_PATH.location, Config::GFX_BITRATE_KBPS.location, + Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS.location, Config::GFX_ENABLE_GPU_TEXTURE_DECODING.location, Config::GFX_ENABLE_PIXEL_LIGHTING.location, Config::GFX_FAST_DEPTH_CALC.location, Config::GFX_MSAA.location, Config::GFX_SSAA.location, Config::GFX_EFB_SCALE.location, Config::GFX_TEXFMT_OVERLAY_ENABLE.location, @@ -73,8 +73,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) Config::GFX_HACK_EFB_ACCESS_ENABLE.location, Config::GFX_HACK_BBOX_ENABLE.location, Config::GFX_HACK_BBOX_PREFER_STENCIL_IMPLEMENTATION.location, Config::GFX_HACK_FORCE_PROGRESSIVE.location, Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location, - Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location, - Config::GFX_HACK_IMMEDIATE_XFB.location, + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location, Config::GFX_HACK_IMMEDIATE_XFB.location, Config::GFX_HACK_COPY_EFB_ENABLED.location, Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location, Config::GFX_HACK_VERTEX_ROUDING.location, diff --git a/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp index 046bcf6631..3585df4cc3 100644 --- a/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/MovieConfigLoader.cpp @@ -39,7 +39,6 @@ static void LoadFromDTM(Config::Layer* config_layer, Movie::DTMHeader* dtm) else config_layer->Set(Config::MAIN_GC_LANGUAGE, static_cast(dtm->language)); - config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable); config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam); config_layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, dtm->bSkipXFBCopyToRam); diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp index c8ec4a3d0b..46575ed2de 100644 --- a/Source/Core/Core/HW/VideoInterface.cpp +++ b/Source/Core/Core/HW/VideoInterface.cpp @@ -799,9 +799,9 @@ void FakeVIUpdate(u32 xfb_address, u32 fb_width, u32 fb_height) m_VBlankTimingEven.PSB = 4; m_PictureConfiguration.WPL = fb_width / 16; m_PictureConfiguration.STD = fb_stride / 16; - + UpdateParameters(); - + u32 total_halflines = GetHalfLinesPerEvenField() + GetHalfLinesPerOddField(); if ((s_half_line_count - s_even_field_first_hl) % total_halflines < diff --git a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp index ec2e4809c5..ad30644749 100644 --- a/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp +++ b/Source/Core/DolphinQt2/Config/Graphics/HacksWidget.cpp @@ -69,8 +69,7 @@ void HacksWidget::CreateWidgets() m_store_xfb_copies = new GraphicsBool(tr("Store XFB Copies to Texture Only"), Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM); - m_immediate_xfb = new GraphicsBool(tr("Immediately Present XFB"), - Config::GFX_HACK_IMMEDIATE_XFB); + m_immediate_xfb = new GraphicsBool(tr("Immediately Present XFB"), Config::GFX_HACK_IMMEDIATE_XFB); xfb_layout->addWidget(m_store_xfb_copies, 1, 0); @@ -171,15 +170,18 @@ void HacksWidget::AddDescriptions() "from RAM.\nLower accuracies cause in-game text to appear garbled in certain " "games.\n\nIf unsure, use the rightmost value."); - static const char* TR_STORE_XFB_TO_TEXTURE_DESCRIPTION = QT_TR_NOOP( + static const char* TR_STORE_XFB_TO_TEXTURE_DESCRIPTION = QT_TR_NOOP( "Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " - "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to Texture\nDisabled = XFB Copies to RAM " + "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to " + "Texture\nDisabled = XFB Copies to RAM " "(and Texture)\n\nIf unsure, leave this checked."); - static const char* TR_IMMEDIATE_XFB_DESCRIPTION = QT_TR_NOOP( - "Displays the XFB copies as soon as they are created, without waiting for scanout. Can cause graphical defects " - "in some games if the game doesn't expect all XFB copies to be displayed. However, turning this setting on reduces latency." - "\n\nIf unsure, leave this unchecked."); + static const char* TR_IMMEDIATE_XFB_DESCRIPTION = + QT_TR_NOOP("Displays the XFB copies as soon as they are created, without waiting for " + "scanout. Can cause graphical defects " + "in some games if the game doesn't expect all XFB copies to be displayed. " + "However, turning this setting on reduces latency." + "\n\nIf unsure, leave this unchecked."); static const char* TR_GPU_DECODING_DESCRIPTION = QT_TR_NOOP("Enables texture decoding using the GPU instead of the CPU. This may result in " diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 97c0f38ec9..1f89306a13 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1496,7 +1496,7 @@ void CFrame::ParseHotkeys() OSDChoice = 6; // Toggle immediate present of xfb Config::SetCurrent(Config::GFX_HACK_IMMEDIATE_XFB, - !Config::Get(Config::GFX_HACK_IMMEDIATE_XFB)); + !Config::Get(Config::GFX_HACK_IMMEDIATE_XFB)); } if (IsHotkey(HK_TOGGLE_FOG)) { diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 07dcfb9cd2..7a760422a2 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -202,13 +202,16 @@ static wxString skip_efb_copy_to_ram_desc = wxTRANSLATE( "in a small number of games.\n\nEnabled = EFB Copies to Texture\nDisabled = EFB Copies to RAM " "(and Texture)\n\nIf unsure, leave this checked."); static wxString skip_xfb_copy_to_ram_desc = wxTRANSLATE( - "Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " - "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to Texture\nDisabled = XFB Copies to RAM " - "(and Texture)\n\nIf unsure, leave this checked."); -static wxString immediate_xfb_desc = wxTRANSLATE( - "Displays the XFB copies as soon as they are created, without waiting for scanout. Can cause graphical defects " - "in some games if the game doesn't expect all XFB copies to be displayed. However, turning this setting on reduces latency." - "\n\nIf unsure, leave this unchecked."); + "Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects " + "in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to " + "Texture\nDisabled = XFB Copies to RAM " + "(and Texture)\n\nIf unsure, leave this checked."); +static wxString immediate_xfb_desc = + wxTRANSLATE("Displays the XFB copies as soon as they are created, without waiting for scanout. " + "Can cause graphical defects " + "in some games if the game doesn't expect all XFB copies to be displayed. However, " + "turning this setting on reduces latency." + "\n\nIf unsure, leave this unchecked."); static wxString stc_desc = wxTRANSLATE("The \"Safe\" setting eliminates the likelihood of the GPU missing texture updates " "from RAM.\nLower accuracies cause in-game text to appear garbled in certain " @@ -248,7 +251,7 @@ static wxString cache_hires_textures_desc = static wxString dump_efb_desc = wxTRANSLATE( "Dump the contents of EFB copies to User/Dump/Textures/.\n\nIf unsure, leave this unchecked."); static wxString dump_xfb_desc = wxTRANSLATE( - "Dump the contents of XFB copies to User/Dump/Textures/.\n\nIf unsure, leave this unchecked."); + "Dump the contents of XFB copies to User/Dump/Textures/.\n\nIf unsure, leave this unchecked."); static wxString internal_resolution_frame_dumping_desc = wxTRANSLATE( "Create frame dumps and screenshots at the internal resolution of the renderer, rather than " "the size of the window it is displayed within. If the aspect ratio is widescreen, the output " @@ -779,21 +782,21 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) szr_hacks->Add(szr_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT, space5); } - // - XFB + // - XFB { wxStaticBoxSizer* const group_xfb = new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("External Frame Buffer (XFB)")); group_xfb->Add(CreateCheckBox(page_hacks, _("Store XFB Copies to Texture Only"), - wxGetTranslation(skip_xfb_copy_to_ram_desc), - Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM), - 0, wxLEFT | wxRIGHT, space5); + wxGetTranslation(skip_xfb_copy_to_ram_desc), + Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM), + 0, wxLEFT | wxRIGHT, space5); group_xfb->AddSpacer(space5); group_xfb->Add(CreateCheckBox(page_hacks, _("Immediately Present XFB"), - wxGetTranslation(immediate_xfb_desc), - Config::GFX_HACK_IMMEDIATE_XFB), - 0, wxLEFT | wxRIGHT, space5); + wxGetTranslation(immediate_xfb_desc), + Config::GFX_HACK_IMMEDIATE_XFB), + 0, wxLEFT | wxRIGHT, space5); group_xfb->AddSpacer(space5); szr_hacks->AddSpacer(space5); @@ -885,8 +888,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title) szr_utility->Add(CreateCheckBox(page_advanced, _("Dump EFB Target"), wxGetTranslation(dump_efb_desc), Config::GFX_DUMP_EFB_TARGET)); - szr_utility->Add(CreateCheckBox(page_advanced, _("Dump XFB Target"), - wxGetTranslation(dump_xfb_desc), Config::GFX_DUMP_XFB_TARGET)); + szr_utility->Add(CreateCheckBox(page_advanced, _("Dump XFB Target"), + wxGetTranslation(dump_xfb_desc), + Config::GFX_DUMP_XFB_TARGET)); szr_utility->Add(CreateCheckBox(page_advanced, _("Free Look"), wxGetTranslation(free_look_desc), Config::GFX_FREE_LOOK)); #if defined(HAVE_FFMPEG) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index e4bc024568..5f7a4e39eb 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -157,7 +157,7 @@ void DXTexture::Unmap() { if (!m_staging_texture) return; - + D3D::context->Unmap(m_staging_texture, 0); } diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 2aafb299bf..4fcce4ef03 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -46,8 +46,8 @@ void PSTextureEncoder::Init() // 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, - 1024, 1, 1, D3D11_BIND_RENDER_TARGET); + D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, EFB_WIDTH * 4, 1024, + 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 18aec69490..82e5772b15 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -39,8 +39,8 @@ #include "VideoCommon/RenderState.h" #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/VideoBackendBase.h" -#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoCommon.h" +#include "VideoCommon/VideoConfig.h" #include "VideoCommon/XFMemory.h" namespace DX11 @@ -626,8 +626,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti auto* xfb_texture = static_cast(texture); TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); - BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->GetConfig().width, - xfb_texture->GetConfig().height, Gamma); + BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), + xfb_texture->GetConfig().width, xfb_texture->GetConfig().height, Gamma); // Reset viewport for drawing text D3D11_VIEWPORT vp = diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.cpp b/Source/Core/VideoBackends/OGL/PostProcessing.cpp index 08e0d36c6e..bf34e2a54c 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 = vec2(mix(src_rect.xy, src_rect.zw, rawpos));\n" + " uv0 = vec2(mix(src_rect.xy, src_rect.zw, rawpos));\n" "}\n"; OpenGLPostProcessing::OpenGLPostProcessing() : m_initialized(false) diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 655b69cb4e..05aaef66c4 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1353,7 +1353,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // Copy the framebuffer to screen. glBindFramebuffer(GL_FRAMEBUFFER, 0); - BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); + BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), + xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); // Finish up the current frame, print some stats diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index 78d680fbd2..725cc7a639 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -111,7 +111,8 @@ private: void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const void* data); - void DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, const TargetRectangle& source_rc); + 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); diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 997b53f74b..aa2c60976b 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -388,10 +388,10 @@ void main() void TextureCache::CreateTextureDecodingResources() { static const GLenum gl_view_types[TextureConversionShader::BUFFER_FORMAT_COUNT] = { - GL_R8UI, // BUFFER_FORMAT_R8_UINT - GL_R16UI, // BUFFER_FORMAT_R16_UINT - GL_RG32UI, // BUFFER_FORMAT_R32G32_UINT - GL_RGBA8UI, // BUFFER_FORMAT_RGBA8_UINT + GL_R8UI, // BUFFER_FORMAT_R8_UINT + GL_R16UI, // BUFFER_FORMAT_R16_UINT + GL_RG32UI, // BUFFER_FORMAT_R32G32_UINT + GL_RGBA8UI, // BUFFER_FORMAT_RGBA8_UINT }; glGenTextures(TextureConversionShader::BUFFER_FORMAT_COUNT, diff --git a/Source/Core/VideoBackends/Software/CopyRegion.h b/Source/Core/VideoBackends/Software/CopyRegion.h index 5f3c1bac83..987ec77951 100644 --- a/Source/Core/VideoBackends/Software/CopyRegion.h +++ b/Source/Core/VideoBackends/Software/CopyRegion.h @@ -22,9 +22,9 @@ void copy_region(const T* const source, const MathUtil::Rectangle& srcrect, int destination_y = i + dstrect.top; int destination_offset = (destination_y * dstrect.GetWidth()) + destination_x; - double src_x = std::round(destination_x*x_ratio) + srcrect.left; - double src_y = std::round(destination_y*y_ratio) + srcrect.top; - int src_offset = static_cast((src_y*srcrect.GetWidth()) + src_x); + double src_x = std::round(destination_x * x_ratio) + srcrect.left; + double src_y = std::round(destination_y * y_ratio) + srcrect.top; + int src_offset = static_cast((src_y * srcrect.GetWidth()) + src_x); destination[destination_offset] = source[src_offset]; } diff --git a/Source/Core/VideoBackends/Software/EfbCopy.cpp b/Source/Core/VideoBackends/Software/EfbCopy.cpp index 7a69bb4881..bba64ee7c1 100644 --- a/Source/Core/VideoBackends/Software/EfbCopy.cpp +++ b/Source/Core/VideoBackends/Software/EfbCopy.cpp @@ -14,7 +14,6 @@ namespace EfbCopy { - void ClearEfb() { u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | @@ -34,5 +33,4 @@ void ClearEfb() } } } - } diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index 2ca20b3997..e667a7e584 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -497,7 +497,8 @@ u8* GetPixelPointer(u16 x, u16 y, bool depth) return &efb[GetColorOffset(x, y)]; } -void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale) +void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, + float y_scale) { if (!xfb_in_ram) { @@ -543,8 +544,7 @@ void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& src_ptr[x].Y = scanline[i].Y + 16; // we mix our color differences in 10 bit space so it will round more accurately // U[i] = 1/4 * U[i-1] + 1/2 * U[i] + 1/4 * U[i+1] - src_ptr[x].UV = - 128 + ((scanline[i - 1].U + (scanline[i].U << 1) + scanline[i + 1].U) >> 2); + src_ptr[x].UV = 128 + ((scanline[i - 1].U + (scanline[i].U << 1) + scanline[i + 1].U) >> 2); // YV pixel src_ptr[x + 1].Y = scanline[i + 1].Y + 16; @@ -556,7 +556,9 @@ void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& } // Apply y scaling and copy to the xfb memory location - SW::copy_region(source.data(), source_rect, xfb_in_ram, EFBRectangle{ source_rect.left, source_rect.top, source_rect.right, static_cast(static_cast(source_rect.bottom) * y_scale) }); + SW::copy_region(source.data(), source_rect, xfb_in_ram, + EFBRectangle{source_rect.left, source_rect.top, source_rect.right, + static_cast(static_cast(source_rect.bottom) * y_scale)}); } bool ZCompare(u16 x, u16 y, u32 z) diff --git a/Source/Core/VideoBackends/Software/EfbInterface.h b/Source/Core/VideoBackends/Software/EfbInterface.h index c13b21ac4a..24baf37689 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.h +++ b/Source/Core/VideoBackends/Software/EfbInterface.h @@ -57,7 +57,8 @@ u32 GetDepth(u16 x, u16 y); u8* GetPixelPointer(u16 x, u16 y, bool depth); -void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale); +void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, + float y_scale); extern u32 perf_values[PQ_NUM_MEMBERS]; inline void IncPerfCounterQuadCount(PerfQueryType type) diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 372f15322e..bead74872d 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -92,7 +92,7 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) { - SW::SWTexture * sw_image = static_cast(image); + SW::SWTexture* sw_image = static_cast(image); GLInterface->Update(); // just updates the render window position and the backbuffer size GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 63f0bd82b7..68fbcc133e 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -31,7 +31,6 @@ public: private: SWOGLWindow() {} - struct TextData { std::string text; diff --git a/Source/Core/VideoBackends/Software/SWTexture.cpp b/Source/Core/VideoBackends/Software/SWTexture.cpp index e2752fe0c7..b42f3d4e21 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.cpp +++ b/Source/Core/VideoBackends/Software/SWTexture.cpp @@ -10,7 +10,6 @@ namespace SW { - SWTexture::SWTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config) { } @@ -23,11 +22,12 @@ void SWTexture::CopyRectangleFromTexture(const AbstractTexture* source, const MathUtil::Rectangle& srcrect, const MathUtil::Rectangle& dstrect) { - const SWTexture * software_source_texture = static_cast(source); + const SWTexture* software_source_texture = static_cast(source); if (srcrect.GetWidth() == dstrect.GetWidth() && srcrect.GetHeight() == dstrect.GetHeight()) { - m_data.assign(software_source_texture->GetData(), software_source_texture->GetData() + m_data.size()); + m_data.assign(software_source_texture->GetData(), + software_source_texture->GetData() + m_data.size()); } else { @@ -53,8 +53,8 @@ u8* SWTexture::GetData() std::optional SWTexture::MapFullImpl() { - return AbstractTexture::RawTextureInfo{ GetData(), - m_config.width * 4, m_config.width, m_config.height }; + return AbstractTexture::RawTextureInfo{GetData(), m_config.width * 4, m_config.width, + m_config.height}; } } // namespace SW diff --git a/Source/Core/VideoBackends/Software/SWTexture.h b/Source/Core/VideoBackends/Software/SWTexture.h index 7f130b39e9..fa7fea5308 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.h +++ b/Source/Core/VideoBackends/Software/SWTexture.h @@ -30,7 +30,6 @@ public: u8* GetData(); private: - std::optional MapFullImpl() override; std::vector m_data; diff --git a/Source/Core/VideoBackends/Software/TextureCache.h b/Source/Core/VideoBackends/Software/TextureCache.h index ec46101b70..3573d36ebb 100644 --- a/Source/Core/VideoBackends/Software/TextureCache.h +++ b/Source/Core/VideoBackends/Software/TextureCache.h @@ -7,23 +7,21 @@ 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 + 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 { - TextureEncoder::Encode(dst, params, native_width, bytes_per_row, - num_blocks_y, memory_stride, src_rect, - scale_by_half); + TextureEncoder::Encode(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, + src_rect, scale_by_half); } private: @@ -31,7 +29,7 @@ private: { return std::make_unique(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 { @@ -39,4 +37,4 @@ private: } }; -} // namespace SW +} // namespace SW diff --git a/Source/Core/VideoBackends/Software/TextureEncoder.cpp b/Source/Core/VideoBackends/Software/TextureEncoder.cpp index bceb567524..52a709d04e 100644 --- a/Source/Core/VideoBackends/Software/TextureEncoder.cpp +++ b/Source/Core/VideoBackends/Software/TextureEncoder.cpp @@ -1419,63 +1419,63 @@ static void EncodeZ24halfscale(u8* dst, const u8* src, EFBCopyFormat format) namespace { - void EncodeEfbCopy(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) - { - const u8* src = - EfbInterface::GetPixelPointer(src_rect.left, src_rect.top, params.depth); - - if (scale_by_half) - { - switch (params.efb_format) - { - case PEControl::RGBA6_Z24: - EncodeRGBA6halfscale(dst, src, params.copy_format, params.yuv); - break; - case PEControl::RGB8_Z24: - EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv); - break; - case PEControl::RGB565_Z16: - EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv); - break; - case PEControl::Z24: - EncodeZ24halfscale(dst, src, params.copy_format); - break; - } - } - else - { - switch (params.efb_format) - { - case PEControl::RGBA6_Z24: - EncodeRGBA6(dst, src, params.copy_format, params.yuv); - break; - case PEControl::RGB8_Z24: - EncodeRGB8(dst, src, params.copy_format, params.yuv); - break; - case PEControl::RGB565_Z16: - EncodeRGB8(dst, src, params.copy_format, params.yuv); - break; - case PEControl::Z24: - EncodeZ24(dst, src, params.copy_format); - break; - } - } - } -} - -void Encode(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) +void EncodeEfbCopy(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) { - if (params.copy_format == EFBCopyFormat::XFB) + const u8* src = EfbInterface::GetPixelPointer(src_rect.left, src_rect.top, params.depth); + + if (scale_by_half) { - EfbInterface::EncodeXFB(reinterpret_cast(dst), native_width, src_rect, params.y_scale); + switch (params.efb_format) + { + case PEControl::RGBA6_Z24: + EncodeRGBA6halfscale(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB8_Z24: + EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB565_Z16: + EncodeRGB8halfscale(dst, src, params.copy_format, params.yuv); + break; + case PEControl::Z24: + EncodeZ24halfscale(dst, src, params.copy_format); + break; + } } else { - EncodeEfbCopy(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, src_rect, scale_by_half); + switch (params.efb_format) + { + case PEControl::RGBA6_Z24: + EncodeRGBA6(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB8_Z24: + EncodeRGB8(dst, src, params.copy_format, params.yuv); + break; + case PEControl::RGB565_Z16: + EncodeRGB8(dst, src, params.copy_format, params.yuv); + break; + case PEControl::Z24: + EncodeZ24(dst, src, params.copy_format); + break; + } + } +} +} + +void Encode(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) +{ + if (params.copy_format == EFBCopyFormat::XFB) + { + EfbInterface::EncodeXFB(reinterpret_cast(dst), native_width, + src_rect, params.y_scale); + } + else + { + EncodeEfbCopy(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, src_rect, + scale_by_half); } } } diff --git a/Source/Core/VideoBackends/Software/TextureEncoder.h b/Source/Core/VideoBackends/Software/TextureEncoder.h index ca816b92bd..ec21c97c42 100644 --- a/Source/Core/VideoBackends/Software/TextureEncoder.h +++ b/Source/Core/VideoBackends/Software/TextureEncoder.h @@ -12,6 +12,5 @@ struct EFBCopyParams; namespace TextureEncoder { void Encode(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); + u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half); } diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index b646a59fa8..b8ac91d06b 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -33,14 +33,14 @@ namespace Vulkan { - namespace - { - struct EFBEncodeParams - { - std::array position_uniform; - float y_scale; - }; - } +namespace +{ +struct EFBEncodeParams +{ + std::array position_uniform; + float y_scale; +}; +} TextureConverter::TextureConverter() { } @@ -265,8 +265,8 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p // We also linear filtering for both box filtering and downsampling higher resolutions to 1x // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more // complex down filtering to average all pixels and produce the correct result. - bool linear_filter = (scale_by_half && !params.depth) || g_renderer->GetEFBScale() != 1 || - params.y_scale > 1.0f; + bool linear_filter = + (scale_by_half && !params.depth) || g_renderer->GetEFBScale() != 1 || params.y_scale > 1.0f; draw.SetPSSampler(0, src_texture, linear_filter ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler()); @@ -580,7 +580,7 @@ bool TextureConverter::CreateTexelBuffer() m_texel_buffer_view_r16_uint = CreateTexelBufferView(VK_FORMAT_R16_UINT); m_texel_buffer_view_r32g32_uint = CreateTexelBufferView(VK_FORMAT_R32G32_UINT); m_texel_buffer_view_rgba8_unorm = CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UNORM); - m_texel_buffer_view_rgba8_uint= CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UINT); + m_texel_buffer_view_rgba8_uint = CreateTexelBufferView(VK_FORMAT_R8G8B8A8_UINT); return m_texel_buffer_view_r8_uint != VK_NULL_HANDLE && m_texel_buffer_view_r16_uint != VK_NULL_HANDLE && m_texel_buffer_view_r32g32_uint != VK_NULL_HANDLE && diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp index c06778be52..cbb6e0c063 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp @@ -133,8 +133,8 @@ std::optional VKTexture::MapRegionImpl(u32 leve // Copy to download buffer. m_staging_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), - m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, x, y, width, - height, level, 0); + m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, x, y, width, + height, level, 0); // Restore original state of texture. m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index bdba7468a8..93de3aabe5 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -261,8 +261,8 @@ static void BPWritten(const BPCmd& bp) bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24; g_texture_cache->CopyRenderTargetToTexture(destAddr, EFBCopyFormat::XFB, destStride, - is_depth_copy, srcRect, false, - false, yScale, s_gammaLUT[PE_copy.gamma]); + is_depth_copy, srcRect, false, false, yScale, + s_gammaLUT[PE_copy.gamma]); // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index 5e95cff805..1df2960b1a 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -17,4 +17,3 @@ std::unique_ptr g_framebuffer_manager; unsigned int FramebufferManagerBase::m_EFBLayers = 1; FramebufferManagerBase::~FramebufferManagerBase() = default; - diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.h b/Source/Core/VideoCommon/FramebufferManagerBase.h index 2d725fa346..5e645dc7f7 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/FramebufferManagerBase.h @@ -23,9 +23,7 @@ public: virtual ~FramebufferManagerBase(); static unsigned int GetEFBLayers() { return m_EFBLayers; } - protected: - static unsigned int m_EFBLayers; }; diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index b87ec7ded5..ba909a22b3 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -42,8 +42,8 @@ #include "Core/Host.h" #include "Core/Movie.h" -#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/AVIDump.h" +#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/CPMemory.h" #include "VideoCommon/CommandProcessor.h" @@ -336,7 +336,8 @@ void Renderer::DrawDebugText() "Speed Limit: Unlimited" : StringFromFormat("Speed Limit: %li%%", std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)), - std::string("Copy XFB: ") + xfbcopy_text + (g_ActiveConfig.bImmediateXFB ? " (Immediate)" : ""), + std::string("Copy XFB: ") + xfbcopy_text + + (g_ActiveConfig.bImmediateXFB ? " (Immediate)" : ""), }; enum @@ -691,7 +692,8 @@ bool Renderer::IsFrameDumping() void Renderer::UpdateFrameDumpTexture(float horizontal_scale) { int target_width, target_height; - std::tie(target_width, target_height) = CalculateOutputDimensions(m_last_xfb_texture->GetConfig().width, m_last_xfb_texture->GetConfig().height); + std::tie(target_width, target_height) = CalculateOutputDimensions( + m_last_xfb_texture->GetConfig().width, m_last_xfb_texture->GetConfig().height); if (m_dump_texture == nullptr || m_dump_texture->GetConfig().width != static_cast(target_width) || m_dump_texture->GetConfig().height != static_cast(target_height)) @@ -720,7 +722,7 @@ void Renderer::ShutdownFrameDumping() void Renderer::DumpFrameData(const u8* data, int w, int h, int stride, const AVIDump::Frame& state) { - m_frame_dump_config = FrameDumpConfig{ m_last_xfb_texture, data, w, h, stride, state }; + m_frame_dump_config = FrameDumpConfig{m_last_xfb_texture, data, w, h, stride, state}; if (!m_frame_dump_thread_running.IsSet()) { diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 871939d7ab..ef2560825c 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -208,7 +208,7 @@ private: AVIDump::Frame state; } m_frame_dump_config; - AbstractTexture * m_last_xfb_texture; + AbstractTexture* m_last_xfb_texture; u64 m_last_xfb_id = 0; std::unique_ptr m_dump_texture; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 3a86f4e94c..0c5574ac4a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -376,16 +376,17 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x); u32 copy_height = - std::min((entry->native_height * entry->y_scale) - src_y, (entry_to_update->native_height * entry_to_update->y_scale) - dst_y); + std::min((entry->native_height * entry->y_scale) - src_y, + (entry_to_update->native_height * entry_to_update->y_scale) - dst_y); // If one of the textures is scaled, scale both with the current efb scaling factor if (entry_to_update->native_width != entry_to_update->GetWidth() || entry_to_update->native_height != entry_to_update->GetHeight() || entry->native_width != entry->GetWidth() || entry->native_height != entry->GetHeight()) { - ScaleTextureCacheEntryTo(entry_to_update, - g_renderer->EFBToScaledX(entry_to_update->native_width), - g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); + ScaleTextureCacheEntryTo( + entry_to_update, g_renderer->EFBToScaledX(entry_to_update->native_width), + g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width), g_renderer->EFBToScaledY(entry->native_height * entry->y_scale)); @@ -632,18 +633,18 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) auto entry = GetTexture(address, width, height, texformat, g_ActiveConfig.iSafeTextureCache_ColorSamples, tlutaddr, tlutfmt, - use_mipmaps, tex_levels, from_tmem, tmem_address_even, - tmem_address_odd); + use_mipmaps, tex_levels, from_tmem, tmem_address_even, tmem_address_odd); if (!entry) return nullptr; - + entry->frameCount = FRAMECOUNT_INVALID; bound_textures[stage] = entry; GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); - // We need to keep track of invalided textures until they have actually been replaced or re-loaded + // We need to keep track of invalided textures until they have actually been replaced or + // re-loaded valid_bind_points.set(stage); return entry; @@ -728,8 +729,8 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid if (isPaletteTexture) { palette_size = TexDecoder_GetPaletteSize(texformat); - full_hash = base_hash ^ GetHash64(&texMem[tlutaddr], palette_size, - textureCacheSafetyColorSampleSize); + full_hash = + base_hash ^ GetHash64(&texMem[tlutaddr], palette_size, textureCacheSafetyColorSampleSize); } else { @@ -794,7 +795,8 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid // Do not load strided EFB copies, they are not meant to be used directly. // Also do not directly load EFB copies, which were partly overwritten. - if (entry->IsCopy() && entry->native_width == nativeW && static_cast(entry->native_height * entry->y_scale) == nativeH && + if (entry->IsCopy() && entry->native_width == nativeW && + static_cast(entry->native_height * entry->y_scale) == nativeH && entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures) { // EFB copies have slightly different rules as EFB copy formats have different @@ -829,7 +831,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid else { // For normal textures, all texture parameters need to match - if (!entry->IsCopy() && entry->hash == full_hash && entry->format == full_format && + if (!entry->IsCopy() && entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { @@ -871,8 +873,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid // Example: Tales of Symphonia (GC) uses over 500 small textures in menus, but only around 70 // different ones if (textureCacheSafetyColorSampleSize == 0 || - std::max(texture_size, palette_size) <= - (u32)textureCacheSafetyColorSampleSize * 8) + std::max(texture_size, palette_size) <= (u32)textureCacheSafetyColorSampleSize * 8) { auto hash_range = textures_by_hash.equal_range(full_hash); TexHashCache::iterator hash_iter = hash_range.first; @@ -961,9 +962,9 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid if (decode_on_gpu) { u32 row_stride = bytes_per_block * (expandedWidth / bsw); - g_texture_cache->DecodeTextureOnGPU( - entry, 0, src_data, texture_size, texformat, width, height, - expandedWidth, expandedHeight, row_stride, tlut, tlutfmt); + g_texture_cache->DecodeTextureOnGPU(entry, 0, src_data, texture_size, texformat, width, + height, expandedWidth, expandedHeight, row_stride, tlut, + tlutfmt); } else { @@ -989,13 +990,11 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid dst_buffer = temp; if (!(texformat == TextureFormat::RGBA8 && from_tmem)) { - TexDecoder_Decode(dst_buffer, src_data, expandedWidth, expandedHeight, texformat, tlut, - tlutfmt); + TexDecoder_Decode(dst_buffer, src_data, expandedWidth, expandedHeight, texformat, tlut, tlutfmt); } else { - u8* src_data_gb = - &texMem[tmem_address_odd]; + u8* src_data_gb = &texMem[tmem_address_odd]; TexDecoder_DecodeRGBA8FromTmem(dst_buffer, src_data, src_data_gb, expandedWidth, expandedHeight); } @@ -1009,8 +1008,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid iter = textures_by_address.emplace(address, entry); if (textureCacheSafetyColorSampleSize == 0 || - std::max(texture_size, palette_size) <= - (u32)textureCacheSafetyColorSampleSize * 8) + std::max(texture_size, palette_size) <= (u32)textureCacheSafetyColorSampleSize * 8) { entry->textures_by_hash_iter = textures_by_hash.emplace(full_hash, entry); } @@ -1180,8 +1178,9 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF unsigned int cbufid = UINT_MAX; PEControl::PixelFormat srcFormat = bpmem.zcontrol.pixel_format; bool efbHasAlpha = srcFormat == PEControl::RGBA6_Z24; - - bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam || g_ActiveConfig.backend_info.bForceCopyToRam; + + bool copy_to_ram = + !g_ActiveConfig.bSkipEFBCopyToRam || g_ActiveConfig.backend_info.bForceCopyToRam; bool copy_to_vram = g_ActiveConfig.backend_info.bSupportsCopyToVram; bool is_xfb_copy = false; @@ -1418,7 +1417,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF ColorMask[3] = 0.0f; fConstAdd[3] = 1.0f; cbufid = 30; // just re-use the RGBX8 cbufid from above - copy_to_ram = !g_ActiveConfig.bSkipXFBCopyToRam || g_ActiveConfig.backend_info.bForceCopyToRam; + copy_to_ram = + !g_ActiveConfig.bSkipXFBCopyToRam || g_ActiveConfig.backend_info.bForceCopyToRam; is_xfb_copy = true; break; @@ -1587,7 +1587,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF 0); } - if (g_ActiveConfig.bDumpXFBTarget && is_xfb_copy) + if (g_ActiveConfig.bDumpXFBTarget && is_xfb_copy) { static int xfb_count = 0; entry->texture->Save(StringFromFormat("%sxfb_frame_%i.png", diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 114127a8da..a6aea52e9e 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -46,7 +46,8 @@ struct EFBCopyParams { EFBCopyParams(PEControl::PixelFormat efb_format_, EFBCopyFormat copy_format_, bool depth_, bool yuv_, float y_scale_) - : efb_format(efb_format_), copy_format(copy_format_), depth(depth_), yuv(yuv_), y_scale(y_scale_) + : efb_format(efb_format_), copy_format(copy_format_), depth(depth_), yuv(yuv_), + y_scale(y_scale_) { } @@ -111,7 +112,8 @@ public: ~TCacheEntry(); - void SetGeneralParameters(u32 _addr, u32 _size, TextureAndTLUTFormat _format, bool force_safe_hashing) + void SetGeneralParameters(u32 _addr, u32 _size, TextureAndTLUTFormat _format, + bool force_safe_hashing) { addr = _addr; size_in_bytes = _size; @@ -150,7 +152,6 @@ public: bool IsEfbCopy() const { return is_efb_copy; } bool IsCopy() const { return is_xfb_copy || is_efb_copy; } - u32 NumBlocksY() const; u32 BytesPerRow() const; @@ -186,7 +187,7 @@ public: static bool IsValidBindPoint(u32 i) { return valid_bind_points.test(i); } TCacheEntry* GetTexture(u32 address, u32 width, u32 height, const TextureFormat texformat, const int textureCacheSafetyColorSampleSize, u32 tlutaddr = 0, - TLUTFormat tlutfmt = TLUTFormat::IA8, bool use_mipmaps = false, + TLUTFormat tlutfmt = TLUTFormat::IA8, bool use_mipmaps = false, u32 tex_levels = 1, bool from_tmem = false, u32 tmem_address_even = 0, u32 tmem_address_odd = 0); virtual void BindTextures(); diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 1f608651ca..ad31c2bf9f 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -64,7 +64,8 @@ static void WriteSwizzler(char*& p, EFBCopyFormat format, APIType ApiType) // left, top, of source rectangle within source texture // width of the destination rectangle, scale_factor (1 or 2) if (ApiType == APIType::Vulkan) - WRITE(p, "layout(std140, push_constant) uniform PCBlock { int4 position; float y_scale; } PC;\n"); + WRITE(p, + "layout(std140, push_constant) uniform PCBlock { int4 position; float y_scale; } PC;\n"); else { WRITE(p, "uniform int4 position;\n"); @@ -154,7 +155,7 @@ static void WriteSwizzler(char*& p, EFBCopyFormat format, APIType ApiType) // pixel) WRITE(p, " uv0 += float2(position.xy);\n"); // move to copied rect WRITE(p, " uv0 /= float2(%d, %d);\n", EFB_WIDTH, EFB_HEIGHT); // normalize to [0:1] - WRITE(p, " uv0 /= float2(1, y_scale);\n"); // apply the y scaling + WRITE(p, " uv0 /= float2(1, y_scale);\n"); // apply the y scaling if (ApiType == APIType::OpenGL) // ogl has to flip up and down { WRITE(p, " uv0.y = 1.0-uv0.y;\n"); @@ -666,22 +667,22 @@ static void WriteZ24Encoder(char*& p, APIType ApiType, const EFBCopyParams& para static void WriteXFBEncoder(char*& p, APIType ApiType, const EFBCopyParams& params) { WriteSwizzler(p, EFBCopyFormat::XFB, ApiType); - + WRITE(p, " float3 y_const = float3(0.257, 0.504, 0.098);\n"); WRITE(p, " float3 u_const = float3(-0.148, -0.291, 0.439);\n"); WRITE(p, " float3 v_const = float3(0.439, -0.368, -0.071);\n"); WRITE(p, " float3 color0;\n"); WRITE(p, " float3 color1;\n"); - + WriteSampleColor(p, "rgb", "color0", 0, ApiType, params); WriteSampleColor(p, "rgb", "color1", 1, ApiType, params); WRITE(p, " float3 average = (color0 + color1) * 0.5;\n"); - + WRITE(p, " ocol0.b = dot(color0, y_const) + 0.0625;\n"); WRITE(p, " ocol0.g = dot(average, u_const) + 0.5;\n"); WRITE(p, " ocol0.r = dot(color1, y_const) + 0.0625;\n"); WRITE(p, " ocol0.a = dot(average, v_const) + 0.5;\n"); - + WriteEncoderEnd(p); } @@ -1264,11 +1265,11 @@ static const std::map s_decoding_shader_info{ } )"}}, - // We do the inverse BT.601 conversion for YCbCr to RGB - // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion - { TextureFormat::XFB, - { BUFFER_FORMAT_RGBA8_UINT, 0, 8, 8, false, - R"( + // We do the inverse BT.601 conversion for YCbCr to RGB + // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion + {TextureFormat::XFB, + {BUFFER_FORMAT_RGBA8_UINT, 0, 8, 8, false, + R"( layout(local_size_x = 8, local_size_y = 8) in; void main() diff --git a/Source/Core/VideoCommon/TextureDecoder_Common.cpp b/Source/Core/VideoCommon/TextureDecoder_Common.cpp index 4351a819c0..9dd9f5850c 100644 --- a/Source/Core/VideoCommon/TextureDecoder_Common.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_Common.cpp @@ -3,8 +3,8 @@ // Refer to the license.txt file included. #include -#include #include +#include #include "Common/CommonTypes.h" #include "Common/MathUtil.h" diff --git a/Source/Core/VideoCommon/TextureDecoder_x64.cpp b/Source/Core/VideoCommon/TextureDecoder_x64.cpp index b31d3692f0..e11a58a8c6 100644 --- a/Source/Core/VideoCommon/TextureDecoder_x64.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_x64.cpp @@ -1486,7 +1486,7 @@ void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, Text case TextureFormat::CMPR: TexDecoder_DecodeImpl_CMPR(dst, src, width, height, texformat, tlut, tlutfmt, Wsteps4, Wsteps8); break; - + case TextureFormat::XFB: { for (int y = 0; y < height; y += 1) diff --git a/Source/Core/VideoCommon/VideoCommon.h b/Source/Core/VideoCommon/VideoCommon.h index 5a397084f1..4bd5f59209 100644 --- a/Source/Core/VideoCommon/VideoCommon.h +++ b/Source/Core/VideoCommon/VideoCommon.h @@ -55,7 +55,7 @@ struct TargetRectangle : public MathUtil::Rectangle return (RECT*)this; } #endif - TargetRectangle(const MathUtil::Rectangle &other) : MathUtil::Rectangle(other) {} + TargetRectangle(const MathUtil::Rectangle& other) : MathUtil::Rectangle(other) {} TargetRectangle() = default; }; diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 8779c785d6..03f8a7368c 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -223,7 +223,7 @@ struct VideoConfig final bool bSupportsGPUTextureDecoding; bool bSupportsST3CTextures; bool bSupportsCopyToVram; - bool bForceCopyToRam; // Needed by Software Renderer + bool bForceCopyToRam; // Needed by Software Renderer bool bSupportsBitfield; // Needed by UberShaders, so must stay in VideoCommon bool bSupportsDynamicSamplerIndexing; // Needed by UberShaders, so must stay in VideoCommon bool bSupportsBPTCTextures; From a129a53e56cdff93e2fd092fd56f3e0726408a60 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 13 Sep 2017 23:46:30 -0500 Subject: [PATCH 23/40] Video Common: Improve texture dumping to work with fifoci and fifo_comparer --- Source/Core/Core/Core.cpp | 6 +-- Source/Core/VideoCommon/MainBase.cpp | 9 +++++ Source/Core/VideoCommon/RenderBase.cpp | 43 +++++++++++++++------- Source/Core/VideoCommon/RenderBase.h | 9 ++++- Source/Core/VideoCommon/VideoBackendBase.h | 4 +- 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index d70d9ff712..a081d6e883 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -393,7 +393,7 @@ static void CpuThread() s_is_started = false; if (!_CoreParameter.bCPUThread) - g_video_backend->Video_Cleanup(); + g_video_backend->Video_CleanupShared(); if (_CoreParameter.bFastmem) EMM::UninstallExceptionHandler(); @@ -445,7 +445,7 @@ static void FifoPlayerThread() } if (!_CoreParameter.bCPUThread) - g_video_backend->Video_Cleanup(); + g_video_backend->Video_CleanupShared(); } // Initialize and create emulation thread @@ -654,7 +654,7 @@ static void EmuThread(std::unique_ptr boot) INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str()); if (core_parameter.bCPUThread) - g_video_backend->Video_Cleanup(); + g_video_backend->Video_CleanupShared(); // If we shut down normally, the stop message does not need to be triggered. stop_message_guard.Dismiss(); diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index 38d37113e2..280fed683d 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -45,6 +45,15 @@ void VideoBackendBase::Video_ExitLoop() s_FifoShuttingDown.Set(); } +void VideoBackendBase::Video_CleanupShared() +{ + // First stop any framedumping, which might need to dump the last xfb frame. This process + // can require additional graphics sub-systems so it needs to be done first + g_renderer->ExitFramedumping(); + + Video_Cleanup(); +} + // Run from the CPU thread (from VideoInterface.cpp) void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, u64 ticks) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index ba909a22b3..e63282d527 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -97,11 +97,15 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height) m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits; } -Renderer::~Renderer() +Renderer::~Renderer() = default; + +void Renderer::ExitFramedumping() { ShutdownFrameDumping(); if (m_frame_dump_thread.joinable()) m_frame_dump_thread.join(); + + m_dump_texture.reset(); } void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStride, u32 fbHeight, @@ -625,20 +629,13 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_aspect_wide = flush_count_anamorphic > 0.75 * flush_total; } - // The FinishFrameData 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. - FinishFrameData(); if (IsFrameDumping() && m_last_xfb_texture) { - UpdateFrameDumpTexture(horizontal_scale); - - auto result = m_dump_texture->Map(); - if (result.has_value()) - { - auto raw_data = result.value(); - DumpFrameData(raw_data.data, raw_data.width, raw_data.height, raw_data.stride, - AVIDump::FetchState(ticks)); - } + FinishFrameData(); + } + else + { + ShutdownFrameDumping(); } bool update_frame_count = false; @@ -653,12 +650,18 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const { m_last_xfb_texture = xfb_entry->texture.get(); m_last_xfb_id = xfb_entry->id; + m_last_xfb_ticks = ticks; + m_last_xfb_horizontal_scale = horizontal_scale; // TODO: merge more generic parts into VideoCommon g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, xfb_entry->gamma); m_fps_counter.Update(); update_frame_count = true; + if (IsFrameDumping()) + { + DoDumpFrame(); + } } // Update our last xfb values @@ -685,10 +688,22 @@ bool Renderer::IsFrameDumping() if (SConfig::GetInstance().m_DumpFrames) return true; - ShutdownFrameDumping(); return false; } +void Renderer::DoDumpFrame() +{ + UpdateFrameDumpTexture(m_last_xfb_horizontal_scale); + + auto result = m_dump_texture->Map(); + if (result.has_value()) + { + auto raw_data = result.value(); + DumpFrameData(raw_data.data, raw_data.width, raw_data.height, raw_data.stride, + AVIDump::FetchState(m_last_xfb_ticks)); + } +} + void Renderer::UpdateFrameDumpTexture(float horizontal_scale) { int target_width, target_height; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index ef2560825c..6698f2f66f 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -142,6 +142,8 @@ public: virtual void ChangeSurface(void* new_surface_handle) {} bool UseVertexDepthRange() const; + void ExitFramedumping(); + protected: std::tuple CalculateTargetScale(int x, int y) const; bool CalculateTargetSize(); @@ -179,6 +181,7 @@ protected: u32 m_last_host_config_bits = 0; private: + void DoDumpFrame(); void RunFrameDumps(); void ShutdownFrameDumping(); std::tuple CalculateOutputDimensions(int width, int height); @@ -208,8 +211,10 @@ private: AVIDump::Frame state; } m_frame_dump_config; - AbstractTexture* m_last_xfb_texture; - u64 m_last_xfb_id = 0; + AbstractTexture* m_last_xfb_texture = nullptr; + u64 m_last_xfb_id = std::numeric_limits::max(); + u64 m_last_xfb_ticks = 0; + float m_last_xfb_horizontal_scale = 0.0f; std::unique_ptr m_dump_texture; diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 16d25c7eab..b7d6e1faa8 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -47,7 +47,9 @@ public: virtual void Video_Prepare() = 0; void Video_ExitLoop(); - virtual void Video_Cleanup() = 0; // called from gl/d3d thread + + void Video_CleanupShared(); // called from gl/d3d thread + virtual void Video_Cleanup() = 0; void Video_BeginField(u32, u32, u32, u32, u64); From 4964fc87ae15600252cea8a07df5799e91c11875 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 29 Sep 2017 00:31:08 -0500 Subject: [PATCH 24/40] Video Backends: Remove the right of the xfb region for games where the VI stride does not match the VI width --- Source/Core/VideoBackends/D3D/Render.cpp | 5 ++--- Source/Core/VideoBackends/OGL/Render.cpp | 8 +++----- .../Core/VideoBackends/Software/SWOGLWindow.cpp | 4 +++- Source/Core/VideoBackends/Software/SWOGLWindow.h | 3 ++- .../Core/VideoBackends/Software/SWRenderer.cpp | 4 ++-- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 9 +++++---- Source/Core/VideoBackends/Vulkan/Renderer.h | 2 +- Source/Core/VideoCommon/BPStructs.cpp | 3 ++- Source/Core/VideoCommon/RenderBase.cpp | 16 +++++++++------- Source/Core/VideoCommon/RenderBase.h | 4 ++-- 10 files changed, 31 insertions(+), 27 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 82e5772b15..3f5fce3d10 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -608,7 +608,7 @@ 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) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { ResetAPIState(); @@ -624,9 +624,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // activate linear filtering for the buffer copies D3D::SetLinearCopySampler(); auto* xfb_texture = static_cast(texture); - TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); - BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), + BlitScreen(xfb_region, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->GetConfig().width, xfb_texture->GetConfig().height, Gamma); // Reset viewport for drawing text diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 05aaef66c4..46c9787eb5 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1325,7 +1325,7 @@ 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) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { if (g_ogl_config.bSupportsDebug) { @@ -1337,10 +1337,8 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti auto* xfb_texture = static_cast(texture); - TargetRectangle sourceRc = ConvertEFBRectangle(rc); - sourceRc.left = 0; - sourceRc.right = xfb_texture->GetConfig().width; - sourceRc.top = xfb_texture->GetConfig().height; + TargetRectangle sourceRc = xfb_region; + sourceRc.top = xfb_region.GetHeight(); sourceRc.bottom = 0; ResetAPIState(); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index bead74872d..8027d3fb68 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -90,7 +90,7 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) m_text.push_back({text, x, y, color}); } -void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) +void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region) { SW::SWTexture* sw_image = static_cast(image); GLInterface->Update(); // just updates the render window position and the backbuffer size @@ -103,6 +103,8 @@ void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) glActiveTexture(GL_TEXTURE9); glBindTexture(GL_TEXTURE_2D, m_image_texture); + // TODO: Apply xfb_region + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment glPixelStorei(GL_UNPACK_ROW_LENGTH, sw_image->GetConfig().width); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 68fbcc133e..64ee2414bc 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -9,6 +9,7 @@ #include #include "Common/CommonTypes.h" +#include "VideoCommon/VideoCommon.h" class AbstractTexture; @@ -23,7 +24,7 @@ public: void PrintText(const std::string& text, int x, int y, u32 color); // Image to show, will be swapped immediately - void ShowImage(AbstractTexture* image, float aspect); + void ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region); int PeekMessages(); diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 97311d0e1f..3c05068606 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -43,13 +43,13 @@ void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 colo } // Called on the GPU thread -void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) +void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { OSD::DoCallbacks(OSD::CallbackType::OnFrame); DrawDebugText(); - SWOGLWindow::s_instance->ShowImage(texture, 1.0); + SWOGLWindow::s_instance->ShowImage(texture, xfb_region); UpdateActiveConfig(); } diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index af0bfba451..d5d105ff6b 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -481,7 +481,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) BindEFBToStateTracker(); } -void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) { // Pending/batched EFB pokes should be included in the final image. FramebufferManager::GetInstance()->FlushEFBPokes(); @@ -504,7 +504,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti // Draw to the screen if we have a swap chain. if (m_swap_chain) { - DrawScreen(xfb_texture); + DrawScreen(xfb_texture, xfb_region); // 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 @@ -552,7 +552,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ti g_shader_cache->RetrieveAsyncShaders(); } -void Renderer::DrawScreen(VKTexture* xfb_texture) +void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region) { VkResult res; if (!g_command_buffer_mgr->CheckLastPresentFail()) @@ -605,7 +605,8 @@ void Renderer::DrawScreen(VKTexture* xfb_texture) // Draw TargetRectangle source_rc = xfb_texture->GetConfig().GetRect(); - BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), source_rc, xfb_texture->GetRawTexIdentifier()); + BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), xfb_region, + xfb_texture->GetRawTexIdentifier()); // Draw OSD Util::SetViewportAndScissor(g_command_buffer_mgr->GetCurrentCommandBuffer(), 0, 0, diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h index a94d44138b..2fbf240122 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.h +++ b/Source/Core/VideoBackends/Vulkan/Renderer.h @@ -86,7 +86,7 @@ private: void DestroyShaders(); // Draw the frame, as well as the OSD to the swap chain. - void DrawScreen(VKTexture* xfb_texture); + void DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region); // Copies/scales an image to the currently-bound framebuffer. void BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_rect, diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 93de3aabe5..5bf53832c3 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -270,7 +270,8 @@ static void BPWritten(const BPCmd& bp) if (g_ActiveConfig.bImmediateXFB) { // below div two to convert from bytes to pixels - it expects width, not stride - g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, false, srcRect, CoreTiming::GetTicks()); + g_renderer->Swap(destAddr, destStride / 2, destStride / 2, height, srcRect, + CoreTiming::GetTicks()); } else { diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index e63282d527..8a5ab459d0 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -651,10 +651,14 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const m_last_xfb_texture = xfb_entry->texture.get(); m_last_xfb_id = xfb_entry->id; m_last_xfb_ticks = ticks; - m_last_xfb_horizontal_scale = horizontal_scale; + + auto xfb_rect = xfb_entry->texture->GetConfig().GetRect(); + xfb_rect.right -= EFBToScaledX(fbStride - fbWidth); + + m_last_xfb_region = xfb_rect; // TODO: merge more generic parts into VideoCommon - g_renderer->SwapImpl(xfb_entry->texture.get(), rc, ticks, xfb_entry->gamma); + g_renderer->SwapImpl(xfb_entry->texture.get(), xfb_rect, ticks, xfb_entry->gamma); m_fps_counter.Update(); update_frame_count = true; @@ -693,7 +697,7 @@ bool Renderer::IsFrameDumping() void Renderer::DoDumpFrame() { - UpdateFrameDumpTexture(m_last_xfb_horizontal_scale); + UpdateFrameDumpTexture(); auto result = m_dump_texture->Map(); if (result.has_value()) @@ -704,7 +708,7 @@ void Renderer::DoDumpFrame() } } -void Renderer::UpdateFrameDumpTexture(float horizontal_scale) +void Renderer::UpdateFrameDumpTexture() { int target_width, target_height; std::tie(target_width, target_height) = CalculateOutputDimensions( @@ -719,9 +723,7 @@ void Renderer::UpdateFrameDumpTexture(float horizontal_scale) config.rendertarget = true; m_dump_texture = g_texture_cache->CreateTexture(config); } - auto source_rect = m_last_xfb_texture->GetConfig().GetRect(); - source_rect.right /= horizontal_scale; - m_dump_texture->CopyRectangleFromTexture(m_last_xfb_texture, source_rect, + m_dump_texture->CopyRectangleFromTexture(m_last_xfb_texture, m_last_xfb_region, EFBRectangle{0, 0, target_width, target_height}); } diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 6698f2f66f..8abfdb9894 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -185,7 +185,7 @@ private: void RunFrameDumps(); void ShutdownFrameDumping(); std::tuple CalculateOutputDimensions(int width, int height); - void UpdateFrameDumpTexture(float horizontal_scale); + void UpdateFrameDumpTexture(); PEControl::PixelFormat m_prev_efb_format = PEControl::INVALID_FMT; unsigned int m_efb_scale = 1; @@ -214,7 +214,7 @@ private: AbstractTexture* m_last_xfb_texture = nullptr; u64 m_last_xfb_id = std::numeric_limits::max(); u64 m_last_xfb_ticks = 0; - float m_last_xfb_horizontal_scale = 0.0f; + EFBRectangle m_last_xfb_region; std::unique_ptr m_dump_texture; From 74610646ce678ed0644617c2de23544b446ea6dd Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 29 Sep 2017 00:32:04 -0500 Subject: [PATCH 25/40] TextureCacheBase: Add XFB specific functions --- Source/Core/VideoCommon/RenderBase.cpp | 2 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 380 +++++++++++++++++++ Source/Core/VideoCommon/TextureCacheBase.h | 52 +++ 3 files changed, 433 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 8a5ab459d0..1aa7918e96 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -643,7 +643,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const { constexpr int force_safe_texture_cache_hash = 0; // Get the current XFB from texture cache - auto* xfb_entry = g_texture_cache->GetTexture(xfbAddr, fbWidth, fbHeight, TextureFormat::XFB, + auto* xfb_entry = g_texture_cache->GetXFBTexture(xfbAddr, fbStride, fbHeight, TextureFormat::XFB, force_safe_texture_cache_hash); if (xfb_entry && xfb_entry->id != m_last_xfb_id) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 0c5574ac4a..4116bc2617 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1103,6 +1103,377 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 wid return entry; } +TextureCacheBase::TCacheEntry* +TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, TextureFormat tex_format, + int texture_cache_safety_color_sample_size) +{ + auto tex_info = ComputeTextureInformation(address, width, height, tex_format, + texture_cache_safety_color_sample_size, false, 0, 0, 0, + TLUTFormat::IA8, 1); + if (!tex_info) + { + return nullptr; + } + + TCacheEntry* entry = GetXFBFromCache(tex_info.value()); + if (entry != nullptr) + { + return entry; + } + + entry = CreateNormalTexture(tex_info.value()); + + // At this point, the XFB wasn't found in cache + // this means the address is most likely not pointing at an xfb copy but instead + // an area of memory. Let's attempt to stitch all entries in this memory space + // together + if (LoadTextureFromOverlappingTextures(entry, tex_info.value())) + { + return entry; + } + + // At this point, the xfb address is truly "bogus" + // it likely is an area of memory defined by the CPU + // so load it from memory + LoadTextureFromMemory(entry, tex_info.value()); + return entry; +} + +std::optional TextureCacheBase::ComputeTextureInformation( + u32 address, u32 width, u32 height, TextureFormat tex_format, + int texture_cache_safety_color_sample_size, bool from_tmem, u32 tmem_address_even, + u32 tmem_address_odd, u32 tlut_address, TLUTFormat tlut_format, u32 levels) +{ + TextureLookupInformation tex_info; + + tex_info.from_tmem = from_tmem; + tex_info.tmem_address_even = tmem_address_even; + tex_info.tmem_address_odd = tmem_address_odd; + + tex_info.address = address; + + if (from_tmem) + tex_info.src_data = &texMem[tex_info.tmem_address_even]; + else + tex_info.src_data = Memory::GetPointer(tex_info.address); + + if (tex_info.src_data == nullptr) + { + ERROR_LOG(VIDEO, "Trying to use an invalid texture address 0x%8x", tex_info.address); + return {}; + } + + tex_info.texture_cache_safety_color_sample_size = texture_cache_safety_color_sample_size; + + // TexelSizeInNibbles(format) * width * height / 16; + tex_info.block_width = TexDecoder_GetBlockWidthInTexels(tex_format); + tex_info.block_height = TexDecoder_GetBlockHeightInTexels(tex_format); + + tex_info.bytes_per_block = + (tex_info.block_width * tex_info.block_height * TexDecoder_GetTexelSizeInNibbles(tex_format)) + / 2; + + tex_info.expanded_width = Common::AlignUp(width, tex_info.block_width); + tex_info.expanded_height = Common::AlignUp(height, tex_info.block_height); + + tex_info.total_bytes = TexDecoder_GetTextureSizeInBytes(tex_info.expanded_width, + tex_info.expanded_height, tex_format); + + tex_info.native_width = width; + tex_info.native_height = height; + tex_info.native_levels = levels; + + // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in + // the mipmap chain + // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we + // limit the mipmap count to 6 there + tex_info.computed_levels = std::min( + IntLog2(std::max(tex_info.native_width, tex_info.native_height)) + 1, tex_info.native_levels); + + tex_info.full_format = TextureAndTLUTFormat(tex_format, tlut_format); + tex_info.tlut_address = tlut_address; + + // TODO: This doesn't hash GB tiles for preloaded RGBA8 textures (instead, it's hashing more data + // from the low tmem bank than it should) + tex_info.base_hash = GetHash64(tex_info.src_data, tex_info.total_bytes, + tex_info.texture_cache_safety_color_sample_size); + + tex_info.is_palette_texture = IsColorIndexed(tex_format); + + if (tex_info.is_palette_texture) + { + tex_info.palette_size = TexDecoder_GetPaletteSize(tex_format); + tex_info.full_hash = + tex_info.base_hash ^ GetHash64(&texMem[tex_info.tlut_address], tex_info.palette_size, + tex_info.texture_cache_safety_color_sample_size); + } + else + { + tex_info.full_hash = tex_info.base_hash; + } + + if (g_ActiveConfig.bDumpTextures) + { + tex_info.dump_base_name = HiresTexture::GenBaseName( + tex_info.src_data, tex_info.total_bytes, &texMem[tex_info.tlut_address], + tex_info.palette_size, tex_info.native_width, tex_info.native_height, + tex_info.full_format.texfmt, tex_info.use_mipmaps, true); + } + + return tex_info; +} + +TextureCacheBase::TCacheEntry* +TextureCacheBase::GetXFBFromCache(const TextureLookupInformation& tex_info) +{ + auto iter_range = textures_by_address.equal_range(tex_info.address); + TexAddrCache::iterator iter = iter_range.first; + + while (iter != iter_range.second) + { + TCacheEntry* entry = iter->second; + + if ((entry->is_xfb_copy || entry->format.texfmt == TextureFormat::XFB) && + entry->native_width == tex_info.native_width && + static_cast(entry->native_height * entry->y_scale) == + tex_info.native_height && + entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures) + { + if (tex_info.base_hash == entry->hash && !entry->reference_changed) + { + return entry; + } + else + { + // At this point, we either have an xfb copy that has changed its hash + // or an xfb created by stitching or from memory that has been changed + // we are safe to invalidate this + iter = InvalidateTexture(iter); + continue; + } + } + + ++iter; + } + + return nullptr; +} + +bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_update, + const TextureLookupInformation& tex_info) +{ + bool updated_entry = false; + + u32 numBlocksX = entry_to_update->native_width / tex_info.block_width; + + auto iter = FindOverlappingTextures(entry_to_update->addr, entry_to_update->size_in_bytes); + while (iter.first != iter.second) + { + TCacheEntry* entry = iter.first->second; + if (entry != entry_to_update && entry->IsCopy() && !entry->tmem_only && + entry->references.count(entry_to_update) == 0 && + entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes) && + entry->memory_stride == entry_to_update->memory_stride) + { + if (entry->hash == entry->CalculateHash()) + { + if (tex_info.is_palette_texture) + { + TCacheEntry* decoded_entry = + ApplyPaletteToEntry(entry, nullptr, tex_info.full_format.tlutfmt); + if (decoded_entry) + { + // Link the efb copy with the partially updated texture, so we won't apply this partial + // update again + entry->CreateReference(entry_to_update); + // Mark the texture update as used, as if it was loaded directly + entry->frameCount = FRAMECOUNT_INVALID; + entry = decoded_entry; + } + else + { + ++iter.first; + continue; + } + } + + s32 src_x, src_y, dst_x, dst_y; + + // Note for understanding the math: + // Normal textures can't be strided, so the 2 missing cases with src_x > 0 don't exist + if (entry->addr >= entry_to_update->addr) + { + s32 block_offset = (entry->addr - entry_to_update->addr) / tex_info.bytes_per_block; + s32 block_x = block_offset % numBlocksX; + s32 block_y = block_offset / numBlocksX; + src_x = 0; + src_y = 0; + dst_x = block_x * tex_info.block_width; + dst_y = block_y * tex_info.block_height; + } + else + { + s32 block_offset = (entry_to_update->addr - entry->addr) / tex_info.bytes_per_block; + s32 block_x = block_offset % numBlocksX; + s32 block_y = block_offset / numBlocksX; + src_x = block_x * tex_info.block_width; + src_y = block_y * tex_info.block_height; + dst_x = 0; + dst_y = 0; + } + + u32 copy_width = + std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x); + u32 copy_height = + std::min((entry->native_height * entry->y_scale) - src_y, + (entry_to_update->native_height * entry_to_update->y_scale) - dst_y); + + // If one of the textures is scaled, scale both with the current efb scaling factor + if (entry_to_update->native_width != entry_to_update->GetWidth() || + (entry_to_update->native_height * entry_to_update->y_scale) != entry_to_update->GetHeight() || + entry->native_width != entry->GetWidth() || (entry->native_height * entry->y_scale) != entry->GetHeight()) + { + ScaleTextureCacheEntryTo( + entry_to_update, g_renderer->EFBToScaledX(entry_to_update->native_width), + g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); + ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width), + g_renderer->EFBToScaledY(entry->native_height * entry->y_scale)); + + src_x = g_renderer->EFBToScaledX(src_x); + src_y = g_renderer->EFBToScaledY(src_y); + dst_x = g_renderer->EFBToScaledX(dst_x); + dst_y = g_renderer->EFBToScaledY(dst_y); + copy_width = g_renderer->EFBToScaledX(copy_width); + copy_height = g_renderer->EFBToScaledY(copy_height); + } + + MathUtil::Rectangle srcrect, dstrect; + srcrect.left = src_x; + srcrect.top = src_y; + srcrect.right = (src_x + copy_width); + srcrect.bottom = (src_y + copy_height); + + dstrect.left = dst_x; + dstrect.top = dst_y; + dstrect.right = (dst_x + copy_width); + dstrect.bottom = (dst_y + copy_height); + + entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, dstrect); + + updated_entry = true; + + if (tex_info.is_palette_texture) + { + // Remove the temporary converted texture, it won't be used anywhere else + // TODO: It would be nice to convert and copy in one step, but this code path isn't common + InvalidateTexture(GetTexCacheIter(entry)); + } + else + { + // Link the two textures together, so we won't apply this partial update again + entry->CreateReference(entry_to_update); + // Mark the texture update as used, as if it was loaded directly + entry->frameCount = FRAMECOUNT_INVALID; + } + } + else + { + // If the hash does not match, this EFB copy will not be used for anything, so remove it + iter.first = InvalidateTexture(iter.first); + continue; + } + } + ++iter.first; + } + + return updated_entry; +} + +TextureCacheBase::TCacheEntry* TextureCacheBase::CreateNormalTexture(const TextureLookupInformation& tex_info) +{ + // create the entry/texture + TextureConfig config; + config.width = tex_info.native_width; + config.height = tex_info.native_height; + config.levels = tex_info.computed_levels; + config.format = AbstractTextureFormat::RGBA8; + config.rendertarget = true; + + TCacheEntry* entry = AllocateCacheEntry(config); + GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); + + if (!entry) + return nullptr; + + textures_by_address.emplace(tex_info.address, entry); + if (tex_info.texture_cache_safety_color_sample_size == 0 || + std::max(tex_info.total_bytes, tex_info.palette_size) <= (u32)tex_info.texture_cache_safety_color_sample_size * 8) + { + entry->textures_by_hash_iter = textures_by_hash.emplace(tex_info.full_hash, entry); + } + + entry->SetGeneralParameters(tex_info.address, tex_info.total_bytes, tex_info.full_format, false); + entry->SetDimensions(tex_info.native_width, tex_info.native_height, tex_info.computed_levels); + entry->SetHashes(tex_info.base_hash, tex_info.full_hash); + entry->is_custom_tex = false; + entry->memory_stride = entry->BytesPerRow(); + entry->SetNotCopy(); + + INCSTAT(stats.numTexturesUploaded); + SETSTAT(stats.numTexturesAlive, textures_by_address.size()); + + if (g_ActiveConfig.bDumpTextures) + { + DumpTexture(entry, tex_info.dump_base_name, 0); + } + + return entry; +} + +void TextureCacheBase::LoadTextureFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info) +{ + // We can decode on the GPU if it is a supported format and the flag is enabled. + // Currently we don't decode RGBA8 textures from Tmem, as that would require copying from both + // banks, and if we're doing an copy we may as well just do the whole thing on the CPU, since + // there's no conversion between formats. In the future this could be extended with a separate + // shader, however. + bool decode_on_gpu = g_ActiveConfig.UseGPUTextureDecoding() && + g_texture_cache->SupportsGPUTextureDecode(tex_info.full_format.texfmt, + tex_info.full_format.tlutfmt) && + !(tex_info.from_tmem && tex_info.full_format.texfmt == TextureFormat::RGBA8); + + LoadTextureLevelZeroFromMemory(entry_to_update, tex_info, decode_on_gpu); +} + +void TextureCacheBase::LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info, bool decode_on_gpu) +{ + const u8* tlut = &texMem[tex_info.tlut_address]; + + if (decode_on_gpu) + { + u32 row_stride = tex_info.bytes_per_block * (tex_info.expanded_width / tex_info.block_width); + g_texture_cache->DecodeTextureOnGPU(entry_to_update, 0, tex_info.src_data, tex_info.total_bytes, tex_info.full_format.texfmt, tex_info.native_width, + tex_info.native_height, tex_info.expanded_width, tex_info.expanded_height, row_stride, tlut, + tex_info.full_format.tlutfmt); + } + else + { + size_t decoded_texture_size = tex_info.expanded_width * sizeof(u32) * tex_info.expanded_height; + CheckTempSize(decoded_texture_size); + if (!(tex_info.full_format.texfmt == TextureFormat::RGBA8 && tex_info.from_tmem)) + { + TexDecoder_Decode(temp, tex_info.src_data, tex_info.expanded_width, tex_info.expanded_height, tex_info.full_format.texfmt, tlut, tex_info.full_format.tlutfmt); + } + else + { + u8* src_data_gb = &texMem[tex_info.tmem_address_odd]; + TexDecoder_DecodeRGBA8FromTmem(temp, tex_info.src_data, src_data_gb, tex_info.expanded_width, tex_info.expanded_height); + } + + entry_to_update->texture->Load(0, tex_info.native_width, tex_info.native_height, tex_info.expanded_width, temp, decoded_texture_size); + } +} + void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, @@ -1518,6 +1889,15 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF while (iter.first != iter.second) { TCacheEntry* entry = iter.first->second; + + if (entry->addr == dstAddr && entry->is_xfb_copy) + { + for (auto& reference : entry->references) + { + reference->reference_changed = true; + } + } + if (entry->OverlapsMemoryRange(dstAddr, covered_range)) { u32 overlap_range = std::min(entry->addr + entry->size_in_bytes, dstAddr + covered_range) - diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index a6aea52e9e..c248f75dd9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -64,6 +66,44 @@ struct EFBCopyParams float y_scale; }; +struct TextureLookupInformation +{ + u32 address; + + u32 block_width; + u32 block_height; + u32 bytes_per_block; + + u32 expanded_width; + u32 expanded_height; + u32 native_width; + u32 native_height; + u32 total_bytes; + u32 native_levels = 1; + u32 computed_levels; + + u64 base_hash; + u64 full_hash; + + TextureAndTLUTFormat full_format; + u32 tlut_address = 0; + + bool is_palette_texture = false; + u32 palette_size = 0; + + bool use_mipmaps = false; + + bool from_tmem = false; + u32 tmem_address_even = 0; + u32 tmem_address_odd = 0; + + int texture_cache_safety_color_sample_size = 0; // Default to safe hashing + + u8* src_data; + + std::string dump_base_name; +}; + class TextureCacheBase { private: @@ -92,6 +132,8 @@ public: float gamma = 1.0f; u64 id; + bool reference_changed = false; // used by xfb to determine when a reference xfb changed + unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view unsigned int native_levels; @@ -190,6 +232,16 @@ public: TLUTFormat tlutfmt = TLUTFormat::IA8, bool use_mipmaps = false, u32 tex_levels = 1, bool from_tmem = false, u32 tmem_address_even = 0, u32 tmem_address_odd = 0); + + TCacheEntry* GetXFBTexture(u32 address, u32 width, u32 height, TextureFormat texformat, + int textureCacheSafetyColorSampleSize); + std::optional ComputeTextureInformation(u32 address, u32 width, u32 height, TextureFormat texformat, + int textureCacheSafetyColorSampleSize, bool from_tmem, u32 tmem_address_even, u32 tmem_address_odd, u32 tlutaddr, TLUTFormat tlutfmt, u32 levels); + TCacheEntry* GetXFBFromCache(const TextureLookupInformation& tex_info); + bool LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info); + TCacheEntry* CreateNormalTexture(const TextureLookupInformation& tex_info); + void LoadTextureFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info); + void LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info, bool decode_on_gpu); virtual void BindTextures(); void CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, From 2c87a53f113be4e407b83eed5078e3d570001cff Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 29 Sep 2017 22:46:48 -0500 Subject: [PATCH 26/40] TextureCacheBase: make sure stitching rectangle bounds don't exceed the texture size they are meant to represent --- Source/Core/VideoCommon/TextureCacheBase.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 4116bc2617..2310631b94 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1353,11 +1353,31 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_ srcrect.right = (src_x + copy_width); srcrect.bottom = (src_y + copy_height); + if (static_cast(entry->GetWidth()) == srcrect.GetWidth()) + { + srcrect.right -= 1; + } + + if (static_cast(entry->GetHeight()) == srcrect.GetHeight()) + { + srcrect.bottom -= 1; + } + dstrect.left = dst_x; dstrect.top = dst_y; dstrect.right = (dst_x + copy_width); dstrect.bottom = (dst_y + copy_height); + if (static_cast(entry_to_update->GetWidth()) == dstrect.GetWidth()) + { + dstrect.right -= 1; + } + + if (static_cast(entry_to_update->GetHeight()) == dstrect.GetHeight()) + { + dstrect.bottom -= 1; + } + entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, dstrect); updated_entry = true; From f8c2806830804ec322ecebb3f9ada4f732c6b738 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 30 Sep 2017 16:29:14 -0500 Subject: [PATCH 27/40] Game Inis: Set Zelda Collector's Edition to have Immediate Mode set to false to avoid graphical errors in NES games. --- Data/Sys/GameSettings/PZL.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/Data/Sys/GameSettings/PZL.ini b/Data/Sys/GameSettings/PZL.ini index 4746515384..1b68d6e91d 100644 --- a/Data/Sys/GameSettings/PZL.ini +++ b/Data/Sys/GameSettings/PZL.ini @@ -21,6 +21,7 @@ EmulationIssues = Hold B while booting the game to enable Progressive Scan for N [Video_Hacks] EFBToTextureEnable = False +ImmediateXFBEnable = False [Video_Settings] SafeTextureCacheColorSamples = 0 From 7248dd47d5b48564a1ed049bdf392146dca2d72a Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 1 Oct 2017 11:19:29 -0500 Subject: [PATCH 28/40] Hybrid XFB: Fix lint errors --- Source/Core/VideoBackends/D3D/Render.cpp | 3 +- Source/Core/VideoBackends/OGL/Render.cpp | 3 +- .../VideoBackends/Software/SWRenderer.cpp | 3 +- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 3 +- Source/Core/VideoCommon/RenderBase.cpp | 4 +- Source/Core/VideoCommon/RenderBase.h | 6 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 72 +++++++++++-------- Source/Core/VideoCommon/TextureCacheBase.h | 22 +++--- 8 files changed, 69 insertions(+), 47 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 3f5fce3d10..11bbea61c2 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -608,7 +608,8 @@ 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& xfb_region, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, + float Gamma) { ResetAPIState(); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 46c9787eb5..2125102fe0 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1325,7 +1325,8 @@ 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& xfb_region, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, + float Gamma) { if (g_ogl_config.bSupportsDebug) { diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 3c05068606..4f1fafd989 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -43,7 +43,8 @@ void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 colo } // Called on the GPU thread -void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) +void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, + float Gamma) { OSD::DoCallbacks(OSD::CallbackType::OnFrame); diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index d5d105ff6b..d72f2929c3 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -481,7 +481,8 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) BindEFBToStateTracker(); } -void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks, + float Gamma) { // Pending/batched EFB pokes should be included in the final image. FramebufferManager::GetInstance()->FlushEFBPokes(); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 1aa7918e96..0db81bb885 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -643,8 +643,8 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const { constexpr int force_safe_texture_cache_hash = 0; // Get the current XFB from texture cache - auto* xfb_entry = g_texture_cache->GetXFBTexture(xfbAddr, fbStride, fbHeight, TextureFormat::XFB, - force_safe_texture_cache_hash); + auto* xfb_entry = g_texture_cache->GetXFBTexture( + xfbAddr, fbStride, fbHeight, TextureFormat::XFB, force_safe_texture_cache_hash); if (xfb_entry && xfb_entry->id != m_last_xfb_id) { diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 8abfdb9894..b622372b90 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -131,8 +131,10 @@ public: virtual void BBoxWrite(int index, u16 value) = 0; // Finish up the current frame, print some stats - void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks); - virtual void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma = 1.0f) = 0; + void Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, + u64 ticks); + virtual void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, + float Gamma = 1.0f) = 0; PEControl::PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; } void StorePixelFormat(PEControl::PixelFormat new_format) { m_prev_efb_format = new_format; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 2310631b94..32d1e8d7dc 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -650,12 +650,11 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) return entry; } -TextureCacheBase::TCacheEntry* TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, - const TextureFormat texformat, - const int textureCacheSafetyColorSampleSize, u32 tlutaddr, - TLUTFormat tlutfmt, bool use_mipmaps, - u32 tex_levels, bool from_tmem, u32 tmem_address_even, - u32 tmem_address_odd) +TextureCacheBase::TCacheEntry* +TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFormat texformat, + const int textureCacheSafetyColorSampleSize, u32 tlutaddr, + TLUTFormat tlutfmt, bool use_mipmaps, u32 tex_levels, bool from_tmem, + u32 tmem_address_even, u32 tmem_address_odd) { // TexelSizeInNibbles(format) * width * height / 16; const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat); @@ -1169,16 +1168,16 @@ std::optional TextureCacheBase::ComputeTextureInformat tex_info.block_width = TexDecoder_GetBlockWidthInTexels(tex_format); tex_info.block_height = TexDecoder_GetBlockHeightInTexels(tex_format); - tex_info.bytes_per_block = - (tex_info.block_width * tex_info.block_height * TexDecoder_GetTexelSizeInNibbles(tex_format)) - / 2; + tex_info.bytes_per_block = (tex_info.block_width * tex_info.block_height * + TexDecoder_GetTexelSizeInNibbles(tex_format)) / + 2; tex_info.expanded_width = Common::AlignUp(width, tex_info.block_width); tex_info.expanded_height = Common::AlignUp(height, tex_info.block_height); - + tex_info.total_bytes = TexDecoder_GetTextureSizeInBytes(tex_info.expanded_width, tex_info.expanded_height, tex_format); - + tex_info.native_width = width; tex_info.native_height = height; tex_info.native_levels = levels; @@ -1204,8 +1203,8 @@ std::optional TextureCacheBase::ComputeTextureInformat { tex_info.palette_size = TexDecoder_GetPaletteSize(tex_format); tex_info.full_hash = - tex_info.base_hash ^ GetHash64(&texMem[tex_info.tlut_address], tex_info.palette_size, - tex_info.texture_cache_safety_color_sample_size); + tex_info.base_hash ^ GetHash64(&texMem[tex_info.tlut_address], tex_info.palette_size, + tex_info.texture_cache_safety_color_sample_size); } else { @@ -1330,14 +1329,16 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_ // If one of the textures is scaled, scale both with the current efb scaling factor if (entry_to_update->native_width != entry_to_update->GetWidth() || - (entry_to_update->native_height * entry_to_update->y_scale) != entry_to_update->GetHeight() || - entry->native_width != entry->GetWidth() || (entry->native_height * entry->y_scale) != entry->GetHeight()) + (entry_to_update->native_height * entry_to_update->y_scale) != + entry_to_update->GetHeight() || + entry->native_width != entry->GetWidth() || + (entry->native_height * entry->y_scale) != entry->GetHeight()) { ScaleTextureCacheEntryTo( - entry_to_update, g_renderer->EFBToScaledX(entry_to_update->native_width), - g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); + entry_to_update, g_renderer->EFBToScaledX(entry_to_update->native_width), + g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width), - g_renderer->EFBToScaledY(entry->native_height * entry->y_scale)); + g_renderer->EFBToScaledY(entry->native_height * entry->y_scale)); src_x = g_renderer->EFBToScaledX(src_x); src_y = g_renderer->EFBToScaledY(src_y); @@ -1409,7 +1410,8 @@ bool TextureCacheBase::LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_ return updated_entry; } -TextureCacheBase::TCacheEntry* TextureCacheBase::CreateNormalTexture(const TextureLookupInformation& tex_info) +TextureCacheBase::TCacheEntry* +TextureCacheBase::CreateNormalTexture(const TextureLookupInformation& tex_info) { // create the entry/texture TextureConfig config; @@ -1427,7 +1429,8 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::CreateNormalTexture(const Textu textures_by_address.emplace(tex_info.address, entry); if (tex_info.texture_cache_safety_color_sample_size == 0 || - std::max(tex_info.total_bytes, tex_info.palette_size) <= (u32)tex_info.texture_cache_safety_color_sample_size * 8) + std::max(tex_info.total_bytes, tex_info.palette_size) <= + (u32)tex_info.texture_cache_safety_color_sample_size * 8) { entry->textures_by_hash_iter = textures_by_hash.emplace(tex_info.full_hash, entry); } @@ -1450,7 +1453,8 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::CreateNormalTexture(const Textu return entry; } -void TextureCacheBase::LoadTextureFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info) +void TextureCacheBase::LoadTextureFromMemory(TCacheEntry* entry_to_update, + const TextureLookupInformation& tex_info) { // We can decode on the GPU if it is a supported format and the flag is enabled. // Currently we don't decode RGBA8 textures from Tmem, as that would require copying from both @@ -1458,23 +1462,26 @@ void TextureCacheBase::LoadTextureFromMemory(TCacheEntry* entry_to_update, const // there's no conversion between formats. In the future this could be extended with a separate // shader, however. bool decode_on_gpu = g_ActiveConfig.UseGPUTextureDecoding() && - g_texture_cache->SupportsGPUTextureDecode(tex_info.full_format.texfmt, - tex_info.full_format.tlutfmt) && - !(tex_info.from_tmem && tex_info.full_format.texfmt == TextureFormat::RGBA8); + g_texture_cache->SupportsGPUTextureDecode(tex_info.full_format.texfmt, + tex_info.full_format.tlutfmt) && + !(tex_info.from_tmem && tex_info.full_format.texfmt == TextureFormat::RGBA8); LoadTextureLevelZeroFromMemory(entry_to_update, tex_info, decode_on_gpu); } -void TextureCacheBase::LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info, bool decode_on_gpu) +void TextureCacheBase::LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_update, + const TextureLookupInformation& tex_info, + bool decode_on_gpu) { const u8* tlut = &texMem[tex_info.tlut_address]; if (decode_on_gpu) { u32 row_stride = tex_info.bytes_per_block * (tex_info.expanded_width / tex_info.block_width); - g_texture_cache->DecodeTextureOnGPU(entry_to_update, 0, tex_info.src_data, tex_info.total_bytes, tex_info.full_format.texfmt, tex_info.native_width, - tex_info.native_height, tex_info.expanded_width, tex_info.expanded_height, row_stride, tlut, - tex_info.full_format.tlutfmt); + g_texture_cache->DecodeTextureOnGPU( + entry_to_update, 0, tex_info.src_data, tex_info.total_bytes, tex_info.full_format.texfmt, + tex_info.native_width, tex_info.native_height, tex_info.expanded_width, + tex_info.expanded_height, row_stride, tlut, tex_info.full_format.tlutfmt); } else { @@ -1482,15 +1489,18 @@ void TextureCacheBase::LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_upda CheckTempSize(decoded_texture_size); if (!(tex_info.full_format.texfmt == TextureFormat::RGBA8 && tex_info.from_tmem)) { - TexDecoder_Decode(temp, tex_info.src_data, tex_info.expanded_width, tex_info.expanded_height, tex_info.full_format.texfmt, tlut, tex_info.full_format.tlutfmt); + TexDecoder_Decode(temp, tex_info.src_data, tex_info.expanded_width, tex_info.expanded_height, + tex_info.full_format.texfmt, tlut, tex_info.full_format.tlutfmt); } else { u8* src_data_gb = &texMem[tex_info.tmem_address_odd]; - TexDecoder_DecodeRGBA8FromTmem(temp, tex_info.src_data, src_data_gb, tex_info.expanded_width, tex_info.expanded_height); + TexDecoder_DecodeRGBA8FromTmem(temp, tex_info.src_data, src_data_gb, tex_info.expanded_width, + tex_info.expanded_height); } - entry_to_update->texture->Load(0, tex_info.native_width, tex_info.native_height, tex_info.expanded_width, temp, decoded_texture_size); + entry_to_update->texture->Load(0, tex_info.native_width, tex_info.native_height, + tex_info.expanded_width, temp, decoded_texture_size); } } diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index c248f75dd9..696c6ec888 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -97,7 +97,7 @@ struct TextureLookupInformation u32 tmem_address_even = 0; u32 tmem_address_odd = 0; - int texture_cache_safety_color_sample_size = 0; // Default to safe hashing + int texture_cache_safety_color_sample_size = 0; // Default to safe hashing u8* src_data; @@ -132,7 +132,7 @@ public: float gamma = 1.0f; u64 id; - bool reference_changed = false; // used by xfb to determine when a reference xfb changed + bool reference_changed = false; // used by xfb to determine when a reference xfb changed unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view @@ -234,14 +234,20 @@ public: u32 tmem_address_odd = 0); TCacheEntry* GetXFBTexture(u32 address, u32 width, u32 height, TextureFormat texformat, - int textureCacheSafetyColorSampleSize); - std::optional ComputeTextureInformation(u32 address, u32 width, u32 height, TextureFormat texformat, - int textureCacheSafetyColorSampleSize, bool from_tmem, u32 tmem_address_even, u32 tmem_address_odd, u32 tlutaddr, TLUTFormat tlutfmt, u32 levels); + int textureCacheSafetyColorSampleSize); + std::optional + ComputeTextureInformation(u32 address, u32 width, u32 height, TextureFormat texformat, + int textureCacheSafetyColorSampleSize, bool from_tmem, + u32 tmem_address_even, u32 tmem_address_odd, u32 tlutaddr, + TLUTFormat tlutfmt, u32 levels); TCacheEntry* GetXFBFromCache(const TextureLookupInformation& tex_info); - bool LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info); + bool LoadTextureFromOverlappingTextures(TCacheEntry* entry_to_update, + const TextureLookupInformation& tex_info); TCacheEntry* CreateNormalTexture(const TextureLookupInformation& tex_info); - void LoadTextureFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info); - void LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_update, const TextureLookupInformation& tex_info, bool decode_on_gpu); + void LoadTextureFromMemory(TCacheEntry* entry_to_update, + const TextureLookupInformation& tex_info); + void LoadTextureLevelZeroFromMemory(TCacheEntry* entry_to_update, + const TextureLookupInformation& tex_info, bool decode_on_gpu); virtual void BindTextures(); void CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 dstStride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, From 0f7f4ccaf9dd054b40691b82eedd2c61dc61d25a Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 2 Oct 2017 00:21:10 -0500 Subject: [PATCH 29/40] Software Backend: allow screenshots/video to be taken with valid data --- Source/Core/VideoBackends/Software/SWTexture.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/Software/SWTexture.cpp b/Source/Core/VideoBackends/Software/SWTexture.cpp index b42f3d4e21..66e76f09a5 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.cpp +++ b/Source/Core/VideoBackends/Software/SWTexture.cpp @@ -10,8 +10,21 @@ namespace SW { +namespace +{ +#pragma pack(push, 1) +struct Pixel +{ + u8 r; + u8 g; + u8 b; + u8 a; +}; +#pragma pack(pop) +} SWTexture::SWTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config) { + m_data.resize(tex_config.width * tex_config.height * 4); } void SWTexture::Bind(unsigned int stage) @@ -31,7 +44,8 @@ void SWTexture::CopyRectangleFromTexture(const AbstractTexture* source, } else { - copy_region(software_source_texture->GetData(), srcrect, GetData(), dstrect); + copy_region(reinterpret_cast(software_source_texture->GetData()), srcrect, + reinterpret_cast(GetData()), dstrect); } } From 1a1c3560ceb9c6d1db7b460e843998d504871bb1 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 2 Oct 2017 00:33:47 -0500 Subject: [PATCH 30/40] Software Backend: Rename 'copy_region' to 'CopyRegion' --- Source/Core/VideoBackends/Software/CopyRegion.h | 4 ++-- Source/Core/VideoBackends/Software/EfbInterface.cpp | 6 +++--- Source/Core/VideoBackends/Software/SWTexture.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoBackends/Software/CopyRegion.h b/Source/Core/VideoBackends/Software/CopyRegion.h index 987ec77951..fd695b8d3a 100644 --- a/Source/Core/VideoBackends/Software/CopyRegion.h +++ b/Source/Core/VideoBackends/Software/CopyRegion.h @@ -9,8 +9,8 @@ namespace SW // Modified from // http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/ template -void copy_region(const T* const source, const MathUtil::Rectangle& srcrect, T* destination, - const MathUtil::Rectangle& dstrect) +void CopyRegion(const T* const source, const MathUtil::Rectangle& srcrect, T* destination, + const MathUtil::Rectangle& dstrect) { double x_ratio = srcrect.GetWidth() / static_cast(dstrect.GetWidth()); double y_ratio = srcrect.GetHeight() / static_cast(dstrect.GetHeight()); diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index e667a7e584..55462ce33f 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -556,9 +556,9 @@ void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& } // Apply y scaling and copy to the xfb memory location - SW::copy_region(source.data(), source_rect, xfb_in_ram, - EFBRectangle{source_rect.left, source_rect.top, source_rect.right, - static_cast(static_cast(source_rect.bottom) * y_scale)}); + SW::CopyRegion(source.data(), source_rect, xfb_in_ram, + EFBRectangle{source_rect.left, source_rect.top, source_rect.right, + static_cast(static_cast(source_rect.bottom) * y_scale)}); } bool ZCompare(u16 x, u16 y, u32 z) diff --git a/Source/Core/VideoBackends/Software/SWTexture.cpp b/Source/Core/VideoBackends/Software/SWTexture.cpp index 66e76f09a5..2ca31343f4 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.cpp +++ b/Source/Core/VideoBackends/Software/SWTexture.cpp @@ -44,8 +44,8 @@ void SWTexture::CopyRectangleFromTexture(const AbstractTexture* source, } else { - copy_region(reinterpret_cast(software_source_texture->GetData()), srcrect, - reinterpret_cast(GetData()), dstrect); + CopyRegion(reinterpret_cast(software_source_texture->GetData()), srcrect, + reinterpret_cast(GetData()), dstrect); } } From ada37ec6420bfb83e85308eca37edb83419ad0ec Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sun, 8 Oct 2017 15:52:59 -0500 Subject: [PATCH 31/40] TextureCacheBase: Remove vertical scaling from EFB path and have copy checks only check EFBs --- Source/Core/VideoCommon/TextureCacheBase.cpp | 21 +++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 32d1e8d7dc..3637ae7b4f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -376,19 +376,18 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale u32 copy_width = std::min(entry->native_width - src_x, entry_to_update->native_width - dst_x); u32 copy_height = - std::min((entry->native_height * entry->y_scale) - src_y, - (entry_to_update->native_height * entry_to_update->y_scale) - dst_y); + std::min(entry->native_height - src_y, entry_to_update->native_height - dst_y); // If one of the textures is scaled, scale both with the current efb scaling factor if (entry_to_update->native_width != entry_to_update->GetWidth() || entry_to_update->native_height != entry_to_update->GetHeight() || entry->native_width != entry->GetWidth() || entry->native_height != entry->GetHeight()) { - ScaleTextureCacheEntryTo( - entry_to_update, g_renderer->EFBToScaledX(entry_to_update->native_width), - g_renderer->EFBToScaledY(entry_to_update->native_height * entry_to_update->y_scale)); + ScaleTextureCacheEntryTo(entry_to_update, + g_renderer->EFBToScaledX(entry_to_update->native_width), + g_renderer->EFBToScaledY(entry_to_update->native_height)); ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width), - g_renderer->EFBToScaledY(entry->native_height * entry->y_scale)); + g_renderer->EFBToScaledY(entry->native_height)); src_x = g_renderer->EFBToScaledX(src_x); src_y = g_renderer->EFBToScaledY(src_y); @@ -794,8 +793,7 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo // Do not load strided EFB copies, they are not meant to be used directly. // Also do not directly load EFB copies, which were partly overwritten. - if (entry->IsCopy() && entry->native_width == nativeW && - static_cast(entry->native_height * entry->y_scale) == nativeH && + if (entry->IsEfbCopy() && entry->native_width == nativeW && entry->native_height == nativeH && entry->memory_stride == entry->BytesPerRow() && !entry->may_have_overlapping_textures) { // EFB copies have slightly different rules as EFB copy formats have different @@ -830,7 +828,7 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo else { // For normal textures, all texture parameters need to match - if (!entry->IsCopy() && entry->hash == full_hash && entry->format == full_format && + if (!entry->IsEfbCopy() && entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { @@ -846,7 +844,7 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo // Example: Sonic the Fighters (inside Sonic Gems Collection) // Skip EFB copies here, so they can be used for partial texture updates if (entry->frameCount != FRAMECOUNT_INVALID && entry->frameCount < temp_frameCount && - !entry->IsCopy() && !(isPaletteTexture && entry->base_hash == base_hash)) + !entry->IsEfbCopy() && !(isPaletteTexture && entry->base_hash == base_hash)) { temp_frameCount = entry->frameCount; oldest_entry = iter; @@ -881,8 +879,7 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo TCacheEntry* entry = hash_iter->second; // All parameters, except the address, need to match here if (entry->format == full_format && entry->native_levels >= tex_levels && - entry->native_width == nativeW && - static_cast(entry->native_height * entry->y_scale) == nativeH) + entry->native_width == nativeW && entry->native_height == nativeH) { entry = DoPartialTextureUpdates(hash_iter->second, &texMem[tlutaddr], tlutfmt); From cf8c007769d400811628a5d9694762afeed0ce1c Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 10 Oct 2017 23:08:28 -0500 Subject: [PATCH 32/40] Game Inis: Turn on immediate mode by default for competitive games (Melee, Brawl, Tatsunoko, Mario Party 5) --- Data/Sys/GameSettings/GAL.ini | 3 +++ Data/Sys/GameSettings/GP5.ini | 2 ++ Data/Sys/GameSettings/RF7.ini | 2 ++ Data/Sys/GameSettings/RSB.ini | 3 +++ Data/Sys/GameSettings/STK.ini | 2 ++ 5 files changed, 12 insertions(+) diff --git a/Data/Sys/GameSettings/GAL.ini b/Data/Sys/GameSettings/GAL.ini index 5937932868..98c71287c8 100644 --- a/Data/Sys/GameSettings/GAL.ini +++ b/Data/Sys/GameSettings/GAL.ini @@ -19,3 +19,6 @@ EmulationIssues = [Video_Stereoscopy] StereoConvergence = 64 + +[Video_Hacks] +ImmediateXFBEnable = True diff --git a/Data/Sys/GameSettings/GP5.ini b/Data/Sys/GameSettings/GP5.ini index 760be43119..1ac01528b6 100644 --- a/Data/Sys/GameSettings/GP5.ini +++ b/Data/Sys/GameSettings/GP5.ini @@ -20,3 +20,5 @@ EmulationIssues = [Video_Hacks] EFBToTextureEnable = False +[Video_Hacks] +ImmediateXFBEnable = True diff --git a/Data/Sys/GameSettings/RF7.ini b/Data/Sys/GameSettings/RF7.ini index c71ae4faff..cc9569746b 100644 --- a/Data/Sys/GameSettings/RF7.ini +++ b/Data/Sys/GameSettings/RF7.ini @@ -17,3 +17,5 @@ EmulationIssues = [ActionReplay] # Add action replay cheats here. +[Video_Hacks] +ImmediateXFBEnable = True diff --git a/Data/Sys/GameSettings/RSB.ini b/Data/Sys/GameSettings/RSB.ini index 783cc4770b..f283352c23 100644 --- a/Data/Sys/GameSettings/RSB.ini +++ b/Data/Sys/GameSettings/RSB.ini @@ -19,3 +19,6 @@ EmulationIssues = Classic mode score report needs real xfb. Nes masterpieces and [Video_Stereoscopy] StereoConvergence = 136 + +[Video_Hacks] +ImmediateXFBEnable = True diff --git a/Data/Sys/GameSettings/STK.ini b/Data/Sys/GameSettings/STK.ini index 5700ecde68..0327877dfa 100644 --- a/Data/Sys/GameSettings/STK.ini +++ b/Data/Sys/GameSettings/STK.ini @@ -17,3 +17,5 @@ EmulationStateId = 5 [ActionReplay] # Add action replay cheats here. +[Video_Hacks] +ImmediateXFBEnable = True From 332af8aa491a320d00b4989e9e4f1a25b59588c3 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 16 Oct 2017 22:41:18 -0500 Subject: [PATCH 33/40] TextureCacheBase: Fix issue in Rogue Squadron 2 where overlapping textures caused a hash change which would cause us to do a lookup from memory that gave us an incorrect result in XFB2Ram --- Source/Core/VideoCommon/TextureCacheBase.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 3637ae7b4f..8d97bd759d 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1938,6 +1938,19 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF } entry->may_have_overlapping_textures = true; + // There are cases (Rogue Squadron 2 / Texas Holdem on Wiiware) where + // for xfb copies the textures overlap which causes the hash of the first copy + // to be different (from when it was originally created). This has no implications + // for XFB2Tex because the underlying memory doesn't change (dummy values) but + // can affect XFB2Ram when we compare the texture cache copy hash with the + // newly computed hash + // By calculating the hash when we receive overlapping xfbs, we are able + // to mitigate this + if (entry->is_xfb_copy && copy_to_ram) + { + entry->hash = entry->CalculateHash(); + } + // Do not load textures by hash, if they were at least partly overwritten by an efb copy. // In this case, comparing the hash is not enough to check, if two textures are identical. if (entry->textures_by_hash_iter != textures_by_hash.end()) From bf7db3f88835d3b69800c9ed5596e31c7ba96346 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 24 Oct 2017 00:44:14 -0500 Subject: [PATCH 34/40] Software Backend: Remove reinterpret_cast which violates the strict aliasing rule --- .../VideoBackends/Software/EfbInterface.cpp | 17 +++++++++++------ .../Core/VideoBackends/Software/EfbInterface.h | 3 +-- .../Core/VideoBackends/Software/SWTexture.cpp | 11 +++++++++-- .../VideoBackends/Software/TextureEncoder.cpp | 3 +-- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index 55462ce33f..a94ac467b8 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -497,8 +497,7 @@ u8* GetPixelPointer(u16 x, u16 y, bool depth) return &efb[GetColorOffset(x, y)]; } -void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, - float y_scale) +void EncodeXFB(u8* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale) { if (!xfb_in_ram) { @@ -555,10 +554,16 @@ void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& src_ptr += memory_stride; } - // Apply y scaling and copy to the xfb memory location - SW::CopyRegion(source.data(), source_rect, xfb_in_ram, - EFBRectangle{source_rect.left, source_rect.top, source_rect.right, - static_cast(static_cast(source_rect.bottom) * y_scale)}); + auto dest_rect = EFBRectangle{source_rect.left, source_rect.top, source_rect.right, + static_cast(static_cast(source_rect.bottom) * y_scale)}; + + const std::size_t destination_size = dest_rect.GetWidth() * dest_rect.GetHeight() * 2; + static std::vector destination; + destination.resize(dest_rect.GetWidth() * dest_rect.GetHeight()); + + SW::CopyRegion(source.data(), source_rect, destination.data(), dest_rect); + + memcpy(xfb_in_ram, destination.data(), destination_size); } bool ZCompare(u16 x, u16 y, u32 z) diff --git a/Source/Core/VideoBackends/Software/EfbInterface.h b/Source/Core/VideoBackends/Software/EfbInterface.h index 24baf37689..a95d6b8aeb 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.h +++ b/Source/Core/VideoBackends/Software/EfbInterface.h @@ -57,8 +57,7 @@ u32 GetDepth(u16 x, u16 y); u8* GetPixelPointer(u16 x, u16 y, bool depth); -void EncodeXFB(yuv422_packed* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, - float y_scale); +void EncodeXFB(u8* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale); extern u32 perf_values[PQ_NUM_MEMBERS]; inline void IncPerfCounterQuadCount(PerfQueryType type) diff --git a/Source/Core/VideoBackends/Software/SWTexture.cpp b/Source/Core/VideoBackends/Software/SWTexture.cpp index 2ca31343f4..aa279b520b 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.cpp +++ b/Source/Core/VideoBackends/Software/SWTexture.cpp @@ -44,8 +44,15 @@ void SWTexture::CopyRectangleFromTexture(const AbstractTexture* source, } else { - CopyRegion(reinterpret_cast(software_source_texture->GetData()), srcrect, - reinterpret_cast(GetData()), dstrect); + std::vector source_pixels; + source_pixels.resize(srcrect.GetHeight() * srcrect.GetWidth() * 4); + memcpy(source_pixels.data(), software_source_texture->GetData(), source_pixels.size()); + + std::vector destination_pixels; + destination_pixels.resize(dstrect.GetHeight() * dstrect.GetWidth() * 4); + + CopyRegion(source_pixels.data(), srcrect, destination_pixels.data(), dstrect); + memcpy(GetData(), destination_pixels.data(), destination_pixels.size()); } } diff --git a/Source/Core/VideoBackends/Software/TextureEncoder.cpp b/Source/Core/VideoBackends/Software/TextureEncoder.cpp index 52a709d04e..4d0997ebf5 100644 --- a/Source/Core/VideoBackends/Software/TextureEncoder.cpp +++ b/Source/Core/VideoBackends/Software/TextureEncoder.cpp @@ -1469,8 +1469,7 @@ void Encode(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_pe { if (params.copy_format == EFBCopyFormat::XFB) { - EfbInterface::EncodeXFB(reinterpret_cast(dst), native_width, - src_rect, params.y_scale); + EfbInterface::EncodeXFB(dst, native_width, src_rect, params.y_scale); } else { From be1853f95671987476fed1cad460e275bbf47713 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 25 Oct 2017 21:04:10 -0500 Subject: [PATCH 35/40] Game inis: Update Wiiware game Midnight Bowling to disable 'Immediate Mode' by default --- Data/Sys/GameSettings/WB8.ini | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Data/Sys/GameSettings/WB8.ini b/Data/Sys/GameSettings/WB8.ini index 5524348a3b..0461fcc431 100644 --- a/Data/Sys/GameSettings/WB8.ini +++ b/Data/Sys/GameSettings/WB8.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Requires Virtual XFB to prevent flickering. +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -17,6 +17,5 @@ EmulationIssues = Requires Virtual XFB to prevent flickering. [ActionReplay] # Add action replay cheats here. -[Video_Settings] -UseXFB = True -UseRealXFB = False +[Video_Hacks] +ImmediateXFBEnable = False From 8678e8ddd34e5d67ca08f2d6ec9a9e9aa61cf996 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 27 Oct 2017 13:58:42 -0500 Subject: [PATCH 36/40] Texture Cache Base: Optimization to allow stitched or memory xfb textures to be looked up from cache directly if they were defined previously and their hash hasn't changed --- Source/Core/VideoCommon/TextureCacheBase.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 8d97bd759d..46e48673d0 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1119,6 +1119,11 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, TextureForma entry = CreateNormalTexture(tex_info.value()); + // XFBs created for the purpose of being a container for textures from memory + // or as a container for overlapping textures, never need to be combined + // with other textures + entry->may_have_overlapping_textures = false; + // At this point, the XFB wasn't found in cache // this means the address is most likely not pointing at an xfb copy but instead // an area of memory. Let's attempt to stitch all entries in this memory space From 61541ab243552c755004e069ef392e68741966c8 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 1 Nov 2017 22:05:34 -0500 Subject: [PATCH 37/40] Enhance xfb dumping to distinguish between the xfbs created from memory and the xfbs created from overlapping copies --- Source/Core/VideoCommon/TextureCacheBase.cpp | 45 +++++++++++--------- Source/Core/VideoCommon/TextureCacheBase.h | 2 - 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 46e48673d0..ee43fba30f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1111,7 +1111,9 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, TextureForma return nullptr; } - TCacheEntry* entry = GetXFBFromCache(tex_info.value()); + const TextureLookupInformation tex_info_value = tex_info.value(); + + TCacheEntry* entry = GetXFBFromCache(tex_info_value); if (entry != nullptr) { return entry; @@ -1128,15 +1130,29 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, TextureForma // this means the address is most likely not pointing at an xfb copy but instead // an area of memory. Let's attempt to stitch all entries in this memory space // together - if (LoadTextureFromOverlappingTextures(entry, tex_info.value())) + bool loaded_from_overlapping = LoadTextureFromOverlappingTextures(entry, tex_info_value); + + if (!loaded_from_overlapping) { - return entry; + // At this point, the xfb address is truly "bogus" + // it likely is an area of memory defined by the CPU + // so load it from memory + LoadTextureFromMemory(entry, tex_info_value); + } + + if (g_ActiveConfig.bDumpXFBTarget) + { + // While this isn't really an xfb copy, we can treat it as such + // for dumping purposes + static int xfb_count = 0; + const std::string xfb_type = loaded_from_overlapping ? "combined" : "from_memory"; + entry->texture->Save(StringFromFormat("%sxfb_%s_%i.png", + File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + xfb_type.c_str(), + xfb_count++), + 0); } - // At this point, the xfb address is truly "bogus" - // it likely is an area of memory defined by the CPU - // so load it from memory - LoadTextureFromMemory(entry, tex_info.value()); return entry; } @@ -1213,14 +1229,6 @@ std::optional TextureCacheBase::ComputeTextureInformat tex_info.full_hash = tex_info.base_hash; } - if (g_ActiveConfig.bDumpTextures) - { - tex_info.dump_base_name = HiresTexture::GenBaseName( - tex_info.src_data, tex_info.total_bytes, &texMem[tex_info.tlut_address], - tex_info.palette_size, tex_info.native_width, tex_info.native_height, - tex_info.full_format.texfmt, tex_info.use_mipmaps, true); - } - return tex_info; } @@ -1447,11 +1455,6 @@ TextureCacheBase::CreateNormalTexture(const TextureLookupInformation& tex_info) INCSTAT(stats.numTexturesUploaded); SETSTAT(stats.numTexturesAlive, textures_by_address.size()); - if (g_ActiveConfig.bDumpTextures) - { - DumpTexture(entry, tex_info.dump_base_name, 0); - } - return entry; } @@ -2015,7 +2018,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF if (g_ActiveConfig.bDumpXFBTarget && is_xfb_copy) { static int xfb_count = 0; - entry->texture->Save(StringFromFormat("%sxfb_frame_%i.png", + entry->texture->Save(StringFromFormat("%sxfb_copy_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), xfb_count++), 0); diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 696c6ec888..5eee06c6d8 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -100,8 +100,6 @@ struct TextureLookupInformation int texture_cache_safety_color_sample_size = 0; // Default to safe hashing u8* src_data; - - std::string dump_base_name; }; class TextureCacheBase From 8d1cbeb25e538efffc1053f1385ff39695e36404 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 1 Nov 2017 23:07:24 -0500 Subject: [PATCH 38/40] Hybrid XFB: Fix lint errors --- Source/Core/VideoCommon/TextureCacheBase.cpp | 9 +++++---- Source/Core/VideoCommon/TextureDecoder_x64.cpp | 14 ++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ee43fba30f..042dbd4e8a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -986,12 +986,14 @@ TextureCacheBase::GetTexture(u32 address, u32 width, u32 height, const TextureFo dst_buffer = temp; if (!(texformat == TextureFormat::RGBA8 && from_tmem)) { - TexDecoder_Decode(dst_buffer, src_data, expandedWidth, expandedHeight, texformat, tlut, tlutfmt); + TexDecoder_Decode(dst_buffer, src_data, expandedWidth, expandedHeight, texformat, tlut, + tlutfmt); } else { u8* src_data_gb = &texMem[tmem_address_odd]; - TexDecoder_DecodeRGBA8FromTmem(dst_buffer, src_data, src_data_gb, expandedWidth, expandedHeight); + TexDecoder_DecodeRGBA8FromTmem(dst_buffer, src_data, src_data_gb, expandedWidth, + expandedHeight); } entry->texture->Load(0, width, height, expandedWidth, dst_buffer, decoded_texture_size); @@ -1148,8 +1150,7 @@ TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, TextureForma const std::string xfb_type = loaded_from_overlapping ? "combined" : "from_memory"; entry->texture->Save(StringFromFormat("%sxfb_%s_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - xfb_type.c_str(), - xfb_count++), + xfb_type.c_str(), xfb_count++), 0); } diff --git a/Source/Core/VideoCommon/TextureDecoder_x64.cpp b/Source/Core/VideoCommon/TextureDecoder_x64.cpp index e11a58a8c6..8a55bb5a53 100644 --- a/Source/Core/VideoCommon/TextureDecoder_x64.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_x64.cpp @@ -1494,23 +1494,25 @@ void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, Text for (int x = 0; x < width; x += 2) { size_t offset = static_cast((y * width + x) * 2); - + // We do this one color sample (aka 2 RGB pixles) at a time int Y1 = int(src[offset]) - 16; int U = int(src[offset + 1]) - 128; int Y2 = int(src[offset + 2]) - 16; int V = int(src[offset + 3]) - 128; - + // We do the inverse BT.601 conversion for YCbCr to RGB // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion u8 R1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255)); - u8 G1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); + u8 G1 = + static_cast(MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); u8 B1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255)); - + u8 R2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255)); - u8 G2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); + u8 G2 = + static_cast(MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); u8 B2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255)); - + dst[y * width + x] = 0xff000000 | B1 << 16 | G1 << 8 | R1; dst[y * width + x + 1] = 0xff000000 | B2 << 16 | G2 << 8 | R2; } From dd54617a083ae6136015602a46298020f2f20012 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 4 Nov 2017 12:04:26 -0500 Subject: [PATCH 39/40] TextureCacheBase: Set uninitialized XFB memory to fuchsia color --- Source/Core/VideoCommon/TextureCacheBase.cpp | 48 +++++++++++++++++--- Source/Core/VideoCommon/TextureCacheBase.h | 2 + 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 042dbd4e8a..07b6609282 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1878,14 +1878,21 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF } else { - // Hack: Most games don't actually need the correct texture data in RAM - // and we can just keep a copy in VRAM. We zero the memory so we - // can check it hasn't changed before using our copy in VRAM. - u8* ptr = dst; - for (u32 i = 0; i < num_blocks_y; i++) + if (is_xfb_copy) { - memset(ptr, 0, bytes_per_row); - ptr += dstStride; + UninitializeXFBMemory(dst, dstStride, bytes_per_row, num_blocks_y); + } + else + { + // Hack: Most games don't actually need the correct texture data in RAM + // and we can just keep a copy in VRAM. We zero the memory so we + // can check it hasn't changed before using our copy in VRAM. + u8* ptr = dst; + for (u32 i = 0; i < num_blocks_y; i++) + { + memset(ptr, 0, bytes_per_row); + ptr += dstStride; + } } } @@ -2030,6 +2037,33 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstF } } +void TextureCacheBase::UninitializeXFBMemory(u8* dst, u32 stride, u32 bytes_per_row, + u32 num_blocks_y) +{ + // Originally, we planned on using a 'key color' + // for alpha to address partial xfbs (Mario Strikers / Chicken Little). + // This work was removed since it was unfinished but there + // was still a desire to differentiate between the old and the new approach + // which is why we still set uninitialized xfb memory to fuchsia + // (Y=1,U=254,V=254) instead of dark green (Y=0,U=0,V=0) in YUV + // like is done in the EFB path. + for (u32 i = 0; i < num_blocks_y; i++) + { + for (u32 offset = 0; offset < bytes_per_row; offset++) + { + if (offset % 2) + { + dst[offset] = 254; + } + else + { + dst[offset] = 1; + } + } + dst += stride; + } +} + TextureCacheBase::TCacheEntry* TextureCacheBase::AllocateCacheEntry(const TextureConfig& config) { std::unique_ptr texture = AllocateTexture(config); diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 5eee06c6d8..a9700ad68c 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -323,6 +323,8 @@ private: // Removes and unlinks texture from texture cache and returns it to the pool TexAddrCache::iterator InvalidateTexture(TexAddrCache::iterator t_iter); + void UninitializeXFBMemory(u8* dst, u32 stride, u32 bytes_per_row, u32 num_blocks_y); + TexAddrCache textures_by_address; TexHashCache textures_by_hash; TexPool texture_pool; From 1f1574b7ab032afa7b3a600a071699f2cbea124e Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 6 Nov 2017 22:45:10 -0600 Subject: [PATCH 40/40] Game inis: Update Def Jam: Fight for NY to disable 'Immediate Mode' by default (it has cutscenes) --- Data/Sys/GameSettings/GNWE69.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Data/Sys/GameSettings/GNWE69.ini b/Data/Sys/GameSettings/GNWE69.ini index 70fd9328ef..bc6a90a416 100644 --- a/Data/Sys/GameSettings/GNWE69.ini +++ b/Data/Sys/GameSettings/GNWE69.ini @@ -9,6 +9,9 @@ Patch Region = 0x7e000000 [OnFrame] # Add memory patches to be applied every frame here. +[Video_Hacks] +ImmediateXFBEnable = False + [ActionReplay] # Add action replay cheats here. $Max/Infinite Cash