diff options
| m--------- | externals/dynarmic | 0 | ||||
| -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 |
11 files changed, 107 insertions, 99 deletions
diff --git a/externals/dynarmic b/externals/dynarmic | |||
| Subproject a1cbea7948372989218a4e6159a95998d65876a | Subproject befe547d5631024a70d81d2ccee808bbfcb3854 | ||
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, | |||
| 20 | const u32 target_sample_count, const u32 source_sample_count, | 20 | const u32 target_sample_count, const u32 source_sample_count, |
| 21 | UpsamplerState* state) { | 21 | UpsamplerState* state) { |
| 22 | constexpr u32 WindowSize = 10; | 22 | constexpr u32 WindowSize = 10; |
| 23 | constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow1{ | 23 | constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{ |
| 24 | 51.93359375f, -18.80078125f, 9.73046875f, -5.33203125f, 2.84375f, | 24 | 0.95376587f, -0.12872314f, 0.060028076f, -0.032470703f, 0.017669678f, |
| 25 | -1.41015625f, 0.62109375f, -0.2265625f, 0.0625f, -0.00390625f, | 25 | -0.009124756f, 0.004272461f, -0.001739502f, 0.000579834f, -0.000091552734f, |
| 26 | }; | 26 | }; |
| 27 | constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow2{ | 27 | constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{ |
| 28 | 105.35546875f, -24.52734375f, 11.9609375f, -6.515625f, 3.52734375f, | 28 | 0.8230896f, -0.19161987f, 0.093444824f, -0.05090332f, 0.027557373f, |
| 29 | -1.796875f, 0.828125f, -0.32421875f, 0.1015625f, -0.015625f, | 29 | -0.014038086f, 0.0064697266f, -0.002532959f, 0.00079345703f, -0.00012207031f, |
| 30 | }; | 30 | }; |
| 31 | constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow3{ | 31 | constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{ |
| 32 | 122.08203125f, -16.47656250f, 7.68359375f, -4.15625000f, 2.26171875f, | 32 | 0.6298828f, -0.19274902f, 0.09725952f, -0.05319214f, 0.028625488f, |
| 33 | -1.16796875f, 0.54687500f, -0.22265625f, 0.07421875f, -0.01171875f, | 33 | -0.014373779f, 0.006500244f, -0.0024719238f, 0.0007324219f, -0.000091552734f, |
| 34 | }; | 34 | }; |
| 35 | constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow4{ | 35 | constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{ |
| 36 | 23.73437500f, -9.62109375f, 5.07812500f, -2.78125000f, 1.46875000f, | 36 | 0.4057312f, -0.1468811f, 0.07601929f, -0.041656494f, 0.022216797f, |
| 37 | -0.71484375f, 0.30859375f, -0.10546875f, 0.02734375f, 0.00000000f, | 37 | -0.011016846f, 0.004852295f, -0.0017700195f, 0.00048828125f, -0.000030517578f, |
| 38 | }; | 38 | }; |
| 39 | constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow5{ | 39 | constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{ |
| 40 | 80.62500000f, -24.67187500f, 12.44921875f, -6.80859375f, 3.66406250f, | 40 | 0.1854248f, -0.075164795f, 0.03967285f, -0.021728516f, 0.011474609f, |
| 41 | -1.83984375f, 0.83203125f, -0.31640625f, 0.09375000f, -0.01171875f, | 41 | -0.005584717f, 0.0024108887f, -0.0008239746f, 0.00021362305f, 0.0f, |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | if (!state->initialized) { | 44 | if (!state->initialized) { |
| @@ -91,52 +91,31 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, | |||
| 91 | static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize); | 91 | static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize); |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | auto calculate_sample = [&state](std::span<const Common::FixedPoint<24, 8>> coeffs1, | 94 | auto calculate_sample = [&state](std::span<const Common::FixedPoint<17, 15>> coeffs1, |
| 95 | std::span<const Common::FixedPoint<24, 8>> coeffs2) -> s32 { | 95 | std::span<const Common::FixedPoint<17, 15>> coeffs2) -> s32 { |
| 96 | auto output_index{state->history_output_index}; | 96 | auto output_index{state->history_output_index}; |
| 97 | auto start_pos{output_index - state->history_start_index + 1U}; | 97 | u64 result{0}; |
| 98 | auto end_pos{10U}; | ||
| 99 | 98 | ||
| 100 | if (start_pos < 10) { | 99 | for (u32 coeff_index = 0; coeff_index < 10; coeff_index++) { |
| 101 | end_pos = start_pos; | 100 | result += static_cast<u64>(state->history[output_index].to_raw()) * |
| 102 | } | 101 | coeffs1[coeff_index].to_raw(); |
| 103 | |||
| 104 | u64 prev_contrib{0}; | ||
| 105 | u32 coeff_index{0}; | ||
| 106 | for (; coeff_index < end_pos; coeff_index++, output_index--) { | ||
| 107 | prev_contrib += static_cast<u64>(state->history[output_index].to_raw()) * | ||
| 108 | coeffs1[coeff_index].to_raw(); | ||
| 109 | } | ||
| 110 | 102 | ||
| 111 | auto end_index{state->history_end_index}; | 103 | output_index = output_index == state->history_start_index ? state->history_end_index |
| 112 | for (; start_pos < 9; start_pos++, coeff_index++, end_index--) { | 104 | : output_index - 1; |
| 113 | prev_contrib += static_cast<u64>(state->history[end_index].to_raw()) * | ||
| 114 | coeffs1[coeff_index].to_raw(); | ||
| 115 | } | 105 | } |
| 116 | 106 | ||
| 117 | output_index = | 107 | output_index = |
| 118 | static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize); | 108 | static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize); |
| 119 | start_pos = state->history_end_index - output_index + 1U; | ||
| 120 | end_pos = 10U; | ||
| 121 | 109 | ||
| 122 | if (start_pos < 10) { | 110 | for (u32 coeff_index = 0; coeff_index < 10; coeff_index++) { |
| 123 | end_pos = start_pos; | 111 | result += static_cast<u64>(state->history[output_index].to_raw()) * |
| 124 | } | 112 | coeffs2[coeff_index].to_raw(); |
| 125 | |||
| 126 | u64 next_contrib{0}; | ||
| 127 | coeff_index = 0; | ||
| 128 | for (; coeff_index < end_pos; coeff_index++, output_index++) { | ||
| 129 | next_contrib += static_cast<u64>(state->history[output_index].to_raw()) * | ||
| 130 | coeffs2[coeff_index].to_raw(); | ||
| 131 | } | ||
| 132 | 113 | ||
| 133 | auto start_index{state->history_start_index}; | 114 | output_index = output_index == state->history_end_index ? state->history_start_index |
| 134 | for (; start_pos < 9; start_pos++, start_index++, coeff_index++) { | 115 | : output_index + 1; |
| 135 | next_contrib += static_cast<u64>(state->history[start_index].to_raw()) * | ||
| 136 | coeffs2[coeff_index].to_raw(); | ||
| 137 | } | 116 | } |
| 138 | 117 | ||
| 139 | return static_cast<s32>(((prev_contrib >> 15) + (next_contrib >> 15)) >> 8); | 118 | return static_cast<s32>(result >> (8 + 15)); |
| 140 | }; | 119 | }; |
| 141 | 120 | ||
| 142 | switch (state->ratio.to_int_floor()) { | 121 | switch (state->ratio.to_int_floor()) { |
| @@ -150,23 +129,23 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input, | |||
| 150 | break; | 129 | break; |
| 151 | 130 | ||
| 152 | case 1: | 131 | case 1: |
| 153 | output[write_index] = calculate_sample(SincWindow3, SincWindow4); | 132 | output[write_index] = calculate_sample(WindowedSinc1, WindowedSinc5); |
| 154 | break; | 133 | break; |
| 155 | 134 | ||
| 156 | case 2: | 135 | case 2: |
| 157 | output[write_index] = calculate_sample(SincWindow2, SincWindow1); | 136 | output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4); |
| 158 | break; | 137 | break; |
| 159 | 138 | ||
| 160 | case 3: | 139 | case 3: |
| 161 | output[write_index] = calculate_sample(SincWindow5, SincWindow5); | 140 | output[write_index] = calculate_sample(WindowedSinc3, WindowedSinc3); |
| 162 | break; | 141 | break; |
| 163 | 142 | ||
| 164 | case 4: | 143 | case 4: |
| 165 | output[write_index] = calculate_sample(SincWindow1, SincWindow2); | 144 | output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2); |
| 166 | break; | 145 | break; |
| 167 | 146 | ||
| 168 | case 5: | 147 | case 5: |
| 169 | output[write_index] = calculate_sample(SincWindow4, SincWindow3); | 148 | output[write_index] = calculate_sample(WindowedSinc5, WindowedSinc1); |
| 170 | break; | 149 | break; |
| 171 | } | 150 | } |
| 172 | state->sample_index = static_cast<u8>((state->sample_index + 1) % 6); | 151 | 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, | |||
| 183 | break; | 162 | break; |
| 184 | 163 | ||
| 185 | case 1: | 164 | case 1: |
| 186 | output[write_index] = calculate_sample(SincWindow2, SincWindow1); | 165 | output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4); |
| 187 | break; | 166 | break; |
| 188 | 167 | ||
| 189 | case 2: | 168 | case 2: |
| 190 | output[write_index] = calculate_sample(SincWindow1, SincWindow2); | 169 | output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2); |
| 191 | break; | 170 | break; |
| 192 | } | 171 | } |
| 193 | state->sample_index = static_cast<u8>((state->sample_index + 1) % 3); | 172 | 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, | |||
| 204 | break; | 183 | break; |
| 205 | 184 | ||
| 206 | case 1: | 185 | case 1: |
| 207 | output[write_index] = calculate_sample(SincWindow1, SincWindow2); | 186 | output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2); |
| 208 | break; | 187 | break; |
| 209 | 188 | ||
| 210 | case 2: | 189 | case 2: |
| 211 | increment(); | 190 | increment(); |
| 212 | output[write_index] = calculate_sample(SincWindow2, SincWindow1); | 191 | output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4); |
| 213 | break; | 192 | break; |
| 214 | } | 193 | } |
| 215 | state->sample_index = static_cast<u8>((state->sample_index + 1) % 3); | 194 | 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() { | |||
| 129 | info.up_scale = 1; | 129 | info.up_scale = 1; |
| 130 | info.down_shift = 0; | 130 | info.down_shift = 0; |
| 131 | break; | 131 | break; |
| 132 | case ResolutionSetup::Res3_2X: | ||
| 133 | info.up_scale = 3; | ||
| 134 | info.down_shift = 1; | ||
| 135 | break; | ||
| 132 | case ResolutionSetup::Res2X: | 136 | case ResolutionSetup::Res2X: |
| 133 | info.up_scale = 2; | 137 | info.up_scale = 2; |
| 134 | info.down_shift = 0; | 138 | info.down_shift = 0; |
| @@ -149,6 +153,14 @@ void UpdateRescalingInfo() { | |||
| 149 | info.up_scale = 6; | 153 | info.up_scale = 6; |
| 150 | info.down_shift = 0; | 154 | info.down_shift = 0; |
| 151 | break; | 155 | break; |
| 156 | case ResolutionSetup::Res7X: | ||
| 157 | info.up_scale = 7; | ||
| 158 | info.down_shift = 0; | ||
| 159 | break; | ||
| 160 | case ResolutionSetup::Res8X: | ||
| 161 | info.up_scale = 8; | ||
| 162 | info.down_shift = 0; | ||
| 163 | break; | ||
| 152 | default: | 164 | default: |
| 153 | ASSERT(false); | 165 | ASSERT(false); |
| 154 | info.up_scale = 1; | 166 | 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 { | |||
| 56 | Res1_2X = 0, | 56 | Res1_2X = 0, |
| 57 | Res3_4X = 1, | 57 | Res3_4X = 1, |
| 58 | Res1X = 2, | 58 | Res1X = 2, |
| 59 | Res2X = 3, | 59 | Res3_2X = 3, |
| 60 | Res3X = 4, | 60 | Res2X = 4, |
| 61 | Res4X = 5, | 61 | Res3X = 5, |
| 62 | Res5X = 6, | 62 | Res4X = 6, |
| 63 | Res6X = 7, | 63 | Res5X = 7, |
| 64 | Res6X = 8, | ||
| 65 | Res7X = 9, | ||
| 66 | Res8X = 10, | ||
| 64 | }; | 67 | }; |
| 65 | 68 | ||
| 66 | enum class ScalingFilter : u32 { | 69 | 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, | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | 144 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, |
| 145 | std::uintptr_t user_data) { | 145 | std::uintptr_t user_data, bool wait) { |
| 146 | std::scoped_lock scope{basic_lock}; | 146 | { |
| 147 | const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { | 147 | std::scoped_lock lk{basic_lock}; |
| 148 | return e.type.lock().get() == event_type.get() && e.user_data == user_data; | 148 | const auto itr = |
| 149 | }); | 149 | std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { |
| 150 | 150 | return e.type.lock().get() == event_type.get() && e.user_data == user_data; | |
| 151 | // Removing random items breaks the invariant so we have to re-establish it. | 151 | }); |
| 152 | if (itr != event_queue.end()) { | 152 | |
| 153 | event_queue.erase(itr, event_queue.end()); | 153 | // Removing random items breaks the invariant so we have to re-establish it. |
| 154 | std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 154 | if (itr != event_queue.end()) { |
| 155 | event_queue.erase(itr, event_queue.end()); | ||
| 156 | std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | // Force any in-progress events to finish | ||
| 161 | if (wait) { | ||
| 162 | std::scoped_lock lk{advance_lock}; | ||
| 155 | } | 163 | } |
| 156 | } | 164 | } |
| 157 | 165 | ||
| @@ -190,20 +198,6 @@ u64 CoreTiming::GetClockTicks() const { | |||
| 190 | return CpuCyclesToClockCycles(ticks); | 198 | return CpuCyclesToClockCycles(ticks); |
| 191 | } | 199 | } |
| 192 | 200 | ||
| 193 | void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { | ||
| 194 | std::scoped_lock lock{basic_lock}; | ||
| 195 | |||
| 196 | const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { | ||
| 197 | return e.type.lock().get() == event_type.get(); | ||
| 198 | }); | ||
| 199 | |||
| 200 | // Removing random items breaks the invariant so we have to re-establish it. | ||
| 201 | if (itr != event_queue.end()) { | ||
| 202 | event_queue.erase(itr, event_queue.end()); | ||
| 203 | std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | std::optional<s64> CoreTiming::Advance() { | 201 | std::optional<s64> CoreTiming::Advance() { |
| 208 | std::scoped_lock lock{advance_lock, basic_lock}; | 202 | std::scoped_lock lock{advance_lock, basic_lock}; |
| 209 | global_timer = GetGlobalTimeNs().count(); | 203 | 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: | |||
| 98 | const std::shared_ptr<EventType>& event_type, | 98 | const std::shared_ptr<EventType>& event_type, |
| 99 | std::uintptr_t user_data = 0, bool absolute_time = false); | 99 | std::uintptr_t user_data = 0, bool absolute_time = false); |
| 100 | 100 | ||
| 101 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data); | 101 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data, |
| 102 | bool wait = true); | ||
| 102 | 103 | ||
| 103 | /// We only permit one event of each type in the queue at a time. | 104 | void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type, |
| 104 | void RemoveEvent(const std::shared_ptr<EventType>& event_type); | 105 | std::uintptr_t user_data) { |
| 106 | UnscheduleEvent(event_type, user_data, false); | ||
| 107 | } | ||
| 105 | 108 | ||
| 106 | void AddTicks(u64 ticks_to_add); | 109 | void AddTicks(u64 ticks_to_add); |
| 107 | 110 | ||
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() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void KHardwareTimer::Finalize() { | 20 | void KHardwareTimer::Finalize() { |
| 21 | this->DisableInterrupt(); | 21 | m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); |
| 22 | m_wakeup_time = std::numeric_limits<s64>::max(); | ||
| 22 | m_event_type.reset(); | 23 | m_event_type.reset(); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| @@ -59,7 +60,8 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) { | |||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | void KHardwareTimer::DisableInterrupt() { | 62 | void KHardwareTimer::DisableInterrupt() { |
| 62 | m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); | 63 | m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type, |
| 64 | reinterpret_cast<uintptr_t>(this)); | ||
| 63 | m_wakeup_time = std::numeric_limits<s64>::max(); | 65 | m_wakeup_time = std::numeric_limits<s64>::max(); |
| 64 | } | 66 | } |
| 65 | 67 | ||
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() { | |||
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | s64 NVFlinger::GetNextTicks() const { | 314 | s64 NVFlinger::GetNextTicks() const { |
| 315 | static constexpr s64 max_hertz = 120LL; | ||
| 316 | |||
| 317 | const auto& settings = Settings::values; | 315 | const auto& settings = Settings::values; |
| 318 | auto speed_scale = 1.f; | 316 | auto speed_scale = 1.f; |
| 319 | if (settings.use_multi_core.GetValue()) { | 317 | if (settings.use_multi_core.GetValue()) { |
| @@ -327,9 +325,11 @@ s64 NVFlinger::GetNextTicks() const { | |||
| 327 | } | 325 | } |
| 328 | } | 326 | } |
| 329 | 327 | ||
| 330 | const auto next_ticks = ((1000000000 * (1LL << swap_interval)) / max_hertz); | 328 | // As an extension, treat nonpositive swap interval as framerate multiplier. |
| 329 | const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval) | ||
| 330 | : 60.f / static_cast<f32>(swap_interval); | ||
| 331 | 331 | ||
| 332 | return static_cast<s64>(speed_scale * static_cast<float>(next_ticks)); | 332 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | } // namespace Service::NVFlinger | 335 | } // 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: | |||
| 133 | /// layers. | 133 | /// layers. |
| 134 | u32 next_buffer_queue_id = 1; | 134 | u32 next_buffer_queue_id = 1; |
| 135 | 135 | ||
| 136 | u32 swap_interval = 1; | 136 | s32 swap_interval = 1; |
| 137 | 137 | ||
| 138 | /// Event that handles screen composition. | 138 | /// Event that handles screen composition. |
| 139 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; | 139 | 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) { | |||
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | void Maxwell3D::ProcessFirmwareCall4() { | 469 | void Maxwell3D::ProcessFirmwareCall4() { |
| 470 | LOG_WARNING(HW_GPU, "(STUBBED) called"); | 470 | LOG_DEBUG(HW_GPU, "(STUBBED) called"); |
| 471 | 471 | ||
| 472 | // Firmware call 4 is a blob that changes some registers depending on its parameters. | 472 | // Firmware call 4 is a blob that changes some registers depending on its parameters. |
| 473 | // These registers don't affect emulation and so are stubbed by setting 0xd00 to 1. | 473 | // 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 @@ | |||
| 366 | </item> | 366 | </item> |
| 367 | <item> | 367 | <item> |
| 368 | <property name="text"> | 368 | <property name="text"> |
| 369 | <string>1.5X (1080p/1620p) [EXPERIMENTAL]</string> | ||
| 370 | </property> | ||
| 371 | </item> | ||
| 372 | <item> | ||
| 373 | <property name="text"> | ||
| 369 | <string>2X (1440p/2160p)</string> | 374 | <string>2X (1440p/2160p)</string> |
| 370 | </property> | 375 | </property> |
| 371 | </item> | 376 | </item> |
| @@ -389,6 +394,16 @@ | |||
| 389 | <string>6X (4320p/6480p)</string> | 394 | <string>6X (4320p/6480p)</string> |
| 390 | </property> | 395 | </property> |
| 391 | </item> | 396 | </item> |
| 397 | <item> | ||
| 398 | <property name="text"> | ||
| 399 | <string>7X (5040p/7560p)</string> | ||
| 400 | </property> | ||
| 401 | </item> | ||
| 402 | <item> | ||
| 403 | <property name="text"> | ||
| 404 | <string>8X (5760p/8640p)</string> | ||
| 405 | </property> | ||
| 406 | </item> | ||
| 392 | </widget> | 407 | </widget> |
| 393 | </item> | 408 | </item> |
| 394 | </layout> | 409 | </layout> |