mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-10 06:02:40 +00:00
Revert "A quick experiment on frame rate target"
This commit is contained in:
@@ -21,7 +21,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
|||||||
RENDERER_RESOLUTION("resolution_setup"),
|
RENDERER_RESOLUTION("resolution_setup"),
|
||||||
RENDERER_FRAME_GEN_MULTIPLIER("frame_gen_multiplier"),
|
RENDERER_FRAME_GEN_MULTIPLIER("frame_gen_multiplier"),
|
||||||
RENDERER_FRAME_GEN_QUEUE_TARGET("frame_gen_queue_target"),
|
RENDERER_FRAME_GEN_QUEUE_TARGET("frame_gen_queue_target"),
|
||||||
RENDERER_FRAME_GEN_TARGET_RATE("frame_gen_target_rate"),
|
|
||||||
RENDERER_FRAME_GEN_FLOW_SCALE("frame_gen_flow_scale"),
|
RENDERER_FRAME_GEN_FLOW_SCALE("frame_gen_flow_scale"),
|
||||||
RENDERER_VSYNC("use_vsync"),
|
RENDERER_VSYNC("use_vsync"),
|
||||||
RENDERER_SCALING_FILTER("scaling_filter"),
|
RENDERER_SCALING_FILTER("scaling_filter"),
|
||||||
|
|||||||
-10
@@ -100,7 +100,6 @@ abstract class SettingsItem(
|
|||||||
BooleanSetting.RENDERER_FRAME_GEN.key,
|
BooleanSetting.RENDERER_FRAME_GEN.key,
|
||||||
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key,
|
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key,
|
||||||
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key,
|
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key,
|
||||||
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key,
|
|
||||||
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key,
|
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key,
|
||||||
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key,
|
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key,
|
||||||
BooleanSetting.RENDERER_FRAME_GEN_FP16.key,
|
BooleanSetting.RENDERER_FRAME_GEN_FP16.key,
|
||||||
@@ -641,15 +640,6 @@ abstract class SettingsItem(
|
|||||||
valuesId = R.array.frameGenMultiplierValues
|
valuesId = R.array.frameGenMultiplierValues
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SingleChoiceSetting(
|
|
||||||
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE,
|
|
||||||
titleId = R.string.frame_gen_target_rate,
|
|
||||||
descriptionId = R.string.frame_gen_target_rate_description,
|
|
||||||
choicesId = R.array.frameGenTargetRateNames,
|
|
||||||
valuesId = R.array.frameGenTargetRateValues
|
|
||||||
)
|
|
||||||
)
|
|
||||||
put(
|
put(
|
||||||
SingleChoiceSetting(
|
SingleChoiceSetting(
|
||||||
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET,
|
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET,
|
||||||
|
|||||||
+1
-7
@@ -125,13 +125,7 @@ class SettingsFragmentPresenter(
|
|||||||
add(HeaderSetting(R.string.frame_gen))
|
add(HeaderSetting(R.string.frame_gen))
|
||||||
|
|
||||||
add(BooleanSetting.RENDERER_FRAME_GEN.key)
|
add(BooleanSetting.RENDERER_FRAME_GEN.key)
|
||||||
add(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
|
add(IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key)
|
||||||
if (IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(
|
|
||||||
getNeedsGlobalForKey(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
|
|
||||||
) == 0
|
|
||||||
) {
|
|
||||||
add(IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key)
|
|
||||||
}
|
|
||||||
add(IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key)
|
add(IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key)
|
||||||
add(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
|
add(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
|
||||||
if (!BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.getBoolean(
|
if (!BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.getBoolean(
|
||||||
|
|||||||
@@ -174,24 +174,6 @@
|
|||||||
<item>4</item>
|
<item>4</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<string-array name="frameGenTargetRateNames">
|
|
||||||
<item>@string/frame_gen_target_rate_off</item>
|
|
||||||
<item>@string/frame_gen_target_rate_60</item>
|
|
||||||
<item>@string/frame_gen_target_rate_90</item>
|
|
||||||
<item>@string/frame_gen_target_rate_120</item>
|
|
||||||
<item>@string/frame_gen_target_rate_144</item>
|
|
||||||
<item>@string/frame_gen_target_rate_165</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<integer-array name="frameGenTargetRateValues">
|
|
||||||
<item>0</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>90</item>
|
|
||||||
<item>120</item>
|
|
||||||
<item>144</item>
|
|
||||||
<item>165</item>
|
|
||||||
</integer-array>
|
|
||||||
|
|
||||||
<string-array name="frameGenQueueTargetNames">
|
<string-array name="frameGenQueueTargetNames">
|
||||||
<item>@string/frame_gen_queue_target_0</item>
|
<item>@string/frame_gen_queue_target_0</item>
|
||||||
<item>@string/frame_gen_queue_target_1</item>
|
<item>@string/frame_gen_queue_target_1</item>
|
||||||
|
|||||||
@@ -301,14 +301,6 @@
|
|||||||
<string name="frame_gen">Frame generation</string>
|
<string name="frame_gen">Frame generation</string>
|
||||||
<string name="frame_gen_submenu_description">Manage and configure frame generation</string>
|
<string name="frame_gen_submenu_description">Manage and configure frame generation</string>
|
||||||
<string name="frame_gen_description">Insert interpolated frames between rendered ones using Lossless Scaling. Forces FIFO presentation while enabled.</string>
|
<string name="frame_gen_description">Insert interpolated frames between rendered ones using Lossless Scaling. Forces FIFO presentation while enabled.</string>
|
||||||
<string name="frame_gen_target_rate">Target frame rate</string>
|
|
||||||
<string name="frame_gen_target_rate_description">Aim for a fixed output rate by adjusting the multiplier as the game\'s own frame rate moves. Pick a rate your display can actually present.</string>
|
|
||||||
<string name="frame_gen_target_rate_off">Off (use fixed multiplier)</string>
|
|
||||||
<string name="frame_gen_target_rate_60">60 fps</string>
|
|
||||||
<string name="frame_gen_target_rate_90">90 fps</string>
|
|
||||||
<string name="frame_gen_target_rate_120">120 fps</string>
|
|
||||||
<string name="frame_gen_target_rate_144">144 fps</string>
|
|
||||||
<string name="frame_gen_target_rate_165">165 fps</string>
|
|
||||||
<string name="frame_gen_multiplier">Frame multiplier</string>
|
<string name="frame_gen_multiplier">Frame multiplier</string>
|
||||||
<string name="frame_gen_multiplier_description">How many frames to display for each rendered frame. Higher values cost proportionally more GPU time. Asking for more than your display can present will slow emulation down.</string>
|
<string name="frame_gen_multiplier_description">How many frames to display for each rendered frame. Higher values cost proportionally more GPU time. Asking for more than your display can present will slow emulation down.</string>
|
||||||
<string name="frame_gen_multiplier_2x">2x</string>
|
<string name="frame_gen_multiplier_2x">2x</string>
|
||||||
|
|||||||
@@ -392,16 +392,6 @@ size_t FrameGenGenerations() {
|
|||||||
return FrameGenMultiplier() - 1;
|
return FrameGenMultiplier() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FrameGenMaxGenerations() {
|
|
||||||
if (!values.frame_gen.GetValue()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (values.frame_gen_target_rate.GetValue() != 0) {
|
|
||||||
return MAX_FRAME_GEN_MULTIPLIER - 1;
|
|
||||||
}
|
|
||||||
return FrameGenMultiplier() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreGlobalState(bool is_powered_on) {
|
void RestoreGlobalState(bool is_powered_on) {
|
||||||
// If a game is running, DO NOT restore the global settings state
|
// If a game is running, DO NOT restore the global settings state
|
||||||
if (is_powered_on) {
|
if (is_powered_on) {
|
||||||
|
|||||||
@@ -423,17 +423,6 @@ struct Values {
|
|||||||
true,
|
true,
|
||||||
&frame_gen};
|
&frame_gen};
|
||||||
|
|
||||||
SwitchableSetting<u32, true> frame_gen_target_rate{linkage,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
240,
|
|
||||||
"frame_gen_target_rate",
|
|
||||||
Category::Renderer,
|
|
||||||
Specialization::Countable,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
&frame_gen};
|
|
||||||
|
|
||||||
SwitchableSetting<u32, true> frame_gen_queue_target{linkage,
|
SwitchableSetting<u32, true> frame_gen_queue_target{linkage,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
@@ -945,8 +934,6 @@ constexpr u32 MAX_FRAME_GEN_MULTIPLIER = 4;
|
|||||||
|
|
||||||
[[nodiscard]] size_t FrameGenGenerations();
|
[[nodiscard]] size_t FrameGenGenerations();
|
||||||
|
|
||||||
[[nodiscard]] size_t FrameGenMaxGenerations();
|
|
||||||
|
|
||||||
bool getDebugKnobAt(u8 i);
|
bool getDebugKnobAt(u8 i);
|
||||||
|
|
||||||
void UpdateGPUAccuracy();
|
void UpdateGPUAccuracy();
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ constexpr u64 LSFG_REQUIRED_FRAMES = 2;
|
|||||||
return std::clamp(stepped, 0.25f, 1.0f);
|
return std::clamp(stepped, 0.25f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32 BASE_RATE_SMOOTHING = 0.1f;
|
[[nodiscard]] size_t ConfiguredGenerations() {
|
||||||
constexpr u32 GENERATION_CHANGE_VOTES = 30;
|
return Settings::FrameGenGenerations();
|
||||||
|
}
|
||||||
|
|
||||||
bool IsBlueFirst(VkFormat format) {
|
bool IsBlueFirst(VkFormat format) {
|
||||||
return format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B8G8R8A8_SRGB;
|
return format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B8G8R8A8_SRGB;
|
||||||
@@ -196,68 +197,11 @@ FrameGen::FrameGen(MemoryAllocator& memory_allocator_, Scheduler& scheduler_)
|
|||||||
|
|
||||||
FrameGen::~FrameGen() = default;
|
FrameGen::~FrameGen() = default;
|
||||||
|
|
||||||
void FrameGen::UpdateBaseRate() {
|
|
||||||
const auto now = Clock::now();
|
|
||||||
if (last_process_time.time_since_epoch().count() != 0) {
|
|
||||||
const f32 seconds = std::chrono::duration<f32>(now - last_process_time).count();
|
|
||||||
const f32 rate = seconds > 0.0f ? 1.0f / seconds : 0.0f;
|
|
||||||
if (rate >= 1.0f && rate <= 1000.0f) {
|
|
||||||
smoothed_base_rate = smoothed_base_rate <= 0.0f
|
|
||||||
? rate
|
|
||||||
: smoothed_base_rate +
|
|
||||||
(rate - smoothed_base_rate) * BASE_RATE_SMOOTHING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_process_time = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FrameGen::DesiredGenerations() const {
|
|
||||||
if (!Settings::values.frame_gen.GetValue()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 target = Settings::values.frame_gen_target_rate.GetValue();
|
|
||||||
if (target == 0) {
|
|
||||||
return Settings::FrameGenGenerations();
|
|
||||||
}
|
|
||||||
if (smoothed_base_rate <= 1.0f) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t multiplier = static_cast<size_t>(static_cast<f32>(target) / smoothed_base_rate);
|
|
||||||
return std::clamp<size_t>(multiplier, 1, LSFG_MAX_GENERATIONS + 1) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameGen::UpdateGenerationCount() {
|
|
||||||
const size_t desired = DesiredGenerations();
|
|
||||||
if (desired == stable_generations) {
|
|
||||||
pending_generation_votes = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desired != pending_generations) {
|
|
||||||
pending_generations = desired;
|
|
||||||
pending_generation_votes = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++pending_generation_votes >= GENERATION_CHANGE_VOTES) {
|
|
||||||
stable_generations = desired;
|
|
||||||
pending_generation_votes = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FrameGen::WantedGenerations() {
|
|
||||||
UpdateBaseRate();
|
|
||||||
UpdateGenerationCount();
|
|
||||||
return unavailable ? 0 : stable_generations;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameGen::Process(const Device& device, Frame* frame, VkFormat format, VkExtent2D guest_extent,
|
void FrameGen::Process(const Device& device, Frame* frame, VkFormat format, VkExtent2D guest_extent,
|
||||||
bool generate) {
|
bool generate) {
|
||||||
generated = false;
|
generated = false;
|
||||||
|
|
||||||
if (unavailable || !Settings::values.frame_gen.GetValue()) {
|
if (unavailable || ConfiguredGenerations() == 0) {
|
||||||
if (chain) {
|
if (chain) {
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
chain.reset();
|
chain.reset();
|
||||||
@@ -290,8 +234,8 @@ void FrameGen::Process(const Device& device, Frame* frame, VkFormat format, VkEx
|
|||||||
|
|
||||||
const u64 count = frame_count++;
|
const u64 count = frame_count++;
|
||||||
last_count = count;
|
last_count = count;
|
||||||
last_generations = stable_generations;
|
last_generations = ConfiguredGenerations();
|
||||||
generated = generate && last_generations > 0 && count + 1 >= LSFG_REQUIRED_FRAMES;
|
generated = generate && count + 1 >= LSFG_REQUIRED_FRAMES;
|
||||||
|
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([this, source = *frame->image, extent, count,
|
scheduler.Record([this, source = *frame->image, extent, count,
|
||||||
@@ -311,6 +255,13 @@ void FrameGen::Process(const Device& device, Frame* frame, VkFormat format, VkEx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t FrameGen::WantedGenerations() const {
|
||||||
|
if (unavailable) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ConfiguredGenerations();
|
||||||
|
}
|
||||||
|
|
||||||
size_t FrameGen::GeneratedFrameCount() const {
|
size_t FrameGen::GeneratedFrameCount() const {
|
||||||
return generated ? last_generations : 0;
|
return generated ? last_generations : 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
@@ -25,19 +24,14 @@ public:
|
|||||||
void Process(const Device& device, Frame* frame, VkFormat format, VkExtent2D guest_extent,
|
void Process(const Device& device, Frame* frame, VkFormat format, VkExtent2D guest_extent,
|
||||||
bool generate);
|
bool generate);
|
||||||
|
|
||||||
[[nodiscard]] size_t WantedGenerations();
|
[[nodiscard]] size_t WantedGenerations() const;
|
||||||
|
|
||||||
[[nodiscard]] size_t GeneratedFrameCount() const;
|
[[nodiscard]] size_t GeneratedFrameCount() const;
|
||||||
|
|
||||||
void GenerateInto(const Device& device, Frame* destination, size_t generation);
|
void GenerateInto(const Device& device, Frame* destination, size_t generation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Clock = std::chrono::steady_clock;
|
|
||||||
|
|
||||||
void Rebuild(const Device& device, VkExtent2D extent, VkFormat format, f32 flow_scale);
|
void Rebuild(const Device& device, VkExtent2D extent, VkFormat format, f32 flow_scale);
|
||||||
void UpdateBaseRate();
|
|
||||||
void UpdateGenerationCount();
|
|
||||||
[[nodiscard]] size_t DesiredGenerations() const;
|
|
||||||
void DumpDebugImages(u64 count);
|
void DumpDebugImages(u64 count);
|
||||||
|
|
||||||
MemoryAllocator& memory_allocator;
|
MemoryAllocator& memory_allocator;
|
||||||
@@ -52,12 +46,6 @@ private:
|
|||||||
u64 frame_count{};
|
u64 frame_count{};
|
||||||
u64 last_count{};
|
u64 last_count{};
|
||||||
size_t last_generations{};
|
size_t last_generations{};
|
||||||
|
|
||||||
Clock::time_point last_process_time{};
|
|
||||||
f32 smoothed_base_rate{};
|
|
||||||
size_t stable_generations{};
|
|
||||||
size_t pending_generations{};
|
|
||||||
u32 pending_generation_votes{};
|
|
||||||
bool generated{};
|
bool generated{};
|
||||||
bool unavailable{};
|
bool unavailable{};
|
||||||
bool dumped{};
|
bool dumped{};
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ void PresentManager::SetImageCount() {
|
|||||||
// We cannot have more than 7 images in flight at any given time.
|
// We cannot have more than 7 images in flight at any given time.
|
||||||
// FRAMES_IN_FLIGHT is 8, and the cache TICKS_TO_DESTROY is 8.
|
// FRAMES_IN_FLIGHT is 8, and the cache TICKS_TO_DESTROY is 8.
|
||||||
// Mali drivers will give us 6.
|
// Mali drivers will give us 6.
|
||||||
const size_t generations = Settings::FrameGenMaxGenerations();
|
const size_t generations = Settings::FrameGenGenerations();
|
||||||
const size_t queued_composites = Settings::values.frame_gen_queue_target.GetValue() + 1;
|
const size_t queued_composites = Settings::values.frame_gen_queue_target.GetValue() + 1;
|
||||||
image_count =
|
image_count =
|
||||||
std::clamp<size_t>((generations + 1) * queued_composites, swapchain.GetImageCount(),
|
std::clamp<size_t>((generations + 1) * queued_composites, swapchain.GetImageCount(),
|
||||||
|
|||||||
Reference in New Issue
Block a user