Compare commits

..

1 Commits

Author SHA1 Message Date
Eden CI 8feb7d9c65 [dist, android] Update translations from Transifex
Signed-off-by: Eden CI <ci@eden-emu.dev>
2026-06-27 10:01:56 -04:00
159 changed files with 11710 additions and 11982 deletions
+386 -327
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+424 -367
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+442 -385
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+384 -327
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+470 -413
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+420 -363
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
+383 -326
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -59,11 +59,6 @@ endif()
if (PLATFORM_PS4 OR PLATFORM_MANAGARM)
# Doesn't support VA-API, don't go thru the embarrassment of trying to enable it
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi)
elseif (ANDROID)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-mediacodec
--enable-jni
)
elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING AND NOT ANDROID)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
@@ -31,7 +31,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
ENABLE_BUFFER_HISTORY("enable_buffer_history"),
USE_OPTIMIZED_VERTEX_BUFFERS("use_optimized_vertex_buffers"),
ENABLE_GPU_BUFFER_READBACK("enable_gpu_buffer_readback"),
SYNC_MEMORY_OPERATIONS("sync_memory_operations"),
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
RENDERER_DEBUG("debug"),
@@ -806,13 +806,6 @@ abstract class SettingsItem(
descriptionId = R.string.enable_buffer_history_description
)
)
put(
SwitchSetting(
BooleanSetting.ENABLE_GPU_BUFFER_READBACK,
titleId = R.string.enable_gpu_buffer_readback,
descriptionId = R.string.enable_gpu_buffer_readback_description
)
)
put(
SwitchSetting(
BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS,
@@ -292,7 +292,6 @@ class SettingsFragmentPresenter(
add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
add(BooleanSetting.RENDERER_REACTIVE_FLUSHING.key)
add(BooleanSetting.ENABLE_BUFFER_HISTORY.key)
add(BooleanSetting.ENABLE_GPU_BUFFER_READBACK.key)
add(BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS.key)
add(HeaderSetting(R.string.hacks))
+1 -1
View File
@@ -27,7 +27,7 @@ if (ARCHITECTURE_arm64)
target_link_libraries(yuzu-android PRIVATE adrenotools)
endif()
target_link_libraries(yuzu-android PRIVATE ${FFmpeg_LIBRARIES} OpenSSL::SSL cpp-jwt::cpp-jwt)
target_link_libraries(yuzu-android PRIVATE OpenSSL::SSL cpp-jwt::cpp-jwt)
if (ENABLE_UPDATE_CHECKER)
target_compile_definitions(yuzu-android PUBLIC ENABLE_UPDATE_CHECKER)
endif()
-11
View File
@@ -36,10 +36,6 @@
#include <frontend_common/content_manager.h>
#include <jni.h>
extern "C" {
#include <libavcodec/jni.h>
}
#include "common/android/multiplayer/multiplayer.h"
#include "common/android/android_common.h"
#include "common/android/id_cache.h"
@@ -684,13 +680,6 @@ const char* fallback_cpu_detection() {
} // namespace
extern "C" {
jint InitFFmpegOnLoad(JavaVM* vm) {
av_jni_set_java_vm(vm, nullptr);
return 0;
}
}
extern "C" {
void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jobject instance,
@@ -573,8 +573,6 @@
<string name="gpu_log_level_description">مستوى التفاصيل لسجلات وحدة معالجة الرسومات (كلما زاد المستوى، زادت التفاصيل وزادت التكاليف الإضافية)</string>
<string name="gpu_log_vulkan_calls">تسجيل استدعاءات واجهة برمجة تطبيقات Vulkan</string>
<string name="gpu_log_vulkan_calls_description">تتبع جميع استدعاءات واجهة برمجة تطبيقات Vulkan في المخزن المؤقت الحلقي</string>
<string name="gpu_log_shader_dumps">تفريغ التظليل</string>
<string name="gpu_log_shader_dumps_description">حفظ تظليل SPIR-V المجمع في ملفات</string>
<string name="gpu_log_memory_tracking">تتبع ذاكرة وحدة معالجة الرسومات</string>
<string name="gpu_log_memory_tracking_description">مراقبة تخصيصات ذاكرة وحدة معالجة الرسومات وإلغاء تخصيصها</string>
<string name="gpu_log_driver_debug">معلومات تصحيح أخطاء برنامج التشغيل</string>
@@ -567,8 +567,6 @@
<string name="gpu_log_level_description">Nivel de detalle de los registros de la GPU (más alto = más detalles, más sobrecarga)</string>
<string name="gpu_log_vulkan_calls">Registros de llamadas del API de Vulkan</string>
<string name="gpu_log_vulkan_calls_description">Rastrear todas las llamadas del API de Vulkan en el búfer circular</string>
<string name="gpu_log_shader_dumps">Volcar sombreadores</string>
<string name="gpu_log_shader_dumps_description">Guardar sombreadores compilados de SPIR-V en archivos</string>
<string name="gpu_log_memory_tracking">Rastrear memoria de la GPU</string>
<string name="gpu_log_memory_tracking_description">Monitorizar las asignaciones y desasignaciones de memoria de la GPU</string>
<string name="gpu_log_driver_debug">Información de depuración del controlador</string>
@@ -527,8 +527,6 @@
<string name="gpu_logging_header">Journalisation GPU</string>
<string name="gpu_log_level">Niveau de journalisation</string>
<string name="gpu_log_vulkan_calls">Journaliser les appels API Vulkan</string>
<string name="gpu_log_shader_dumps">Extraire les shaders</string>
<string name="gpu_log_shader_dumps_description">Sauvegarder le shader SPIR-V complié dans les fichiers</string>
<string name="gpu_log_memory_tracking">Monitorer la mémoire GPU</string>
<string name="gpu_log_memory_tracking_description">Monitorer les allocations et désallocations de la mémoire GPU</string>
<string name="gpu_log_driver_debug">Informations de débogage du pilote</string>
@@ -566,8 +566,6 @@
<string name="gpu_log_level_description">Уровень детализации логов ГПУ (больше значение = больше деталей, выше нагрузка)</string>
<string name="gpu_log_vulkan_calls">Записывать вызовы Vulkan API</string>
<string name="gpu_log_vulkan_calls_description">Отслеживать все вызовы Vulkan API в кольцевом буфере</string>
<string name="gpu_log_shader_dumps">Выгрузить шейдеры</string>
<string name="gpu_log_shader_dumps_description">Сохранять скомпилированные SPIR-V шейдеры в файлы</string>
<string name="gpu_log_memory_tracking">Отслеживать память ГПУ</string>
<string name="gpu_log_memory_tracking_description">Мониторить выделение и освобождение памяти ГПУ</string>
<string name="gpu_log_driver_debug">Отладочная информация драйвера</string>
@@ -569,8 +569,6 @@
<string name="gpu_log_level_description">Рівень подробиць у журналі ГП (вищий = більше подробиць, більший вплив на швидкодію)</string>
<string name="gpu_log_vulkan_calls">Записувати виклики API Vulkan</string>
<string name="gpu_log_vulkan_calls_description">Відстежувати всі виклики API Vulkan у кільцевому буфері</string>
<string name="gpu_log_shader_dumps">Зберігати шейдери</string>
<string name="gpu_log_shader_dumps_description">Зберігати до файлів скомпільовані шейдери SPIR-V</string>
<string name="gpu_log_memory_tracking">Відстежувати пам’ять ГП</string>
<string name="gpu_log_memory_tracking_description">Відстежувати використання і звільнення пам’яті ГП</string>
<string name="gpu_log_driver_debug">Зневаджувальна інформація драйверів</string>
@@ -563,8 +563,6 @@
<string name="gpu_log_level_description">GPU 日志的详细级别(数值越高 = 细节越多,开销越大)</string>
<string name="gpu_log_vulkan_calls">记录 Vulkan API 调用</string>
<string name="gpu_log_vulkan_calls_description">在环形缓冲区中跟踪所有 Vulkan API 调用</string>
<string name="gpu_log_shader_dumps">转储着色器</string>
<string name="gpu_log_shader_dumps_description">保存已编译的着色器 SPIR-V 到文件中</string>
<string name="gpu_log_memory_tracking">追踪 GPU 内存</string>
<string name="gpu_log_memory_tracking_description">监控 GPU 内存的分配和释放</string>
<string name="gpu_log_driver_debug">驱动调试信息</string>
@@ -503,8 +503,6 @@
<string name="renderer_reactive_flushing_description">Improves rendering accuracy in some games at the cost of performance.</string>
<string name="enable_buffer_history">Enable buffer history</string>
<string name="enable_buffer_history_description">Enables access to previous buffer states. This option may improve rendering quality and performance consistency in some games.</string>
<string name="enable_gpu_buffer_readback">Enable GPU Buffer Readback</string>
<string name="enable_gpu_buffer_readback_description">Preserves GPU-modified buffer data by reading it back before uploads. Some games require this to render certain effects properly. May cause issues if the hardware cannot handle the additional workload.</string>
<string name="use_optimized_vertex_buffers">Optimized Vertex Buffers</string>
<string name="use_optimized_vertex_buffers_description">Enables optimized vertex buffer binding for improved performance. Requires Mesa 26.0+ Turnip drivers/ QCOM drivers. Will crash on older Turnip drivers (25.3 and below).</string>
-3
View File
@@ -427,11 +427,8 @@ namespace Common::Android {
extern "C" {
#endif
jint InitFFmpegOnLoad(JavaVM *vm);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
s_java_vm = vm;
InitFFmpegOnLoad(vm);
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION) != JNI_OK)
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
+1 -1
View File
@@ -350,7 +350,7 @@ struct System::Impl {
// Register with applet manager
// All threads are started, begin main process execution, now that we're in the clear
applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params);
applet_manager.CreateAndInsertByFrontendAppletParameters(std::make_unique<Service::Process>(*std::move(process)), params);
if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) {
+6 -6
View File
@@ -729,7 +729,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface(ctx, ensure_token_id);
rb.PushIpcInterface(ensure_token_id);
}
void LoadIdTokenCacheDeprecated(HLERequestContext& ctx) {
@@ -921,7 +921,7 @@ void Module::Interface::GetProfile(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IProfile>(ctx, system, user_id, *profile_manager);
rb.PushIpcInterface<IProfile>(system, user_id, *profile_manager);
}
void Module::Interface::IsUserRegistrationRequestPermitted(HLERequestContext& ctx) {
@@ -993,7 +993,7 @@ void Module::Interface::GetBaasAccountManagerForApplication(HLERequestContext& c
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IManagerForApplication>(ctx, system, profile_manager);
rb.PushIpcInterface<IManagerForApplication>(system, profile_manager);
}
void Module::Interface::IsUserAccountSwitchLocked(HLERequestContext& ctx) {
@@ -1089,7 +1089,7 @@ void Module::Interface::GetProfileEditor(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IProfileEditor>(ctx, system, user_id, *profile_manager);
rb.PushIpcInterface<IProfileEditor>(system, user_id, *profile_manager);
}
void Module::Interface::GetBaasAccountAdministrator(HLERequestContext &ctx) {
@@ -1100,7 +1100,7 @@ void Module::Interface::GetBaasAccountAdministrator(HLERequestContext &ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IAdministrator>(ctx, system, uuid);
rb.PushIpcInterface<IAdministrator>(system, uuid);
}
void Module::Interface::ListQualifiedUsers(HLERequestContext& ctx) {
@@ -1143,7 +1143,7 @@ void Module::Interface::GetBaasAccountManagerForSystemService(HLERequestContext&
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IManagerForSystemService>(ctx, system, uuid);
rb.PushIpcInterface<IManagerForSystemService>(system, uuid);
}
void Module::Interface::StoreSaveDataThumbnailSystem(HLERequestContext& ctx) {
+1 -1
View File
@@ -35,7 +35,7 @@ void IAsyncContext::GetSystemEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, completion_event->GetReadableEvent());
rb.PushCopyObjects(completion_event->GetReadableEvent());
}
void IAsyncContext::Cancel(HLERequestContext& ctx) {
-4
View File
@@ -109,10 +109,6 @@ struct Applet {
std::list<std::shared_ptr<Applet>> child_applets{};
bool is_completed{};
std::shared_ptr<Applet> reserved_applet{};
bool unwind_after_reserved{};
bool is_winding{};
// Self state
bool exit_locked{};
s32 fatal_section_count{};
@@ -25,13 +25,6 @@ void AppletStorageChannel::Push(Kernel::KernelCore& kernel, std::shared_ptr<ISto
m_event.Signal(kernel);
}
void AppletStorageChannel::Unpop(Kernel::KernelCore& kernel, std::shared_ptr<IStorage> storage) {
std::scoped_lock lk{m_lock};
m_data.emplace_front(std::move(storage));
m_event.Signal(kernel);
}
Result AppletStorageChannel::Pop(Kernel::KernelCore& kernel, std::shared_ptr<IStorage>* out_storage) {
std::scoped_lock lk{m_lock};
@@ -26,7 +26,6 @@ public:
~AppletStorageChannel();
void Push(Kernel::KernelCore& kernel, std::shared_ptr<IStorage> storage);
void Unpop(Kernel::KernelCore& kernel, std::shared_ptr<IStorage> storage);
Result Pop(Kernel::KernelCore& kernel, std::shared_ptr<IStorage>* out_storage);
Kernel::KReadableEvent* GetEvent();
+1 -1
View File
@@ -267,7 +267,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) {
if (Settings::values.enable_overlay && m_window_system->GetOverlayDisplayApplet() == nullptr) {
if (auto overlay_process = CreateProcess(m_system, static_cast<u64>(AppletProgramId::OverlayDisplay), 0, 0)) {
auto overlay_applet = std::make_shared<Applet>(m_system, std::move(overlay_process), false);
auto overlay_applet = std::make_shared<Applet>(m_system, std::make_unique<Service::Process>(*std::move(overlay_process)), false);
overlay_applet->program_id = static_cast<u64>(AppletProgramId::OverlayDisplay);
overlay_applet->applet_id = AppletId::OverlayDisplay;
overlay_applet->type = AppletType::OverlayApplet;
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -15,10 +12,7 @@ namespace Service::AM {
HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) {
m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid", true);
this->RegisterCurrentProcess();
}
void HidRegistration::RegisterCurrentProcess() {
if (m_process.IsInitialized()) {
m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
true);
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -27,7 +24,6 @@ public:
explicit HidRegistration(Core::System& system, Process& process);
~HidRegistration();
void RegisterCurrentProcess();
void EnableAppletToGetInput(bool enable);
private:
@@ -171,18 +171,6 @@ void LifecycleManager::SignalSystemEventIfNeeded(Kernel::KernelCore& kernel) {
}
}
void LifecycleManager::ResetForRelaunch() {
m_unordered_messages.clear();
m_activity_state = ActivityState::BackgroundVisible;
m_requested_focus_state = FocusState{};
m_acknowledged_focus_state = FocusState{};
m_has_focus_state_changed = true;
m_suspend_mode = SuspendMode::NoOverride;
m_forced_suspend = false;
}
bool LifecycleManager::PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message) {
const auto message = this->PopMessageInOrderOfPriority();
this->SignalSystemEventIfNeeded(kernel);
@@ -138,8 +138,6 @@ public:
void PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message);
bool PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message);
void ResetForRelaunch();
private:
FocusState GetFocusStateWhileForegroundObscured() const;
FocusState GetFocusStateWhileBackground(bool is_obscured) const;
+8 -24
View File
@@ -40,23 +40,23 @@ namespace {
}
}
[[nodiscard]] inline std::unique_ptr<Process> CreateProcessImpl(std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) {
[[nodiscard]] inline std::optional<Process> CreateProcessImpl(std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) {
// Get the appropriate loader to parse this NCA.
out_loader = Loader::GetLoader(system, file, program_id, program_index);
// Ensure we have a loader which can parse the NCA.
if (out_loader) {
// Try to load the process.
auto process = std::make_unique<Process>(system);
auto process = std::make_optional<Process>(system);
if (process->Initialize(*out_loader, out_load_result)) {
return process;
}
}
return nullptr;
return std::nullopt;
}
} // Anonymous namespace
std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation) {
std::optional<Process> CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation) {
// Attempt to load program NCA.
FileSys::VirtualFile nca_raw{};
@@ -66,7 +66,7 @@ std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, u8
// Ensure we retrieved a program NCA.
if (!nca_raw) {
return nullptr;
return std::nullopt;
}
// Ensure we have a suitable version.
@@ -76,7 +76,7 @@ std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, u8
(nca.GetKeyGeneration() < minimum_key_generation ||
nca.GetKeyGeneration() > maximum_key_generation)) {
LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, nca.GetKeyGeneration());
return nullptr;
return std::nullopt;
}
}
@@ -85,7 +85,7 @@ std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, u8
return CreateProcessImpl(loader, status, system, nca_raw, program_id, 0);
}
std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control, std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) {
std::optional<Process> CreateApplicationProcess(std::vector<u8>& out_control, std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) {
if (auto process = CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); process) {
FileSys::NACP nacp;
if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
@@ -110,23 +110,7 @@ std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control,
system.GetARPManager().Register(launch.title_id, launch, out_control);
return process;
}
return nullptr;
}
bool ReinitializeProcess(Core::System& system, Process& process, u64 program_id) {
auto& storage = system.GetContentProviderUnion();
const auto nca_raw = storage.GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
if (!nca_raw) {
return false;
}
auto loader = Loader::GetLoader(system, nca_raw, program_id, 0);
if (!loader) {
return false;
}
Loader::ResultStatus status{};
return process.Initialize(*loader, status);
return std::nullopt;
}
} // namespace Service::AM
+2 -4
View File
@@ -27,9 +27,7 @@ class Process;
namespace Service::AM {
std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation);
std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control, std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index);
bool ReinitializeProcess(Core::System& system, Process& process, u64 program_id);
std::optional<Process> CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation);
std::optional<Process> CreateApplicationProcess(std::vector<u8>& out_control, std::unique_ptr<Loader::AppLoader>& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index);
} // namespace Service::AM
@@ -35,9 +35,9 @@ Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_applicati
std::unique_ptr<Loader::AppLoader> loader;
Loader::ResultStatus result;
auto process = CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0);
R_UNLESS(process != nullptr, ResultUnknown);
R_UNLESS(process != std::nullopt, ResultUnknown);
const auto applet = std::make_shared<Applet>(system, std::move(process), true);
const auto applet = std::make_shared<Applet>(system, std::make_unique<Service::Process>(*std::move(process)), true);
applet->program_id = program_id;
applet->applet_id = AppletId::Application;
applet->type = AppletType::Application;
@@ -88,9 +88,9 @@ Result IApplicationCreator::CreateSystemApplication(
std::vector<u8> control;
std::unique_ptr<Loader::AppLoader> loader;
auto process = CreateProcess(system, application_id, 1, 22);
R_UNLESS(process != nullptr, ResultUnknown);
R_UNLESS(process != std::nullopt, ResultUnknown);
const auto applet = std::make_shared<Applet>(system, std::move(process), true);
const auto applet = std::make_shared<Applet>(system, std::make_unique<Service::Process>(*std::move(process)), true);
applet->program_id = application_id;
applet->applet_id = AppletId::Starter;
applet->type = AppletType::LibraryApplet;
@@ -75,7 +75,7 @@ ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
{105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"},
{106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"},
{110, nullptr, "NeedsToExitProcess"},
{120, D<&ILibraryAppletAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"},
{120, nullptr, "GetLibraryAppletInfo"},
{150, nullptr, "RequestForAppletToGetForeground"},
{160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle"}, //2.0.0+
{170, D<&ILibraryAppletAccessor::Unknown170>, "Unknown170"}, //22.0.0+
@@ -218,16 +218,6 @@ Result ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(Out<u64> out_handl
R_SUCCEED();
}
Result ILibraryAppletAccessor::GetLibraryAppletInfo(
Out<LibraryAppletInfo> out_library_applet_info) {
LOG_INFO(Service_AM, "called");
*out_library_applet_info = {
.applet_id = m_applet->applet_id,
.library_applet_mode = m_applet->library_applet_mode,
};
R_SUCCEED();
}
Result ILibraryAppletAccessor::Unknown170(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Service_AM, "(STUBBED) called");
*out_event = m_applet->unknown_event.GetHandle();
@@ -6,7 +6,6 @@
#pragma once
#include "core/hle/service/am/service/library_applet_self_accessor.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
@@ -22,10 +21,6 @@ public:
std::shared_ptr<Applet> applet);
~ILibraryAppletAccessor();
std::shared_ptr<Applet> GetApplet() const {
return m_applet;
}
private:
Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsCompleted(Out<bool> out_is_completed);
@@ -42,7 +37,6 @@ private:
Result GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetPopInteractiveOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetIndirectLayerConsumerHandle(Out<u64> out_handle);
Result GetLibraryAppletInfo(Out<LibraryAppletInfo> out_library_applet_info);
Result Unknown170(OutCopyHandle<Kernel::KReadableEvent> out_event);
void FrontendExecute();
@@ -123,7 +123,7 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
auto process = CreateProcess(system, program_id, Firmware1400, Firmware2200);
if (process) {
const auto applet = std::make_shared<Applet>(system, std::move(process), false);
const auto applet = std::make_shared<Applet>(system, std::make_unique<Service::Process>(*std::move(process)), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
@@ -233,9 +233,8 @@ Result ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext(
R_SUCCEED();
}
Result ILibraryAppletSelfAccessor::UnpopInData(SharedPointer<IStorage> storage) {
LOG_INFO(Service_AM, "called");
m_broker->GetInData().Unpop(system.Kernel(), storage);
Result ILibraryAppletSelfAccessor::UnpopInData() {
LOG_WARNING(Service_AM, "(STUBBED) called");
R_SUCCEED();
}
@@ -72,7 +72,7 @@ private:
Result ReportVisibleError(ErrorCode error_code);
Result ReportVisibleErrorWithErrorContext(
ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context);
Result UnpopInData(SharedPointer<IStorage> storage);
Result UnpopInData();
Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language);
Result GetCurrentApplicationId(Out<u64> out_application_id);
Result GetMainAppletAvailableUsers(Out<bool> out_can_select_any_user, Out<s32> out_users_count,
@@ -1,11 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/am/applet.h"
#include "core/hle/service/am/frontend/applets.h"
#include "core/hle/service/am/service/library_applet_accessor.h"
#include "core/hle/service/am/service/process_winding_controller.h"
@@ -45,18 +43,6 @@ Result IProcessWindingController::OpenCallingLibraryApplet(
Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet) {
LOG_INFO(Service_AM, "called");
std::shared_ptr<Applet> reserved_applet;
{
std::scoped_lock lk{m_applet->lock};
reserved_applet = std::move(m_applet->reserved_applet);
}
if (reserved_applet != nullptr) {
*out_calling_library_applet = std::make_shared<ILibraryAppletAccessor>(
system, reserved_applet->caller_applet_broker, reserved_applet);
R_SUCCEED();
}
const auto caller_applet = m_applet->caller_applet.lock();
if (caller_applet == nullptr) {
LOG_ERROR(Service_AM, "No caller applet available");
@@ -88,82 +74,22 @@ Result IProcessWindingController::PopContext(Out<SharedPointer<IStorage>> out_co
}
Result IProcessWindingController::CancelWindingReservation() {
LOG_INFO(Service_AM, "called");
std::scoped_lock lk{m_applet->lock};
m_applet->reserved_applet.reset();
m_applet->unwind_after_reserved = false;
LOG_WARNING(Service_AM, "STUBBED");
R_SUCCEED();
}
Result IProcessWindingController::WindAndDoReserved() {
LOG_INFO(Service_AM, "called");
std::shared_ptr<Applet> reserved_applet;
{
std::scoped_lock lk{m_applet->lock};
reserved_applet = m_applet->reserved_applet;
m_applet->display_layer_manager.SetWindowVisibility(false);
m_applet->exit_locked = false;
system.SetExitLocked(false);
}
if (reserved_applet) {
{
std::scoped_lock lk{m_applet->lock};
m_applet->is_winding = true;
}
{
std::scoped_lock lk{reserved_applet->lock};
reserved_applet->window_visible = true;
reserved_applet->process->Run();
}
if (reserved_applet->frontend) {
reserved_applet->frontend->Initialize();
reserved_applet->frontend->Execute();
}
} else {
LOG_WARNING(Service_AM, "called without a reserved applet to start");
}
m_applet->process->Terminate();
LOG_WARNING(Service_AM, "STUBBED");
R_SUCCEED();
}
Result IProcessWindingController::ReserveToStartAndWaitAndUnwindThis(
SharedPointer<ILibraryAppletAccessor> reserved_applet_accessor) {
LOG_INFO(Service_AM, "called");
if (reserved_applet_accessor == nullptr) {
LOG_ERROR(Service_AM, "No applet accessor provided");
R_THROW(ResultUnknown);
}
std::scoped_lock lk{m_applet->lock};
m_applet->reserved_applet = reserved_applet_accessor->GetApplet();
m_applet->unwind_after_reserved = true;
Result IProcessWindingController::ReserveToStartAndWaitAndUnwindThis() {
LOG_WARNING(Service_AM, "STUBBED");
R_SUCCEED();
}
Result IProcessWindingController::ReserveToStartAndWait(
SharedPointer<ILibraryAppletAccessor> reserved_applet_accessor) {
LOG_INFO(Service_AM, "called");
if (reserved_applet_accessor == nullptr) {
LOG_ERROR(Service_AM, "No applet accessor provided");
R_THROW(ResultUnknown);
}
std::scoped_lock lk{m_applet->lock};
m_applet->reserved_applet = reserved_applet_accessor->GetApplet();
m_applet->unwind_after_reserved = false;
Result IProcessWindingController::ReserveToStartAndWait() {
LOG_WARNING(Service_AM, "STUBBED");
R_SUCCEED();
}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -29,9 +29,8 @@ private:
Result PopContext(Out<SharedPointer<IStorage>> out_context);
Result CancelWindingReservation();
Result WindAndDoReserved();
Result ReserveToStartAndWaitAndUnwindThis(
SharedPointer<ILibraryAppletAccessor> reserved_applet_accessor);
Result ReserveToStartAndWait(SharedPointer<ILibraryAppletAccessor> reserved_applet_accessor);
Result ReserveToStartAndWaitAndUnwindThis();
Result ReserveToStartAndWait();
const std::shared_ptr<Applet> m_applet;
};
-57
View File
@@ -9,7 +9,6 @@
#include "core/hle/service/am/applet.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/event_observer.h"
#include "core/hle/service/am/process_creation.h"
#include "core/hle/service/am/window_system.h"
namespace Service::AM {
@@ -241,37 +240,6 @@ void WindowSystem::PruneTerminatedAppletsLocked() {
continue;
}
// A winding applet has had its own process killed but is kept alive as a transparent slot
// while the reserved applet running in its place finishes (see WindAndDoReserved()).
if (applet->is_winding) {
if (!applet->child_applets.empty()) {
it = std::next(it);
continue;
}
const bool unwind = applet->unwind_after_reserved;
applet->is_winding = false;
applet->unwind_after_reserved = false;
if (unwind && this->RestartAppletProcessLocked(applet.get())) {
const u64 new_aruid = applet->aruid.pid;
const auto next = std::next(it);
if (new_aruid != aruid) {
auto node = m_applets.extract(it);
node.key() = new_aruid;
m_applets.insert(std::move(node));
}
applet->process->Run();
m_event_observer->RequestUpdate();
it = next;
continue;
}
applet->reserved_applet.reset();
}
// Terminated, so ensure all child applets are terminated.
if (!applet->child_applets.empty()) {
this->TerminateChildAppletsLocked(applet.get());
@@ -333,28 +301,6 @@ void WindowSystem::PruneTerminatedAppletsLocked() {
}
}
bool WindowSystem::RestartAppletProcessLocked(Applet* applet) {
if (!ReinitializeProcess(m_system, *applet->process, applet->program_id)) {
LOG_ERROR(Service_AM, "Failed to restart winding applet_id={}",
static_cast<u32>(applet->applet_id));
return false;
}
applet->aruid.pid = applet->process->GetProcessId();
applet->is_process_running = false;
applet->is_completed = false;
applet->hid_registration.RegisterCurrentProcess();
applet->lifecycle_manager.ResetForRelaunch();
applet->is_activity_runnable = false;
applet->launch_reason.flag = 1;
m_event_observer->TrackAppletProcess(*applet);
return true;
}
bool WindowSystem::LockHomeMenuIntoForegroundLocked() {
// If the home menu is not locked into foreground, then there's nothing to do.
if (m_home_menu == nullptr || !m_home_menu_foreground_locked) {
@@ -406,9 +352,6 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b
const bool has_obscuring_child_applets = [&] {
for (const auto& child_applet : applet->child_applets) {
std::scoped_lock lk2{child_applet->lock};
if (child_applet->is_winding) {
return true;
}
const auto mode = child_applet->library_applet_mode;
if (child_applet->is_process_running && child_applet->window_visible &&
(mode == LibraryAppletMode::AllForeground ||
-1
View File
@@ -61,7 +61,6 @@ public:
private:
void PruneTerminatedAppletsLocked();
bool RestartAppletProcessLocked(Applet* applet);
bool LockHomeMenuIntoForegroundLocked();
void TerminateChildAppletsLocked(Applet* applet);
void UpdateAppletStateLocked(Applet* applet, bool is_foreground, bool overlay_blocking = false);
+2 -2
View File
@@ -82,7 +82,7 @@ void APM::OpenSession(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISession>(ctx, system, controller);
rb.PushIpcInterface<ISession>(system, controller);
}
void APM::GetPerformanceMode(HLERequestContext& ctx) {
@@ -125,7 +125,7 @@ void APM_Sys::GetPerformanceEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISession>(ctx, system, controller);
rb.PushIpcInterface<ISession>(system, controller);
}
void APM_Sys::SetCpuBoostMode(HLERequestContext& ctx) {
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -48,7 +45,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IRequest>(ctx, system);
rb.PushIpcInterface<IRequest>(system);
}
};
+7 -7
View File
@@ -184,7 +184,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(readable_event.Signal(system.Kernel()));
rb.PushCopyObjects(ctx, readable_event);
rb.PushCopyObjects(readable_event);
}
void Cancel(HLERequestContext& ctx) {
@@ -400,7 +400,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, notification_event->GetReadableEvent());
rb.PushCopyObjects(notification_event->GetReadableEvent());
}
void Clear(HLERequestContext& ctx) {
@@ -476,7 +476,7 @@ private:
void Module::Interface::CreateFriendService(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IFriendService>(ctx, system);
rb.PushIpcInterface<IFriendService>(system);
LOG_DEBUG(Service_Friend, "called");
}
@@ -488,12 +488,12 @@ void Module::Interface::CreateNotificationService(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INotificationService>(ctx, system, uuid);
rb.PushIpcInterface<INotificationService>(system, uuid);
}
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, const char* name)
: ServiceFramework{system_, name}, module{std::move(module_)}
{}
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
const char* name)
: ServiceFramework{system_, name}, module{std::move(module_)} {}
Module::Interface::~Interface() = default;
+1 -1
View File
@@ -279,7 +279,7 @@ void ARP_W::AcquireRegistrar(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface(ctx, registrar);
rb.PushIpcInterface(registrar);
}
void ARP_W::UnregisterApplicationInstance(HLERequestContext& ctx) {
+1 -1
View File
@@ -28,7 +28,7 @@ void BGTC_T::OpenTaskService(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ITaskService>(ctx, system);
rb.PushIpcInterface<ITaskService>(system);
}
ITaskService::ITaskService(Core::System& system_) : ServiceFramework{system_, "ITaskService"} {
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -59,7 +56,7 @@ ECTX_AW::~ECTX_AW() = default;
void ECTX_AW::CreateContextRegistrar(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IContextRegistrar>(ctx, system);
rb.PushIpcInterface<IContextRegistrar>(std::make_shared<IContextRegistrar>(system));
}
} // namespace Service::Glue
@@ -726,7 +726,7 @@ void IHidSystemServer::AcquireConnectionTriggerTimeoutEvent(HLERequestContext& c
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, acquire_device_registered_event->GetReadableEvent());
rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent());
}
void IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx) {
@@ -734,7 +734,7 @@ void IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport(HLEReque
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, acquire_device_registered_event->GetReadableEvent());
rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent());
}
void IHidSystemServer::GetRegisteredDevices(HLERequestContext& ctx) {
@@ -759,7 +759,7 @@ void IHidSystemServer::AcquireUniquePadConnectionEventHandle(HLERequestContext&
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.PushCopyObjects(ctx, unique_pad_connection_event->GetReadableEvent());
rb.PushCopyObjects(unique_pad_connection_event->GetReadableEvent());
rb.Push(ResultSuccess);
}
@@ -776,7 +776,7 @@ void IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestConte
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, joy_detach_event->GetReadableEvent());
rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
}
void IHidSystemServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
+2 -2
View File
@@ -31,7 +31,7 @@ class Memory;
}
namespace IPC {
struct ResponseBuilder;
class ResponseBuilder;
}
namespace Service {
@@ -392,7 +392,7 @@ public:
}
private:
friend struct IPC::ResponseBuilder;
friend class IPC::ResponseBuilder;
void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming);
+153 -91
View File
@@ -24,7 +24,45 @@ namespace IPC {
constexpr Result ResultSessionClosed{ErrorModule::HIPC, 301};
struct ResponseBuilder {
class RequestHelperBase {
protected:
Service::HLERequestContext* context = nullptr;
u32* cmdbuf;
u32 index = 0;
public:
explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {}
explicit RequestHelperBase(Service::HLERequestContext& ctx)
: context(&ctx), cmdbuf(ctx.CommandBuffer()) {}
void Skip(u32 size_in_words, bool set_to_null) {
if (set_to_null) {
memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
}
index += size_in_words;
}
/**
* Aligns the current position forward to a 16-byte boundary, padding with zeros.
*/
void AlignWithPadding() {
if (index & 3) {
Skip(static_cast<u32>(4 - (index & 3)), true);
}
}
u32 GetCurrentOffset() const {
return index;
}
void SetCurrentOffset(u32 offset) {
index = offset;
}
};
class ResponseBuilder : public RequestHelperBase {
public:
/// Flags used for customizing the behavior of ResponseBuilder
enum class Flags : u32 {
None = 0,
@@ -33,13 +71,14 @@ struct ResponseBuilder {
AlwaysMoveHandles = 1,
};
inline explicit ResponseBuilder(Service::HLERequestContext& ctx, u32 normal_params_size_, u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0, Flags flags = Flags::None)
: cmdbuf(ctx.CommandBuffer())
, normal_params_size(normal_params_size_)
, num_handles_to_copy(num_handles_to_copy_)
, num_objects_to_move(num_objects_to_move_)
{
std::memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH);
explicit ResponseBuilder(Service::HLERequestContext& ctx, u32 normal_params_size_,
u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0,
Flags flags = Flags::None)
: RequestHelperBase(ctx), normal_params_size(normal_params_size_),
num_handles_to_copy(num_handles_to_copy_),
num_objects_to_move(num_objects_to_move_), kernel{ctx.kernel} {
memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH);
IPC::CommandHeader header{};
auto const mgr = ctx.GetManager().get();
@@ -78,7 +117,9 @@ struct ResponseBuilder {
handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy_);
handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move);
PushRaw(handle_descriptor_header);
ctx.handles_offset = index;
Skip(num_handles_to_copy + num_handles_to_move, true);
}
@@ -90,6 +131,7 @@ struct ResponseBuilder {
domain_header.num_objects = num_domain_objects;
PushRaw(domain_header);
}
IPC::DataPayloadHeader data_payload_header{};
data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O');
PushRaw(data_payload_header);
@@ -99,39 +141,34 @@ struct ResponseBuilder {
ctx.data_payload_offset = index;
ctx.write_size += index;
ctx.domain_offset = u32(index + raw_data_size / sizeof(u32));
ctx.domain_offset = static_cast<u32>(index + raw_data_size / sizeof(u32));
}
inline void Skip(u32 size_in_words, bool set_to_null) {
if (set_to_null) std::memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
index += size_in_words;
}
/// @brief Aligns the current position forward to a 16-byte boundary, padding with zeros.
inline void AlignWithPadding() { if (index & 3) Skip(u32(4 - (index & 3)), true); }
inline u32 GetCurrentOffset() const { return index; }
inline void SetCurrentOffset(u32 offset) { index = offset; }
template <class T>
void PushIpcInterface(std::shared_ptr<T> iface) {
auto manager{context->GetManager()};
template <class T> inline void PushIpcInterface(Service::HLERequestContext& ctx, std::shared_ptr<T> iface) {
auto manager = ctx.GetManager();
if (manager->IsDomain()) {
ctx.AddDomainObject(std::move(iface));
context->AddDomainObject(std::move(iface));
} else {
ASSERT(Kernel::GetCurrentProcess(ctx.kernel).GetResourceLimit()->Reserve(ctx.kernel, Kernel::LimitableResource::SessionCountMax, 1));
ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1));
auto* session = Kernel::KSession::Create(ctx.kernel);
session->Initialize(ctx.kernel, nullptr, 0);
Kernel::KSession::Register(ctx.kernel, session);
auto* session = Kernel::KSession::Create(kernel);
session->Initialize(kernel, nullptr, 0);
Kernel::KSession::Register(kernel, session);
auto next_manager = std::make_shared<Service::SessionRequestManager>(ctx.kernel, manager->GetServerManager());
auto next_manager = std::make_shared<Service::SessionRequestManager>(
kernel, manager->GetServerManager());
next_manager->SetSessionHandler(iface);
manager->GetServerManager().RegisterSession(&session->GetServerSession(), next_manager);
ctx.AddMoveObject(&session->GetClientSession());
context->AddMoveObject(&session->GetClientSession());
}
}
template <class T, class... Args> inline void PushIpcInterface(Service::HLERequestContext& ctx, Args&&... args) {
PushIpcInterface<T>(ctx, std::make_shared<T>(std::forward<Args>(args)...));
template <class T, class... Args>
void PushIpcInterface(Args&&... args) {
PushIpcInterface<T>(std::make_shared<T>(std::forward<Args>(args)...));
}
void PushImpl(s8 value);
@@ -147,38 +184,59 @@ struct ResponseBuilder {
void PushImpl(bool value);
void PushImpl(Result value);
template <typename T> inline void Push(T value) {
template <typename T>
void Push(T value) {
return PushImpl(value);
}
template <typename First, typename... Other>
void Push(const First& first_value, const Other&... other_values);
/// @brief Helper function for pushing strongly-typed enumeration values.
/// @tparam Enum The enumeration type to be pushed
/// @param value The value to push.
/// @note The underlying size of the enumeration type is the size of the data that gets pushed.
/// e.g. "enum class SomeEnum : u16" will push a u16-sized amount of data.
template <typename Enum> inline void PushEnum(Enum value) {
/**
* Helper function for pushing strongly-typed enumeration values.
*
* @tparam Enum The enumeration type to be pushed
*
* @param value The value to push.
*
* @note The underlying size of the enumeration type is the size of the
* data that gets pushed. e.g. "enum class SomeEnum : u16" will
* push a u16-sized amount of data.
*/
template <typename Enum>
void PushEnum(Enum value) {
static_assert(std::is_enum_v<Enum>, "T must be an enum type within a PushEnum call.");
static_assert(!std::is_convertible_v<Enum, int>, "enum type in PushEnum must be a strongly typed enum.");
static_assert(!std::is_convertible_v<Enum, int>,
"enum type in PushEnum must be a strongly typed enum.");
Push(static_cast<std::underlying_type_t<Enum>>(value));
}
/// @brief Copies the content of the given trivially copyable class to the buffer as a normal param
/// @note: The input class must be correctly packed/padded to fit hardware layout.
template <typename T> void PushRaw(const T& value);
template <typename... O> void PushMoveObjects(Service::HLERequestContext& ctx, O*... pointers);
template <typename... O> void PushMoveObjects(Service::HLERequestContext& ctx, O&... pointers);
template <typename... O> void PushCopyObjects(Service::HLERequestContext& ctx, O*... pointers);
template <typename... O> void PushCopyObjects(Service::HLERequestContext& ctx, O&... pointers);
/**
* @brief Copies the content of the given trivially copyable class to the buffer as a normal
* param
* @note: The input class must be correctly packed/padded to fit hardware layout.
*/
template <typename T>
void PushRaw(const T& value);
u32* cmdbuf;
u32 index = 0;
template <typename... O>
void PushMoveObjects(O*... pointers);
template <typename... O>
void PushMoveObjects(O&... pointers);
template <typename... O>
void PushCopyObjects(O*... pointers);
template <typename... O>
void PushCopyObjects(O&... pointers);
private:
u32 normal_params_size{};
u32 num_handles_to_copy{};
u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent
u32 data_payload_index{};
Kernel::KernelCore& kernel;
};
/// Push ///
@@ -193,7 +251,8 @@ inline void ResponseBuilder::PushImpl(u32 value) {
template <typename T>
void ResponseBuilder::PushRaw(const T& value) {
static_assert(std::is_trivially_copyable_v<T>, "It's undefined behavior to use memcpy with non-trivially copyable objects");
static_assert(std::is_trivially_copyable_v<T>,
"It's undefined behavior to use memcpy with non-trivially copyable objects");
std::memcpy(cmdbuf + index, &value, sizeof(T));
index += (sizeof(T) + 3) / 4; // round up to word length
}
@@ -213,8 +272,8 @@ inline void ResponseBuilder::PushImpl(s16 value) {
}
inline void ResponseBuilder::PushImpl(s64 value) {
PushImpl(u32(value));
PushImpl(u32(value >> 32));
PushImpl(static_cast<u32>(value));
PushImpl(static_cast<u32>(value >> 32));
}
inline void ResponseBuilder::PushImpl(u8 value) {
@@ -226,8 +285,8 @@ inline void ResponseBuilder::PushImpl(u16 value) {
}
inline void ResponseBuilder::PushImpl(u64 value) {
PushImpl(u32(value));
PushImpl(u32(value >> 32));
PushImpl(static_cast<u32>(value));
PushImpl(static_cast<u32>(value >> 32));
}
inline void ResponseBuilder::PushImpl(float value) {
@@ -253,88 +312,90 @@ void ResponseBuilder::Push(const First& first_value, const Other&... other_value
}
template <typename... O>
inline void ResponseBuilder::PushCopyObjects(Service::HLERequestContext& ctx, O*... pointers) {
inline void ResponseBuilder::PushCopyObjects(O*... pointers) {
auto objects = {pointers...};
for (auto& object : objects) {
ctx.AddCopyObject(object);
context->AddCopyObject(object);
}
}
template <typename... O>
inline void ResponseBuilder::PushCopyObjects(Service::HLERequestContext& ctx, O&... pointers) {
inline void ResponseBuilder::PushCopyObjects(O&... pointers) {
auto objects = {&pointers...};
for (auto& object : objects) {
ctx.AddCopyObject(object);
context->AddCopyObject(object);
}
}
template <typename... O>
inline void ResponseBuilder::PushMoveObjects(Service::HLERequestContext& ctx, O*... pointers) {
inline void ResponseBuilder::PushMoveObjects(O*... pointers) {
auto objects = {pointers...};
for (auto& object : objects) {
ctx.AddMoveObject(object);
context->AddMoveObject(object);
}
}
template <typename... O>
inline void ResponseBuilder::PushMoveObjects(Service::HLERequestContext& ctx, O&... pointers) {
inline void ResponseBuilder::PushMoveObjects(O&... pointers) {
auto objects = {&pointers...};
for (auto& object : objects) {
ctx.AddMoveObject(object);
context->AddMoveObject(object);
}
}
struct RequestParser {
inline explicit RequestParser(u32* command_buffer) : cmdbuf(command_buffer) {}
inline explicit RequestParser(Service::HLERequestContext& ctx)
: cmdbuf(ctx.CommandBuffer())
{
class RequestParser : public RequestHelperBase {
public:
explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {}
explicit RequestParser(Service::HLERequestContext& ctx) : RequestHelperBase(ctx) {
// TIPC does not have data payload offset
if (!ctx.IsTipc()) {
ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete");
Skip(ctx.GetDataPayloadOffset(), false);
}
// Skip the u64 command id, it's already stored in the context
static constexpr u32 CommandIdSize = 2;
Skip(CommandIdSize, false);
}
inline void Skip(u32 size_in_words, bool set_to_null) {
if (set_to_null) std::memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
index += size_in_words;
}
/// @brief Aligns the current position forward to a 16-byte boundary, padding with zeros.
inline void AlignWithPadding() { if (index & 3) Skip(u32(4 - (index & 3)), true); }
inline u32 GetCurrentOffset() const { return index; }
inline void SetCurrentOffset(u32 offset) { index = offset; }
template <typename T>
T Pop();
template <typename T> T Pop();
template <typename T> void Pop(T& value);
template <typename First, typename... Other> void Pop(First& first_value, Other&... other_values);
template <typename T>
void Pop(T& value);
template <typename First, typename... Other>
void Pop(First& first_value, Other&... other_values);
template <typename T>
T PopEnum() {
static_assert(std::is_enum_v<T>, "T must be an enum type within a PopEnum call.");
static_assert(!std::is_convertible_v<T, int>, "enum type in PopEnum must be a strongly typed enum.");
return T(Pop<std::underlying_type_t<T>>());
static_assert(!std::is_convertible_v<T, int>,
"enum type in PopEnum must be a strongly typed enum.");
return static_cast<T>(Pop<std::underlying_type_t<T>>());
}
/// @brief Reads the next normal parameters as a struct, by copying it
/// @note: The output class must be correctly packed/padded to fit hardware layout.
template <typename T> void PopRaw(T& value);
/**
* @brief Reads the next normal parameters as a struct, by copying it
* @note: The output class must be correctly packed/padded to fit hardware layout.
*/
template <typename T>
void PopRaw(T& value);
/// @brief Reads the next normal parameters as a struct, by copying it into a new value
/// @note: The output class must be correctly packed/padded to fit hardware layout.
template <typename T> T PopRaw();
/**
* @brief Reads the next normal parameters as a struct, by copying it into a new value
* @note: The output class must be correctly packed/padded to fit hardware layout.
*/
template <typename T>
T PopRaw();
template <class T> [[nodiscard]] std::weak_ptr<T> PopIpcInterface(Service::HLERequestContext& ctx) {
ASSERT(ctx.GetManager()->IsDomain());
ASSERT(ctx.GetDomainMessageHeader().input_object_count > 0);
return ctx.GetDomainHandler<T>(Pop<u32>() - 1);
template <class T>
std::weak_ptr<T> PopIpcInterface() {
ASSERT(context->GetManager()->IsDomain());
ASSERT(context->GetDomainMessageHeader().input_object_count > 0);
return context->GetDomainHandler<T>(Pop<u32>() - 1);
}
u32* cmdbuf;
u32 index = 0;
};
/// Pop ///
@@ -346,7 +407,7 @@ inline u32 RequestParser::Pop() {
template <>
inline s32 RequestParser::Pop() {
return s32(Pop<u32>());
return static_cast<s32>(Pop<u32>());
}
// Ignore the -Wclass-memaccess warning on memcpy for non-trivially default constructible objects.
@@ -356,7 +417,8 @@ inline s32 RequestParser::Pop() {
#endif
template <typename T>
void RequestParser::PopRaw(T& value) {
static_assert(std::is_trivially_copyable_v<T>, "It's undefined behavior to use memcpy with non-trivially copyable objects");
static_assert(std::is_trivially_copyable_v<T>,
"It's undefined behavior to use memcpy with non-trivially copyable objects");
std::memcpy(&value, cmdbuf + index, sizeof(T));
index += (sizeof(T) + 3) / 4; // round up to word length
}
+1 -1
View File
@@ -353,7 +353,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ILogger>(ctx, system);
rb.PushIpcInterface<ILogger>(system);
}
};
+4 -4
View File
@@ -151,7 +151,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IAm>(ctx, system);
rb.PushIpcInterface<IAm>(system);
}
};
@@ -173,7 +173,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<MFIUser>(ctx, system);
rb.PushIpcInterface<MFIUser>(system);
}
};
@@ -195,7 +195,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IUser>(ctx, system);
rb.PushIpcInterface<IUser>(system);
}
};
@@ -217,7 +217,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISystem>(ctx, system);
rb.PushIpcInterface<ISystem>(system);
}
};
+3 -3
View File
@@ -143,7 +143,7 @@ void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, GetManager()->AttachAvailabilityChangeEvent());
rb.PushCopyObjects(GetManager()->AttachAvailabilityChangeEvent());
}
void NfcInterface::StartDetection(HLERequestContext& ctx) {
@@ -203,7 +203,7 @@ void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(result);
rb.PushCopyObjects(ctx, out_event);
rb.PushCopyObjects(out_event);
}
void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
@@ -217,7 +217,7 @@ void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(result);
rb.PushCopyObjects(ctx, out_event);
rb.PushCopyObjects(out_event);
}
void NfcInterface::SetNfcEnabled(HLERequestContext& ctx) {
+3 -3
View File
@@ -157,7 +157,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IUser>(ctx, system);
rb.PushIpcInterface<IUser>(system);
}
};
@@ -179,7 +179,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISystem>(ctx, system);
rb.PushIpcInterface<ISystem>(system);
}
};
@@ -201,7 +201,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IDebug>(ctx, system);
rb.PushIpcInterface<IDebug>(system);
}
};
+8 -8
View File
@@ -307,7 +307,7 @@ private:
void GetSystemEventReadableHandle(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 2};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, evt_scan_complete->GetReadableEvent(),
rb.PushCopyObjects(evt_scan_complete->GetReadableEvent(),
evt_processing->GetReadableEvent());
}
@@ -452,7 +452,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 2};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, event1->GetReadableEvent(), event2->GetReadableEvent());
rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent());
}
void Cancel(HLERequestContext& ctx) {
@@ -528,7 +528,7 @@ void IGeneralService::CreateScanRequest(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IScanRequest>(ctx, system);
rb.PushIpcInterface<IScanRequest>(system);
}
void IGeneralService::CreateRequest(HLERequestContext& ctx) {
@@ -537,7 +537,7 @@ void IGeneralService::CreateRequest(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IRequest>(ctx, system);
rb.PushIpcInterface<IRequest>(system);
}
void IGeneralService::GetCurrentNetworkProfile(HLERequestContext& ctx) {
@@ -716,7 +716,7 @@ void IGeneralService::GetNetworkProfile(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INetworkProfile>(ctx, system);
rb.PushIpcInterface<INetworkProfile>(system);
}
void IGeneralService::SetNetworkProfile(HLERequestContext& ctx) {
@@ -869,7 +869,7 @@ void IGeneralService::CreateTemporaryNetworkProfile(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 6, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INetworkProfile>(ctx, system);
rb.PushIpcInterface<INetworkProfile>(system);
rb.PushRaw<u128>(uuid);
}
@@ -1124,7 +1124,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IGeneralService>(ctx, system);
rb.PushIpcInterface<IGeneralService>(system);
}
void CreateGeneralService(HLERequestContext& ctx) {
@@ -1132,7 +1132,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IGeneralService>(ctx, system);
rb.PushIpcInterface<IGeneralService>(system);
}
};
+6 -6
View File
@@ -53,7 +53,7 @@ private:
LOG_WARNING(Service_NIM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAsync>(ctx, system);
rb.PushIpcInterface<IShopServiceAsync>(system);
}
};
@@ -75,7 +75,7 @@ private:
LOG_WARNING(Service_NIM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAccessor>(ctx, system);
rb.PushIpcInterface<IShopServiceAccessor>(system);
}
};
@@ -336,7 +336,7 @@ private:
LOG_DEBUG(Service_NIM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAccessServer>(ctx, system);
rb.PushIpcInterface<IShopServiceAccessServer>(system);
}
void IsLargeResourceAvailable(HLERequestContext& ctx) {
@@ -356,7 +356,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IShopServiceAccessServer>(ctx, system);
rb.PushIpcInterface<IShopServiceAccessServer>(system);
}
};
@@ -439,7 +439,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, finished_event->GetReadableEvent());
rb.PushCopyObjects(finished_event->GetReadableEvent());
}
void GetResult(HLERequestContext& ctx) {
@@ -500,7 +500,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IEnsureNetworkClockAvailabilityService>(ctx, system);
rb.PushIpcInterface<IEnsureNetworkClockAvailabilityService>(system);
}
// TODO(ogniK): Do we need these?
@@ -359,8 +359,8 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestCo
IPC::ResponseBuilder rb{ctx, 2, 1, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, async_value->ReadableEvent());
rb.PushIpcInterface(ctx, std::move(async_value));
rb.PushCopyObjects(async_value->ReadableEvent());
rb.PushIpcInterface(std::move(async_value));
}
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(
@@ -199,7 +199,7 @@ void NVDRV::QueryEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3, 1};
rb.Push(ResultSuccess);
auto& readable_event = event->GetReadableEvent();
rb.PushCopyObjects(ctx, readable_event);
rb.PushCopyObjects(readable_event);
rb.PushEnum(NvResult::Success);
} else {
LOG_ERROR(Service_NVDRV, "Invalid event request!");
-11
View File
@@ -6,8 +6,6 @@
#pragma once
#include <utility>
#include "common/common_types.h"
namespace Core {
@@ -30,15 +28,6 @@ public:
inline explicit Process(Core::System& system) noexcept : m_system(system) {}
inline ~Process() { this->Finalize(); }
Process(const Process&) = delete;
Process& operator=(const Process&) = delete;
Process& operator=(Process&&) = delete;
inline Process(Process&& other) noexcept
: m_system(other.m_system), m_process(std::exchange(other.m_process, nullptr)),
m_main_thread_stack_size(std::exchange(other.m_main_thread_stack_size, 0)),
m_main_thread_priority(std::exchange(other.m_main_thread_priority, 0)),
m_process_started(std::exchange(other.m_process_started, false)) {}
bool Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result);
void Finalize();
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -127,7 +124,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IClkrstSession>(ctx, system, device_code);
rb.PushIpcInterface<IClkrstSession>(system, device_code);
}
};
+1 -1
View File
@@ -161,7 +161,7 @@ private:
IPC::ResponseBuilder rb{ctx, 10, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, *process);
rb.PushCopyObjects(*process);
rb.PushRaw(program_location);
rb.PushRaw(override_status);
}
+3 -3
View File
@@ -147,7 +147,7 @@ void IAlarmService::CreateWakeupAlarm(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISteadyClockAlarm>(ctx, system, m_alarms, AlarmType::WakeupAlarm);
rb.PushIpcInterface<ISteadyClockAlarm>(system, m_alarms, AlarmType::WakeupAlarm);
}
void IAlarmService::CreateBackgroundTaskAlarm(HLERequestContext& ctx) {
@@ -155,7 +155,7 @@ void IAlarmService::CreateBackgroundTaskAlarm(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISteadyClockAlarm>(ctx, system, m_alarms, AlarmType::BackgroundTaskAlarm);
rb.PushIpcInterface<ISteadyClockAlarm>(system, m_alarms, AlarmType::BackgroundTaskAlarm);
}
ISteadyClockAlarm::ISteadyClockAlarm(Core::System& system_, Alarms& alarms, AlarmType type)
@@ -179,7 +179,7 @@ void ISteadyClockAlarm::GetAlarmEvent(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, m_alarm.GetEventHandle());
rb.PushCopyObjects(m_alarm.GetEventHandle());
}
void ISteadyClockAlarm::Enable(HLERequestContext& ctx) {
+2 -2
View File
@@ -67,7 +67,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(ctx, state_change_event->GetReadableEvent());
rb.PushCopyObjects(state_change_event->GetReadableEvent());
}
void UnbindStateChangeEvent(HLERequestContext& ctx) {
@@ -186,7 +186,7 @@ void PSM::OpenSession(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IPsmSession>(ctx, system);
rb.PushIpcInterface<IPsmSession>(system);
}
void PSM::GetBatteryVoltageState(HLERequestContext& ctx) {
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -85,7 +82,7 @@ void TS::OpenSession(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISession>(ctx, system);
rb.PushIpcInterface<ISession>(system);
}
} // namespace Service::PTM
+5 -4
View File
@@ -140,7 +140,7 @@ void SM::GetServiceCmif(HLERequestContext& ctx) {
if (result == ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(result);
rb.PushMoveObjects(ctx, client_session);
rb.PushMoveObjects(client_session);
} else {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -157,7 +157,7 @@ void SM::GetServiceTipc(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(result);
rb.PushMoveObjects(ctx, result == ResultSuccess ? client_session : nullptr);
rb.PushMoveObjects(result == ResultSuccess ? client_session : nullptr);
}
static std::string PopServiceName(IPC::RequestParser& rp) {
@@ -230,7 +230,8 @@ void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_s
max_session_count, is_light);
Kernel::KServerPort* server_port{};
if (const auto result = service_manager.RegisterService(std::addressof(server_port), name, max_session_count, nullptr);
if (const auto result = service_manager.RegisterService(std::addressof(server_port), name,
max_session_count, nullptr);
result.IsError()) {
LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", result.raw);
IPC::ResponseBuilder rb{ctx, 2};
@@ -240,7 +241,7 @@ void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_s
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(ResultSuccess);
rb.PushMoveObjects(ctx, server_port);
rb.PushMoveObjects(server_port);
}
void SM::UnregisterService(HLERequestContext& ctx) {
+1 -1
View File
@@ -60,7 +60,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) {
// We succeeded.
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(ResultSuccess);
rb.PushMoveObjects(ctx, session->GetClientSession());
rb.PushMoveObjects(session->GetClientSession());
}
void Controller::CloneCurrentObjectEx(HLERequestContext& ctx) {
+5 -3
View File
@@ -543,7 +543,8 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
if (res == ResultSuccess) {
rb.PushIpcInterface<ISslConnection>(ctx, system, ssl_version, shared_data, std::move(backend));
rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data,
std::move(backend));
}
}
@@ -623,11 +624,12 @@ private:
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<Parameters>();
LOG_WARNING(Service_SSL, "(STUBBED) called, api_version={}, pid_placeholder={}", parameters.ssl_version.api_version, parameters.pid_placeholder);
LOG_WARNING(Service_SSL, "(STUBBED) called, api_version={}, pid_placeholder={}",
parameters.ssl_version.api_version, parameters.pid_placeholder);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISslContext>(ctx, system, parameters.ssl_version);
rb.PushIpcInterface<ISslContext>(system, parameters.ssl_version);
}
void SetInterfaceVersion(HLERequestContext& ctx) {
+2 -2
View File
@@ -155,7 +155,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IPdSession>(ctx, system);
rb.PushIpcInterface<IPdSession>(system);
}
};
@@ -199,7 +199,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IPdCradleSession>(ctx, system);
rb.PushIpcInterface<IPdCradleSession>(system);
}
};
+2 -2
View File
@@ -50,8 +50,8 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service
auto& controller = controller_data[aruid_index][i];
controller.device = hid_core.GetEmulatedControllerByIndex(i);
Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this, i, kernel = &hid_core.kernel](Core::HID::ControllerTriggerType type) {
ControllerUpdate(*kernel, type, i);
.on_change = [this, i](Core::HID::ControllerTriggerType type) {
ControllerUpdate(hid_core.kernel, type, i);
},
.is_npad_service = true,
};
@@ -403,9 +403,6 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
if (info.uses_sampled_1d) {
ctx.AddCapability(spv::Capability::Sampled1D);
}
if (info.uses_image_1d) {
ctx.AddCapability(spv::Capability::Image1D);
}
if (info.uses_sparse_residency) {
ctx.AddCapability(spv::Capability::SparseResidency);
}
@@ -435,7 +432,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
}
if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id ||
info.uses_subgroup_shuffles) &&
profile.support_vote && profile.SupportsSubgroupStage(ctx.stage)) {
profile.support_vote) {
ctx.AddCapability(spv::Capability::GroupNonUniformBallot);
ctx.AddCapability(spv::Capability::GroupNonUniformShuffle);
if (!profile.warp_size_potentially_larger_than_guest) {
@@ -202,8 +202,7 @@ void EmitGetIndirectBranchVariable(EmitContext&) {
}
Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8 &&
ctx.profile.support_uniform_and_storage_buffer_8bit) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) {
const Id load{GetCbuf(ctx, ctx.U8, &UniformDefinitions::U8, sizeof(u8), binding, offset,
ctx.load_const_func_u8)};
return ctx.OpUConvert(ctx.U32[1], load);
@@ -220,8 +219,7 @@ Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& of
}
Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8 &&
ctx.profile.support_uniform_and_storage_buffer_8bit) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) {
const Id load{GetCbuf(ctx, ctx.S8, &UniformDefinitions::S8, sizeof(s8), binding, offset,
ctx.load_const_func_u8)};
return ctx.OpSConvert(ctx.U32[1], load);
@@ -238,8 +236,7 @@ Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& of
}
Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16 &&
ctx.profile.support_uniform_and_storage_buffer_16bit) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) {
const Id load{GetCbuf(ctx, ctx.U16, &UniformDefinitions::U16, sizeof(u16), binding, offset,
ctx.load_const_func_u16)};
return ctx.OpUConvert(ctx.U32[1], load);
@@ -256,8 +253,7 @@ Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
}
Id EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16 &&
ctx.profile.support_uniform_and_storage_buffer_16bit) {
if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) {
const Id load{GetCbuf(ctx, ctx.S16, &UniformDefinitions::S16, sizeof(s16), binding, offset,
ctx.load_const_func_u16)};
return ctx.OpSConvert(ctx.U32[1], load);
@@ -260,13 +260,6 @@ bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) {
return ctx.textures.at(info.descriptor_index).is_multisample;
}
bool IsTextureInteger(EmitContext& ctx, const IR::TextureInstInfo& info) {
if (info.type == TextureType::Buffer) {
return false;
}
return ctx.textures.at(info.descriptor_index).is_integer;
}
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
if (info.relaxed_precision != 0) {
@@ -487,14 +480,11 @@ Id EmitBoundImageWrite(EmitContext&) {
Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id bias_lc, const IR::Value& offset) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const bool is_integer{IsTextureInteger(ctx, info)};
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
Id color;
if (ctx.stage == Stage::Fragment) {
const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0,
bias_lc, offset);
color = Emit(&EmitContext::OpImageSparseSampleImplicitLod,
&EmitContext::OpImageSampleImplicitLod, ctx, inst, result_type,
return Emit(&EmitContext::OpImageSparseSampleImplicitLod,
&EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4],
Texture(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
} else {
// We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as
@@ -502,29 +492,26 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value&
// derivatives
const Id lod{ctx.Const(0.0f)};
const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset);
color = Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type,
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
}
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color;
}
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id lod, const IR::Value& offset) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const bool is_integer{IsTextureInteger(ctx, info)};
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
const ImageOperands operands(ctx, false, true, false, lod, offset);
Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
#ifdef __ANDROID__
if (!is_integer && Settings::values.fix_bloom_effects.GetValue()) {
if (Settings::values.fix_bloom_effects.GetValue()) {
result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f));
}
#endif
return is_integer ? ctx.OpBitcast(ctx.F32[4], result) : result;
return result;
}
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
@@ -560,39 +547,30 @@ Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va
Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
const IR::Value& offset, const IR::Value& offset2) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const bool is_integer{IsTextureInteger(ctx, info)};
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
const ImageOperands operands(ctx, offset, offset2);
if (ctx.profile.need_gather_subpixel_offset) {
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords);
}
const Id color{Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst,
result_type, Texture(ctx, info, index), coords,
ctx.Const(info.gather_component), operands.MaskOptional(),
operands.Span())};
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color;
return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst,
ctx.F32[4], Texture(ctx, info, index), coords, ctx.Const(info.gather_component),
operands.MaskOptional(), operands.Span());
}
Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
const IR::Value& offset, const IR::Value& offset2, Id dref) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const bool is_integer{IsTextureInteger(ctx, info)};
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
const ImageOperands operands(ctx, offset, offset2);
if (ctx.profile.need_gather_subpixel_offset) {
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords);
}
const Id color{Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather,
ctx, inst, result_type, Texture(ctx, info, index), coords, dref,
operands.MaskOptional(), operands.Span())};
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color;
return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst,
ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.MaskOptional(),
operands.Span());
}
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
Id lod, Id ms) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const bool is_integer{IsTextureInteger(ctx, info)};
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
AddOffsetToCoordinates(ctx, info, coords, offset);
if (info.type == TextureType::Buffer) {
lod = Id{};
@@ -602,10 +580,8 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
lod = Id{};
}
const ImageOperands operands(lod, ms);
const Id color{Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst,
result_type, TextureImage(ctx, info, index), coords,
operands.MaskOptional(), operands.Span())};
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color;
return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
}
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,
@@ -650,17 +626,14 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id derivatives, const IR::Value& offset, Id lod_clamp) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const bool is_integer{IsTextureInteger(ctx, info)};
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
const auto operands = info.num_derivatives == 3
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
ctx.Def(offset), {}, lod_clamp)
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
info.num_derivatives, offset, lod_clamp);
const Id color{Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type,
Texture(ctx, info, index), coords, operands.Mask(), operands.Span())};
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color;
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
}
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) {
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,14 +10,7 @@ Id SubgroupScope(EmitContext& ctx) {
return ctx.Const(static_cast<u32>(spv::Scope::Subgroup));
}
bool StageSupportsSubgroups(EmitContext& ctx) {
return ctx.profile.SupportsSubgroupStage(ctx.stage);
}
Id GetThreadId(EmitContext& ctx) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.u32_zero_value;
}
return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id);
}
@@ -78,9 +68,6 @@ Id GetMaxThreadId(EmitContext& ctx, Id thread_id, Id clamp, Id segmentation_mask
}
Id SelectValue(EmitContext& ctx, Id in_range, Id value, Id src_thread_id) {
if (!StageSupportsSubgroups(ctx)) {
return value;
}
return ctx.OpSelect(
ctx.U32[1], in_range,
ctx.OpGroupNonUniformShuffle(ctx.U32[1], SubgroupScope(ctx), value, src_thread_id), value);
@@ -102,9 +89,6 @@ Id EmitLaneId(EmitContext& ctx) {
}
Id EmitVoteAll(EmitContext& ctx, Id pred) {
if (!StageSupportsSubgroups(ctx)) {
return pred;
}
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return ctx.OpGroupNonUniformAll(ctx.U1, SubgroupScope(ctx), pred);
}
@@ -118,9 +102,6 @@ Id EmitVoteAll(EmitContext& ctx, Id pred) {
}
Id EmitVoteAny(EmitContext& ctx, Id pred) {
if (!StageSupportsSubgroups(ctx)) {
return pred;
}
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return ctx.OpGroupNonUniformAny(ctx.U1, SubgroupScope(ctx), pred);
}
@@ -134,9 +115,6 @@ Id EmitVoteAny(EmitContext& ctx, Id pred) {
}
Id EmitVoteEqual(EmitContext& ctx, Id pred) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.true_value;
}
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return ctx.OpGroupNonUniformAllEqual(ctx.U1, SubgroupScope(ctx), pred);
}
@@ -151,9 +129,6 @@ Id EmitVoteEqual(EmitContext& ctx, Id pred) {
}
Id EmitSubgroupBallot(EmitContext& ctx, Id pred) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.OpSelect(ctx.U32[1], pred, ctx.Const(1u), ctx.u32_zero_value);
}
const Id ballot{ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred)};
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U);
@@ -162,37 +137,22 @@ Id EmitSubgroupBallot(EmitContext& ctx, Id pred) {
}
Id EmitSubgroupEqMask(EmitContext& ctx) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.Const(1u);
}
return LoadMask(ctx, ctx.subgroup_mask_eq);
}
Id EmitSubgroupLtMask(EmitContext& ctx) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.u32_zero_value;
}
return LoadMask(ctx, ctx.subgroup_mask_lt);
}
Id EmitSubgroupLeMask(EmitContext& ctx) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.Const(1u);
}
return LoadMask(ctx, ctx.subgroup_mask_le);
}
Id EmitSubgroupGtMask(EmitContext& ctx) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.u32_zero_value;
}
return LoadMask(ctx, ctx.subgroup_mask_gt);
}
Id EmitSubgroupGeMask(EmitContext& ctx) {
if (!StageSupportsSubgroups(ctx)) {
return ctx.Const(1u);
}
return LoadMask(ctx, ctx.subgroup_mask_ge);
}
@@ -262,7 +222,7 @@ Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id
Id EmitFSwizzleAdd(EmitContext& ctx, Id op_a, Id op_b, Id swizzle) {
const Id three{ctx.Const(3U)};
Id mask{GetThreadId(ctx)};
Id mask{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three);
mask = ctx.OpShiftLeftLogical(ctx.U32[1], mask, ctx.Const(1U));
mask = ctx.OpShiftRightLogical(ctx.U32[1], swizzle, mask);
@@ -30,7 +30,7 @@ enum class Operation {
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
const spv::ImageFormat format{spv::ImageFormat::Unknown};
const Id type{desc.is_integer ? ctx.U32[1] : ctx.F32[1]};
const Id type{ctx.F32[1]};
const bool depth{desc.is_depth};
const bool ms{desc.is_multisample};
switch (desc.type) {
@@ -1126,7 +1126,7 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
}
IR::Type types{info.used_constant_buffer_types | info.used_indirect_cbuf_types};
if (True(types & IR::Type::U8)) {
if (profile.support_int8 && profile.support_uniform_and_storage_buffer_8bit) {
if (profile.support_int8) {
DefineConstBuffers(*this, info, &UniformDefinitions::U8, binding, U8, 'u', sizeof(u8));
DefineConstBuffers(*this, info, &UniformDefinitions::S8, binding, S8, 's', sizeof(s8));
} else {
@@ -1134,7 +1134,7 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
}
}
if (True(types & IR::Type::U16)) {
if (profile.support_int16 && profile.support_uniform_and_storage_buffer_16bit) {
if (profile.support_int16) {
DefineConstBuffers(*this, info, &UniformDefinitions::U16, binding, U16, 'u',
sizeof(u16));
DefineConstBuffers(*this, info, &UniformDefinitions::S16, binding, S16, 's',
@@ -1196,18 +1196,10 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) {
IR::Type types{info.used_indirect_cbuf_types};
bool supports_aliasing = profile.support_descriptor_aliasing;
if (supports_aliasing && True(types & IR::Type::U8)) {
if (profile.support_int8 && profile.support_uniform_and_storage_buffer_8bit) {
load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8);
} else {
types |= IR::Type::U32;
}
load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8);
}
if (supports_aliasing && True(types & IR::Type::U16)) {
if (profile.support_int16 && profile.support_uniform_and_storage_buffer_16bit) {
load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16);
} else {
types |= IR::Type::U32;
}
load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16);
}
if (supports_aliasing && True(types & IR::Type::F32)) {
load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32);
@@ -1383,7 +1375,6 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in
.image_type = image_type,
.count = desc.count,
.is_multisample = desc.is_multisample,
.is_integer = desc.is_integer,
});
if (profile.supported_spirv >= 0x00010400) {
interfaces.push_back(id);
@@ -1447,7 +1438,7 @@ void EmitContext::DefineInputs(const IR::Program& program) {
if (info.uses_is_helper_invocation) {
is_helper_invocation = DefineInput(*this, U1, false, spv::BuiltIn::HelperInvocation);
}
if (info.uses_subgroup_mask && profile.SupportsSubgroupStage(stage)) {
if (info.uses_subgroup_mask) {
subgroup_mask_eq = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupEqMaskKHR);
subgroup_mask_lt = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupLtMaskKHR);
subgroup_mask_le = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupLeMaskKHR);
@@ -1461,10 +1452,9 @@ void EmitContext::DefineInputs(const IR::Program& program) {
Decorate(subgroup_mask_ge, spv::Decoration::Flat);
}
}
if ((info.uses_fswzadd || info.uses_subgroup_invocation_id || info.uses_subgroup_shuffles ||
(profile.warp_size_potentially_larger_than_guest &&
(info.uses_subgroup_vote || info.uses_subgroup_mask))) &&
profile.SupportsSubgroupStage(stage)) {
if (info.uses_fswzadd || info.uses_subgroup_invocation_id || info.uses_subgroup_shuffles ||
(profile.warp_size_potentially_larger_than_guest &&
(info.uses_subgroup_vote || info.uses_subgroup_mask))) {
AddCapability(spv::Capability::GroupNonUniform);
subgroup_local_invocation_id =
DefineInput(*this, U32[1], false, spv::BuiltIn::SubgroupLocalInvocationId);
@@ -42,7 +42,6 @@ struct TextureDefinition {
Id image_type;
u32 count;
bool is_multisample;
bool is_integer;
};
struct TextureBufferDefinition {
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -46,10 +43,6 @@ union TextureInstInfo {
BitField<25, 2, u32> num_derivatives;
BitField<27, 3, ImageFormat> image_format;
BitField<30, 1, u32> ndv_is_active;
/// Only meaningful for the sampled-texture family (ImageSampleImplicitLod, ImageFetch,
/// ImageGather, etc.); unused/zero for storage-image opcodes, which carry their own
/// is_integer via ImageDescriptor/ImageBufferDescriptor instead.
BitField<31, 1, u32> is_integer;
};
static_assert(sizeof(TextureInstInfo) <= sizeof(u32));

Some files were not shown because too many files have changed in this diff Show More