Compare commits

..

3 commits

Author SHA1 Message Date
9353cf51e6
add to existing icc/clang block
All checks were successful
eden-license / license-header (pull_request) Successful in 24s
Signed-off-by: crueter <crueter@eden-emu.dev>
2025-09-26 19:09:37 -04:00
nyx
df1b777860 limit to apple only
All checks were successful
eden-license / license-header (pull_request) Successful in 22s
2025-09-26 04:48:52 +02:00
nyx
c9c5278028 [cmake, macos] Suppress warnings for unused private members 2025-09-26 04:48:52 +02:00
17 changed files with 121 additions and 169 deletions

View file

@ -310,7 +310,6 @@ endif()
if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX))
set(HAS_NCE 1)
add_compile_definitions(HAS_NCE=1)
find_package(oaknut 2.0.1)
endif()
if (YUZU_ROOM)

View file

@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
include(FindPackageHandleStandardArgs)
find_package(PkgConfig QUIET)
pkg_search_module(sirit QUIET IMPORTED_TARGET sirit)
find_package_handle_standard_args(sirit
REQUIRED_VARS sirit_LINK_LIBRARIES
VERSION_VAR sirit_VERSION
)

View file

@ -10,7 +10,7 @@
"repo": "eden-emulator/sirit",
"sha": "db1f1e8ab5",
"hash": "73eb3a042848c63a10656545797e85f40d142009dfb7827384548a385e1e28e1ac72f42b25924ce530d58275f8638554281e884d72f9c7aaf4ed08690a414b05",
"find_args": "CONFIG",
"find_args": "MODULE",
"options": [
"SIRIT_USE_SYSTEM_SPIRV_HEADERS ON"
]

View file

@ -27,8 +27,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" android:required="false" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
@ -95,10 +93,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" />
</activity>
<service android:name="org.yuzu.yuzu_emu.utils.ForegroundService" android:foregroundServiceType="specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="Keep emulation running in background"/>
</service>
<provider
android:name=".features.DocumentProvider"
android:authorities="${applicationId}.user"

View file

