mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 07:39:26 +01:00
Merge pull request #8554 from stenzek/present-duplicate-frames
Add an option to present duplicate frames
This commit is contained in:
commit
a63510a55a
@ -585,6 +585,7 @@ public final class SettingsFragmentPresenter
|
||||
Setting gpuTextureDecoding = gfxSection.getSetting(SettingsFile.KEY_GPU_TEXTURE_DECODING);
|
||||
Setting xfbToTexture = hacksSection.getSetting(SettingsFile.KEY_XFB_TEXTURE);
|
||||
Setting immediateXfb = hacksSection.getSetting(SettingsFile.KEY_IMMEDIATE_XFB);
|
||||
Setting skipDuplicateXfbs = hacksSection.getSetting(SettingsFile.KEY_SKIP_DUPLICATE_XFBS);
|
||||
Setting fastDepth = gfxSection.getSetting(SettingsFile.KEY_FAST_DEPTH);
|
||||
|
||||
sl.add(new HeaderSetting(null, null, R.string.embedded_frame_buffer, 0));
|
||||
@ -613,6 +614,9 @@ public final class SettingsFragmentPresenter
|
||||
R.string.xfb_copy_method, R.string.xfb_copy_method_description, true, xfbToTexture));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_IMMEDIATE_XFB, Settings.SECTION_GFX_HACKS,
|
||||
R.string.immediate_xfb, R.string.immediate_xfb_description, false, immediateXfb));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_SKIP_DUPLICATE_XFBS, Settings.SECTION_GFX_HACKS,
|
||||
R.string.skip_duplicate_xfbs, R.string.skip_duplicate_xfbs_description, true,
|
||||
skipDuplicateXfbs));
|
||||
|
||||
sl.add(new HeaderSetting(null, null, R.string.other, 0));
|
||||
sl.add(new CheckBoxSetting(SettingsFile.KEY_FAST_DEPTH, Settings.SECTION_GFX_SETTINGS,
|
||||
|
@ -89,6 +89,7 @@ public final class SettingsFile
|
||||
public static final String KEY_GPU_TEXTURE_DECODING = "EnableGPUTextureDecoding";
|
||||
public static final String KEY_XFB_TEXTURE = "XFBToTextureEnable";
|
||||
public static final String KEY_IMMEDIATE_XFB = "ImmediateXFBEnable";
|
||||
public static final String KEY_SKIP_DUPLICATE_XFBS = "SkipDuplicateXFBs";
|
||||
public static final String KEY_FAST_DEPTH = "FastDepthCalc";
|
||||
public static final String KEY_ASPECT_RATIO = "AspectRatio";
|
||||
public static final String KEY_SHADER_COMPILATION_MODE = "ShaderCompilationMode";
|
||||
|
@ -232,6 +232,8 @@
|
||||
<string name="xfb_copy_method_description">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. If unsure, leave this checked.</string>
|
||||
<string name="immediate_xfb">Immediately Present XFB</string>
|
||||
<string name="immediate_xfb_description">Displays the XFB copies as soon as they are created, without waiting for scanout. Causes graphical defects in some games but reduces latency. If unsure, leave this unchecked.</string>
|
||||
<string name="skip_duplicate_xfbs">Immediately Present XFB</string>
|
||||
<string name="skip_duplicate_xfbs_description">Skips presentation of duplicate frames. This may improve performance on low-end devices, while making frame pacing less consistent. If unsure, leave this checked.</string>
|
||||
<string name="disable_destination_alpha">Disable Destination Alpha</string>
|
||||
<string name="disable_destination_alpha_description">Disables emulation of a hardware feature called destination alpha, which is used in many games for various effects.</string>
|
||||
<string name="fast_depth_calculation">Fast Depth Calculation</string>
|
||||
|
@ -154,6 +154,8 @@ const ConfigInfo<bool> GFX_HACK_DISABLE_COPY_TO_VRAM{{System::GFX, "Hacks", "Dis
|
||||
false};
|
||||
const ConfigInfo<bool> GFX_HACK_DEFER_EFB_COPIES{{System::GFX, "Hacks", "DeferEFBCopies"}, true};
|
||||
const ConfigInfo<bool> GFX_HACK_IMMEDIATE_XFB{{System::GFX, "Hacks", "ImmediateXFBEnable"}, false};
|
||||
const ConfigInfo<bool> GFX_HACK_SKIP_DUPLICATE_XFBS{{System::GFX, "Hacks", "SkipDuplicateXFBs"},
|
||||
true};
|
||||
const ConfigInfo<bool> GFX_HACK_COPY_EFB_SCALED{{System::GFX, "Hacks", "EFBScaledCopy"}, true};
|
||||
const ConfigInfo<bool> GFX_HACK_EFB_EMULATE_FORMAT_CHANGES{
|
||||
{System::GFX, "Hacks", "EFBEmulateFormatChanges"}, false};
|
||||
|
@ -111,6 +111,7 @@ extern const ConfigInfo<bool> GFX_HACK_SKIP_XFB_COPY_TO_RAM;
|
||||
extern const ConfigInfo<bool> GFX_HACK_DISABLE_COPY_TO_VRAM;
|
||||
extern const ConfigInfo<bool> GFX_HACK_DEFER_EFB_COPIES;
|
||||
extern const ConfigInfo<bool> GFX_HACK_IMMEDIATE_XFB;
|
||||
extern const ConfigInfo<bool> GFX_HACK_SKIP_DUPLICATE_XFBS;
|
||||
extern const ConfigInfo<bool> GFX_HACK_COPY_EFB_SCALED;
|
||||
extern const ConfigInfo<bool> GFX_HACK_EFB_EMULATE_FORMAT_CHANGES;
|
||||
extern const ConfigInfo<bool> GFX_HACK_VERTEX_ROUDING;
|
||||
|
@ -28,7 +28,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr std::array<const Config::ConfigLocation*, 92> s_setting_saveable = {
|
||||
static constexpr std::array<const Config::ConfigLocation*, 93> s_setting_saveable = {
|
||||
// Main.Core
|
||||
|
||||
&Config::MAIN_DEFAULT_ISO.location,
|
||||
@ -136,6 +136,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
|
||||
&Config::GFX_HACK_DISABLE_COPY_TO_VRAM.location,
|
||||
&Config::GFX_HACK_DEFER_EFB_COPIES.location,
|
||||
&Config::GFX_HACK_IMMEDIATE_XFB.location,
|
||||
&Config::GFX_HACK_SKIP_DUPLICATE_XFBS.location,
|
||||
&Config::GFX_HACK_COPY_EFB_SCALED.location,
|
||||
&Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location,
|
||||
&Config::GFX_HACK_VERTEX_ROUDING.location,
|
||||
|
@ -86,9 +86,12 @@ 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_skip_duplicate_xfbs = new GraphicsBool(tr("Skip Presenting Duplicate Frames"),
|
||||
Config::GFX_HACK_SKIP_DUPLICATE_XFBS);
|
||||
|
||||
xfb_layout->addWidget(m_store_xfb_copies);
|
||||
xfb_layout->addWidget(m_immediate_xfb);
|
||||
xfb_layout->addWidget(m_skip_duplicate_xfbs);
|
||||
|
||||
// Other
|
||||
auto* other_box = new QGroupBox(tr("Other"));
|
||||
@ -117,6 +120,7 @@ void HacksWidget::CreateWidgets()
|
||||
setLayout(main_layout);
|
||||
|
||||
UpdateDeferEFBCopiesEnabled();
|
||||
UpdateSkipPresentingDuplicateFramesEnabled();
|
||||
}
|
||||
|
||||
void HacksWidget::OnBackendChanged(const QString& backend_name)
|
||||
@ -140,6 +144,8 @@ void HacksWidget::ConnectWidgets()
|
||||
[this](int) { UpdateDeferEFBCopiesEnabled(); });
|
||||
connect(m_store_xfb_copies, &QCheckBox::stateChanged,
|
||||
[this](int) { UpdateDeferEFBCopiesEnabled(); });
|
||||
connect(m_immediate_xfb, &QCheckBox::stateChanged,
|
||||
[this](int) { UpdateSkipPresentingDuplicateFramesEnabled(); });
|
||||
}
|
||||
|
||||
void HacksWidget::LoadSettings()
|
||||
@ -235,6 +241,12 @@ void HacksWidget::AddDescriptions()
|
||||
"expect all XFB copies to be displayed. However, turning this setting on reduces "
|
||||
"latency.\n\nIf unsure, leave this unchecked.");
|
||||
|
||||
static const char TR_SKIP_DUPLICATE_XFBS_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Skips presentation of duplicate frames (XFB copies) in 25fps/30fps games. This may improve "
|
||||
"performance on low-end devices, while making frame pacing less consistent.\n\nDisable this "
|
||||
"option as well as enabling V-Sync for optimal frame pacing.\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.\n\nThis may result in "
|
||||
"performance gains in some scenarios, or on systems where the CPU is the "
|
||||
@ -263,6 +275,7 @@ void HacksWidget::AddDescriptions()
|
||||
AddDescription(m_accuracy, TR_ACCUARCY_DESCRIPTION);
|
||||
AddDescription(m_store_xfb_copies, TR_STORE_XFB_TO_TEXTURE_DESCRIPTION);
|
||||
AddDescription(m_immediate_xfb, TR_IMMEDIATE_XFB_DESCRIPTION);
|
||||
AddDescription(m_skip_duplicate_xfbs, TR_SKIP_DUPLICATE_XFBS_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);
|
||||
@ -277,3 +290,10 @@ void HacksWidget::UpdateDeferEFBCopiesEnabled()
|
||||
const bool can_defer = m_store_efb_copies->isChecked() && m_store_xfb_copies->isChecked();
|
||||
m_defer_efb_copies->setEnabled(!can_defer);
|
||||
}
|
||||
|
||||
void HacksWidget::UpdateSkipPresentingDuplicateFramesEnabled()
|
||||
{
|
||||
// If Immediate XFB is on, there's no point to skipping duplicate XFB copies as immediate presents
|
||||
// when the XFB is created, therefore all XFB copies will be unique.
|
||||
m_skip_duplicate_xfbs->setEnabled(!m_immediate_xfb->isChecked());
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ private:
|
||||
// External Framebuffer
|
||||
QCheckBox* m_store_xfb_copies;
|
||||
QCheckBox* m_immediate_xfb;
|
||||
QCheckBox* m_skip_duplicate_xfbs;
|
||||
|
||||
// Other
|
||||
QCheckBox* m_fast_depth_calculation;
|
||||
@ -50,4 +51,5 @@ private:
|
||||
void AddDescriptions();
|
||||
|
||||
void UpdateDeferEFBCopiesEnabled();
|
||||
void UpdateSkipPresentingDuplicateFramesEnabled();
|
||||
};
|
||||
|
@ -1190,8 +1190,10 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6
|
||||
MathUtil::Rectangle<int> xfb_rect;
|
||||
const auto* xfb_entry =
|
||||
g_texture_cache->GetXFBTexture(xfb_addr, fb_width, fb_height, fb_stride, &xfb_rect);
|
||||
if (xfb_entry && xfb_entry->id != m_last_xfb_id)
|
||||
if (xfb_entry &&
|
||||
(!g_ActiveConfig.bSkipPresentingDuplicateXFBs || xfb_entry->id != m_last_xfb_id))
|
||||
{
|
||||
const bool is_duplicate_frame = xfb_entry->id == m_last_xfb_id;
|
||||
m_last_xfb_id = xfb_entry->id;
|
||||
|
||||
// Since we use the common pipelines here and draw vertices if a batch is currently being
|
||||
@ -1235,20 +1237,24 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6
|
||||
SetWindowSize(xfb_rect.GetWidth(), xfb_rect.GetHeight());
|
||||
}
|
||||
|
||||
m_fps_counter.Update();
|
||||
if (!is_duplicate_frame)
|
||||
{
|
||||
m_fps_counter.Update();
|
||||
|
||||
DolphinAnalytics::PerformanceSample perf_sample;
|
||||
perf_sample.speed_ratio = SystemTimers::GetEstimatedEmulationPerformance();
|
||||
perf_sample.num_prims = g_stats.this_frame.num_prims + g_stats.this_frame.num_dl_prims;
|
||||
perf_sample.num_draw_calls = g_stats.this_frame.num_draw_calls;
|
||||
DolphinAnalytics::Instance().ReportPerformanceInfo(std::move(perf_sample));
|
||||
DolphinAnalytics::PerformanceSample perf_sample;
|
||||
perf_sample.speed_ratio = SystemTimers::GetEstimatedEmulationPerformance();
|
||||
perf_sample.num_prims = g_stats.this_frame.num_prims + g_stats.this_frame.num_dl_prims;
|
||||
perf_sample.num_draw_calls = g_stats.this_frame.num_draw_calls;
|
||||
DolphinAnalytics::Instance().ReportPerformanceInfo(std::move(perf_sample));
|
||||
|
||||
if (IsFrameDumping())
|
||||
DumpCurrentFrame(xfb_entry->texture.get(), xfb_rect, ticks);
|
||||
if (IsFrameDumping())
|
||||
DumpCurrentFrame(xfb_entry->texture.get(), xfb_rect, ticks);
|
||||
|
||||
// Begin new frame
|
||||
m_frame_count++;
|
||||
g_stats.ResetFrame();
|
||||
}
|
||||
|
||||
// Begin new frame
|
||||
m_frame_count++;
|
||||
g_stats.ResetFrame();
|
||||
g_shader_cache->RetrieveAsyncShaders();
|
||||
g_vertex_manager->OnEndFrame();
|
||||
BeginImGuiFrame();
|
||||
@ -1263,16 +1269,18 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6
|
||||
// rate and not waiting for vblank. Otherwise, we'd end up with a huge list of pending copies.
|
||||
g_texture_cache->FlushEFBCopies();
|
||||
|
||||
// Remove stale EFB/XFB copies.
|
||||
g_texture_cache->Cleanup(m_frame_count);
|
||||
if (!is_duplicate_frame)
|
||||
{
|
||||
// Remove stale EFB/XFB copies.
|
||||
g_texture_cache->Cleanup(m_frame_count);
|
||||
Core::Callback_VideoCopiedToXFB(true);
|
||||
}
|
||||
|
||||
// Handle any config changes, this gets propogated to the backend.
|
||||
CheckForConfigChanges();
|
||||
g_Config.iSaveTargetId = 0;
|
||||
|
||||
EndUtilityDrawing();
|
||||
|
||||
Core::Callback_VideoCopiedToXFB(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -152,6 +152,7 @@ void VideoConfig::Refresh()
|
||||
bDisableCopyToVRAM = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
|
||||
bDeferEFBCopies = Config::Get(Config::GFX_HACK_DEFER_EFB_COPIES);
|
||||
bImmediateXFB = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
|
||||
bSkipPresentingDuplicateXFBs = Config::Get(Config::GFX_HACK_SKIP_DUPLICATE_XFBS);
|
||||
bCopyEFBScaled = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
|
||||
bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
|
||||
bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING);
|
||||
|
@ -124,6 +124,7 @@ struct VideoConfig final
|
||||
bool bDisableCopyToVRAM;
|
||||
bool bDeferEFBCopies;
|
||||
bool bImmediateXFB;
|
||||
bool bSkipPresentingDuplicateXFBs;
|
||||
bool bCopyEFBScaled;
|
||||
int iSafeTextureCache_ColorSamples;
|
||||
float fAspectRatioHackW, fAspectRatioHackH;
|
||||
|
Loading…
x
Reference in New Issue
Block a user