Merge pull request #9993 from Techjar/late-vi-output
VI: Implement post-scanout XFB output
This commit is contained in:
commit
c79757618d
|
@ -0,0 +1,16 @@
|
|||
# GCHE78, GCHP78 - WWE Crush Hour
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
|
||||
[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]
|
||||
EarlyXFBOutput = False
|
|
@ -143,6 +143,7 @@ const Info<bool> GFX_HACK_DISABLE_COPY_TO_VRAM{{System::GFX, "Hacks", "DisableCo
|
|||
const Info<bool> GFX_HACK_DEFER_EFB_COPIES{{System::GFX, "Hacks", "DeferEFBCopies"}, true};
|
||||
const Info<bool> GFX_HACK_IMMEDIATE_XFB{{System::GFX, "Hacks", "ImmediateXFBEnable"}, false};
|
||||
const Info<bool> GFX_HACK_SKIP_DUPLICATE_XFBS{{System::GFX, "Hacks", "SkipDuplicateXFBs"}, true};
|
||||
const Info<bool> GFX_HACK_EARLY_XFB_OUTPUT{{System::GFX, "Hacks", "EarlyXFBOutput"}, true};
|
||||
const Info<bool> GFX_HACK_COPY_EFB_SCALED{{System::GFX, "Hacks", "EFBScaledCopy"}, true};
|
||||
const Info<bool> GFX_HACK_EFB_EMULATE_FORMAT_CHANGES{
|
||||
{System::GFX, "Hacks", "EFBEmulateFormatChanges"}, false};
|
||||
|
|
|
@ -118,6 +118,7 @@ extern const Info<bool> GFX_HACK_DISABLE_COPY_TO_VRAM;
|
|||
extern const Info<bool> GFX_HACK_DEFER_EFB_COPIES;
|
||||
extern const Info<bool> GFX_HACK_IMMEDIATE_XFB;
|
||||
extern const Info<bool> GFX_HACK_SKIP_DUPLICATE_XFBS;
|
||||
extern const Info<bool> GFX_HACK_EARLY_XFB_OUTPUT;
|
||||
extern const Info<bool> GFX_HACK_COPY_EFB_SCALED;
|
||||
extern const Info<bool> GFX_HACK_EFB_EMULATE_FORMAT_CHANGES;
|
||||
extern const Info<bool> GFX_HACK_VERTEX_ROUDING;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "Common/Config/Config.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
@ -757,7 +758,7 @@ static void LogField(FieldType field, u32 xfb_address)
|
|||
GetTicksPerOddField());
|
||||
}
|
||||
|
||||
static void BeginField(FieldType field, u64 ticks)
|
||||
static void OutputField(FieldType field, u64 ticks)
|
||||
{
|
||||
// Could we fit a second line of data in the stride?
|
||||
// (Datel's Wii FreeLoaders are the only titles known to set WPL to 0)
|
||||
|
@ -811,16 +812,30 @@ static void BeginField(FieldType field, u64 ticks)
|
|||
|
||||
LogField(field, xfbAddr);
|
||||
|
||||
// This assumes the game isn't going to change the VI registers while a
|
||||
// frame is scanning out.
|
||||
// To correctly handle that case we would need to collate all changes
|
||||
// to VI during scanout and delay outputting the frame till then.
|
||||
// Outputting the entire frame using a single set of VI register values isn't accurate, as games
|
||||
// can change the register values during scanout. To correctly emulate the scanout process, we
|
||||
// would need to collate all changes to the VI registers during scanout.
|
||||
if (xfbAddr)
|
||||
g_video_backend->Video_BeginField(xfbAddr, fbWidth, fbStride, fbHeight, ticks);
|
||||
g_video_backend->Video_OutputXFB(xfbAddr, fbWidth, fbStride, fbHeight, ticks);
|
||||
}
|
||||
|
||||
static void EndField()
|
||||
static void BeginField(FieldType field, u64 ticks)
|
||||
{
|
||||
// Outputting the frame at the beginning of scanout reduces latency. This assumes the game isn't
|
||||
// going to change the VI registers while a frame is scanning out.
|
||||
if (Config::Get(Config::GFX_HACK_EARLY_XFB_OUTPUT))
|
||||
OutputField(field, ticks);
|
||||
}
|
||||
|
||||
static void EndField(FieldType field, u64 ticks)
|
||||
{
|
||||
// If the game does change VI registers while a frame is scanning out, we can defer output
|
||||
// until the end so the last register values are used. This still isn't accurate, but it does
|
||||
// produce more acceptable results in some problematic cases.
|
||||
// Currently, this is only known to be necessary to eliminate flickering in WWE Crush Hour.
|
||||
if (!Config::Get(Config::GFX_HACK_EARLY_XFB_OUTPUT))
|
||||
OutputField(field, ticks);
|
||||
|
||||
Core::VideoThrottle();
|
||||
Core::OnFrameEnd();
|
||||
}
|
||||
|
@ -849,11 +864,11 @@ void Update(u64 ticks)
|
|||
}
|
||||
else if (s_half_line_count == s_even_field_last_hl)
|
||||
{
|
||||
EndField();
|
||||
EndField(FieldType::Even, ticks);
|
||||
}
|
||||
else if (s_half_line_count == s_odd_field_last_hl)
|
||||
{
|
||||
EndField();
|
||||
EndField(FieldType::Odd, ticks);
|
||||
}
|
||||
|
||||
// If this half-line is at a field boundary, deal with frame stepping before potentially
|
||||
|
|
|
@ -373,7 +373,7 @@ void RunGpuLoop()
|
|||
|
||||
// This call is pretty important in DualCore mode and must be called in the FIFO Loop.
|
||||
// If we don't, s_swapRequested or s_efbAccessRequested won't be set to false
|
||||
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing
|
||||
// leading the CPU thread to wait in Video_OutputXFB or Video_AccessEFB thus slowing
|
||||
// things down.
|
||||
AsyncRequests::GetInstance()->PullEvents();
|
||||
}
|
||||
|
|
|
@ -83,8 +83,8 @@ void VideoBackendBase::Video_ExitLoop()
|
|||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void VideoBackendBase::Video_BeginField(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
|
||||
u64 ticks)
|
||||
void VideoBackendBase::Video_OutputXFB(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
|
||||
u64 ticks)
|
||||
{
|
||||
if (m_initialized && g_renderer && !g_ActiveConfig.bImmediateXFB)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
void Video_ExitLoop();
|
||||
|
||||
void Video_BeginField(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
|
||||
void Video_OutputXFB(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
|
||||
|
||||
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 data);
|
||||
u32 Video_GetQueryResult(PerfQueryType type);
|
||||
|
|
Loading…
Reference in New Issue