Browse Source

[GPU]: Implement a working Frame-Skip into Android

pull/263/head
Gamer64 7 months ago
committed by crueter
parent
commit
77da1a32e0
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
  2. 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
  3. 18
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
  4. 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
  5. 12
      src/android/app/src/main/res/values/arrays.xml
  6. 2
      src/common/settings.h
  7. 52
      src/video_core/gpu.cpp
  8. 3
      src/video_core/gpu.h

1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt

@ -51,7 +51,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
ENABLE_RAII("enable_raii"), ENABLE_RAII("enable_raii"),
FRAME_INTERPOLATION("frame_interpolation"), FRAME_INTERPOLATION("frame_interpolation"),
// FRAME_SKIPPING("frame_skipping"),
PERF_OVERLAY_BACKGROUND("perf_overlay_background"), PERF_OVERLAY_BACKGROUND("perf_overlay_background"),
SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"), SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"),

1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt

@ -42,6 +42,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
RENDERER_SAMPLE_SHADING_FRACTION("sample_shading_fraction"), RENDERER_SAMPLE_SHADING_FRACTION("sample_shading_fraction"),
FAST_CPU_TIME("fast_cpu_time"), FAST_CPU_TIME("fast_cpu_time"),
CPU_TICKS("cpu_ticks"), CPU_TICKS("cpu_ticks"),
FRAME_SKIPPING("frame_skipping"),
FAST_GPU_TIME("fast_gpu_time"), FAST_GPU_TIME("fast_gpu_time"),
BAT_TEMPERATURE_UNIT("bat_temperature_unit"), BAT_TEMPERATURE_UNIT("bat_temperature_unit"),
CABINET_APPLET("cabinet_applet_mode"), CABINET_APPLET("cabinet_applet_mode"),

18
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt

