diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/audio_core/renderer/command/resample/upsample.cpp | 97 | ||||
-rw-r--r-- | src/common/settings.cpp | 12 | ||||
-rw-r--r-- | src/common/settings.h | 13 | ||||
-rw-r--r-- | src/core/core_timing.cpp | 42 | ||||
-rw-r--r-- | src/core/core_timing.h | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/k_hardware_timer.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.h | 2 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_graphics.ui | 15 |
10 files changed, 107 insertions, 99 deletions
diff --git a/src/audio_core/renderer/command/resample/upsample.cpp b/src/audio_core/renderer/command/resample/upsample.cpp index 6c3ff31f7..5f7db12ca 100644 --- a/src/audio_core/renderer/command/resample/upsample.cpp +++ b/src/audio_core/renderer/command/resample/upsample.cpp @@ -20,25 +20,25 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, const u32 target_sample_count, const u32 source_sample_count, UpsamplerState* state) { constexpr u32 WindowSize = 10; - constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow1{ - 51.93359375f, -18.80078125f, 9.73046875f, -5.33203125f, 2.84375f, - -1.41015625f, 0.62109375f, -0.2265625f, 0.0625f, -0.00390625f, + constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{ + 0.95376587f, -0.12872314f, 0.060028076f, -0.032470703f, 0.017669678f, + -0.009124756f, 0.004272461f, -0.001739502f, 0.000579834f, -0.000091552734f, }; - constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow2{ - 105.35546875f, -24.52734375f, 11.9609375f, -6.515625f, 3.52734375f, - -1.796875f, 0.828125f, -0.32421875f, 0.1015625f, -0.015625f, + constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{ + 0.8230896f, -0.19161987f, 0.093444824f, -0.05090332f, 0.027557373f, + -0.014038086f, 0.0064697266f, -0.002532959f, 0.00079345703f, -0.00012207031f, }; - constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow3{ - 122.08203125f, -16.47656250f, 7.68359375f, -4.15625000f, 2.26171875f, - -1.16796875f, 0.54687500f, -0.22265625f, 0.07421875f, -0.01171875f, + constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{ + 0.6298828f, -0.19274902f, 0.09725952f, -0.05319214f, 0.028625488f, + -0.014373779f, 0.006500244f, -0.0024719238f, 0.0007324219f, -0.000091552734f, }; - constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow4{ - 23.73437500f, -9.62109375f, 5.07812500f, -2.78125000f, 1.46875000f, - -0.71484375f, 0.30859375f, -0.10546875f, 0.02734375f, 0.00000000f, + constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{ + 0.4057312f, -0.1468811f, 0.07601929f, -0.041656494f, 0.022216797f, + -0.011016846f, 0.004852295f, -0.0017700195f, 0.00048828125f, -0.000030517578f, }; - constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow5{ - 80.62500000f, -24.67187500f, 12.44921875f, -6.80859375f, 3.66406250f, - -1.83984375f, 0.83203125f, -0.31640625f, 0.09375000f, -0.01171875f, + constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{ + 0.1854248f, -0.075164795f, 0.03967285f, -0.021728516f, 0.011474609f, + -0.005584717f, 0.0024108887f, -0.0008239746f, 0.00021362305f, 0.0f, }; if (!state->initialized) { @@ -91,52 +91,31 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize); }; - auto calculate_sample = [&state](std::span<const Common::FixedPoint<24, 8>> coeffs1, - std::span<const Common::FixedPoint<24, 8>> coeffs2) -> s32 { + auto calculate_sample = [&state](std::span<const Common::FixedPoint<17, 15>> coeffs1, + std::span<const Common::FixedPoint<17, 15>> coeffs2) -> s32 { auto output_index{state->history_output_index}; - auto start_pos{output_index - state->history_start_index + 1U}; - auto end_pos{10U}; + u64 result{0}; - if (start_pos < 10) { - end_pos = start_pos; - } - - u64 prev_contrib{0}; - u32 coeff_index{0}; - for (; coeff_index < end_pos; coeff_index++, output_index--) { - prev_contrib += static_cast<u64>(state->history[output_index].to_raw()) * - coeffs1[coeff_index].to_raw(); - } + for (u32 coeff_index = 0; coeff_index < 10; coeff_index++) { + result += static_cast<u64>(state->history[output_index].to_raw()) * + coeffs1[coeff_index].to_raw(); - auto end_index{state->history_end_index}; - for (; start_pos < 9; start_pos++, coeff_index++, end_index--) { - prev_contrib += static_cast<u64>(state->history[end_index].to_raw()) * - coeffs1[coeff_index].to_raw(); + output_index = output_index == state->history_start_index ? state->history_end_index + : output_index - 1; } output_index = static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize); - start_pos = state->history_end_index - output_index + 1U; - end_pos = 10U; - if (start_pos < 10) { - end_pos = start_pos; - } - - u64 next_contrib{0}; - coeff_index = 0; - for (; coeff_index < end_pos; coeff_index++, output_index++) { - next_contrib += static_cast<u64>(state->history[output_index].to_raw()) * - coeffs2[coeff_index].to_raw(); - } + for (u32 coeff_index = 0; coeff_index < 10; coeff_index++) { + result += static_cast<u64>(state->history[output_index].to_raw()) * + coeffs2[coeff_index].to_raw(); - auto start_index{state->history_start_index}; - for (; start_pos < 9; start_pos++, start_index++, coeff_index++) { - next_contrib += static_cast<u64>(state->history[start_index].to_raw()) * - coeffs2[coeff_index].to_raw(); + output_index = output_index == state->history_end_index ? state->history_start_index + : output_index + 1; } - return static_cast<s32>(((prev_contrib >> 15) + (next_contrib >> 15)) >> 8); + return static_cast<s32>(result >> (8 + 15)); }; switch (state->ratio.to_int_floor()) { @@ -150,23 +129,23 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, break; case 1: - output[write_index] = calculate_sample(SincWindow3, SincWindow4); + output[write_index] = calculate_sample(WindowedSinc1, WindowedSinc5); break; case 2: - output[write_index] = calculate_sample(SincWindow2, SincWindow1); + output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4); break; case 3: - output[write_index] = calculate_sample(SincWindow5, SincWindow5); + output[write_index] = calculate_sample(WindowedSinc3, WindowedSinc3); break; case 4: - output[write_index] = calculate_sample(SincWindow1, SincWindow2); + output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2); break; case 5: - output[write_index] = calculate_sample(SincWindow4, SincWindow3); + output[write_index] = calculate_sample(WindowedSinc5, WindowedSinc1); break; } state->sample_index = static_cast<u8>((state->sample_index + 1) % 6); @@ -183,11 +162,11 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, break; case 1: - output[write_index] = calculate_sample(SincWindow2, SincWindow1); + output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4); break; case 2: - output[write_index] = calculate_sample(SincWindow1, SincWindow2); + output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2); break; } state->sample_index = static_cast<u8>((state->sample_index + 1) % 3); @@ -204,12 +183,12 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, break; case 1: - output[write_index] = calculate_sample(SincWindow1, SincWindow2); + output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2); break; case 2: increment(); - output[write_index] = calculate_sample(SincWindow2, SincWindow1); + output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4); break; } state->sample_index = static_cast<u8>((state->sample_index + 1) % 3); diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 1638b79f5..b1a2aa8b2 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -129,6 +129,10 @@ void UpdateRescalingInfo() { info.up_scale = 1; info.down_shift = 0; break; + case ResolutionSetup::Res3_2X: + info.up_scale = 3; + info.down_shift = 1; + break; case ResolutionSetup::Res2X: info.up_scale = 2; info.down_shift = 0; @@ -149,6 +153,14 @@ void UpdateRescalingInfo() { info.up_scale = 6; info.down_shift = 0; break; + case ResolutionSetup::Res7X: + info.up_scale = 7; + info.down_shift = 0; + break; + case ResolutionSetup::Res8X: + info.up_scale = 8; + info.down_shift = 0; + break; default: ASSERT(false); info.up_scale = 1; diff --git a/src/common/settings.h b/src/common/settings.h index a457e3f23..80b2eeabc 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -56,11 +56,14 @@ enum class ResolutionSetup : u32 { Res1_2X = 0, Res3_4X = 1, Res1X = 2, - Res2X = 3, - Res3X = 4, - Res4X = 5, - Res5X = 6, - Res6X = 7, + Res3_2X = 3, + Res2X = 4, + Res3X = 5, + Res4X = 6, + Res5X = 7, + Res6X = 8, + Res7X = 9, + Res8X = 10, }; enum class ScalingFilter : u32 { diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 0e7b5f943..6bac6722f 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -142,16 +142,24 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, } void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, - std::uintptr_t user_data) { - std::scoped_lock scope{basic_lock}; - const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { - return e.type.lock().get() == event_type.get() && e.user_data == user_data; - }); - - // Removing random items breaks the invariant so we have to re-establish it. - if (itr != event_queue.end()) { - event_queue.erase(itr, event_queue.end()); - std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); + std::uintptr_t user_data, bool wait) { + { + std::scoped_lock lk{basic_lock}; + const auto itr = + std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { + return e.type.lock().get() == event_type.get() && e.user_data == user_data; + }); + + // Removing random items breaks the invariant so we have to re-establish it. + if (itr != event_queue.end()) { + event_queue.erase(itr, event_queue.end()); + std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); + } + } + + // Force any in-progress events to finish + if (wait) { + std::scoped_lock lk{advance_lock}; } } @@ -190,20 +198,6 @@ u64 CoreTiming::GetClockTicks() const { return CpuCyclesToClockCycles(ticks); } -void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { - std::scoped_lock lock{basic_lock}; - - const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { - return e.type.lock().get() == event_type.get(); - }); - - // Removing random items breaks the invariant so we have to re-establish it. - if (itr != event_queue.end()) { - event_queue.erase(itr, event_queue.end()); - std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - } -} - std::optional<s64> CoreTiming::Advance() { std::scoped_lock lock{advance_lock, basic_lock}; global_timer = GetGlobalTimeNs().count(); diff --git a/src/core/core_timing.h b/src/core/core_timing.h index b5925193c..da366637b 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -98,10 +98,13 @@ public: const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data = 0, bool absolute_time = false); - void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data); + void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data, + bool wait = true); - /// We only permit one event of each type in the queue at a time. - void RemoveEvent(const std::shared_ptr<EventType>& event_type); + void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type, + std::uintptr_t user_data) { + UnscheduleEvent(event_type, user_data, false); + } void AddTicks(u64 ticks_to_add); diff --git a/src/core/hle/kernel/k_hardware_timer.cpp b/src/core/hle/kernel/k_hardware_timer.cpp index 6bba79ea0..4dcd53821 100644 --- a/src/core/hle/kernel/k_hardware_timer.cpp +++ b/src/core/hle/kernel/k_hardware_timer.cpp @@ -18,7 +18,8 @@ void KHardwareTimer::Initialize() { } void KHardwareTimer::Finalize() { - this->DisableInterrupt(); + m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); + m_wakeup_time = std::numeric_limits<s64>::max(); m_event_type.reset(); } @@ -59,7 +60,8 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) { } void KHardwareTimer::DisableInterrupt() { - m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); + m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type, + reinterpret_cast<uintptr_t>(this)); m_wakeup_time = std::numeric_limits<s64>::max(); } diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index d1cbadde4..f4416f5b2 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -312,8 +312,6 @@ void NVFlinger::Compose() { } s64 NVFlinger::GetNextTicks() const { - static constexpr s64 max_hertz = 120LL; - const auto& settings = Settings::values; auto speed_scale = 1.f; if (settings.use_multi_core.GetValue()) { @@ -327,9 +325,11 @@ s64 NVFlinger::GetNextTicks() const { } } - const auto next_ticks = ((1000000000 * (1LL << swap_interval)) / max_hertz); + // As an extension, treat nonpositive swap interval as framerate multiplier. + const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval) + : 60.f / static_cast<f32>(swap_interval); - return static_cast<s64>(speed_scale * static_cast<float>(next_ticks)); + return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); } } // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 9b22397db..3828cf272 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -133,7 +133,7 @@ private: /// layers. u32 next_buffer_queue_id = 1; - u32 swap_interval = 1; + s32 swap_interval = 1; /// Event that handles screen composition. std::shared_ptr<Core::Timing::EventType> multi_composition_event; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 97f547789..68ceda519 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -467,7 +467,7 @@ void Maxwell3D::ProcessMacroBind(u32 data) { } void Maxwell3D::ProcessFirmwareCall4() { - LOG_WARNING(HW_GPU, "(STUBBED) called"); + LOG_DEBUG(HW_GPU, "(STUBBED) called"); // Firmware call 4 is a blob that changes some registers depending on its parameters. // These registers don't affect emulation and so are stubbed by setting 0xd00 to 1. diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index aa02cc63c..bb9910a53 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -366,6 +366,11 @@ </item> <item> <property name="text"> + <string>1.5X (1080p/1620p) [EXPERIMENTAL]</string> + </property> + </item> + <item> + <property name="text"> <string>2X (1440p/2160p)</string> </property> </item> @@ -389,6 +394,16 @@ <string>6X (4320p/6480p)</string> </property> </item> + <item> + <property name="text"> + <string>7X (5040p/7560p)</string> + </property> + </item> + <item> + <property name="text"> + <string>8X (5760p/8640p)</string> + </property> + </item> </widget> </item> </layout> |