mirror of
https://github.com/PabloMK7/citra
synced 2024-11-15 05:08:23 +00:00
Implement game render thread delay (#180)
More details: https://www.reddit.com/r/Citra/comments/1e1v4e1/fixing_luigis_mansion_2_performance_issues_once/
This commit is contained in:
parent
cc220928bd
commit
e90795b616
13 changed files with 168 additions and 3 deletions
|
@ -40,7 +40,8 @@ enum class IntSetting(
|
||||||
VSYNC("use_vsync_new", Settings.SECTION_RENDERER, 1),
|
VSYNC("use_vsync_new", Settings.SECTION_RENDERER, 1),
|
||||||
DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, 0),
|
DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, 0),
|
||||||
TEXTURE_FILTER("texture_filter", Settings.SECTION_RENDERER, 0),
|
TEXTURE_FILTER("texture_filter", Settings.SECTION_RENDERER, 0),
|
||||||
USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, 1);
|
USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, 1),
|
||||||
|
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0);
|
||||||
|
|
||||||
override var int: Int = defaultValue
|
override var int: Int = defaultValue
|
||||||
|
|
||||||
|
|
|
@ -729,6 +729,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||||
IntSetting.TEXTURE_FILTER.defaultValue
|
IntSetting.TEXTURE_FILTER.defaultValue
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SliderSetting(
|
||||||
|
IntSetting.DELAY_RENDER_THREAD_US,
|
||||||
|
R.string.delay_render_thread,
|
||||||
|
R.string.delay_render_thread_description,
|
||||||
|
0,
|
||||||
|
16000,
|
||||||
|
" μs",
|
||||||
|
IntSetting.DELAY_RENDER_THREAD_US.key,
|
||||||
|
IntSetting.DELAY_RENDER_THREAD_US.defaultValue.toFloat()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
add(HeaderSetting(R.string.stereoscopy))
|
add(HeaderSetting(R.string.stereoscopy))
|
||||||
add(
|
add(
|
||||||
|
|
|
@ -169,6 +169,7 @@ void Config::ReadValues() {
|
||||||
ReadSetting("Renderer", Settings::values.bg_red);
|
ReadSetting("Renderer", Settings::values.bg_red);
|
||||||
ReadSetting("Renderer", Settings::values.bg_green);
|
ReadSetting("Renderer", Settings::values.bg_green);
|
||||||
ReadSetting("Renderer", Settings::values.bg_blue);
|
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||||
|
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
Settings::values.layout_option = static_cast<Settings::LayoutOption>(sdl2_config->GetInteger(
|
Settings::values.layout_option = static_cast<Settings::LayoutOption>(sdl2_config->GetInteger(
|
||||||
|
|
|
@ -175,6 +175,10 @@ anaglyph_shader_name =
|
||||||
# 0: Nearest, 1 (default): Linear
|
# 0: Nearest, 1 (default): Linear
|
||||||
filter_mode =
|
filter_mode =
|
||||||
|
|
||||||
|
# Delays the game render thread by the specified amount of microseconds
|
||||||
|
# Set to 0 for no delay, only useful in dynamic-fps games to simulate GPU delay.
|
||||||
|
delay_game_render_thread_us =
|
||||||
|
|
||||||
[Layout]
|
[Layout]
|
||||||
# Layout for the screen inside the render window.
|
# Layout for the screen inside the render window.
|
||||||
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
||||||
|
|
|
@ -663,5 +663,7 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
||||||
<string name="artic_base_connect">Conectar con Artic Base</string>
|
<string name="artic_base_connect">Conectar con Artic Base</string>
|
||||||
<string name="artic_base_connect_description">Conectar con una consola real que esté ejecutando un servidor Artic Base</string>
|
<string name="artic_base_connect_description">Conectar con una consola real que esté ejecutando un servidor Artic Base</string>
|
||||||
<string name="artic_base_enter_address">Introduce la dirección del servidor Artic Base</string>
|
<string name="artic_base_enter_address">Introduce la dirección del servidor Artic Base</string>
|
||||||
|
<string name="delay_render_thread">Retrasa el hilo de dibujado del juego</string>
|
||||||
|
<string name="delay_render_thread_description">Retrasa el hilo de dibujado del juego cuando envía datos a la GPU. Ayuda con problemas de rendimiento en los (muy pocos) juegos de fps dinámicos.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -689,5 +689,7 @@
|
||||||
<string name="artic_base_connect_description">Connect to a real console that is running an Artic Base server</string>
|
<string name="artic_base_connect_description">Connect to a real console that is running an Artic Base server</string>
|
||||||
<string name="artic_base_connect">Connect to Artic Base</string>
|
<string name="artic_base_connect">Connect to Artic Base</string>
|
||||||
<string name="artic_base_enter_address">Enter Artic Base server address</string>
|
<string name="artic_base_enter_address">Enter Artic Base server address</string>
|
||||||
|
<string name="delay_render_thread">Delay game render thread</string>
|
||||||
|
<string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) dynamic-fps games.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -147,6 +147,7 @@ void Config::ReadValues() {
|
||||||
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
||||||
ReadSetting("Renderer", Settings::values.texture_filter);
|
ReadSetting("Renderer", Settings::values.texture_filter);
|
||||||
ReadSetting("Renderer", Settings::values.texture_sampling);
|
ReadSetting("Renderer", Settings::values.texture_sampling);
|
||||||
|
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
ReadSetting("Renderer", Settings::values.mono_render_option);
|
ReadSetting("Renderer", Settings::values.mono_render_option);
|
||||||
ReadSetting("Renderer", Settings::values.render_3d);
|
ReadSetting("Renderer", Settings::values.render_3d);
|
||||||
|
|
|
@ -667,6 +667,8 @@ void Config::ReadRendererValues() {
|
||||||
ReadGlobalSetting(Settings::values.texture_filter);
|
ReadGlobalSetting(Settings::values.texture_filter);
|
||||||
ReadGlobalSetting(Settings::values.texture_sampling);
|
ReadGlobalSetting(Settings::values.texture_sampling);
|
||||||
|
|
||||||
|
ReadGlobalSetting(Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
ReadBasicSetting(Settings::values.use_shader_jit);
|
ReadBasicSetting(Settings::values.use_shader_jit);
|
||||||
}
|
}
|
||||||
|
@ -1168,6 +1170,8 @@ void Config::SaveRendererValues() {
|
||||||
WriteGlobalSetting(Settings::values.texture_filter);
|
WriteGlobalSetting(Settings::values.texture_filter);
|
||||||
WriteGlobalSetting(Settings::values.texture_sampling);
|
WriteGlobalSetting(Settings::values.texture_sampling);
|
||||||
|
|
||||||
|
WriteGlobalSetting(Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(),
|
WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(),
|
||||||
true);
|
true);
|
||||||
|
|
|
@ -26,6 +26,10 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QStrin
|
||||||
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
|
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
|
||||||
ui->graphics_api_combo->setCurrentIndex(-1);
|
ui->graphics_api_combo->setCurrentIndex(-1);
|
||||||
|
|
||||||
|
const auto width = static_cast<int>(QString::fromStdString("000000000").size() * 6);
|
||||||
|
ui->delay_render_display_label->setMinimumWidth(width);
|
||||||
|
ui->delay_render_combo->setVisible(!Settings::IsConfiguringGlobal());
|
||||||
|
|
||||||
auto graphics_api_combo_model =
|
auto graphics_api_combo_model =
|
||||||
qobject_cast<QStandardItemModel*>(ui->graphics_api_combo->model());
|
qobject_cast<QStandardItemModel*>(ui->graphics_api_combo->model());
|
||||||
#ifndef ENABLE_SOFTWARE_RENDERER
|
#ifndef ENABLE_SOFTWARE_RENDERER
|
||||||
|
@ -82,12 +86,25 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QStrin
|
||||||
connect(ui->graphics_api_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
connect(ui->graphics_api_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
&ConfigureGraphics::SetPhysicalDeviceComboVisibility);
|
&ConfigureGraphics::SetPhysicalDeviceComboVisibility);
|
||||||
|
|
||||||
|
connect(ui->delay_render_slider, &QSlider::valueChanged, this, [&](int value) {
|
||||||
|
ui->delay_render_display_label->setText(
|
||||||
|
QStringLiteral("%1 ms")
|
||||||
|
.arg(((double)value) / 1000.f, 0, 'f', 3)
|
||||||
|
.rightJustified(QString::fromStdString("000000000").size()));
|
||||||
|
});
|
||||||
|
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureGraphics::~ConfigureGraphics() = default;
|
ConfigureGraphics::~ConfigureGraphics() = default;
|
||||||
|
|
||||||
void ConfigureGraphics::SetConfiguration() {
|
void ConfigureGraphics::SetConfiguration() {
|
||||||
|
ui->delay_render_slider->setValue(Settings::values.delay_game_render_thread_us.GetValue());
|
||||||
|
ui->delay_render_display_label->setText(
|
||||||
|
QStringLiteral("%1 ms")
|
||||||
|
.arg(((double)ui->delay_render_slider->value()) / 1000, 0, 'f', 3)
|
||||||
|
.rightJustified(QString::fromStdString("000000000").size()));
|
||||||
|
|
||||||
if (!Settings::IsConfiguringGlobal()) {
|
if (!Settings::IsConfiguringGlobal()) {
|
||||||
ConfigurationShared::SetHighlight(ui->graphics_api_group,
|
ConfigurationShared::SetHighlight(ui->graphics_api_group,
|
||||||
!Settings::values.graphics_api.UsingGlobal());
|
!Settings::values.graphics_api.UsingGlobal());
|
||||||
|
@ -101,6 +118,16 @@ void ConfigureGraphics::SetConfiguration() {
|
||||||
&Settings::values.texture_sampling);
|
&Settings::values.texture_sampling);
|
||||||
ConfigurationShared::SetHighlight(ui->widget_texture_sampling,
|
ConfigurationShared::SetHighlight(ui->widget_texture_sampling,
|
||||||
!Settings::values.texture_sampling.UsingGlobal());
|
!Settings::values.texture_sampling.UsingGlobal());
|
||||||
|
ConfigurationShared::SetHighlight(
|
||||||
|
ui->delay_render_layout, !Settings::values.delay_game_render_thread_us.UsingGlobal());
|
||||||
|
|
||||||
|
if (Settings::values.delay_game_render_thread_us.UsingGlobal()) {
|
||||||
|
ui->delay_render_combo->setCurrentIndex(0);
|
||||||
|
ui->delay_render_slider->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
ui->delay_render_combo->setCurrentIndex(1);
|
||||||
|
ui->delay_render_slider->setEnabled(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ui->graphics_api_combo->setCurrentIndex(
|
ui->graphics_api_combo->setCurrentIndex(
|
||||||
static_cast<int>(Settings::values.graphics_api.GetValue()));
|
static_cast<int>(Settings::values.graphics_api.GetValue()));
|
||||||
|
@ -144,6 +171,9 @@ void ConfigureGraphics::ApplyConfiguration() {
|
||||||
ui->toggle_disk_shader_cache, use_disk_shader_cache);
|
ui->toggle_disk_shader_cache, use_disk_shader_cache);
|
||||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync_new, ui->toggle_vsync_new,
|
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync_new, ui->toggle_vsync_new,
|
||||||
use_vsync_new);
|
use_vsync_new);
|
||||||
|
ConfigurationShared::ApplyPerGameSetting(
|
||||||
|
&Settings::values.delay_game_render_thread_us, ui->delay_render_combo,
|
||||||
|
[this](s32) { return ui->delay_render_slider->value(); });
|
||||||
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
||||||
|
@ -170,9 +200,16 @@ void ConfigureGraphics::SetupPerGameUI() {
|
||||||
ui->toggle_async_present->setEnabled(Settings::values.async_presentation.UsingGlobal());
|
ui->toggle_async_present->setEnabled(Settings::values.async_presentation.UsingGlobal());
|
||||||
ui->graphics_api_combo->setEnabled(Settings::values.graphics_api.UsingGlobal());
|
ui->graphics_api_combo->setEnabled(Settings::values.graphics_api.UsingGlobal());
|
||||||
ui->physical_device_combo->setEnabled(Settings::values.physical_device.UsingGlobal());
|
ui->physical_device_combo->setEnabled(Settings::values.physical_device.UsingGlobal());
|
||||||
|
ui->delay_render_combo->setEnabled(
|
||||||
|
Settings::values.delay_game_render_thread_us.UsingGlobal());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(ui->delay_render_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||||
|
ui->delay_render_slider->setEnabled(index == 1);
|
||||||
|
ConfigurationShared::SetHighlight(ui->delay_render_layout, index == 1);
|
||||||
|
});
|
||||||
|
|
||||||
ui->toggle_shader_jit->setVisible(false);
|
ui->toggle_shader_jit->setVisible(false);
|
||||||
|
|
||||||
ConfigurationShared::SetColoredComboBox(
|
ConfigurationShared::SetColoredComboBox(
|
||||||
|
|
|
@ -307,6 +307,83 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="delay_render_layout" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="delay_render_layout_inner">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="delay_render_combo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use global</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use per-game</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_delay_render">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delay game render thread:</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Delays the emulated game render thread the specified amount of milliseconds every time it submits render commands to the GPU.</p><p>Adjust this feature in the (very few) dynamic-fps games to fix performance issues.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="delay_render_slider">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>16000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>250</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickPosition">
|
||||||
|
<enum>QSlider::TicksBelow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="delay_render_display_label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -100,6 +100,7 @@ void LogSettings() {
|
||||||
log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue()));
|
log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue()));
|
||||||
log_setting("Renderer_TextureSampling",
|
log_setting("Renderer_TextureSampling",
|
||||||
GetTextureSamplingName(values.texture_sampling.GetValue()));
|
GetTextureSamplingName(values.texture_sampling.GetValue()));
|
||||||
|
log_setting("Renderer_DelayGameRenderThreasUs", values.delay_game_render_thread_us.GetValue());
|
||||||
log_setting("Stereoscopy_Render3d", values.render_3d.GetValue());
|
log_setting("Stereoscopy_Render3d", values.render_3d.GetValue());
|
||||||
log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue());
|
log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue());
|
||||||
log_setting("Stereoscopy_MonoRenderOption", values.mono_render_option.GetValue());
|
log_setting("Stereoscopy_MonoRenderOption", values.mono_render_option.GetValue());
|
||||||
|
@ -192,6 +193,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||||
values.frame_limit.SetGlobal(true);
|
values.frame_limit.SetGlobal(true);
|
||||||
values.texture_filter.SetGlobal(true);
|
values.texture_filter.SetGlobal(true);
|
||||||
values.texture_sampling.SetGlobal(true);
|
values.texture_sampling.SetGlobal(true);
|
||||||
|
values.delay_game_render_thread_us.SetGlobal(true);
|
||||||
values.layout_option.SetGlobal(true);
|
values.layout_option.SetGlobal(true);
|
||||||
values.swap_screen.SetGlobal(true);
|
values.swap_screen.SetGlobal(true);
|
||||||
values.upright_screen.SetGlobal(true);
|
values.upright_screen.SetGlobal(true);
|
||||||
|
|
|
@ -479,6 +479,8 @@ struct Values {
|
||||||
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"};
|
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"};
|
||||||
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
||||||
"texture_sampling"};
|
"texture_sampling"};
|
||||||
|
SwitchableSetting<u16, true> delay_game_render_thread_us{0, 0, 16000,
|
||||||
|
"delay_game_render_thread_us"};
|
||||||
|
|
||||||
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
|
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
|
||||||
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
|
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <boost/serialization/shared_ptr.hpp>
|
#include <boost/serialization/shared_ptr.hpp>
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
|
@ -410,6 +411,9 @@ void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
auto* command_buffer = GetCommandBuffer(active_thread_id);
|
auto* command_buffer = GetCommandBuffer(active_thread_id);
|
||||||
auto& gpu = system.GPU();
|
auto& gpu = system.GPU();
|
||||||
|
|
||||||
|
bool requires_delay = false;
|
||||||
|
|
||||||
while (command_buffer->number_commands) {
|
while (command_buffer->number_commands) {
|
||||||
if (command_buffer->should_stop) {
|
if (command_buffer->should_stop) {
|
||||||
command_buffer->status.Assign(CommandBuffer::STATUS_STOPPED);
|
command_buffer->status.Assign(CommandBuffer::STATUS_STOPPED);
|
||||||
|
@ -420,6 +424,10 @@ void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Command command = command_buffer->commands[command_buffer->index];
|
Command command = command_buffer->commands[command_buffer->index];
|
||||||
|
if (command.id == CommandId::SubmitCmdList && !requires_delay &&
|
||||||
|
Settings::values.delay_game_render_thread_us.GetValue() != 0) {
|
||||||
|
requires_delay = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Decrease the number of commands remaining and increase the current index
|
// Decrease the number of commands remaining and increase the current index
|
||||||
command_buffer->number_commands.Assign(command_buffer->number_commands - 1);
|
command_buffer->number_commands.Assign(command_buffer->number_commands - 1);
|
||||||
|
@ -435,8 +443,20 @@ void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requires_delay) {
|
||||||
|
ctx.RunAsync(
|
||||||
|
[](Kernel::HLERequestContext& ctx) {
|
||||||
|
return Settings::values.delay_game_render_thread_us.GetValue() * 1000;
|
||||||
|
},
|
||||||
|
[](Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestBuilder rb(ctx, 1, 0);
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) {
|
void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
Loading…
Reference in a new issue