diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS
index 503f9ec1fe..dcb97a5e83 100644
--- a/docs/CODEOWNERS
+++ b/docs/CODEOWNERS
@@ -10,17 +10,18 @@
/.ci @crueter
# cmake
-*.cmake @crueter
-*/CMakeLists.txt @crueter
-*.in @crueter
+*.cmake @crueter
+*CMakeLists.txt @crueter
+*.in @crueter
# individual stuff
-/src/web_service @AleksandrPopovich
-/src/dynarmic @Lizzie
-/src/core @Lizzie @Maufeat @PavelBARABANOV @MrPurple666
-/src/core/hle @Maufeat @PavelBARABANOV @SDK-Chan
-/src/*_room @AleksandrPopovich
-/src/video_core @CamilleLaVey @MaranBr @Wildcard @weakboson
+src/web_service @AleksandrPopovich
+src/dynarmic @Lizzie
+src/core @Lizzie @Maufeat @PavelBARABANOV @MrPurple666 @JPikachu
+src/core/hle @Maufeat @PavelBARABANOV @SDK-Chan
+src/core/arm @Lizzie @MrPurple666
+src/*_room @AleksandrPopovich
+src/video_core @CamilleLaVey @MaranBr @Wildcard @weakboson
# Global owners/triage
* @CamilleLaVey @Maufeat @crueter @MrPurple666 @MaranBr @Lizzie
\ No newline at end of file
diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml
index a758e1c7cd..35f7d20198 100644
--- a/src/android/app/src/main/res/values-ar/strings.xml
+++ b/src/android/app/src/main/res/values-ar/strings.xml
@@ -836,13 +836,13 @@
تمتد إلى النافذة
- Dynarmic (بطيء)
+ Dynarmic (JIT)
تنفيذ التعليمات البرمجية الأصلية (NCE)
دقه
غير آمن
- Paranoid (بطيء)
+ Paranoid
الأسهم
diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml
index 2ee0e1783a..1f73df7385 100644
--- a/src/android/app/src/main/res/values-es/strings.xml
+++ b/src/android/app/src/main/res/values-es/strings.xml
@@ -919,13 +919,13 @@
Ajustar a la ventana
- DynARMic (lento)
+ Dynarmic (JIT)
Ejecución nativa de código (NCE)
Preciso
Impreciso
- Paranoico (Lento)
+ Paranoico
Cruceta
diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml
index 79cf5f49e6..fd5c6ae6ca 100644
--- a/src/android/app/src/main/res/values-fa/strings.xml
+++ b/src/android/app/src/main/res/values-fa/strings.xml
@@ -918,13 +918,13 @@
کشش تا پر کردن پنجره
- دینارمیک (کند)
+ Dynarmic (JIT)
اجرای کد اصلی (NCE)
دقیق
ناامن
- بدگمان (کند)
+ بدگمان
کلیدهای جهتی
diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml
index e9df08a4de..97496ef33d 100644
--- a/src/android/app/src/main/res/values-fr/strings.xml
+++ b/src/android/app/src/main/res/values-fr/strings.xml
@@ -967,13 +967,13 @@
Étirer à la fenêtre
- Dynarmic (Lent)
+ Dynarmic (JIT)
Exécution de code natif (NCE)
Précis
Risqué
- Paranoïaque (Lent)
+ Paranoïaque
Pavé directionnel
diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml
index 4e1624a556..359e8dff9a 100644
--- a/src/android/app/src/main/res/values-he/strings.xml
+++ b/src/android/app/src/main/res/values-he/strings.xml
@@ -844,13 +844,13 @@
הרחב לגודל המסך
- דינמי (איטי)
+ דינמי
ביצוע קוד מקורי (NCE)
מדויק
לא בטוח
- פראנואידי (איטי)
+ פראנואידי
D-pad
diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml
index 061ac07388..36157d1578 100644
--- a/src/android/app/src/main/res/values-hu/strings.xml
+++ b/src/android/app/src/main/res/values-hu/strings.xml
@@ -954,13 +954,13 @@
Ablakhoz nyújtás
- Dinamikus (lassú)
+ Dynarmic (JIT)
Natív kód végrehajtás (Native code execution (NCE))
Pontos
Nem biztonságos
- Paranoid (Lassú)
+ Paranoid
D-pad
diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml
index 6e3b64953f..18e881a97b 100644
--- a/src/android/app/src/main/res/values-id/strings.xml
+++ b/src/android/app/src/main/res/values-id/strings.xml
@@ -911,13 +911,13 @@
Merentangkan
- Dynamic (Lambat)
+ Dynarmic (JIT)
Native code execution (NCE)
Akurat
Berbahaya
- Paranoid (Slow)
+ Paranoid
D Pad
diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml
index 179601f182..0a873b04eb 100644
--- a/src/android/app/src/main/res/values-ja/strings.xml
+++ b/src/android/app/src/main/res/values-ja/strings.xml
@@ -834,13 +834,13 @@
画面に合わせる
- Dynarmic (低速)
+ Dynarmic (JIT)
ネイティブコード実行 (NCE)
正確
不安定
- パラノイド (低速)
+ パラノイド
方向ボタン
diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml
index 6f4dd42af2..e598bb1120 100644
--- a/src/android/app/src/main/res/values-ko/strings.xml
+++ b/src/android/app/src/main/res/values-ko/strings.xml
@@ -910,13 +910,13 @@
화면에 맞춤
- Dynarmic (느림)
+ Dynarmic (JIT)
네이티브 코드 실행 (NCE)
정확함
최적화 (안전하지 않음)
- 최적화하지 않음 (느림)
+ 최적화하지 않음
십자키
diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml
index eec3fdf715..5571c2aea4 100644
--- a/src/android/app/src/main/res/values-pt-rBR/strings.xml
+++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml
@@ -968,13 +968,13 @@ uma tentativa de mapeamento automático
Esticar à janela
- Dynarmic (Lenta)
+ Dynarmic (JIT)
Execução de código nativo (NCE)
Precisa
Não segura
- Paranoica (Lenta)
+ Paranoica
Botões Direcionais
diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml
index d45bf4bfc9..81aa7e92c0 100644
--- a/src/android/app/src/main/res/values-pt-rPT/strings.xml
+++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml
@@ -968,13 +968,13 @@ uma tentativa de mapeamento automático
Esticar à janela
- Dynarmic (Lento)
+ Dynarmic (JIT)
Native code execution (NCE)
Preciso
Inseguro
- Paranoid (Lento)
+ Paranoid
Botões Direcionais
diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml
index 2f7714257f..eee249c44a 100644
--- a/src/android/app/src/main/res/values-ru/strings.xml
+++ b/src/android/app/src/main/res/values-ru/strings.xml
@@ -969,13 +969,13 @@
Растянуть до окна
- Dynarmic (Медленно)
+ Dynarmic (JIT)
Нативное выполнение (NCE)
Точно
Небезопасно
- Параноик (медленно)
+ Параноик
Крестовина
diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml
index e261772fc4..b123757f5a 100644
--- a/src/android/app/src/main/res/values-sr/strings.xml
+++ b/src/android/app/src/main/res/values-sr/strings.xml
@@ -988,13 +988,13 @@
Протезање до прозора
- Динамина (споро)
+ Dynarmic (JIT)
Извођење изворног кода (НЦЕ)
Тачан
Несигуран
- Параноичан (споро)
+ Параноичан
Д-пад
diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml
index bfdc3af3d3..5cf657ef3d 100644
--- a/src/android/app/src/main/res/values-zh-rCN/strings.xml
+++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml
@@ -961,13 +961,13 @@
拉伸窗口
- 动态编译 (慢速)
+ Dynarmic (JIT)
本机代码执行 (NCE)
高精度
低精度
- 偏执模式 (慢速)
+ 偏执模式
十字方向键
diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml
index e64aaa9a54..f4d690dbaa 100644
--- a/src/android/app/src/main/res/values-zh-rTW/strings.xml
+++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml
@@ -966,13 +966,13 @@
延展視窗
- 動態 (慢)
+ Dynarmic (JIT)
機器碼執行 (NCE)
高精度
低精度
- 不合理 (慢)
+ 不合理
方向鍵
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 2cef5903cb..3b76c0ba79 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -1014,13 +1014,13 @@
Stretch to window
- Dynarmic (Slow)
+ Dynarmic (JIT)
Native code execution (NCE)
Accurate
Unsafe
- Paranoid (Slow)
+ Paranoid
D-pad
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 4d9566a60f..6b64ab7820 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -107,8 +107,6 @@ add_library(core STATIC
file_sys/fssystem/fssystem_nca_header.cpp
file_sys/fssystem/fssystem_nca_header.h
file_sys/fssystem/fssystem_nca_reader.cpp
- file_sys/fssystem/fssystem_pooled_buffer.cpp
- file_sys/fssystem/fssystem_pooled_buffer.h
file_sys/fssystem/fssystem_sparse_storage.cpp
file_sys/fssystem/fssystem_sparse_storage.h
file_sys/fssystem/fssystem_switch_storage.h
diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp
index c18fde18f4..aaf7788801 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp
@@ -1,10 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/alignment.h"
#include "common/swap.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
#include "core/file_sys/fssystem/fssystem_utility.h"
namespace FileSys {
@@ -76,13 +78,6 @@ size_t AesCtrStorage::Write(const u8* buffer, size_t size, size_t offset) {
ASSERT(Common::IsAligned(offset, BlockSize));
ASSERT(Common::IsAligned(size, BlockSize));
- // Get a pooled buffer.
- PooledBuffer pooled_buffer;
- const bool use_work_buffer = true;
- if (use_work_buffer) {
- pooled_buffer.Allocate(size, BlockSize);
- }
-
// Setup the counter.
std::array ctr;
std::memcpy(ctr.data(), m_iv.data(), IvSize);
@@ -91,25 +86,20 @@ size_t AesCtrStorage::Write(const u8* buffer, size_t size, size_t offset) {
// Loop until all data is written.
size_t remaining = size;
s64 cur_offset = 0;
+
+ // Get a pooled buffer.
+ std::vector pooled_buffer(BlockSize);
while (remaining > 0) {
// Determine data we're writing and where.
- const size_t write_size =
- use_work_buffer ? (std::min)(pooled_buffer.GetSize(), remaining) : remaining;
-
- void* write_buf;
- if (use_work_buffer) {
- write_buf = pooled_buffer.GetBuffer();
- } else {
- write_buf = const_cast(buffer);
- }
+ const size_t write_size = std::min(pooled_buffer.size(), remaining);
+ u8* write_buf = reinterpret_cast(pooled_buffer.data());
// Encrypt the data.
m_cipher->SetIV(ctr);
- m_cipher->Transcode(buffer, write_size, reinterpret_cast(write_buf),
- Core::Crypto::Op::Encrypt);
+ m_cipher->Transcode(buffer, write_size, write_buf, Core::Crypto::Op::Encrypt);
// Write the encrypted data.
- m_base_storage->Write(reinterpret_cast(write_buf), write_size, offset + cur_offset);
+ m_base_storage->Write(write_buf, write_size, offset + cur_offset);
// Advance.
cur_offset += write_size;
diff --git a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp
index 5ef2544dfb..9e7a104c89 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp
@@ -1,11 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/alignment.h"
#include "common/swap.h"
-#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_aes_xts_storage.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
#include "core/file_sys/fssystem/fssystem_utility.h"
namespace FileSys {
@@ -69,17 +70,14 @@ size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const {
// Decrypt into a pooled buffer.
{
- PooledBuffer tmp_buf(m_block_size, m_block_size);
- ASSERT(tmp_buf.GetSize() >= m_block_size);
-
- std::memset(tmp_buf.GetBuffer(), 0, skip_size);
- std::memcpy(tmp_buf.GetBuffer() + skip_size, buffer, data_size);
+ std::vector tmp_buf(m_block_size, 0);
+ std::memcpy(tmp_buf.data() + skip_size, buffer, data_size);
m_cipher->SetIV(ctr);
- m_cipher->Transcode(tmp_buf.GetBuffer(), m_block_size, tmp_buf.GetBuffer(),
+ m_cipher->Transcode(tmp_buf.data(), m_block_size, tmp_buf.data(),
Core::Crypto::Op::Decrypt);
- std::memcpy(buffer, tmp_buf.GetBuffer() + skip_size, data_size);
+ std::memcpy(buffer, tmp_buf.data() + skip_size, data_size);
}
AddCounter(ctr.data(), IvSize, 1);
diff --git a/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h b/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h
index f96691d03d..60a6d24435 100644
--- a/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h
@@ -1,13 +1,14 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/alignment.h"
-#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/fssystem/fssystem_alignment_matching_storage_impl.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
namespace FileSys {
@@ -89,10 +90,11 @@ private:
VirtualFile m_base_storage;
s64 m_base_storage_size;
size_t m_data_align;
+ mutable std::vector work_buffer;
public:
explicit AlignmentMatchingStoragePooledBuffer(VirtualFile bs, size_t da)
- : m_base_storage(std::move(bs)), m_data_align(da) {
+ : m_base_storage(std::move(bs)), m_data_align(da), work_buffer(da) {
ASSERT(Common::IsPowerOfTwo(da));
}
@@ -104,16 +106,10 @@ public:
// Validate arguments.
ASSERT(buffer != nullptr);
-
s64 bs_size = this->GetSize();
ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size)));
-
- // Allocate a pooled buffer.
- PooledBuffer pooled_buffer;
- pooled_buffer.AllocateParticularlyLarge(m_data_align, m_data_align);
-
- return AlignmentMatchingStorageImpl::Read(m_base_storage, pooled_buffer.GetBuffer(),
- pooled_buffer.GetSize(), m_data_align,
+ return AlignmentMatchingStorageImpl::Read(m_base_storage, work_buffer.data(),
+ work_buffer.size(), m_data_align,
BufferAlign, offset, buffer, size);
}
@@ -125,16 +121,10 @@ public:
// Validate arguments.
ASSERT(buffer != nullptr);
-
s64 bs_size = this->GetSize();
ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size)));
-
- // Allocate a pooled buffer.
- PooledBuffer pooled_buffer;
- pooled_buffer.AllocateParticularlyLarge(m_data_align, m_data_align);
-
- return AlignmentMatchingStorageImpl::Write(m_base_storage, pooled_buffer.GetBuffer(),
- pooled_buffer.GetSize(), m_data_align,
+ return AlignmentMatchingStorageImpl::Write(m_base_storage, work_buffer.data(),
+ work_buffer.size(), m_data_align,
BufferAlign, offset, buffer, size);
}
diff --git a/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp b/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
index f58b154968..ce3b62f26d 100644
--- a/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
+++ b/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
@@ -7,7 +7,6 @@
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
namespace FileSys {
@@ -465,16 +464,8 @@ Result BucketTree::Visitor::Find(s64 virtual_address) {
}
Result BucketTree::Visitor::FindEntrySet(s32* out_index, s64 virtual_address, s32 node_index) {
- const auto node_size = m_tree->m_node_size;
-
- PooledBuffer pool(node_size, 1);
- if (node_size <= pool.GetSize()) {
- R_RETURN(
- this->FindEntrySetWithBuffer(out_index, virtual_address, node_index, pool.GetBuffer()));
- } else {
- pool.Deallocate();
- R_RETURN(this->FindEntrySetWithoutBuffer(out_index, virtual_address, node_index));
- }
+ std::vector pool(m_tree->m_node_size);
+ R_RETURN(FindEntrySetWithBuffer(out_index, virtual_address, node_index, pool.data()));
}
Result BucketTree::Visitor::FindEntrySetWithBuffer(s32* out_index, s64 virtual_address,
@@ -525,15 +516,8 @@ Result BucketTree::Visitor::FindEntrySetWithoutBuffer(s32* out_index, s64 virtua
}
Result BucketTree::Visitor::FindEntry(s64 virtual_address, s32 entry_set_index) {
- const auto entry_set_size = m_tree->m_node_size;
-
- PooledBuffer pool(entry_set_size, 1);
- if (entry_set_size <= pool.GetSize()) {
- R_RETURN(this->FindEntryWithBuffer(virtual_address, entry_set_index, pool.GetBuffer()));
- } else {
- pool.Deallocate();
- R_RETURN(this->FindEntryWithoutBuffer(virtual_address, entry_set_index));
- }
+ std::vector pool(m_tree->m_node_size);
+ R_RETURN(FindEntryWithBuffer(virtual_address, entry_set_index, pool.data()));
}
Result BucketTree::Visitor::FindEntryWithBuffer(s64 virtual_address, s32 entry_set_index,
diff --git a/src/core/file_sys/fssystem/fssystem_bucket_tree_template_impl.h b/src/core/file_sys/fssystem/fssystem_bucket_tree_template_impl.h
index 030b2916b0..fac6c37214 100644
--- a/src/core/file_sys/fssystem/fssystem_bucket_tree_template_impl.h
+++ b/src/core/file_sys/fssystem/fssystem_bucket_tree_template_impl.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -6,7 +9,6 @@
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
namespace FileSys {
@@ -35,23 +37,19 @@ Result BucketTree::ScanContinuousReading(ContinuousReadingInfo* out_info,
R_UNLESS(entry.GetVirtualOffset() <= cur_offset, ResultOutOfRange);
// Create a pooled buffer for our scan.
- PooledBuffer pool(m_node_size, 1);
- char* buffer = nullptr;
-
+ std::vector pool(m_node_size);
s64 entry_storage_size = m_entry_storage->GetSize();
// Read the node.
- if (m_node_size <= pool.GetSize()) {
- buffer = pool.GetBuffer();
- const auto ofs = param.entry_set.index * static_cast(m_node_size);
- R_UNLESS(m_node_size + ofs <= static_cast(entry_storage_size),
- ResultInvalidBucketTreeNodeEntryCount);
+ u8* buffer = reinterpret_cast(pool.data());
+ const auto ofs = param.entry_set.index * s64(m_node_size);
+ R_UNLESS(m_node_size + ofs <= size_t(entry_storage_size),
+ ResultInvalidBucketTreeNodeEntryCount);
- m_entry_storage->Read(reinterpret_cast(buffer), m_node_size, ofs);
- }
+ m_entry_storage->Read(buffer, m_node_size, ofs);
// Calculate extents.
- const auto end_offset = cur_offset + static_cast(param.size);
+ const auto end_offset = cur_offset + s64(param.size);
s64 phys_offset = entry.GetPhysicalOffset();
// Start merge tracking.
@@ -76,14 +74,8 @@ Result BucketTree::ScanContinuousReading(ContinuousReadingInfo* out_info,
s64 next_entry_offset;
if (entry_index + 1 < entry_count) {
- if (buffer != nullptr) {
- const auto ofs = impl::GetBucketTreeEntryOffset(0, m_entry_size, entry_index + 1);
- std::memcpy(std::addressof(next_entry), buffer + ofs, m_entry_size);
- } else {
- const auto ofs = impl::GetBucketTreeEntryOffset(param.entry_set.index, m_node_size,
- m_entry_size, entry_index + 1);
- m_entry_storage->ReadObject(std::addressof(next_entry), ofs);
- }
+ const auto offset = impl::GetBucketTreeEntryOffset(0, m_entry_size, entry_index + 1);
+ std::memcpy(std::addressof(next_entry), buffer + offset, m_entry_size);
next_entry_offset = next_entry.GetVirtualOffset();
R_UNLESS(param.offsets.IsInclude(next_entry_offset), ResultInvalidIndirectEntryOffset);
diff --git a/src/core/file_sys/fssystem/fssystem_compressed_storage.h b/src/core/file_sys/fssystem/fssystem_compressed_storage.h
index 74c98630ec..223d51647e 100644
--- a/src/core/file_sys/fssystem/fssystem_compressed_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_compressed_storage.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,8 +12,6 @@
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_compression_common.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
-#include "core/file_sys/vfs/vfs.h"
namespace FileSys {
@@ -317,23 +318,11 @@ private:
R_SUCCEED_IF(entry_count == 0);
// Get the remaining size in a convenient form.
- const size_t total_required_size =
- static_cast(required_access_physical_size);
+ const size_t total_required_size = size_t(required_access_physical_size);
// Perform the read based on whether we need to allocate a buffer.
if (will_allocate_pooled_buffer) {
- // Allocate a pooled buffer.
- PooledBuffer pooled_buffer;
- if (pooled_buffer.GetAllocatableSizeMax() >= total_required_size) {
- pooled_buffer.Allocate(total_required_size, m_block_size_max);
- } else {
- pooled_buffer.AllocateParticularlyLarge(
- std::min(
- total_required_size,
- PooledBuffer::GetAllocatableParticularlyLargeSizeMax()),
- m_block_size_max);
- }
-
+ std::vector pooled_buffer(std::max(m_block_size_max, total_required_size));
// Read each of the entries.
for (s32 entry_idx = 0; entry_idx < entry_count; ++entry_idx) {
// Determine the current read size.
@@ -342,13 +331,13 @@ private:
if (const size_t target_entry_size =
static_cast(entries[entry_idx].physical_size) +
static_cast(entries[entry_idx].gap_from_prev);
- target_entry_size <= pooled_buffer.GetSize()) {
+ target_entry_size <= pooled_buffer.size()) {
// We'll be using the pooled buffer.
will_use_pooled_buffer = true;
// Determine how much we can read.
const size_t max_size = std::min(
- required_access_physical_size, pooled_buffer.GetSize());
+ required_access_physical_size, pooled_buffer.size());
size_t read_size = 0;
for (auto n = entry_idx; n < entry_count; ++n) {
@@ -376,7 +365,7 @@ private:
// Perform the read based on whether or not we'll use the pooled buffer.
if (will_use_pooled_buffer) {
// Read the compressed data into the pooled buffer.
- auto* const buffer = pooled_buffer.GetBuffer();
+ auto* const buffer = pooled_buffer.data();
m_data_storage->Read(reinterpret_cast(buffer), cur_read_size,
required_access_physical_offset);
@@ -863,11 +852,9 @@ private:
static_cast(unaligned_range->virtual_size));
// Get a pooled buffer for our read.
- PooledBuffer pooled_buffer;
- pooled_buffer.Allocate(size_buffer_required, size_buffer_required);
-
+ std::vector pooled_buffer(size_buffer_required);
// Perform read.
- Result rc = read_impl(pooled_buffer.GetBuffer(), size_buffer_required);
+ Result rc = read_impl(pooled_buffer.data(), size_buffer_required);
if (R_FAILED(rc)) {
R_THROW(rc);
}
@@ -876,8 +863,7 @@ private:
const size_t skip_size = cur_offset - unaligned_range->virtual_offset;
const size_t copy_size = std::min(
cur_size, unaligned_range->GetEndVirtualOffset() - cur_offset);
-
- std::memcpy(cur_dst, pooled_buffer.GetBuffer() + skip_size, copy_size);
+ std::memcpy(cur_dst, pooled_buffer.data() + skip_size, copy_size);
// Advance.
cur_dst += copy_size;
diff --git a/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp b/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp
deleted file mode 100644
index dcd08dac3e..0000000000
--- a/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/alignment.h"
-#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
-
-namespace FileSys {
-
-namespace {
-
-constexpr size_t HeapBlockSize = BufferPoolAlignment;
-static_assert(HeapBlockSize == 4_KiB);
-
-// A heap block is 4KiB. An order is a power of two.
-// This gives blocks of the order 32KiB, 512KiB, 4MiB.
-constexpr s32 HeapOrderMax = 7;
-constexpr s32 HeapOrderMaxForLarge = HeapOrderMax + 3;
-
-constexpr size_t HeapAllocatableSizeMax = HeapBlockSize * (static_cast(1) << HeapOrderMax);
-constexpr size_t HeapAllocatableSizeMaxForLarge =
- HeapBlockSize * (static_cast(1) << HeapOrderMaxForLarge);
-
-} // namespace
-
-size_t PooledBuffer::GetAllocatableSizeMaxCore(bool large) {
- return large ? HeapAllocatableSizeMaxForLarge : HeapAllocatableSizeMax;
-}
-
-void PooledBuffer::AllocateCore(size_t ideal_size, size_t required_size, bool large) {
- // Ensure preconditions.
- ASSERT(m_buffer == nullptr);
-
- // Check that we can allocate this size.
- ASSERT(required_size <= GetAllocatableSizeMaxCore(large));
-
- const size_t target_size =
- (std::min)((std::max)(ideal_size, required_size), GetAllocatableSizeMaxCore(large));
-
- // Dummy implementation for allocate.
- if (target_size > 0) {
- m_buffer =
- reinterpret_cast(::operator new(target_size, std::align_val_t{HeapBlockSize}));
- m_size = target_size;
-
- // Ensure postconditions.
- ASSERT(m_buffer != nullptr);
- }
-}
-
-void PooledBuffer::Shrink(size_t ideal_size) {
- ASSERT(ideal_size <= GetAllocatableSizeMaxCore(true));
-
- // Shrinking to zero means that we have no buffer.
- if (ideal_size == 0) {
- ::operator delete(m_buffer, std::align_val_t{HeapBlockSize});
- m_buffer = nullptr;
- m_size = ideal_size;
- }
-}
-
-} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_pooled_buffer.h b/src/core/file_sys/fssystem/fssystem_pooled_buffer.h
deleted file mode 100644
index 9a6adbcb5a..0000000000
--- a/src/core/file_sys/fssystem/fssystem_pooled_buffer.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-#include "common/literals.h"
-#include "core/hle/result.h"
-
-namespace FileSys {
-
-using namespace Common::Literals;
-
-constexpr inline size_t BufferPoolAlignment = 4_KiB;
-constexpr inline size_t BufferPoolWorkSize = 320;
-
-class PooledBuffer {
- YUZU_NON_COPYABLE(PooledBuffer);
-
-public:
- // Constructor/Destructor.
- constexpr PooledBuffer() : m_buffer(), m_size() {}
-
- PooledBuffer(size_t ideal_size, size_t required_size) : m_buffer(), m_size() {
- this->Allocate(ideal_size, required_size);
- }
-
- ~PooledBuffer() {
- this->Deallocate();
- }
-
- // Move and assignment.
- explicit PooledBuffer(PooledBuffer&& rhs) : m_buffer(rhs.m_buffer), m_size(rhs.m_size) {
- rhs.m_buffer = nullptr;
- rhs.m_size = 0;
- }
-
- PooledBuffer& operator=(PooledBuffer&& rhs) {
- PooledBuffer(std::move(rhs)).Swap(*this);
- return *this;
- }
-
- // Allocation API.
- void Allocate(size_t ideal_size, size_t required_size) {
- return this->AllocateCore(ideal_size, required_size, false);
- }
-
- void AllocateParticularlyLarge(size_t ideal_size, size_t required_size) {
- return this->AllocateCore(ideal_size, required_size, true);
- }
-
- void Shrink(size_t ideal_size);
-
- void Deallocate() {
- // Shrink the buffer to empty.
- this->Shrink(0);
- ASSERT(m_buffer == nullptr);
- }
-
- char* GetBuffer() const {
- ASSERT(m_buffer != nullptr);
- return m_buffer;
- }
-
- size_t GetSize() const {
- ASSERT(m_buffer != nullptr);
- return m_size;
- }
-
-public:
- static size_t GetAllocatableSizeMax() {
- return GetAllocatableSizeMaxCore(false);
- }
- static size_t GetAllocatableParticularlyLargeSizeMax() {
- return GetAllocatableSizeMaxCore(true);
- }
-
-private:
- static size_t GetAllocatableSizeMaxCore(bool large);
-
-private:
- void Swap(PooledBuffer& rhs) {
- std::swap(m_buffer, rhs.m_buffer);
- std::swap(m_size, rhs.m_size);
- }
-
- void AllocateCore(size_t ideal_size, size_t required_size, bool large);
-
-private:
- char* m_buffer;
- size_t m_size;
-};
-
-} // namespace FileSys
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 5f754650d9..eb209bf599 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -8,6 +8,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
+#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
@@ -161,11 +162,114 @@ NvResult nvhost_gpu::ZCullBind(IoctlZCullBind& params) {
}
NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) {
- LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
- params.size, params.mem);
+ LOG_DEBUG(Service_NVDRV, "called, offset={:#X}, size={:#X}, mem={:#X}",
+ params.offset, params.size, params.mem);
+
+ if (!params.mem || !params.size) {
+ std::scoped_lock lk(channel_mutex);
+ if (!channel_state->initialized) {
+ LOG_CRITICAL(Service_NVDRV, "No address space bound for setting up error notifier!");
+ return NvResult::NotInitialized;
+ }
+
+ error_notifier_params = {};
+ LOG_DEBUG(Service_NVDRV, "Error notifier disabled!");
+ return NvResult::Success;
+ }
+
+ constexpr u64 error_notification_size = sizeof(IoctlGetErrorNotification);
+ if (params.size < error_notification_size) {
+ LOG_ERROR(Service_NVDRV, "Error notification size: {:#X} is too small. Need at least {:#X}", params.size,
+ error_notification_size);
+ return NvResult::InvalidSize;
+ }
+
+ auto handle = nvmap.GetHandle(static_cast(params.mem));
+ if (!handle) {
+ LOG_ERROR(Service_NVDRV, "Unknown nvmap handle id {:#X}", params.mem);
+ return NvResult::BadParameter;
+ }
+
+ if (params.offset > handle->size || params.size > (handle->size - params.offset)) {
+ LOG_ERROR(Service_NVDRV, "Error notifier out of bounds: offset={:#X} size={:#X} handle size={:#X}", params.offset,
+ params.size, handle->size);
+ return NvResult::InvalidSize;
+ }
+
+ u64 write_address, write_offset, handle_id;
+ {
+ std::scoped_lock lk(channel_mutex);
+ if (!channel_state->initialized) {
+ LOG_CRITICAL(Service_NVDRV, "No address space bound for setting up error notifier!");
+ return NvResult::NotInitialized;
+ }
+
+ error_notifier_params = params;
+ write_address = handle->address;
+ write_offset = params.offset;
+ handle_id = handle->id;
+ }
+
+ if (write_address) {
+ IoctlGetErrorNotification error_notification{};
+ error_notification.status = static_cast(NotifierStatus::NoError);
+ system.ApplicationMemory().WriteBlock(write_address + write_offset, &error_notification, sizeof(error_notification));
+ } else {
+ LOG_WARNING(Service_NVDRV,
+ "nvmap handle id {:#X} has no virtual address assigned; "
+ "skipping initialization write for error notification!",
+ handle_id);
+ }
+
return NvResult::Success;
}
+void nvhost_gpu::PostErrorNotification(u32 info32, u16 info16, NotifierStatus status) {
+ IoctlSetErrorNotifier error_notifier_params_snapshot{};
+ Kernel::KEvent *error_notifier_event_snapshot{};
+ {
+ std::scoped_lock lk(channel_mutex);
+ error_notifier_params_snapshot = error_notifier_params;
+ error_notifier_event_snapshot = error_notifier_event;
+ }
+
+ if (!error_notifier_params_snapshot.mem || error_notifier_params_snapshot.size < sizeof(IoctlGetErrorNotification)) {
+ LOG_DEBUG(Service_NVDRV, "PostErrorNotification: notifier not configured or too small!");
+ return;
+ }
+
+ auto handle = nvmap.GetHandle(static_cast(error_notifier_params_snapshot.mem));
+ if (!handle || !handle->address) {
+ LOG_ERROR(Service_NVDRV, "PostErrorNotification: invalid handle or virtual address!");
+ return;
+ }
+
+ IoctlGetErrorNotification error_init{};
+ error_init.info32 = info32;
+ error_init.info16 = info16;
+ error_init.status = static_cast(status);
+ const u64 write_size = std::min(sizeof(IoctlGetErrorNotification),
+ error_notifier_params_snapshot.size);
+ if (error_notifier_params_snapshot.offset >= handle->size ||
+ write_size > (handle->size - error_notifier_params_snapshot.offset)) {
+ LOG_ERROR(Service_NVDRV, "PostErrorNotification: bounds check failed!");
+ return;
+ }
+
+ const u64 virtual_address = handle->address + error_notifier_params_snapshot.offset;
+ if (virtual_address < handle->address) {
+ LOG_ERROR(Service_NVDRV, "PostErrorNotification: virtual address overflow!");
+ return;
+ }
+
+ auto &application_memory = system.ApplicationMemory();
+ application_memory.WriteBlock(virtual_address, &error_init, write_size);
+
+ if (error_notifier_event_snapshot) {
+ error_notifier_event_snapshot->Signal();
+ }
+}
+
NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) {
channel_priority = params.priority;
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
@@ -251,7 +355,7 @@ NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
params.flags = allowed_mask;
}
- s32_le ctx_class_number_index =
+ s32_le ctx_class_number_index =
GetObjectContextClassNumberIndex(static_cast(params.class_num));
if (ctx_class_number_index < 0) {
LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#X}",
@@ -324,6 +428,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandL
if (flags.fence_wait.Value()) {
if (flags.increment_value.Value()) {
+ PostErrorNotification(flags.raw, 0, NotifierStatus::GenericError);
return NvResult::BadParameter;
}
@@ -357,7 +462,11 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandL
NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
std::span commands, bool kickoff) {
if (params.num_entries > commands.size()) {
- UNIMPLEMENTED();
+ LOG_ERROR(Service_NVDRV,
+ "SubmitGPFIFO: num_entries={:#X} > provided commands={:#X}",
+ params.num_entries, commands.size());
+
+ PostErrorNotification(params.num_entries, 0, NotifierStatus::BadGpfifo);
return NvResult::InvalidSize;
}
@@ -376,7 +485,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
std::span commands) {
if (params.num_entries > commands.size()) {
- UNIMPLEMENTED();
+ PostErrorNotification(params.num_entries, 0, NotifierStatus::BadGpfifo);
return NvResult::InvalidSize;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index fb0a5be959..16c4a95474 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -66,6 +66,16 @@ private:
CtxChannelGPFIFO = 0xB06F,
};
+ enum class NotifierStatus : u16_le {
+ NoError = 0xFFFF,
+ GenericError = 0x0001,
+ MmuFault = 0x0002,
+ IllegalMethod= 0x0003,
+ InvalidObject= 0x0004,
+ BadGpfifo = 0x0005,
+ TimeoutHang = 0x0006,
+ };
+
struct IoctlSetNvmapFD {
s32_le nvmap_fd{};
};
@@ -172,6 +182,8 @@ private:
s32_le nvmap_fd{};
u64_le user_data{};
IoctlZCullBind zcull_params{};
+ IoctlSetErrorNotifier error_notifier_params{};
+ void PostErrorNotification(u32 info32, u16 info16, NotifierStatus status);
std::array, 6> ctxObjs{};
u32_le channel_priority{};
u32_le channel_timeslice{};
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp
index a262a3dcd5..5c0515d473 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.cpp
+++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp
@@ -53,6 +53,19 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
// Set default speed limit to 100%.
*out_speed_scale = 1.0f;
+ // If no layers are available, skip the logic.
+ bool any_visible = false;
+ for (auto& layer : display.stack.layers) {
+ if (layer->visible) {
+ any_visible = true;
+ break;
+ }
+ }
+ if (!any_visible) {
+ *out_speed_scale = 1.0f;
+ return 1;
+ }
+
// Determine the number of vsync periods to wait before composing again.
std::optional swap_interval{};
bool has_acquired_buffer{};
@@ -110,7 +123,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
}
// If any new buffers were acquired, we can present.
- if (has_acquired_buffer) {
+ if (has_acquired_buffer && !composition_stack.empty()) {
// Sort by Z-index.
std::stable_sort(composition_stack.begin(), composition_stack.end(),
[&](auto& l, auto& r) { return l.z_index < r.z_index; });
@@ -119,6 +132,19 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
nvdisp.Composite(composition_stack);
}
+ // Batch framebuffer releases, instead of one-into-one.
+ std::vector> to_release;
+ for (auto& [layer_id, framebuffer] : m_framebuffers) {
+ if (framebuffer.release_frame_number > m_frame_number || !framebuffer.is_acquired)
+ continue;
+ if (auto layer = display.stack.FindLayer(layer_id); layer)
+ to_release.emplace_back(layer.get(), &framebuffer);
+ }
+ for (auto& [layer, framebuffer] : to_release) {
+ layer->buffer_item_consumer->ReleaseBuffer(framebuffer->item, android::Fence::NoFence());
+ framebuffer->is_acquired = false;
+ }
+
// Advance by at least one frame.
const u32 frame_advance = swap_interval.value_or(1);
m_frame_number += frame_advance;
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index 4439611d2e..35e76624f4 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -41,7 +44,14 @@ PerfStats::~PerfStats() {
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::LogDir);
// %F Date format expanded is "%Y-%m-%d"
- const auto filename = fmt::format("{:%F-%H-%M}_{:016X}.csv", *std::localtime(&t), title_id);
+ const auto filename = fmt::format("{}_{:016X}.csv",
+ [&] {
+ std::ostringstream oss;
+ oss << std::put_time(std::localtime(&t), "%F-%H-%M");
+ return oss.str();
+ }(),
+ title_id);
+
const auto filepath = path / filename;
if (Common::FS::CreateParentDir(filepath)) {
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 4bac8142c3..1723636811 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -33,7 +36,9 @@ std::filesystem::path GetPath(std::string_view type, u64 title_id, std::string_v
std::string GetTimestamp() {
const auto time = std::time(nullptr);
- return fmt::format("{:%FT%H-%M-%S}", *std::localtime(&time));
+ std::ostringstream oss;
+ oss << std::put_time(std::localtime(&time), "%FT%H-%M-%S");
+ return oss.str();
}
using namespace nlohmann;
diff --git a/src/qt_common/shared_translation.cpp b/src/qt_common/shared_translation.cpp
index cdc05e60e0..eb413f28e9 100644
--- a/src/qt_common/shared_translation.cpp
+++ b/src/qt_common/shared_translation.cpp
@@ -246,10 +246,7 @@ std::unique_ptr InitializeTranslations(QObject* parent)
INSERT(Settings,
vram_usage_mode,
tr("VRAM Usage Mode:"),
- tr("Selects whether the emulator should prefer to conserve memory or make maximum usage "
- "of available video memory for performance.\nHas no effect on integrated graphics. "
- "Aggressive mode may severely impact the performance of other applications such as "
- "recording software."));
+ tr("Selects whether the emulator should prefer to conserve memory or make maximum usage of available video memory for performance.\nAggressive mode may severely impact the performance of other applications such as recording software."));
INSERT(Settings,
skip_cpu_inner_invalidation,
tr("Skip CPU Inner Invalidation"),
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index 2c76584c72..23279e49b9 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -470,8 +470,8 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
const std::array wait_semaphores = {present_semaphore, *frame->render_ready};
static constexpr std::array wait_stage_masks{
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
};
const VkSubmitInfo submit_info{
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 6d7c33099b..41917a1b90 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1395,23 +1395,20 @@ void Device::CollectPhysicalMemoryInfo() {
}
device_access_memory += mem_properties.memoryHeaps[element].size;
}
- if (!is_integrated) {
+ if (is_integrated) {
+ const s64 available_memory = static_cast(device_access_memory - device_initial_usage);
+ const u64 memory_size = Settings::values.vram_usage_mode.GetValue() == Settings::VramUsageMode::Aggressive ? 6_GiB : 4_GiB;
+ device_access_memory = static_cast(std::max(std::min(available_memory - 8_GiB, memory_size), std::min(local_memory, memory_size)));
+ } else {
const u64 reserve_memory = std::min(device_access_memory / 8, 1_GiB);
device_access_memory -= reserve_memory;
-
if (Settings::values.vram_usage_mode.GetValue() != Settings::VramUsageMode::Aggressive) {
// Account for resolution scaling in memory limits
const size_t normal_memory = 6_GiB;
const size_t scaler_memory = 1_GiB * Settings::values.resolution_info.ScaleUp(1);
- device_access_memory =
- std::min(device_access_memory, normal_memory + scaler_memory);
+ device_access_memory = std::min(device_access_memory, normal_memory + scaler_memory);
}
-
- return;
}
- const s64 available_memory = static_cast(device_access_memory - device_initial_usage);
- device_access_memory = static_cast(std::max(
- std::min(available_memory - 8_GiB, 6_GiB), std::min(local_memory, 6_GiB)));
}
void Device::CollectToolingInfo() {