@ -22,17 +22,6 @@ fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
class YuzuApplication : Application() {
private fun createNotificationChannels() {
val name: CharSequence = getString(R.string.app_notification_channel_name)
val description = getString(R.string.app_notification_channel_description)
val foregroundService = NotificationChannel(
getString(R.string.app_notification_channel_id),
name,
NotificationManager.IMPORTANCE_DEFAULT
)
foregroundService.description = description
foregroundService.setSound(null, null)
foregroundService.vibrationPattern = null
val noticeChannel = NotificationChannel(
getString(R.string.notice_notification_channel_id),
getString(R.string.notice_notification_channel_name),
@ -45,7 +34,6 @@ class YuzuApplication : Application() {
// or other notification behaviors after this
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(noticeChannel)
notificationManager.createNotificationChannel(foregroundService)
}
override fun onCreate() {

View file

@ -7,7 +7,6 @@
package org.yuzu.yuzu_emu.activities
import android.annotation.SuppressLint
import android.app.Activity
import android.app.PendingIntent
import android.app.PictureInPictureParams
import android.app.RemoteAction
@ -60,7 +59,6 @@ import org.yuzu.yuzu_emu.utils.ParamPackage
import org.yuzu.yuzu_emu.utils.ThemeHelper
import java.text.NumberFormat
import kotlin.math.roundToInt
import org.yuzu.yuzu_emu.utils.ForegroundService
class EmulationActivity : AppCompatActivity(), SensorEventListener {
private lateinit var binding: ActivityEmulationBinding
@ -80,8 +78,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
private val emulationViewModel: EmulationViewModel by viewModels()
private var foregroundService: Intent? = null
override fun onCreate(savedInstanceState: Bundle?) {
Log.gameLaunched = true
ThemeHelper.setTheme(this)
@ -132,9 +128,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
nfcReader = NfcReader(this)
nfcReader.initialize()
foregroundService = Intent(this, ForegroundService::class.java)
startForegroundService(foregroundService)
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.totalMemory)) {
@ -196,12 +189,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
stopMotionSensorListener()
}
override fun onDestroy() {
super.onDestroy()
stopForegroundService(this)
}
override fun onUserLeaveHint() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
@ -524,12 +511,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
companion object {
const val EXTRA_SELECTED_GAME = "SelectedGame"
fun stopForegroundService(activity: Activity) {
val startIntent = Intent(activity, ForegroundService::class.java)
startIntent.action = ForegroundService.ACTION_STOP
activity.startForegroundService(startIntent)
}
fun launch(activity: AppCompatActivity, game: Game) {
val launcher = Intent(activity, EmulationActivity::class.java)
launcher.putExtra(EXTRA_SELECTED_GAME, game)

View file

@ -48,7 +48,6 @@ import java.io.BufferedOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import androidx.core.content.edit
import org.yuzu.yuzu_emu.activities.EmulationActivity
import kotlin.text.compareTo
class MainActivity : AppCompatActivity(), ThemeProvider {
@ -189,9 +188,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (it) checkKeys()
}
// Dismiss previous notifications (should not happen unless a crash occurred)
EmulationActivity.stopForegroundService(this)
setInsets()
}
@ -297,11 +293,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
themeId = resId
}
override fun onDestroy() {
EmulationActivity.stopForegroundService(this)
super.onDestroy()
}
val getGamesDirectory =
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
if (result != null) {

View file

@ -1,79 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
package org.yuzu.yuzu_emu.utils
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.activities.EmulationActivity
/**
* A service that shows a permanent notification in the background to avoid the app getting
* cleared from memory by the system.
*/
class ForegroundService : Service() {
companion object {
const val EMULATION_RUNNING_NOTIFICATION = 0x1000
const val ACTION_STOP = "stop"
}
private fun showRunningNotification() {
// Intent is used to resume emulation if the notification is clicked
val contentIntent = PendingIntent.getActivity(
this,
0,
Intent(this, EmulationActivity::class.java),
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val builder =
NotificationCompat.Builder(this, getString(R.string.app_notification_channel_id))
.setSmallIcon(R.drawable.ic_stat_notification_logo)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.app_notification_running))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setOngoing(true)
.setVibrate(null)
.setSound(null)
.setContentIntent(contentIntent)
startForeground(EMULATION_RUNNING_NOTIFICATION, builder.build())
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onCreate() {
showRunningNotification()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent?.action == ACTION_STOP) {
try {
NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION)
stopForeground(STOP_FOREGROUND_REMOVE)
} catch (e: Exception) {
Log.error("Failed to stop foreground service")
}
stopSelfResult(startId)
return START_NOT_STICKY
}
if (intent != null) {
showRunningNotification()
}
return START_STICKY
}
override fun onDestroy() =
NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION)
}

View file

@ -8,11 +8,6 @@
<string name="notice_notification_channel_id" translatable="false">noticesAndErrors</string>
<string name="notice_notification_channel_description">Shows notifications when something goes wrong.</string>
<string name="notification_permission_not_granted">Notification permission not granted!</string>
<string name="app_notification_channel_name" translatable="false">Eden</string>
<string name="app_notification_channel_id" translatable="false">Eden</string>
<string name="app_notification_channel_description">Eden Switch emulator notifications</string>
<string name="app_notification_running">Eden is Running</string>
<!-- Stats Overlay settings -->
<string name="enhanced_fps_suffix">(Enhanced)</string>

View file

@ -32,6 +32,7 @@ add_library(
atomic_ops.h
bit_cast.h
bit_field.h
bit_set.h
bit_util.h
bounded_threadsafe_queue.h
cityhash.cpp

86
src/common/bit_set.h Normal file
View file

@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <bit>
#include "common/alignment.h"
#include "common/bit_util.h"
#include "common/common_types.h"
namespace Common {
namespace impl {
template <typename Storage, size_t N>
class BitSet {
public:
constexpr BitSet() = default;
constexpr void SetBit(size_t i) {
this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord);
}
constexpr void ClearBit(size_t i) {
this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord);
}
constexpr size_t CountLeadingZero() const {
for (size_t i = 0; i < NumWords; i++) {
if (this->words[i]) {
return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]);
}
}
return FlagsPerWord * NumWords;
}
constexpr size_t GetNextSet(size_t n) const {
for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) {
Storage word = this->words[i];
if (!IsAligned(n + 1, FlagsPerWord)) {
word &= GetBitMask(n % FlagsPerWord) - 1;
}
if (word) {
return FlagsPerWord * i + CountLeadingZeroImpl(word);
}
}
return FlagsPerWord * NumWords;
}
private:
static_assert(std::is_unsigned_v<Storage>);
static_assert(sizeof(Storage) <= sizeof(u64));
static constexpr size_t FlagsPerWord = BitSize<Storage>();
static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord;
static constexpr auto CountLeadingZeroImpl(Storage word) {
return std::countl_zero(static_cast<unsigned long long>(word)) -
(BitSize<unsigned long long>() - FlagsPerWord);
}
static constexpr Storage GetBitMask(size_t bit) {
return Storage(1) << (FlagsPerWord - 1 - bit);
}
std::array<Storage, NumWords> words{};
};
} // namespace impl
template <size_t N>
using BitSet8 = impl::BitSet<u8, N>;
template <size_t N>
using BitSet16 = impl::BitSet<u16, N>;
template <size_t N>
using BitSet32 = impl::BitSet<u32, N>;
template <size_t N>
using BitSet64 = impl::BitSet<u64, N>;
} // namespace Common

View file

@ -1224,7 +1224,7 @@ if (HAS_NCE)
arm/nce/patcher.h
arm/nce/visitor_base.h
)
target_link_libraries(core PRIVATE merry::oaknut)
target_link_libraries(core PRIVATE merry::mcl merry::oaknut)
endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)