@ -242,15 +242,15 @@ abstract class SettingsItem(
descriptionId = R.string.frame_interpolation_description descriptionId = R.string.frame_interpolation_description
) )
) )
// put(
// SwitchSetting(
// BooleanSetting.FRAME_SKIPPING,
// titleId = R.string.frame_skipping,
// descriptionId = R.string.frame_skipping_description
// )
// )
put(
SingleChoiceSetting(
IntSetting.FRAME_SKIPPING,
titleId = R.string.frame_skipping,
descriptionId = R.string.frame_skipping_description,
choicesId = R.array.frameSkippingNames,
valuesId = R.array.frameSkippingValues
)
)
put( put(
SwitchSetting( SwitchSetting(
dockedModeSetting, dockedModeSetting,

1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt

@ -450,6 +450,7 @@ class SettingsFragmentPresenter(
add(BooleanSetting.RENDERER_EARLY_RELEASE_FENCES.key) add(BooleanSetting.RENDERER_EARLY_RELEASE_FENCES.key)
add(BooleanSetting.BUFFER_REORDER_DISABLE.key) add(BooleanSetting.BUFFER_REORDER_DISABLE.key)
add(BooleanSetting.FRAME_INTERPOLATION.key) add(BooleanSetting.FRAME_INTERPOLATION.key)
add(IntSetting.FRAME_SKIPPING.key)
add(BooleanSetting.RENDERER_FAST_GPU.key) add(BooleanSetting.RENDERER_FAST_GPU.key)
add(IntSetting.FAST_GPU_TIME.key) add(IntSetting.FAST_GPU_TIME.key)
add(IntSetting.RENDERER_SHADER_BACKEND.key) add(IntSetting.RENDERER_SHADER_BACKEND.key)

12
src/android/app/src/main/res/values/arrays.xml

@ -21,6 +21,18 @@
<item>1</item> <item>1</item>
</integer-array> </integer-array>
<string-array name="frameSkippingNames">
<item>@string/disabled</item>
<item>1</item>
<item>2</item>
</string-array>
<integer-array name="frameSkippingValues">
<item>0</item>
<item>1</item>
<item>2</item>
</integer-array>
<string-array name="memoryNames"> <string-array name="memoryNames">
<item>@string/memory_4gb</item> <item>@string/memory_4gb</item>
<item>@string/memory_6gb</item> <item>@string/memory_6gb</item>

2
src/common/settings.h

@ -325,9 +325,9 @@ struct Values {
#ifdef __ANDROID__ #ifdef __ANDROID__
SwitchableSetting<bool> frame_interpolation{linkage, true, "frame_interpolation", Category::Renderer, SwitchableSetting<bool> frame_interpolation{linkage, true, "frame_interpolation", Category::Renderer,
Specialization::RuntimeList}; Specialization::RuntimeList};
#endif
SwitchableSetting<bool> frame_skipping{linkage, false, "frame_skipping", Category::Renderer, SwitchableSetting<bool> frame_skipping{linkage, false, "frame_skipping", Category::Renderer,
Specialization::RuntimeList}; Specialization::RuntimeList};
#endif
SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache", SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache",
Category::Renderer}; Category::Renderer};
SwitchableSetting<SpirvOptimizeMode, true> optimize_spirv_output{linkage, SwitchableSetting<SpirvOptimizeMode, true> optimize_spirv_output{linkage,

52
src/video_core/gpu.cpp

@ -223,17 +223,23 @@ struct GPU::Impl {
system.GetPerfStats().EndGameFrame(); system.GetPerfStats().EndGameFrame();
} }
void ResetFrameCounter() {
frame_count.store(0, std::memory_order_relaxed);
}
/// Performs any additional setup necessary in order to begin GPU emulation. /// Performs any additional setup necessary in order to begin GPU emulation.
/// This can be used to launch any necessary threads and register any necessary /// This can be used to launch any necessary threads and register any necessary
/// core timing events. /// core timing events.
void Start() { void Start() {
Settings::UpdateGPUAccuracy(); Settings::UpdateGPUAccuracy();
ResetFrameCounter();
gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler); gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler);
} }
void NotifyShutdown() { void NotifyShutdown() {
std::unique_lock lk{sync_mutex}; std::unique_lock lk{sync_mutex};
shutting_down.store(true, std::memory_order::relaxed); shutting_down.store(true, std::memory_order::relaxed);
ResetFrameCounter();
sync_cv.notify_all(); sync_cv.notify_all();
} }
@ -291,10 +297,16 @@ struct GPU::Impl {
void RequestComposite(std::vector<Tegra::FramebufferConfig>&& layers, void RequestComposite(std::vector<Tegra::FramebufferConfig>&& layers,
std::vector<Service::Nvidia::NvFence>&& fences) { std::vector<Service::Nvidia::NvFence>&& fences) {
// Increment frame counter
const u64 current_frame = frame_count.fetch_add(1, std::memory_order_relaxed) + 1;
const u32 frame_skip_value = Settings::values.frame_skipping.GetValue();
const bool skip_frame = frame_skip_value > 0 &&
(current_frame % (static_cast<u64>(frame_skip_value) + 1) != 0);
size_t num_fences{fences.size()}; size_t num_fences{fences.size()};
size_t current_request_counter{}; size_t current_request_counter{};
{ {
std::unique_lock<std::mutex> lk(request_swap_mutex);
std::unique_lock<std::mutex> lk{request_swap_mutex};
if (free_swap_counters.empty()) { if (free_swap_counters.empty()) {
current_request_counter = request_swap_counters.size(); current_request_counter = request_swap_counters.size();
request_swap_counters.emplace_back(num_fences); request_swap_counters.emplace_back(num_fences);
@ -305,23 +317,33 @@ struct GPU::Impl {
} }
} }
const auto wait_fence = const auto wait_fence =
RequestSyncOperation([this, current_request_counter, &layers, &fences, num_fences] {
RequestSyncOperation([this, current_request_counter, &layers, &fences, num_fences, skip_frame] {
auto& syncpoint_manager = host1x.GetSyncpointManager(); auto& syncpoint_manager = host1x.GetSyncpointManager();
if (num_fences == 0) { if (num_fences == 0) {
renderer->Composite(layers);
}
const auto executer = [this, current_request_counter, layers_copy = layers]() {
{
std::unique_lock<std::mutex> lk(request_swap_mutex);
if (--request_swap_counters[current_request_counter] != 0) {
return;
if (!skip_frame) {
renderer->Composite(layers);
} else {
system.GetPerfStats().EndGameFrame();
}
} else {
const auto executer = [this, current_request_counter, layers_copy = std::move(layers), skip_frame]() {
{
std::unique_lock<std::mutex> lk{request_swap_mutex};
if (--request_swap_counters[current_request_counter] != 0) {
return;
}
free_swap_counters.push_back(current_request_counter);
}
// Handle frame skipping in executer
if (!skip_frame) {
renderer->Composite(layers_copy);
} else {
system.GetPerfStats().EndGameFrame();
} }
free_swap_counters.push_back(current_request_counter);
};
for (size_t i = 0; i < num_fences; i++) {
syncpoint_manager.RegisterGuestAction(fences[i].id, fences[i].value, executer);
} }
renderer->Composite(layers_copy);
};
for (size_t i = 0; i < num_fences; i++) {
syncpoint_manager.RegisterGuestAction(fences[i].id, fences[i].value, executer);
} }
}); });
gpu_thread.TickGPU(); gpu_thread.TickGPU();
@ -353,6 +375,8 @@ struct GPU::Impl {
/// When true, we are about to shut down emulation session, so terminate outstanding tasks /// When true, we are about to shut down emulation session, so terminate outstanding tasks
std::atomic_bool shutting_down{}; std::atomic_bool shutting_down{};
std::atomic<u64> frame_count{0};
std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{}; std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{};
std::array<std::list<u32>, Service::Nvidia::MaxSyncPoints> syncpt_interrupts; std::array<std::list<u32>, Service::Nvidia::MaxSyncPoints> syncpt_interrupts;

3
src/video_core/gpu.h

@ -220,6 +220,9 @@ public:
std::vector<u8> GetAppletCaptureBuffer(); std::vector<u8> GetAppletCaptureBuffer();
// Reset frame counter
void ResetFrameCounter();
/// Performs any additional setup necessary in order to begin GPU emulation. /// Performs any additional setup necessary in order to begin GPU emulation.
/// This can be used to launch any necessary threads and register any necessary /// This can be used to launch any necessary threads and register any necessary
/// core timing events. /// core timing events.

Loading…
Cancel
Save