summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/audio_core/sink/cubeb_sink.cpp3
-rw-r--r--src/audio_core/sink/sdl2_sink.cpp3
-rw-r--r--src/audio_core/sink/sink.h12
-rw-r--r--src/audio_core/sink/sink_stream.cpp41
-rw-r--r--src/common/fs/path_util.cpp6
-rw-r--r--src/common/fs/path_util.h2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp35
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_core.cpp4
-rw-r--r--src/core/hle/service/nvnflinger/buffer_slot.h1
-rw-r--r--src/yuzu/configuration/configure_ui.cpp4
-rw-r--r--src/yuzu/configuration/qt_config.cpp5
-rw-r--r--src/yuzu/main.cpp6
-rw-r--r--src/yuzu/uisettings.h3
14 files changed, 88 insertions, 39 deletions
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp
index 51a23fe15..d97ca2a40 100644
--- a/src/audio_core/sink/cubeb_sink.cpp
+++ b/src/audio_core/sink/cubeb_sink.cpp
@@ -253,8 +253,9 @@ CubebSink::~CubebSink() {
#endif
}
-SinkStream* CubebSink::AcquireSinkStream(Core::System& system, u32 system_channels,
+SinkStream* CubebSink::AcquireSinkStream(Core::System& system, u32 system_channels_,
const std::string& name, StreamType type) {
+ system_channels = system_channels_;
SinkStreamPtr& stream = sink_streams.emplace_back(std::make_unique<CubebSinkStream>(
ctx, device_channels, system_channels, output_device, input_device, name, type, system));
diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp
index 96e0efce2..7dd155ff0 100644
--- a/src/audio_core/sink/sdl2_sink.cpp
+++ b/src/audio_core/sink/sdl2_sink.cpp
@@ -168,8 +168,9 @@ SDLSink::SDLSink(std::string_view target_device_name) {
SDLSink::~SDLSink() = default;
-SinkStream* SDLSink::AcquireSinkStream(Core::System& system, u32 system_channels,
+SinkStream* SDLSink::AcquireSinkStream(Core::System& system, u32 system_channels_,
const std::string&, StreamType type) {
+ system_channels = system_channels_;
SinkStreamPtr& stream = sink_streams.emplace_back(std::make_unique<SDLSinkStream>(
device_channels, system_channels, output_device, input_device, type, system));
return stream.get();
diff --git a/src/audio_core/sink/sink.h b/src/audio_core/sink/sink.h
index f28c6d126..e22e8c3e5 100644
--- a/src/audio_core/sink/sink.h
+++ b/src/audio_core/sink/sink.h
@@ -85,9 +85,21 @@ public:
*/
virtual void SetSystemVolume(f32 volume) = 0;
+ /**
+ * Get the number of channels the game has set, can be different to the host hardware's support.
+ * Either 2 or 6.
+ *
+ * @return Number of device channels.
+ */
+ u32 GetSystemChannels() const {
+ return system_channels;
+ }
+
protected:
/// Number of device channels supported by the hardware
u32 device_channels{2};
+ /// Number of channels the game is sending
+ u32 system_channels{2};
};
using SinkPtr = std::unique_ptr<Sink>;
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp
index 2a09db599..c047b0668 100644
--- a/src/audio_core/sink/sink_stream.cpp
+++ b/src/audio_core/sink/sink_stream.cpp
@@ -40,29 +40,36 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span<s16> samples) {
if (system_channels == 6 && device_channels == 2) {
// We're given 6 channels, but our device only outputs 2, so downmix.
- static constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
+ // Front = 1.0
+ // Center = 0.596
+ // LFE = 0.354
+ // Back = 0.707
+ static constexpr std::array<f32, 4> down_mix_coeff{1.0, 0.596f, 0.354f, 0.707f};
for (u32 read_index = 0, write_index = 0; read_index < samples.size();
read_index += system_channels, write_index += device_channels) {
+ const auto fl =
+ static_cast<f32>(samples[read_index + static_cast<u32>(Channels::FrontLeft)]);
+ const auto fr =
+ static_cast<f32>(samples[read_index + static_cast<u32>(Channels::FrontRight)]);
+ const auto c =
+ static_cast<f32>(samples[read_index + static_cast<u32>(Channels::Center)]);
+ const auto lfe =
+ static_cast<f32>(samples[read_index + static_cast<u32>(Channels::LFE)]);
+ const auto bl =
+ static_cast<f32>(samples[read_index + static_cast<u32>(Channels::BackLeft)]);
+ const auto br =
+ static_cast<f32>(samples[read_index + static_cast<u32>(Channels::BackRight)]);
+
const auto left_sample{
- ((Common::FixedPoint<49, 15>(
- samples[read_index + static_cast<u32>(Channels::FrontLeft)]) *
- down_mix_coeff[0] +
- samples[read_index + static_cast<u32>(Channels::Center)] * down_mix_coeff[1] +
- samples[read_index + static_cast<u32>(Channels::LFE)] * down_mix_coeff[2] +
- samples[read_index + static_cast<u32>(Channels::BackLeft)] * down_mix_coeff[3]) *
- volume)
- .to_int()};
+ static_cast<s32>((fl * down_mix_coeff[0] + c * down_mix_coeff[1] +
+ lfe * down_mix_coeff[2] + bl * down_mix_coeff[3]) *
+ volume)};
const auto right_sample{
- ((Common::FixedPoint<49, 15>(
- samples[read_index + static_cast<u32>(Channels::FrontRight)]) *
- down_mix_coeff[0] +
- samples[read_index + static_cast<u32>(Channels::Center)] * down_mix_coeff[1] +
- samples[read_index + static_cast<u32>(Channels::LFE)] * down_mix_coeff[2] +
- samples[read_index + static_cast<u32>(Channels::BackRight)] * down_mix_coeff[3]) *
- volume)
- .to_int()};
+ static_cast<s32>((fr * down_mix_coeff[0] + c * down_mix_coeff[1] +
+ lfe * down_mix_coeff[2] + br * down_mix_coeff[3]) *
+ volume)};
samples[write_index + static_cast<u32>(Channels::FrontLeft)] =
static_cast<s16>(std::clamp(left_sample, min, max));
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index d2f50432a..4f69db6f5 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -418,9 +418,9 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se
return std::string(RemoveTrailingSlash(path));
}
-std::string_view GetParentPath(std::string_view path) {
+std::string GetParentPath(std::string_view path) {
if (path.empty()) {
- return path;
+ return std::string(path);
}
#ifdef ANDROID
@@ -439,7 +439,7 @@ std::string_view GetParentPath(std::string_view path) {
name_index = std::max(name_bck_index, name_fwd_index);
}
- return path.substr(0, name_index);
+ return std::string(path.substr(0, name_index));
}
std::string_view GetPathWithoutTop(std::string_view path) {
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index 23c8b1359..59301e7ed 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -302,7 +302,7 @@ enum class DirectorySeparator {
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
// Gets all of the text up to the last '/' or '\' in the path.
-[[nodiscard]] std::string_view GetParentPath(std::string_view path);
+[[nodiscard]] std::string GetParentPath(std::string_view path);
// Gets all of the text after the first '/' or '\' in the path.
[[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path);
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 2f09cade5..23e56c77a 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -359,7 +359,7 @@ private:
void GetActiveChannelCount(HLERequestContext& ctx) {
const auto& sink{system.AudioCore().GetOutputSink()};
- u32 channel_count{sink.GetDeviceChannels()};
+ u32 channel_count{sink.GetSystemChannels()};
LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
index d91886bed..bbe8e06d4 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
@@ -90,6 +90,18 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
LOG_DEBUG(Service_Nvnflinger, "acquiring slot={}", slot);
+ // If the front buffer is still being tracked, update its slot state
+ if (core->StillTracking(*front)) {
+ slots[slot].acquire_called = true;
+ slots[slot].needs_cleanup_on_release = false;
+ slots[slot].buffer_state = BufferState::Acquired;
+
+ // TODO: for now, avoid resetting the fence, so that when we next return this
+ // slot to the producer, it will wait for the fence to pass. We should fix this
+ // by properly waiting for the fence in the BufferItemConsumer.
+ // slots[slot].fence = Fence::NoFence();
+ }
+
// If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to
// avoid unnecessarily remapping this buffer on the consumer side.
if (out_buffer->acquire_called) {
@@ -132,11 +144,28 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
++current;
}
- slots[slot].buffer_state = BufferState::Free;
+ if (slots[slot].buffer_state == BufferState::Acquired) {
+ // TODO: for now, avoid resetting the fence, so that when we next return this
+ // slot to the producer, it can wait for its own fence to pass. We should fix this
+ // by properly waiting for the fence in the BufferItemConsumer.
+ // slots[slot].fence = release_fence;
+ slots[slot].buffer_state = BufferState::Free;
- listener = core->connected_producer_listener;
+ listener = core->connected_producer_listener;
- LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
+ LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
+ } else if (slots[slot].needs_cleanup_on_release) {
+ LOG_DEBUG(Service_Nvnflinger, "releasing a stale buffer slot {} (state = {})", slot,
+ slots[slot].buffer_state);
+ slots[slot].needs_cleanup_on_release = false;
+ return Status::StaleBufferSlot;
+ } else {
+ LOG_ERROR(Service_Nvnflinger,
+ "attempted to release buffer slot {} but its state was {}", slot,
+ slots[slot].buffer_state);
+
+ return Status::BadValue;
+ }
core->SignalDequeueCondition();
}
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
index 4ed5e5978..5d8c861fa 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
@@ -74,6 +74,10 @@ void BufferQueueCore::FreeBufferLocked(s32 slot) {
slots[slot].graphic_buffer.reset();
+ if (slots[slot].buffer_state == BufferState::Acquired) {
+ slots[slot].needs_cleanup_on_release = true;
+ }
+
slots[slot].buffer_state = BufferState::Free;
slots[slot].frame_number = UINT32_MAX;
slots[slot].acquire_called = false;
diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h
index d25bca049..37daca78b 100644
--- a/src/core/hle/service/nvnflinger/buffer_slot.h
+++ b/src/core/hle/service/nvnflinger/buffer_slot.h
@@ -31,6 +31,7 @@ struct BufferSlot final {
u64 frame_number{};
Fence fence;
bool acquire_called{};
+ bool needs_cleanup_on_release{};
bool attached_by_consumer{};
bool is_preallocated{};
};
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index dd43f0a0e..c8e871151 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -193,8 +193,8 @@ void ConfigureUi::RequestGameListUpdate() {
void ConfigureUi::SetConfiguration() {
ui->theme_combobox->setCurrentIndex(
ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme)));
- ui->language_combobox->setCurrentIndex(
- ui->language_combobox->findData(QString::fromStdString(UISettings::values.language)));
+ ui->language_combobox->setCurrentIndex(ui->language_combobox->findData(
+ QString::fromStdString(UISettings::values.language.GetValue())));
ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
ui->show_compat->setChecked(UISettings::values.show_compat.GetValue());
ui->show_size->setChecked(UISettings::values.show_size.GetValue());
diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp
index 636c5e640..417a43ec5 100644
--- a/src/yuzu/configuration/qt_config.cpp
+++ b/src/yuzu/configuration/qt_config.cpp
@@ -187,7 +187,6 @@ void QtConfig::ReadPathValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
UISettings::values.roms_path = ReadStringSetting(std::string("romsPath"));
- UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath"));
UISettings::values.game_dir_deprecated =
ReadStringSetting(std::string("gameListRootDir"), std::string("."));
UISettings::values.game_dir_deprecated_deepscan =
@@ -225,8 +224,6 @@ void QtConfig::ReadPathValues() {
UISettings::values.recent_files =
QString::fromStdString(ReadStringSetting(std::string("recentFiles")))
.split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive);
- UISettings::values.language =
- ReadStringSetting(std::string("language"), std::make_optional(std::string("")));
EndGroup();
}
@@ -409,7 +406,6 @@ void QtConfig::SavePathValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
WriteSetting(std::string("romsPath"), UISettings::values.roms_path);
- WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path);
BeginArray(std::string("gamedirs"));
for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
SetArrayIndex(i);
@@ -422,7 +418,6 @@ void QtConfig::SavePathValues() {
WriteSetting(std::string("recentFiles"),
UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString());
- WriteSetting(std::string("language"), UISettings::values.language);
EndGroup();
}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f31ed7ebb..059fcf041 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -5147,12 +5147,12 @@ void GMainWindow::UpdateUITheme() {
void GMainWindow::LoadTranslation() {
bool loaded;
- if (UISettings::values.language.empty()) {
+ if (UISettings::values.language.GetValue().empty()) {
// If the selected language is empty, use system locale
loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
} else {
// Otherwise load from the specified file
- loaded = translator.load(QString::fromStdString(UISettings::values.language),
+ loaded = translator.load(QString::fromStdString(UISettings::values.language.GetValue()),
QStringLiteral(":/languages/"));
}
@@ -5164,7 +5164,7 @@ void GMainWindow::LoadTranslation() {
}
void GMainWindow::OnLanguageChanged(const QString& locale) {
- if (UISettings::values.language != std::string("en")) {
+ if (UISettings::values.language.GetValue() != std::string("en")) {
qApp->removeTranslator(&translator);
}
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 549a39e1b..f9906be33 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -154,12 +154,11 @@ struct Values {
Setting<u32> screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots};
std::string roms_path;
- std::string symbols_path;
std::string game_dir_deprecated;
bool game_dir_deprecated_deepscan;
QVector<GameDir> game_dirs;
QStringList recent_files;
- std::string language;
+ Setting<std::string> language{linkage, {}, "language", Category::Paths};
std::string theme;