View file

@ -27,11 +27,11 @@ template <>
struct std::hash<PatchCacheKey> {
size_t operator()(const PatchCacheKey& key) const {
// Simple XOR hash of first few bytes
size_t hash_ = 0;
size_t hash = 0;
for (size_t i = 0; i < key.module_id.size(); ++i) {
hash_ ^= static_cast<size_t>(key.module_id[i]) << ((i % sizeof(size_t)) * 8);
hash ^= static_cast<size_t>(key.module_id[i]) << ((i % sizeof(size_t)) * 8);
}
return hash_ ^ std::hash<uintptr_t>{}(key.offset);
return hash ^ std::hash<uintptr_t>{}(key.offset);
}
};

View file

@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -8,12 +5,10 @@
#include <array>
#include <bit>
#include <bitset>
#include <concepts>
#include <cstddef>
#include "common/alignment.h"
#include "common/assert.h"
#include "common/bit_set.h"
#include "common/common_types.h"
#include "common/concepts.h"
@ -164,7 +159,7 @@ public:
}
if (m_queues[priority].PushBack(core, member)) {
m_available_priorities[core].set(std::size_t(priority));
m_available_priorities[core].SetBit(priority);
}
}
@ -177,7 +172,7 @@ public:
}
if (m_queues[priority].PushFront(core, member)) {
m_available_priorities[core].set(std::size_t(priority));
m_available_priorities[core].SetBit(priority);
}
}
@ -190,19 +185,14 @@ public:
}
if (m_queues[priority].Remove(core, member)) {
m_available_priorities[core].reset(std::size_t(priority));
m_available_priorities[core].ClearBit(priority);
}
}
constexpr Member* GetFront(s32 core) const {
ASSERT(IsValidCore(core));
const s32 priority = s32([](auto const& e) {
for (size_t i = 0; i < e.size(); ++i)
if (e[i])
return i;
return e.size();
}(m_available_priorities[core]));
const s32 priority = static_cast<s32>(m_available_priorities[core].CountLeadingZero());
if (priority <= LowestPriority) {
return m_queues[priority].GetFront(core);
} else {
@ -221,22 +211,16 @@ public:
}
}
template<size_t N>
constexpr size_t GetNextSet(std::bitset<N> const& bit, size_t n) const {
for (size_t i = n + 1; i < bit.size(); i++)
if (bit[i])
return i;
return bit.size();
}
constexpr Member* GetNext(s32 core, const Member* member) const {
ASSERT(IsValidCore(core));
Member* next = member->GetPriorityQueueEntry(core).GetNext();
if (next == nullptr) {
s32 priority = s32(GetNextSet(m_available_priorities[core], member->GetPriority()));
if (priority <= LowestPriority)
const s32 priority = static_cast<s32>(
m_available_priorities[core].GetNextSet(member->GetPriority()));
if (priority <= LowestPriority) {
next = m_queues[priority].GetFront(core);
}
}
return next;
}
@ -266,7 +250,7 @@ public:
private:
std::array<KPerCoreQueue, NumPriority> m_queues{};
std::array<std::bitset<NumPriority>, NumCores> m_available_priorities{};
std::array<Common::BitSet64<NumPriority>, NumCores> m_available_priorities{};
};
private:

View file

@ -374,7 +374,7 @@ endif()
target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS})
target_link_libraries(dynarmic
PUBLIC
PRIVATE
fmt::fmt
merry::mcl
)

View file

@ -792,11 +792,6 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
const u32 size = (std::min)(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]);
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer, binding.buffer_id);
const bool sync_buffer = SynchronizeBuffer(buffer, device_addr, size);
if (sync_buffer) {
++channel_state->uniform_cache_hits[0];
}
++channel_state->uniform_cache_shots[0];
const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID &&
size <= channel_state->uniform_buffer_skip_cache_size &&
!memory_tracker.IsRegionGpuModified(device_addr, size);
@ -827,6 +822,12 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
device_memory.ReadBlockUnsafe(device_addr, span.data(), size);
return;
}
// Classic cached path
const bool sync_cached = SynchronizeBuffer(buffer, device_addr, size);
if (sync_cached) {
++channel_state->uniform_cache_hits[0];
}
++channel_state->uniform_cache_shots[0];
// Skip binding if it's not needed and if the bound buffer is not the fast version
// This exists to avoid instances where the fast buffer is bound and a GPU write happens

View file

@ -31,7 +31,7 @@ struct DescriptorBank {
bool DescriptorBankInfo::IsSuperset(const DescriptorBankInfo& subset) const noexcept {
return uniform_buffers >= subset.uniform_buffers && storage_buffers >= subset.storage_buffers &&
texture_buffers >= subset.texture_buffers && image_buffers >= subset.image_buffers &&
textures >= subset.textures && images >= subset.images;
textures >= subset.textures && images >= subset.image_buffers;
}
template <typename Descriptors>