diff options
32 files changed, 255 insertions, 249 deletions
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 404dcd0e9..6081352a2 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -12,6 +12,7 @@ #include "audio_core/sink/sink_stream.h" #include "common/common_types.h" #include "common/fixed_point.h" +#include "common/scope_exit.h" #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" @@ -19,9 +20,12 @@ namespace AudioCore::Sink { void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { - if (type == StreamType::In) { + SCOPE_EXIT({ queue.enqueue(buffer); - queued_buffers++; + ++queued_buffers; + }); + + if (type == StreamType::In) { return; } @@ -66,16 +70,17 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { static_cast<s16>(std::clamp(right_sample, min, max)); } - samples = samples.subspan(0, samples.size() / system_channels * device_channels); + samples_buffer.Push(samples.subspan(0, samples.size() / system_channels * device_channels)); + return; + } - } else if (system_channels == 2 && device_channels == 6) { + if (system_channels == 2 && device_channels == 6) { // We need moar samples! Not all games will provide 6 channel audio. // TODO: Implement some upmixing here. Currently just passthrough, with other // channels left as silence. - auto new_size = samples.size() / system_channels * device_channels; - tmp_samples.resize_destructive(new_size); + std::vector<s16> new_samples(samples.size() / system_channels * device_channels); - for (u32 read_index = 0, write_index = 0; read_index < new_size; + for (u32 read_index = 0, write_index = 0; read_index < samples.size(); read_index += system_channels, write_index += device_channels) { const auto left_sample{static_cast<s16>(std::clamp( static_cast<s32>( @@ -83,7 +88,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { volume), min, max))}; - tmp_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample; + new_samples[write_index + static_cast<u32>(Channels::FrontLeft)] = left_sample; const auto right_sample{static_cast<s16>(std::clamp( static_cast<s32>( @@ -91,20 +96,21 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) { volume), min, max))}; - tmp_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample; + new_samples[write_index + static_cast<u32>(Channels::FrontRight)] = right_sample; } - samples = std::span<s16>(tmp_samples); - } else if (volume != 1.0f) { - for (u32 i = 0; i < samples.size(); i++) { + samples_buffer.Push(new_samples); + return; + } + + if (volume != 1.0f) { + for (u32 i = 0; i < samples.size(); ++i) { samples[i] = static_cast<s16>( std::clamp(static_cast<s32>(static_cast<f32>(samples[i]) * volume), min, max)); } } samples_buffer.Push(samples); - queue.enqueue(buffer); - queued_buffers++; } std::vector<s16> SinkStream::ReleaseBuffer(u64 num_samples) { diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h index 98d72ace1..6a4996ca3 100644 --- a/src/audio_core/sink/sink_stream.h +++ b/src/audio_core/sink/sink_stream.h @@ -16,7 +16,6 @@ #include "common/polyfill_thread.h" #include "common/reader_writer_queue.h" #include "common/ring_buffer.h" -#include "common/scratch_buffer.h" #include "common/thread.h" namespace Core { @@ -256,8 +255,6 @@ private: /// Signalled when ring buffer entries are consumed std::condition_variable_any release_cv; std::mutex release_mutex; - /// Temporary buffer for appending samples when upmixing - Common::ScratchBuffer<s16> tmp_samples{}; }; using SinkStreamPtr = std::unique_ptr<SinkStream>; diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index 416680d44..5c961b202 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h @@ -54,7 +54,7 @@ public: return push_count; } - std::size_t Push(const std::span<T> input) { + std::size_t Push(std::span<const T> input) { return Push(input.data(), input.size()); } diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h index 6fe907953..d5961b020 100644 --- a/src/common/scratch_buffer.h +++ b/src/common/scratch_buffer.h @@ -5,7 +5,6 @@ #include <iterator> -#include "common/concepts.h" #include "common/make_unique_for_overwrite.h" namespace Common { @@ -19,15 +18,22 @@ namespace Common { template <typename T> class ScratchBuffer { public: - using iterator = T*; - using const_iterator = const T*; - using value_type = T; using element_type = T; - using iterator_category = std::contiguous_iterator_tag; + using value_type = T; + using size_type = size_t; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using iterator = pointer; + using const_iterator = const_pointer; + using iterator_category = std::random_access_iterator_tag; + using iterator_concept = std::contiguous_iterator_tag; ScratchBuffer() = default; - explicit ScratchBuffer(size_t initial_capacity) + explicit ScratchBuffer(size_type initial_capacity) : last_requested_size{initial_capacity}, buffer_capacity{initial_capacity}, buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {} @@ -39,7 +45,7 @@ public: /// This will only grow the buffer's capacity if size is greater than the current capacity. /// The previously held data will remain intact. - void resize(size_t size) { + void resize(size_type size) { if (size > buffer_capacity) { auto new_buffer = Common::make_unique_for_overwrite<T[]>(size); std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get()); @@ -51,7 +57,7 @@ public: /// This will only grow the buffer's capacity if size is greater than the current capacity. /// The previously held data will be destroyed if a reallocation occurs. - void resize_destructive(size_t size) { + void resize_destructive(size_type size) { if (size > buffer_capacity) { buffer_capacity = size; buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity); @@ -59,43 +65,43 @@ public: last_requested_size = size; } - [[nodiscard]] T* data() noexcept { + [[nodiscard]] pointer data() noexcept { return buffer.get(); } - [[nodiscard]] const T* data() const noexcept { + [[nodiscard]] const_pointer data() const noexcept { return buffer.get(); } - [[nodiscard]] T* begin() noexcept { + [[nodiscard]] iterator begin() noexcept { return data(); } - [[nodiscard]] const T* begin() const noexcept { + [[nodiscard]] const_iterator begin() const noexcept { return data(); } - [[nodiscard]] T* end() noexcept { + [[nodiscard]] iterator end() noexcept { return data() + last_requested_size; } - [[nodiscard]] const T* end() const noexcept { + [[nodiscard]] const_iterator end() const noexcept { return data() + last_requested_size; } - [[nodiscard]] T& operator[](size_t i) { + [[nodiscard]] reference operator[](size_type i) { return buffer[i]; } - [[nodiscard]] const T& operator[](size_t i) const { + [[nodiscard]] const_reference operator[](size_type i) const { return buffer[i]; } - [[nodiscard]] size_t size() const noexcept { + [[nodiscard]] size_type size() const noexcept { return last_requested_size; } - [[nodiscard]] size_t capacity() const noexcept { + [[nodiscard]] size_type capacity() const noexcept { return buffer_capacity; } @@ -106,8 +112,8 @@ public: } private: - size_t last_requested_size{}; - size_t buffer_capacity{}; + size_type last_requested_size{}; + size_type buffer_capacity{}; std::unique_ptr<T[]> buffer{}; }; diff --git a/src/common/settings.h b/src/common/settings.h index ae5ed93d8..59e96e74f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -527,12 +527,10 @@ struct Values { Setting<bool> mouse_panning{false, "mouse_panning"}; Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"}; Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"}; - Setting<u8, true> mouse_panning_deadzone_x_counterweight{ - 0, 0, 100, "mouse_panning_deadzone_x_counterweight"}; - Setting<u8, true> mouse_panning_deadzone_y_counterweight{ - 0, 0, 100, "mouse_panning_deadzone_y_counterweight"}; - Setting<u8, true> mouse_panning_decay_strength{22, 0, 100, "mouse_panning_decay_strength"}; - Setting<u8, true> mouse_panning_min_decay{5, 0, 100, "mouse_panning_min_decay"}; + Setting<u8, true> mouse_panning_deadzone_counterweight{20, 0, 100, + "mouse_panning_deadzone_counterweight"}; + Setting<u8, true> mouse_panning_decay_strength{18, 0, 100, "mouse_panning_decay_strength"}; + Setting<u8, true> mouse_panning_min_decay{6, 0, 100, "mouse_panning_min_decay"}; Setting<bool> mouse_enabled{false, "mouse_enabled"}; Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index c8d574993..526a39130 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -5,7 +5,7 @@ #include "audio_core/renderer/audio_device.h" #include "common/common_funcs.h" #include "common/logging/log.h" -#include "common/settings.h" +#include "common/scratch_buffer.h" #include "common/string_util.h" #include "core/core.h" #include "core/hle/kernel/k_event.h" @@ -124,12 +124,15 @@ private: void GetReleasedAudioInBuffer(HLERequestContext& ctx) { const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); - tmp_buffer.resize_destructive(write_buffer_size); - tmp_buffer[0] = 0; + released_buffer.resize_destructive(write_buffer_size); + released_buffer[0] = 0; - const auto count = impl->GetReleasedBuffers(tmp_buffer); + const auto count = impl->GetReleasedBuffers(released_buffer); - ctx.WriteBuffer(tmp_buffer); + LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", + impl->GetSystem().GetSessionId(), count); + + ctx.WriteBuffer(released_buffer); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -155,7 +158,6 @@ private: LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); rb.Push(buffer_count); } @@ -195,7 +197,7 @@ private: KernelHelpers::ServiceContext service_context; Kernel::KEvent* event; std::shared_ptr<AudioCore::AudioIn::In> impl; - Common::ScratchBuffer<u64> tmp_buffer; + Common::ScratchBuffer<u64> released_buffer; }; AudInU::AudInU(Core::System& system_) diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 032c8c11f..23f84a29f 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -9,6 +9,7 @@ #include "audio_core/renderer/audio_device.h" #include "common/common_funcs.h" #include "common/logging/log.h" +#include "common/scratch_buffer.h" #include "common/string_util.h" #include "common/swap.h" #include "core/core.h" @@ -102,8 +103,8 @@ private: AudioOutBuffer buffer{}; std::memcpy(&buffer, in_buffer.data(), sizeof(AudioOutBuffer)); - [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()}; - LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", sessionid, tag); + LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", + impl->GetSystem().GetSessionId(), tag); auto result = impl->AppendBuffer(buffer, tag); @@ -123,12 +124,15 @@ private: void GetReleasedAudioOutBuffers(HLERequestContext& ctx) { const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); - tmp_buffer.resize_destructive(write_buffer_size); - tmp_buffer[0] = 0; + released_buffer.resize_destructive(write_buffer_size); + released_buffer[0] = 0; - const auto count = impl->GetReleasedBuffers(tmp_buffer); + const auto count = impl->GetReleasedBuffers(released_buffer); - ctx.WriteBuffer(tmp_buffer); + ctx.WriteBuffer(released_buffer); + + LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", + impl->GetSystem().GetSessionId(), count); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -154,7 +158,6 @@ private: LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); rb.Push(buffer_count); } @@ -165,7 +168,6 @@ private: LOG_DEBUG(Service_Audio, "called. Played samples={}", samples_played); IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); rb.Push(samples_played); } @@ -205,7 +207,7 @@ private: KernelHelpers::ServiceContext service_context; Kernel::KEvent* event; std::shared_ptr<AudioCore::AudioOut::Out> impl; - Common::ScratchBuffer<u64> tmp_buffer; + Common::ScratchBuffer<u64> released_buffer; }; AudOutU::AudOutU(Core::System& system_) diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 12845c23a..003870176 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -15,6 +15,7 @@ #include "common/common_funcs.h" #include "common/logging/log.h" #include "common/polyfill_ranges.h" +#include "common/scratch_buffer.h" #include "common/string_util.h" #include "core/core.h" #include "core/hle/kernel/k_event.h" @@ -119,23 +120,23 @@ private: auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0}; if (is_buffer_b) { const auto buffersB{ctx.BufferDescriptorB()}; - tmp_output.resize_destructive(buffersB[0].Size()); - tmp_performance.resize_destructive(buffersB[1].Size()); + output_buffer.resize_destructive(buffersB[0].Size()); + performance_buffer.resize_destructive(buffersB[1].Size()); } else { const auto buffersC{ctx.BufferDescriptorC()}; - tmp_output.resize_destructive(buffersC[0].Size()); - tmp_performance.resize_destructive(buffersC[1].Size()); + output_buffer.resize_destructive(buffersC[0].Size()); + performance_buffer.resize_destructive(buffersC[1].Size()); } - auto result = impl->RequestUpdate(input, tmp_performance, tmp_output); + auto result = impl->RequestUpdate(input, performance_buffer, output_buffer); if (result.IsSuccess()) { if (is_buffer_b) { - ctx.WriteBufferB(tmp_output.data(), tmp_output.size(), 0); - ctx.WriteBufferB(tmp_performance.data(), tmp_performance.size(), 1); + ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0); + ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1); } else { - ctx.WriteBufferC(tmp_output.data(), tmp_output.size(), 0); - ctx.WriteBufferC(tmp_performance.data(), tmp_performance.size(), 1); + ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0); + ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1); } } else { LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); @@ -233,8 +234,8 @@ private: Kernel::KEvent* rendered_event; Manager& manager; std::unique_ptr<Renderer> impl; - Common::ScratchBuffer<u8> tmp_output; - Common::ScratchBuffer<u8> tmp_performance; + Common::ScratchBuffer<u8> output_buffer; + Common::ScratchBuffer<u8> performance_buffer; }; class IAudioDevice final : public ServiceFramework<IAudioDevice> { diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index c835f6cb7..fa77007f3 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -11,6 +11,7 @@ #include "common/assert.h" #include "common/logging/log.h" +#include "common/scratch_buffer.h" #include "core/hle/service/audio/hwopus.h" #include "core/hle/service/ipc_helpers.h" @@ -68,13 +69,13 @@ private: ExtraBehavior extra_behavior) { u32 consumed = 0; u32 sample_count = 0; - tmp_samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>()); + samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>()); if (extra_behavior == ExtraBehavior::ResetContext) { ResetDecoderContext(); } - if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), tmp_samples, performance)) { + if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) { LOG_ERROR(Audio, "Failed to decode opus data"); IPC::ResponseBuilder rb{ctx, 2}; // TODO(ogniK): Use correct error code @@ -90,7 +91,7 @@ private: if (performance) { rb.Push<u64>(*performance); } - ctx.WriteBuffer(tmp_samples); + ctx.WriteBuffer(samples); } bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input, @@ -154,7 +155,7 @@ private: OpusDecoderPtr decoder; u32 sample_rate; u32 channel_count; - Common::ScratchBuffer<opus_int16> tmp_samples; + Common::ScratchBuffer<opus_int16> samples; }; class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index 348207e25..c8a880e84 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -2,7 +2,6 @@ // SPDX-FileCopyrightText: 2021 Skyline Team and Contributors // SPDX-License-Identifier: GPL-3.0-or-later -#include <cinttypes> #include "common/logging/log.h" #include "core/core.h" #include "core/hle/kernel/k_event.h" @@ -63,12 +62,12 @@ void NVDRV::Ioctl1(HLERequestContext& ctx) { } // Check device - tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); + output_buffer.resize_destructive(ctx.GetWriteBufferSize(0)); const auto input_buffer = ctx.ReadBuffer(0); - const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output); + const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer); if (command.is_out != 0) { - ctx.WriteBuffer(tmp_output); + ctx.WriteBuffer(output_buffer); } IPC::ResponseBuilder rb{ctx, 3}; @@ -90,12 +89,12 @@ void NVDRV::Ioctl2(HLERequestContext& ctx) { const auto input_buffer = ctx.ReadBuffer(0); const auto input_inlined_buffer = ctx.ReadBuffer(1); - tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); + output_buffer.resize_destructive(ctx.GetWriteBufferSize(0)); const auto nv_result = - nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, tmp_output); + nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer); if (command.is_out != 0) { - ctx.WriteBuffer(tmp_output); + ctx.WriteBuffer(output_buffer); } IPC::ResponseBuilder rb{ctx, 3}; @@ -116,12 +115,14 @@ void NVDRV::Ioctl3(HLERequestContext& ctx) { } const auto input_buffer = ctx.ReadBuffer(0); - tmp_output.resize_destructive(ctx.GetWriteBufferSize(0)); - tmp_output_inline.resize_destructive(ctx.GetWriteBufferSize(1)); - const auto nv_result = nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output_inline); + output_buffer.resize_destructive(ctx.GetWriteBufferSize(0)); + inline_output_buffer.resize_destructive(ctx.GetWriteBufferSize(1)); + + const auto nv_result = + nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, inline_output_buffer); if (command.is_out != 0) { - ctx.WriteBuffer(tmp_output, 0); - ctx.WriteBuffer(tmp_output_inline, 1); + ctx.WriteBuffer(output_buffer, 0); + ctx.WriteBuffer(inline_output_buffer, 1); } IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index 4b593ff90..6e98115dc 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h @@ -4,6 +4,7 @@ #pragma once #include <memory> + #include "common/scratch_buffer.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/service.h" @@ -34,8 +35,8 @@ private: u64 pid{}; bool is_initialized{}; - Common::ScratchBuffer<u8> tmp_output; - Common::ScratchBuffer<u8> tmp_output_inline; + Common::ScratchBuffer<u8> output_buffer; + Common::ScratchBuffer<u8> inline_output_buffer; }; } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvnflinger/parcel.h b/src/core/hle/service/nvnflinger/parcel.h index 23ba315a0..e2c9bbd50 100644 --- a/src/core/hle/service/nvnflinger/parcel.h +++ b/src/core/hle/service/nvnflinger/parcel.h @@ -6,6 +6,7 @@ #include <memory> #include <span> #include <vector> + #include <boost/container/small_vector.hpp> #include "common/alignment.h" @@ -148,9 +149,9 @@ public: this->WriteImpl(0U, m_object_buffer); } - std::vector<u8> Serialize() const { - std::vector<u8> output_buffer(sizeof(ParcelHeader) + m_data_buffer.size() + - m_object_buffer.size()); + std::span<u8> Serialize() { + m_output_buffer.resize(sizeof(ParcelHeader) + m_data_buffer.size() + + m_object_buffer.size()); ParcelHeader header{}; header.data_size = static_cast<u32>(m_data_buffer.size()); @@ -158,17 +159,17 @@ public: header.objects_size = static_cast<u32>(m_object_buffer.size()); header.objects_offset = header.data_offset + header.data_size; - std::memcpy(output_buffer.data(), &header, sizeof(header)); - std::ranges::copy(m_data_buffer, output_buffer.data() + header.data_offset); - std::ranges::copy(m_object_buffer, output_buffer.data() + header.objects_offset); + std::memcpy(m_output_buffer.data(), &header, sizeof(ParcelHeader)); + std::ranges::copy(m_data_buffer, m_output_buffer.data() + header.data_offset); + std::ranges::copy(m_object_buffer, m_output_buffer.data() + header.objects_offset); - return output_buffer; + return m_output_buffer; } private: - template <typename T> + template <typename T, size_t BufferSize> requires(std::is_trivially_copyable_v<T>) - void WriteImpl(const T& val, boost::container::small_vector<u8, 0x200>& buffer) { + void WriteImpl(const T& val, boost::container::small_vector<u8, BufferSize>& buffer) { const size_t aligned_size = Common::AlignUp(sizeof(T), 4); const size_t old_size = buffer.size(); buffer.resize(old_size + aligned_size); @@ -177,8 +178,9 @@ private: } private: - boost::container::small_vector<u8, 0x200> m_data_buffer; - boost::container::small_vector<u8, 0x200> m_object_buffer; + boost::container::small_vector<u8, 0x1B0> m_data_buffer; + boost::container::small_vector<u8, 0x40> m_object_buffer; + boost::container::small_vector<u8, 0x200> m_output_buffer; }; } // namespace Service::android diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index f07cf8a0e..dac29c78f 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -12,9 +12,13 @@ namespace InputCommon { constexpr int update_time = 10; -constexpr float default_stick_sensitivity = 0.0044f; -constexpr float default_motion_sensitivity = 0.0003f; +constexpr float default_panning_sensitivity = 0.0010f; +constexpr float default_stick_sensitivity = 0.0006f; +constexpr float default_deadzone_counterweight = 0.01f; +constexpr float default_motion_panning_sensitivity = 2.5f; +constexpr float default_motion_sensitivity = 0.416f; constexpr float maximum_rotation_speed = 2.0f; +constexpr float maximum_stick_range = 1.5f; constexpr int mouse_axis_x = 0; constexpr int mouse_axis_y = 1; constexpr int wheel_axis_x = 2; @@ -81,7 +85,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) { } void Mouse::UpdateStickInput() { - if (!Settings::values.mouse_panning) { + if (!IsMousePanningEnabled()) { return; } @@ -89,26 +93,13 @@ void Mouse::UpdateStickInput() { // Prevent input from exceeding the max range (1.0f) too much, // but allow some room to make it easier to sustain - if (length > 1.2f) { + if (length > maximum_stick_range) { last_mouse_change /= length; - last_mouse_change *= 1.2f; + last_mouse_change *= maximum_stick_range; } - auto mouse_change = last_mouse_change; - - // Bind the mouse change to [0 <= deadzone_counterweight <= 1,1] - if (length < 1.0f) { - const float deadzone_h_counterweight = - Settings::values.mouse_panning_deadzone_x_counterweight.GetValue(); - const float deadzone_v_counterweight = - Settings::values.mouse_panning_deadzone_y_counterweight.GetValue(); - mouse_change /= length; - mouse_change.x *= length + (1 - length) * deadzone_h_counterweight * 0.01f; - mouse_change.y *= length + (1 - length) * deadzone_v_counterweight * 0.01f; - } - - SetAxis(identifier, mouse_axis_x, mouse_change.x); - SetAxis(identifier, mouse_axis_y, -mouse_change.y); + SetAxis(identifier, mouse_axis_x, last_mouse_change.x); + SetAxis(identifier, mouse_axis_y, -last_mouse_change.y); // Decay input over time const float clamped_length = std::min(1.0f, length); @@ -120,14 +111,13 @@ void Mouse::UpdateStickInput() { } void Mouse::UpdateMotionInput() { - // This may need its own sensitivity instead of using the average - const float sensitivity = (Settings::values.mouse_panning_x_sensitivity.GetValue() + - Settings::values.mouse_panning_y_sensitivity.GetValue()) / - 2.0f * default_motion_sensitivity; + const float sensitivity = + IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity; const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + last_motion_change.y * last_motion_change.y); + // Clamp rotation speed if (rotation_velocity > maximum_rotation_speed / sensitivity) { const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity; last_motion_change.x = last_motion_change.x * multiplier; @@ -144,7 +134,7 @@ void Mouse::UpdateMotionInput() { .delta_timestamp = update_time * 1000, }; - if (Settings::values.mouse_panning) { + if (IsMousePanningEnabled()) { last_motion_change.x = 0; last_motion_change.y = 0; } @@ -154,33 +144,42 @@ void Mouse::UpdateMotionInput() { } void Mouse::Move(int x, int y, int center_x, int center_y) { - if (Settings::values.mouse_panning) { + if (IsMousePanningEnabled()) { const auto mouse_change = (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); const float x_sensitivity = - Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity; + Settings::values.mouse_panning_x_sensitivity.GetValue() * default_panning_sensitivity; const float y_sensitivity = - Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity; + Settings::values.mouse_panning_y_sensitivity.GetValue() * default_panning_sensitivity; + const float deadzone_counterweight = + Settings::values.mouse_panning_deadzone_counterweight.GetValue() * + default_deadzone_counterweight; + + last_motion_change += {-mouse_change.y * x_sensitivity, -mouse_change.x * y_sensitivity, 0}; + last_mouse_change.x += mouse_change.x * x_sensitivity; + last_mouse_change.y += mouse_change.y * y_sensitivity; - last_motion_change += {-mouse_change.y, -mouse_change.x, 0}; - last_mouse_change.x += mouse_change.x * x_sensitivity * 0.09f; - last_mouse_change.y += mouse_change.y * y_sensitivity * 0.09f; + // Bind the mouse change to [0 <= deadzone_counterweight <= 1.0] + if (last_mouse_change.Length() < deadzone_counterweight) { + last_mouse_change /= last_mouse_change.Length(); + last_mouse_change *= deadzone_counterweight; + } return; } if (button_pressed) { const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; - const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue(); - const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue(); - SetAxis(identifier, mouse_axis_x, - static_cast<float>(mouse_move.x) * x_sensitivity * 0.0012f); - SetAxis(identifier, mouse_axis_y, - static_cast<float>(-mouse_move.y) * y_sensitivity * 0.0012f); + const float x_sensitivity = + Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity; + const float y_sensitivity = + Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity; + SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * x_sensitivity); + SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * y_sensitivity); last_motion_change = { - static_cast<float>(-mouse_move.y) / 50.0f, - static_cast<float>(-mouse_move.x) / 50.0f, + static_cast<float>(-mouse_move.y) * x_sensitivity, + static_cast<float>(-mouse_move.x) * y_sensitivity, last_motion_change.z, }; } @@ -220,7 +219,7 @@ void Mouse::ReleaseButton(MouseButton button) { SetButton(real_mouse_identifier, static_cast<int>(button), false); SetButton(touch_identifier, static_cast<int>(button), false); - if (!Settings::values.mouse_panning) { + if (!IsMousePanningEnabled()) { SetAxis(identifier, mouse_axis_x, 0); SetAxis(identifier, mouse_axis_y, 0); } @@ -234,7 +233,7 @@ void Mouse::ReleaseButton(MouseButton button) { void Mouse::MouseWheelChange(int x, int y) { wheel_position.x += x; wheel_position.y += y; - last_motion_change.z += static_cast<f32>(y) / 100.0f; + last_motion_change.z += static_cast<f32>(y); SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); } @@ -244,6 +243,11 @@ void Mouse::ReleaseAllButtons() { button_pressed = false; } +bool Mouse::IsMousePanningEnabled() { + // Disable mouse panning when a real mouse is connected + return Settings::values.mouse_panning && !Settings::values.mouse_enabled; +} + std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { std::vector<Common::ParamPackage> devices; devices.emplace_back(Common::ParamPackage{ diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 0e8edcce1..2b93a40b9 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -99,6 +99,8 @@ private: void UpdateStickInput(); void UpdateMotionInput(); + bool IsMousePanningEnabled(); + Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; Common::Vec2<int> mouse_origin; diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index a290d6ea7..f8598fd98 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -174,8 +174,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { src_operand.address = regs.offset_in; DMA::BufferOperand dst_operand; - u32 abs_pitch_out = std::abs(static_cast<s32>(regs.pitch_out)); - dst_operand.pitch = abs_pitch_out; + dst_operand.pitch = static_cast<u32>(std::abs(regs.pitch_out)); dst_operand.width = regs.line_length_in; dst_operand.height = regs.line_count; dst_operand.address = regs.offset_out; @@ -222,7 +221,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { const size_t src_size = CalculateSize(true, bytes_per_pixel, width, height, depth, block_height, block_depth); - const size_t dst_size = static_cast<size_t>(abs_pitch_out) * regs.line_count; + const size_t dst_size = dst_operand.pitch * regs.line_count; read_buffer.resize_destructive(src_size); write_buffer.resize_destructive(dst_size); @@ -231,7 +230,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { UnswizzleSubrect(write_buffer, read_buffer, bytes_per_pixel, width, height, depth, x_offset, src_params.origin.y, x_elements, regs.line_count, block_height, block_depth, - abs_pitch_out); + dst_operand.pitch); memory_manager.WriteBlockCached(regs.offset_out, write_buffer.data(), dst_size); } diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp index cd6a3a9b8..da07a556f 100644 --- a/src/video_core/host1x/codecs/codec.cpp +++ b/src/video_core/host1x/codecs/codec.cpp @@ -290,7 +290,7 @@ void Codec::Decode() { return vp9_decoder->GetFrameBytes(); default: ASSERT(false); - return std::vector<u8>{}; + return std::span<const u8>{}; } }(); AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index ce827eb6c..862904e39 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp @@ -29,15 +29,15 @@ H264::H264(Host1x::Host1x& host1x_) : host1x{host1x_} {} H264::~H264() = default; -const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, - bool is_first_frame) { +std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, + bool is_first_frame) { H264DecoderContext context; host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext)); const s64 frame_number = context.h264_parameter_set.frame_number.Value(); if (!is_first_frame && frame_number != 0) { - frame.resize(context.stream_len); + frame.resize_destructive(context.stream_len); host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); return frame; } @@ -135,14 +135,14 @@ const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist for (s32 index = 0; index < 6; index++) { writer.WriteBit(true); std::span<const u8> matrix{context.weight_scale}; - writer.WriteScalingList(matrix, index * 16, 16); + writer.WriteScalingList(scan, matrix, index * 16, 16); } if (context.h264_parameter_set.transform_8x8_mode_flag) { for (s32 index = 0; index < 2; index++) { writer.WriteBit(true); std::span<const u8> matrix{context.weight_scale_8x8}; - writer.WriteScalingList(matrix, index * 64, 64); + writer.WriteScalingList(scan, matrix, index * 64, 64); } } @@ -188,8 +188,8 @@ void H264BitWriter::WriteBit(bool state) { WriteBits(state ? 1 : 0, 1); } -void H264BitWriter::WriteScalingList(std::span<const u8> list, s32 start, s32 count) { - static Common::ScratchBuffer<u8> scan{}; +void H264BitWriter::WriteScalingList(Common::ScratchBuffer<u8>& scan, std::span<const u8> list, + s32 start, s32 count) { scan.resize_destructive(count); if (count == 16) { std::memcpy(scan.data(), zig_zag_scan.data(), scan.size()); diff --git a/src/video_core/host1x/codecs/h264.h b/src/video_core/host1x/codecs/h264.h index 5cc86454e..d6b556322 100644 --- a/src/video_core/host1x/codecs/h264.h +++ b/src/video_core/host1x/codecs/h264.h @@ -5,9 +5,11 @@ #include <span> #include <vector> + #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" +#include "common/scratch_buffer.h" #include "video_core/host1x/nvdec_common.h" namespace Tegra { @@ -37,7 +39,8 @@ public: /// Based on section 7.3.2.1.1.1 and Table 7-4 in the H.264 specification /// Writes the scaling matrices of the sream - void WriteScalingList(std::span<const u8> list, s32 start, s32 count); + void WriteScalingList(Common::ScratchBuffer<u8>& scan, std::span<const u8> list, s32 start, + s32 count); /// Return the bitstream as a vector. [[nodiscard]] std::vector<u8>& GetByteArray(); @@ -63,11 +66,12 @@ public: ~H264(); /// Compose the H264 frame for FFmpeg decoding - [[nodiscard]] const std::vector<u8>& ComposeFrame( - const Host1x::NvdecCommon::NvdecRegisters& state, bool is_first_frame = false); + [[nodiscard]] std::span<const u8> ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, + bool is_first_frame = false); private: - std::vector<u8> frame; + Common::ScratchBuffer<u8> frame; + Common::ScratchBuffer<u8> scan; Host1x::Host1x& host1x; struct H264ParameterSet { diff --git a/src/video_core/host1x/codecs/vp8.cpp b/src/video_core/host1x/codecs/vp8.cpp index 28fb12cb8..ee6392ff9 100644 --- a/src/video_core/host1x/codecs/vp8.cpp +++ b/src/video_core/host1x/codecs/vp8.cpp @@ -12,7 +12,7 @@ VP8::VP8(Host1x::Host1x& host1x_) : host1x{host1x_} {} VP8::~VP8() = default; -const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { +std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { VP8PictureInfo info; host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); diff --git a/src/video_core/host1x/codecs/vp8.h b/src/video_core/host1x/codecs/vp8.h index 5bf07ecab..7926b73f3 100644 --- a/src/video_core/host1x/codecs/vp8.h +++ b/src/video_core/host1x/codecs/vp8.h @@ -4,10 +4,11 @@ #pragma once #include <array> -#include <vector> +#include <span> #include "common/common_funcs.h" #include "common/common_types.h" +#include "common/scratch_buffer.h" #include "video_core/host1x/nvdec_common.h" namespace Tegra { @@ -24,11 +25,11 @@ public: ~VP8(); /// Compose the VP8 frame for FFmpeg decoding - [[nodiscard]] const std::vector<u8>& ComposeFrame( + [[nodiscard]] std::span<const u8> ComposeFrame( const Host1x::NvdecCommon::NvdecRegisters& state); private: - std::vector<u8> frame; + Common::ScratchBuffer<u8> frame; Host1x::Host1x& host1x; struct VP8PictureInfo { diff --git a/src/video_core/host1x/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp index cf40c9012..306c3d0e8 100644 --- a/src/video_core/host1x/codecs/vp9.cpp +++ b/src/video_core/host1x/codecs/vp9.cpp @@ -3,6 +3,7 @@ #include <algorithm> // for std::copy #include <numeric> + #include "common/assert.h" #include "video_core/host1x/codecs/vp9.h" #include "video_core/host1x/host1x.h" diff --git a/src/video_core/host1x/codecs/vp9.h b/src/video_core/host1x/codecs/vp9.h index d4083e8d3..f1ed19508 100644 --- a/src/video_core/host1x/codecs/vp9.h +++ b/src/video_core/host1x/codecs/vp9.h @@ -4,9 +4,11 @@ #pragma once #include <array> +#include <span> #include <vector> #include "common/common_types.h" +#include "common/scratch_buffer.h" #include "common/stream.h" #include "video_core/host1x/codecs/vp9_types.h" #include "video_core/host1x/nvdec_common.h" @@ -128,8 +130,8 @@ public: return !current_frame_info.show_frame; } - /// Returns a const reference to the composed frame data. - [[nodiscard]] const std::vector<u8>& GetFrameBytes() const { + /// Returns a const span to the composed frame data. + [[nodiscard]] std::span<const u8> GetFrameBytes() const { return frame; } @@ -181,7 +183,7 @@ private: [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader(); Host1x::Host1x& host1x; - std::vector<u8> frame; + Common::ScratchBuffer<u8> frame; std::array<s8, 4> loop_filter_ref_deltas{}; std::array<s8, 2> loop_filter_mode_deltas{}; diff --git a/src/video_core/host1x/codecs/vp9_types.h b/src/video_core/host1x/codecs/vp9_types.h index adad8ed7e..cc9b25690 100644 --- a/src/video_core/host1x/codecs/vp9_types.h +++ b/src/video_core/host1x/codecs/vp9_types.h @@ -5,6 +5,7 @@ #include <array> #include <vector> + #include "common/common_funcs.h" #include "common/common_types.h" diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp index 7624a9b32..6a294c1da 100644 --- a/src/video_core/vulkan_common/vulkan_instance.cpp +++ b/src/video_core/vulkan_common/vulkan_instance.cpp @@ -19,11 +19,9 @@ #include <windows.h> // ensure include order #include <vulkan/vulkan_win32.h> -#elif defined(__APPLE__) -#include <vulkan/vulkan_macos.h> #elif defined(__ANDROID__) #include <vulkan/vulkan_android.h> -#else +#elif !defined(__APPLE__) #include <X11/Xlib.h> #include <vulkan/vulkan_wayland.h> #include <vulkan/vulkan_xlib.h> @@ -68,7 +66,7 @@ namespace { break; #elif defined(__APPLE__) case Core::Frontend::WindowSystemType::Cocoa: - extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); + extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); break; #elif defined(__ANDROID__) case Core::Frontend::WindowSystemType::Android: diff --git a/src/video_core/vulkan_common/vulkan_surface.cpp b/src/video_core/vulkan_common/vulkan_surface.cpp index c34599365..cfea4cd7b 100644 --- a/src/video_core/vulkan_common/vulkan_surface.cpp +++ b/src/video_core/vulkan_common/vulkan_surface.cpp @@ -11,11 +11,9 @@ #include <windows.h> // ensure include order #include <vulkan/vulkan_win32.h> -#elif defined(__APPLE__) -#include <vulkan/vulkan_macos.h> #elif defined(__ANDROID__) #include <vulkan/vulkan_android.h> -#else +#elif !defined(__APPLE__) #include <X11/Xlib.h> #include <vulkan/vulkan_wayland.h> #include <vulkan/vulkan_xlib.h> @@ -44,12 +42,13 @@ vk::SurfaceKHR CreateSurface( } #elif defined(__APPLE__) if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) { - const VkMacOSSurfaceCreateInfoMVK mvk_ci{VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, - nullptr, 0, window_info.render_surface}; - const auto vkCreateMacOSSurfaceMVK = reinterpret_cast<PFN_vkCreateMacOSSurfaceMVK>( - dld.vkGetInstanceProcAddr(*instance, "vkCreateMacOSSurfaceMVK")); - if (!vkCreateMacOSSurfaceMVK || - vkCreateMacOSSurfaceMVK(*instance, &mvk_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { + const VkMetalSurfaceCreateInfoEXT macos_ci = { + .pLayer = static_cast<const CAMetalLayer*>(window_info.render_surface), + }; + const auto vkCreateMetalSurfaceEXT = reinterpret_cast<PFN_vkCreateMetalSurfaceEXT>( + dld.vkGetInstanceProcAddr(*instance, "vkCreateMetalSurfaceEXT")); + if (!vkCreateMetalSurfaceEXT || + vkCreateMetalSurfaceEXT(*instance, &macos_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface"); throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); } diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index b5e70fcd4..32bd75ad8 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -15,6 +15,8 @@ #define VK_NO_PROTOTYPES #ifdef _WIN32 #define VK_USE_PLATFORM_WIN32_KHR +#elif defined(__APPLE__) +#define VK_USE_PLATFORM_METAL_EXT #endif #include <vulkan/vulkan.h> diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 29467d380..195d3556c 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -503,8 +503,7 @@ void Config::ReadMousePanningValues() { ReadBasicSetting(Settings::values.mouse_panning); ReadBasicSetting(Settings::values.mouse_panning_x_sensitivity); ReadBasicSetting(Settings::values.mouse_panning_y_sensitivity); - ReadBasicSetting(Settings::values.mouse_panning_deadzone_x_counterweight); - ReadBasicSetting(Settings::values.mouse_panning_deadzone_y_counterweight); + ReadBasicSetting(Settings::values.mouse_panning_deadzone_counterweight); ReadBasicSetting(Settings::values.mouse_panning_decay_strength); ReadBasicSetting(Settings::values.mouse_panning_min_decay); } @@ -1122,8 +1121,7 @@ void Config::SaveMousePanningValues() { // Don't overwrite values.mouse_panning WriteBasicSetting(Settings::values.mouse_panning_x_sensitivity); WriteBasicSetting(Settings::values.mouse_panning_y_sensitivity); - WriteBasicSetting(Settings::values.mouse_panning_deadzone_x_counterweight); - WriteBasicSetting(Settings::values.mouse_panning_deadzone_y_counterweight); + WriteBasicSetting(Settings::values.mouse_panning_deadzone_counterweight); WriteBasicSetting(Settings::values.mouse_panning_decay_strength); WriteBasicSetting(Settings::values.mouse_panning_min_decay); } diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index 43f6c7b50..611a79477 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui @@ -3105,21 +3105,6 @@ </property> <item> <widget class="QPushButton" name="mousePanningButton"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true">min-width: 68px;</string> - </property> <property name="text"> <string>Configure</string> </property> diff --git a/src/yuzu/configuration/configure_mouse_panning.cpp b/src/yuzu/configuration/configure_mouse_panning.cpp index f183d2740..e37c546b0 100644 --- a/src/yuzu/configuration/configure_mouse_panning.cpp +++ b/src/yuzu/configuration/configure_mouse_panning.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <QCloseEvent> +#include <QMessageBox> #include "common/settings.h" #include "ui_configure_mouse_panning.h" @@ -27,31 +28,34 @@ void ConfigureMousePanning::SetConfiguration(float right_stick_deadzone, float r ui->enable->setChecked(Settings::values.mouse_panning.GetValue()); ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetValue()); ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetValue()); - ui->deadzone_x_counterweight->setValue( - Settings::values.mouse_panning_deadzone_x_counterweight.GetValue()); - ui->deadzone_y_counterweight->setValue( - Settings::values.mouse_panning_deadzone_y_counterweight.GetValue()); + ui->deadzone_counterweight->setValue( + Settings::values.mouse_panning_deadzone_counterweight.GetValue()); ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetValue()); ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetValue()); if (right_stick_deadzone > 0.0f || right_stick_range != 1.0f) { - ui->warning_label->setText(QString::fromStdString( - "Mouse panning works better with a deadzone of 0% and a range of 100%.\n" - "Current values are " + - std::to_string(static_cast<int>(right_stick_deadzone * 100.0f)) + "% and " + - std::to_string(static_cast<int>(right_stick_range * 100.0f)) + "% respectively.")); - } else { - ui->warning_label->hide(); + const QString right_stick_deadzone_str = + QString::fromStdString(std::to_string(static_cast<int>(right_stick_deadzone * 100.0f))); + const QString right_stick_range_str = + QString::fromStdString(std::to_string(static_cast<int>(right_stick_range * 100.0f))); + + ui->warning_label->setText( + tr("Mouse panning works better with a deadzone of 0% and a range of 100%.\nCurrent " + "values are %1% and %2% respectively.") + .arg(right_stick_deadzone_str, right_stick_range_str)); + } + + if (Settings::values.mouse_enabled) { + ui->warning_label->setText( + tr("Emulated mouse is enabled. This is incompatible with mouse panning.")); } } void ConfigureMousePanning::SetDefaultConfiguration() { ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetDefault()); ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetDefault()); - ui->deadzone_x_counterweight->setValue( - Settings::values.mouse_panning_deadzone_x_counterweight.GetDefault()); - ui->deadzone_y_counterweight->setValue( - Settings::values.mouse_panning_deadzone_y_counterweight.GetDefault()); + ui->deadzone_counterweight->setValue( + Settings::values.mouse_panning_deadzone_counterweight.GetDefault()); ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetDefault()); ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetDefault()); } @@ -68,12 +72,19 @@ void ConfigureMousePanning::ApplyConfiguration() { Settings::values.mouse_panning = ui->enable->isChecked(); Settings::values.mouse_panning_x_sensitivity = static_cast<float>(ui->x_sensitivity->value()); Settings::values.mouse_panning_y_sensitivity = static_cast<float>(ui->y_sensitivity->value()); - Settings::values.mouse_panning_deadzone_x_counterweight = - static_cast<float>(ui->deadzone_x_counterweight->value()); - Settings::values.mouse_panning_deadzone_y_counterweight = - static_cast<float>(ui->deadzone_y_counterweight->value()); + Settings::values.mouse_panning_deadzone_counterweight = + static_cast<float>(ui->deadzone_counterweight->value()); Settings::values.mouse_panning_decay_strength = static_cast<float>(ui->decay_strength->value()); Settings::values.mouse_panning_min_decay = static_cast<float>(ui->min_decay->value()); + if (Settings::values.mouse_enabled && Settings::values.mouse_panning) { + Settings::values.mouse_panning = false; + QMessageBox::critical( + this, tr("Emulated mouse is enabled"), + tr("Real mouse input and mouse panning are incompatible. Please disable the " + "emulated mouse in input advanced settings to allow mouse panning.")); + return; + } + accept(); } diff --git a/src/yuzu/configuration/configure_mouse_panning.ui b/src/yuzu/configuration/configure_mouse_panning.ui index 75795b727..84fb7ee80 100644 --- a/src/yuzu/configuration/configure_mouse_panning.ui +++ b/src/yuzu/configuration/configure_mouse_panning.ui @@ -9,10 +9,10 @@ <item> <widget class="QCheckBox" name="enable"> <property name="text"> - <string>Enable</string> + <string>Enable mouse panning</string> </property> <property name="toolTip"> - <string>Can be toggled via a hotkey</string> + <string>Can be toggled via a hotkey. Default hotkey is Ctrl + F9</string> </property> </widget> </item> @@ -89,40 +89,14 @@ </property> <layout class="QGridLayout"> <item row="0" column="0"> - <widget class="QLabel" name="deadzone_x_counterweight_label"> + <widget class="QLabel" name="deadzone_counterweight_label"> <property name="text"> - <string>Horizontal</string> + <string>Deadzone</string> </property> </widget> </item> <item row="0" column="1"> - <widget class="QSpinBox" name="deadzone_x_counterweight"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - <property name="suffix"> - <string>%</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="value"> - <number>0</number> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="deadzone_y_counterweight_label"> - <property name="text"> - <string>Vertical</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="deadzone_y_counterweight"> + <widget class="QSpinBox" name="deadzone_counterweight"> <property name="alignment"> <set>Qt::AlignCenter</set> </property> diff --git a/src/yuzu/qt_common.cpp b/src/yuzu/qt_common.cpp index 5d0fd7674..413402165 100644 --- a/src/yuzu/qt_common.cpp +++ b/src/yuzu/qt_common.cpp @@ -10,6 +10,8 @@ #if !defined(WIN32) && !defined(__APPLE__) #include <qpa/qplatformnativeinterface.h> +#elif defined(__APPLE__) +#include <objc/message.h> #endif namespace QtCommon { @@ -37,9 +39,12 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) Core::Frontend::EmuWindow::WindowSystemInfo wsi; wsi.type = GetWindowSystemType(); +#if defined(WIN32) // Our Win32 Qt external doesn't have the private API. -#if defined(WIN32) || defined(__APPLE__) - wsi.render_surface = window ? reinterpret_cast<void*>(window->winId()) : nullptr; + wsi.render_surface = reinterpret_cast<void*>(window->winId()); +#elif defined(__APPLE__) + wsi.render_surface = reinterpret_cast<void* (*)(id, SEL)>(objc_msgSend)( + reinterpret_cast<id>(window->winId()), sel_registerName("layer")); #else QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); wsi.display_connection = pni->nativeResourceForWindow("display", window); diff --git a/src/yuzu/vk_device_info.cpp b/src/yuzu/vk_device_info.cpp index 7c26a3dc7..e1a0e6a2a 100644 --- a/src/yuzu/vk_device_info.cpp +++ b/src/yuzu/vk_device_info.cpp @@ -26,7 +26,10 @@ Record::~Record() = default; void PopulateRecords(std::vector<Record>& records, QWindow* window) try { using namespace Vulkan; - auto wsi = QtCommon::GetWindowSystemInfo(window); + // Create a test window with a Vulkan surface type for checking present modes. + QWindow test_window(window); + test_window.setSurfaceType(QWindow::VulkanSurface); + auto wsi = QtCommon::GetWindowSystemInfo(&test_window); vk::InstanceDispatch dld; const auto library = OpenLibrary(); |