Compare commits

..

2 Commits

Author SHA1 Message Date
lizzie 5044961cf2 license fix 2026-02-19 08:40:12 +00:00
lizzie a4abca4040 [hle] splay
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-02-19 08:40:12 +00:00
51 changed files with 264 additions and 494 deletions
+3 -1
View File
@@ -407,10 +407,12 @@ if (APPLE)
# moltenvk
if (NOT YUZU_USE_BUNDLED_MOLTENVK)
find_library(MOLTENVK_LIBRARY MoltenVK)
else()
unset(MOLTENVK_LIBRARY)
endif()
# TODO: kosmickrisp?
if (NOT MOLTENVK_LIBRARY OR YUZU_USE_BUNDLED_MOLTENVK)
if (NOT MOLTENVK_LIBRARY)
AddJsonPackage(moltenvk)
set(MOLTENVK_LIBRARY "${moltenvk_SOURCE_DIR}/MoltenVK/dylib/macOS/libMoltenVK.dylib" CACHE STRING "" FORCE)
@@ -66,6 +66,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
LOGIN_SHARE_APPLET("login_share_applet_mode"),
WIFI_WEB_AUTH_APPLET("wifi_web_auth_applet_mode"),
MY_PAGE_APPLET("my_page_applet_mode"),
SPLAY_APPLET("splay_applet_mode"),
INPUT_OVERLAY_AUTO_HIDE("input_overlay_auto_hide"),
OVERLAY_GRID_SIZE("overlay_grid_size"),
DEBUG_KNOBS("debug_knobs"),
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -38,7 +41,8 @@ enum class AppletInfo(val appletId: Int, val entryId: Long = 0) {
OfflineWeb(0x17),
LoginShare(0x18),
WebAuth(0x19),
MyPage(0x1A)
MyPage(0x1A),
Splay(0x64)
}
// Matches enum in Service::NFP::CabinetMode with extra metadata
+1
View File
@@ -168,6 +168,7 @@ struct Values {
linkage, AppletMode::HLE, "wifi_web_auth_applet_mode", Category::LibraryApplet};
Setting<AppletMode> my_page_applet_mode{linkage, AppletMode::LLE, "my_page_applet_mode",
Category::LibraryApplet};
Setting<AppletMode> splay_applet_mode{linkage, AppletMode::LLE, "splay_applet_mode", Category::LibraryApplet};
// Audio
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
+2 -1
View File
@@ -829,6 +829,8 @@ add_library(core STATIC
hle/service/ns/ns_types.h
hle/service/ns/platform_service_manager.cpp
hle/service/ns/platform_service_manager.h
hle/service/ns/notify_service.cpp
hle/service/ns/notify_service.h
hle/service/ns/query_service.cpp
hle/service/ns/query_service.h
hle/service/ns/read_only_application_control_data_interface.cpp
@@ -1219,7 +1221,6 @@ target_link_libraries(core PRIVATE
fmt::fmt
nlohmann_json::nlohmann_json
RenderDoc::API
ZLIB::ZLIB
MbedTLS::mbedcrypto${MBEDTLS_LIB_SUFFIX}
MbedTLS::mbedtls${MBEDTLS_LIB_SUFFIX})
-7
View File
@@ -127,11 +127,6 @@ public:
void UpdatePagesCachedBatch(std::span<const std::pair<DAddr, size_t>> ranges, s32 delta);
private:
struct TranslationEntry {
DAddr guest_page{};
u8* host_ptr{};
};
// Internal helper that performs the update assuming the caller already holds the necessary lock.
void UpdatePagesCachedCountNoLock(DAddr addr, size_t size, s32 delta);
@@ -200,8 +195,6 @@ private:
}
Common::VirtualBuffer<VAddr> cpu_backing_address;
std::array<TranslationEntry, 4> t_slot{};
u32 cache_cursor = 0;
using CounterType = u8;
using CounterAtomicType = std::atomic_uint8_t;
static constexpr size_t subentries = 8 / sizeof(CounterType);
+1 -43
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
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
@@ -247,7 +247,6 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
}
impl->multi_dev_address.Register(new_dev, start_id);
}
t_slot = {};
if (track) {
TrackContinuityImpl(address, virtual_address, size, asid);
}
@@ -279,7 +278,6 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG;
}
}
t_slot = {};
}
template <typename Traits>
void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
@@ -419,26 +417,6 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
template <typename Traits>
void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) {
device_inter->FlushRegion(address, size);
const std::size_t page_offset = address & Memory::YUZU_PAGEMASK;
if (size <= Memory::YUZU_PAGESIZE - page_offset) {
const DAddr guest_page = address & ~static_cast<DAddr>(Memory::YUZU_PAGEMASK);
for (size_t i = 0; i < 4; ++i) {
if (t_slot[i].guest_page == guest_page && t_slot[i].host_ptr != nullptr) {
std::memcpy(dest_pointer, t_slot[i].host_ptr + page_offset, size);
return;
}
}
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
const auto phys_addr = compressed_physical_ptr[page_index];
if (phys_addr != 0) {
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
cache_cursor = (cache_cursor + 1) & 3U;
std::memcpy(dest_pointer, mem_ptr + page_offset, size);
return;
}
}
WalkBlock(
address, size,
[&](size_t copy_amount, DAddr current_vaddr) {
@@ -477,26 +455,6 @@ void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_poin
template <typename Traits>
void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) {
const std::size_t page_offset = address & Memory::YUZU_PAGEMASK;
if (size <= Memory::YUZU_PAGESIZE - page_offset) {
const DAddr guest_page = address & ~static_cast<DAddr>(Memory::YUZU_PAGEMASK);
for (size_t i = 0; i < 4; ++i) {
if (t_slot[i].guest_page == guest_page && t_slot[i].host_ptr != nullptr) {
std::memcpy(dest_pointer, t_slot[i].host_ptr + page_offset, size);
return;
}
}
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
const auto phys_addr = compressed_physical_ptr[page_index];
if (phys_addr != 0) {
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
cache_cursor = (cache_cursor + 1) & 3U;
std::memcpy(dest_pointer, mem_ptr + page_offset, size);
return;
}
}
WalkBlock(
address, size,
[&](size_t copy_amount, DAddr current_vaddr) {
-75
View File
@@ -4,13 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <cstddef>
#include <cstring>
#include <limits>
#include <span>
#include <zlib.h>
#include "common/settings.h"
#include "common/string_util.h"
#include "common/swap.h"
@@ -38,73 +31,6 @@ const std::array<const char*, 16> LANGUAGE_NAMES{{
"BrazilianPortuguese",
}};
namespace {
constexpr std::size_t LEGACY_LANGUAGE_REGION_SIZE = sizeof(std::array<LanguageEntry, 16>);
constexpr std::size_t PACKED_LANGUAGE_REGION_MAX_SIZE = sizeof(LanguageEntry) * 32;
bool InflateRawDeflate(std::span<const u8> compressed, std::vector<u8>& out) {
if (compressed.empty() || compressed.size() > std::numeric_limits<uInt>::max()) {
return false;
}
z_stream stream{};
stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(compressed.data()));
stream.avail_in = static_cast<uInt>(compressed.size());
if (inflateInit2(&stream, -MAX_WBITS) != Z_OK) {
return false;
}
std::array<u8, 0x1000> chunk{};
int ret = Z_OK;
while (ret == Z_OK) {
stream.next_out = reinterpret_cast<Bytef*>(chunk.data());
stream.avail_out = static_cast<uInt>(chunk.size());
ret = inflate(&stream, Z_NO_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END) {
inflateEnd(&stream);
return false;
}
const auto produced = chunk.size() - static_cast<std::size_t>(stream.avail_out);
if (produced != 0) {
if (out.size() + produced > PACKED_LANGUAGE_REGION_MAX_SIZE) {
inflateEnd(&stream);
return false;
}
out.insert(out.end(), chunk.begin(),
chunk.begin() + static_cast<std::ptrdiff_t>(produced));
}
}
inflateEnd(&stream);
return ret == Z_STREAM_END;
}
void DecodePackedLanguageEntries(RawNACP& raw) {
auto* packed_region = reinterpret_cast<u8*>(raw.language_entries.data());
u16_le compressed_size_le{};
std::memcpy(&compressed_size_le, packed_region, sizeof(compressed_size_le));
const auto compressed_size = static_cast<std::size_t>(compressed_size_le);
if (compressed_size == 0 || compressed_size > LEGACY_LANGUAGE_REGION_SIZE - sizeof(u16_le)) {
return;
}
std::vector<u8> decompressed;
if (!InflateRawDeflate(
std::span<const u8>(packed_region + sizeof(u16_le), compressed_size), decompressed)) {
return;
}
if (decompressed.size() < LEGACY_LANGUAGE_REGION_SIZE ||
decompressed.size() % sizeof(LanguageEntry) != 0) {
return;
}
std::memcpy(raw.language_entries.data(), decompressed.data(), LEGACY_LANGUAGE_REGION_SIZE);
}
} // namespace
std::string LanguageEntry::GetApplicationName() const {
return Common::StringFromFixedZeroTerminatedBuffer(application_name.data(),
application_name.size());
@@ -140,7 +66,6 @@ NACP::NACP() = default;
NACP::NACP(VirtualFile file) {
file->ReadObject(&raw);
DecodePackedLanguageEntries(raw);
}
NACP::~NACP() = default;
+5 -2
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -94,7 +94,8 @@ enum class AppletId : u32 {
LoginShare = 0x18,
WebAuth = 0x19,
MyPage = 0x1A,
Lhub = 0x35
Lhub = 0x35,
Splay = 0x64,
};
enum class AppletProgramId : u64 {
@@ -118,6 +119,8 @@ enum class AppletProgramId : u64 {
WebAuth = 0x0100000000001011ull,
Starter = 0x0100000000001012ull,
MyPage = 0x0100000000001013ull,
Maintenance = 0x0100000000001015ull,
Splay = 0x0100000000001048ull,
MaxProgramId = 0x0100000000001FFFull,
};
@@ -172,6 +172,19 @@ void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel)
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
}
void PushInShowSplay(Core::System& system, AppletStorageChannel& channel) {
struct SplayV1 {
std::array<char, 0x100> i_dont_know_what_this_is_used_for;
};
static_assert(sizeof(SplayV1) == 0x100, "MiiEditV3 has incorrect size.");
SplayV1 splay_arguments{};
std::vector<u8> argument_data(sizeof(splay_arguments));
std::memcpy(argument_data.data(), &splay_arguments, sizeof(splay_arguments));
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
}
void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) {
const CommonArguments arguments{
.arguments_version = CommonArgumentVersion::Version3,
@@ -335,6 +348,9 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) {
case AppletId::Controller:
PushInShowController(m_system, InitializeFakeCallerApplet(m_system, applet));
break;
case AppletId::Splay:
PushInShowSplay(m_system, InitializeFakeCallerApplet(m_system, applet));
break;
default:
break;
}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -44,6 +44,7 @@ bool ShouldCreateGuestApplet(AppletId applet_id) {
X(LoginShare, login_share)
X(WebAuth, wifi_web_auth)
X(MyPage, my_page)
X(Splay, splay)
#undef X
@@ -52,48 +53,28 @@ bool ShouldCreateGuestApplet(AppletId applet_id) {
AppletProgramId AppletIdToProgramId(AppletId applet_id) {
switch (applet_id) {
case AppletId::OverlayDisplay:
return AppletProgramId::OverlayDisplay;
case AppletId::QLaunch:
return AppletProgramId::QLaunch;
case AppletId::Starter:
return AppletProgramId::Starter;
case AppletId::Auth:
return AppletProgramId::Auth;
case AppletId::Cabinet:
return AppletProgramId::Cabinet;
case AppletId::Controller:
return AppletProgramId::Controller;
case AppletId::DataErase:
return AppletProgramId::DataErase;
case AppletId::Error:
return AppletProgramId::Error;
case AppletId::NetConnect:
return AppletProgramId::NetConnect;
case AppletId::ProfileSelect:
return AppletProgramId::ProfileSelect;
case AppletId::SoftwareKeyboard:
return AppletProgramId::SoftwareKeyboard;
case AppletId::MiiEdit:
return AppletProgramId::MiiEdit;
case AppletId::Web:
return AppletProgramId::Web;
case AppletId::Shop:
return AppletProgramId::Shop;
case AppletId::PhotoViewer:
return AppletProgramId::PhotoViewer;
case AppletId::Settings:
return AppletProgramId::Settings;
case AppletId::OfflineWeb:
return AppletProgramId::OfflineWeb;
case AppletId::LoginShare:
return AppletProgramId::LoginShare;
case AppletId::WebAuth:
return AppletProgramId::WebAuth;
case AppletId::MyPage:
return AppletProgramId::MyPage;
default:
return static_cast<AppletProgramId>(0);
case AppletId::OverlayDisplay: return AppletProgramId::OverlayDisplay;
case AppletId::QLaunch: return AppletProgramId::QLaunch;
case AppletId::Starter: return AppletProgramId::Starter;
case AppletId::Auth: return AppletProgramId::Auth;
case AppletId::Cabinet: return AppletProgramId::Cabinet;
case AppletId::Controller: return AppletProgramId::Controller;
case AppletId::DataErase: return AppletProgramId::DataErase;
case AppletId::Error: return AppletProgramId::Error;
case AppletId::NetConnect: return AppletProgramId::NetConnect;
case AppletId::ProfileSelect: return AppletProgramId::ProfileSelect;
case AppletId::SoftwareKeyboard: return AppletProgramId::SoftwareKeyboard;
case AppletId::MiiEdit: return AppletProgramId::MiiEdit;
case AppletId::Web: return AppletProgramId::Web;
case AppletId::Shop: return AppletProgramId::Shop;
case AppletId::PhotoViewer: return AppletProgramId::PhotoViewer;
case AppletId::Settings: return AppletProgramId::Settings;
case AppletId::OfflineWeb: return AppletProgramId::OfflineWeb;
case AppletId::LoginShare: return AppletProgramId::LoginShare;
case AppletId::WebAuth: return AppletProgramId::WebAuth;
case AppletId::MyPage: return AppletProgramId::MyPage;
case AppletId::Splay: return AppletProgramId::Splay;
default: return AppletProgramId(0);
}
}
@@ -0,0 +1,42 @@
// 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
#include "common/logging/log.h"
#include "common/uuid.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ns/notify_service.h"
#include "core/hle/service/service.h"
#include "core/launch_timestamp_cache.h"
#include "frontend_common/play_time_manager.h"
namespace Service::NS {
INotifyService::INotifyService(Core::System& system_)
: ServiceFramework{system_, "pdm:ntfy"}
{
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "NotifyAppletEvent"},
{2, nullptr, "NotifyOperationModeChangeEvent"},
{3, nullptr, "NotifyPowerStateChangeEvent"},
{4, nullptr, "NotifyClearAllEvent"},
{5, nullptr, "NotifyEventForDebug"},
{6, nullptr, "SuspendUserAccountEventService"},
{7, nullptr, "ResumeUserAccountEventService"},
{8, nullptr, "Unknown8"},
{9, nullptr, "Unknown9"},
{20, nullptr, "Unknown20"},
{100, nullptr, "Unknown100"},
{101, nullptr, "Unknown101"},
};
// clang-format on
RegisterHandlers(functions);
}
INotifyService::~INotifyService() = default;
} // namespace Service::NS
+25
View File
@@ -0,0 +1,25 @@
// 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
#pragma once
#include "common/uuid.h"
#include "core/hle/service/am/am_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ns/ns_types.h"
#include "core/hle/service/service.h"
#include <memory>
namespace Service::NS {
class INotifyService final : public ServiceFramework<INotifyService> {
public:
explicit INotifyService(Core::System& system_);
~INotifyService() override;
};
} // namespace Service::NS
+5
View File
@@ -1,3 +1,6 @@
// 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
@@ -5,6 +8,7 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/platform_service_manager.h"
#include "core/hle/service/ns/query_service.h"
#include "core/hle/service/ns/notify_service.h"
#include "core/hle/service/ns/service_getter_interface.h"
#include "core/hle/service/ns/system_update_interface.h"
#include "core/hle/service/ns/vulnerability_manager_interface.h"
@@ -33,6 +37,7 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService("ns:vm",
std::make_shared<IVulnerabilityManagerInterface>(system));
server_manager->RegisterNamedService("pdm:qry", std::make_shared<IQueryService>(system));
server_manager->RegisterNamedService("pdm:ntfy", std::make_shared<INotifyService>(system));
server_manager->RegisterNamedService("pl:s",
std::make_shared<IPlatformServiceManager>(system, "pl:s"));
@@ -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
/* This file is part of the dynarmic project.
@@ -14,7 +14,7 @@
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <mcl/type_traits/integer_of_size.hpp>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/a32_emit_x64.h"
#include "dynarmic/backend/x64/abi.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -14,7 +14,7 @@
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <mcl/type_traits/integer_of_size.hpp>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/a64_emit_x64.h"
#include "dynarmic/backend/x64/abi.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -11,7 +11,7 @@
#include <algorithm>
#include "dynarmic/common/common_types.h"
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/block_of_code.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -26,7 +26,7 @@
#include "dynarmic/common/assert.h"
#include <mcl/bit/bit_field.hpp>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/a32_jitstate.h"
#include "dynarmic/backend/x64/abi.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -15,7 +15,9 @@
#include <mcl/bit/bit_field.hpp>
#include "dynarmic/common/common_types.h"
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include <xbyak/xbyak_util.h>
#include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/callback.h"
#include "dynarmic/backend/x64/constant_pool.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -12,7 +12,7 @@
#include <vector>
#include "dynarmic/common/common_types.h"
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
namespace Dynarmic::Backend::X64 {
@@ -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
/* This file is part of the dynarmic project.
@@ -15,7 +15,7 @@
#include "dynarmic/common/common_types.h"
#include <ankerl/unordered_dense.h>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
namespace Dynarmic::Backend::X64 {
@@ -18,7 +18,8 @@
#include <mcl/bitsizeof.hpp>
#include <ankerl/unordered_dense.h>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include <xbyak/xbyak_util.h>
#include <boost/container/small_vector.hpp>
#include "dynarmic/backend/exception_handler.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -19,7 +19,7 @@
#include <mcl/mp/typelist/lower_to_tuple.hpp>
#include "dynarmic/common/common_types.h"
#include <mcl/type_traits/integer_of_size.hpp>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/block_of_code.h"
@@ -7,7 +7,7 @@
*/
#include <bit>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/a32_emit_x64.h"
#include "dynarmic/backend/x64/a64_emit_x64.h"
@@ -18,7 +18,7 @@
#include <mcl/bitsizeof.hpp>
#include "dynarmic/common/common_types.h"
#include <mcl/type_traits/function_info.hpp>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/block_of_code.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -21,7 +21,7 @@
#include <mcl/mp/typelist/lower_to_tuple.hpp>
#include <mcl/type_traits/function_info.hpp>
#include <mcl/type_traits/integer_of_size.hpp>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/block_of_code.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -9,7 +9,7 @@
#include "dynarmic/common/assert.h"
#include "dynarmic/common/common_types.h"
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
namespace Dynarmic::Backend::X64 {
@@ -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
/* This file is part of the dynarmic project.
@@ -9,7 +9,7 @@
#pragma once
#include "dynarmic/common/assert.h"
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
namespace Dynarmic::Backend::X64 {
@@ -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
/* This file is part of the dynarmic project.
@@ -16,7 +16,7 @@
#include <fmt/ostream.h>
#include "dynarmic/common/assert.h"
#include <bit>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/stack_layout.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -14,7 +14,7 @@
#include "boost/container/small_vector.hpp"
#include "dynarmic/common/common_types.h"
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include <boost/container/static_vector.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/pool/pool_alloc.hpp>
@@ -1,15 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <unordered_map>
#include <unordered_set>
// TODO: Defining this crashes e v e r y t h i n g
// #define XBYAK_STD_UNORDERED_SET ankerl::unordered_dense::set
// #define XBYAK_STD_UNORDERED_MAP ankerl::unordered_dense::map
// #define XBYAK_STD_UNORDERED_MULTIMAP boost::unordered_multimap
#include <xbyak/xbyak.h>
#include <xbyak/xbyak_util.h>
@@ -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
/* This file is part of the dynarmic project.
@@ -8,7 +8,7 @@
#include <mutex>
#include <optional>
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/hostloc.h"
@@ -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
/* This file is part of the dynarmic project.
@@ -8,7 +8,7 @@
#pragma once
#include "dynarmic/backend/x64/xbyak.h"
#include <xbyak/xbyak.h>
namespace Dynarmic {
+5 -5
View File
@@ -24,7 +24,7 @@ add_executable(dynarmic_tests
A64/real_world.cpp
A64/testenv.h
)
target_link_libraries(dynarmic_tests PRIVATE merry::oaknut unordered_dense::unordered_dense)
target_link_libraries(dynarmic_tests PRIVATE merry::oaknut)
if (DYNARMIC_TESTS_USE_UNICORN)
target_link_libraries(dynarmic_tests PRIVATE Unicorn::Unicorn)
@@ -72,7 +72,7 @@ add_executable(dynarmic_print_info
print_info.cpp
)
create_target_directory_groups(dynarmic_print_info)
target_link_libraries(dynarmic_print_info PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense)
target_link_libraries(dynarmic_print_info PRIVATE dynarmic fmt::fmt merry::mcl)
if (BOOST_NO_HEADERS)
target_link_libraries(dynarmic_print_info PRIVATE Boost::variant Boost::icl Boost::pool)
else()
@@ -93,7 +93,7 @@ add_executable(dynarmic_test_generator
create_target_directory_groups(dynarmic_test_generator)
target_link_libraries(dynarmic_test_generator PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense)
target_link_libraries(dynarmic_test_generator PRIVATE dynarmic fmt::fmt merry::mcl)
if (BOOST_NO_HEADERS)
target_link_libraries(dynarmic_test_generator PRIVATE Boost::variant Boost::icl Boost::pool)
else()
@@ -110,7 +110,7 @@ add_executable(dynarmic_test_reader
test_reader.cpp
)
create_target_directory_groups(dynarmic_test_reader)
target_link_libraries(dynarmic_test_reader PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense)
target_link_libraries(dynarmic_test_reader PRIVATE dynarmic fmt::fmt merry::mcl)
if (BOOST_NO_HEADERS)
target_link_libraries(dynarmic_test_reader PRIVATE Boost::variant Boost::icl Boost::pool)
else()
@@ -123,7 +123,7 @@ target_compile_definitions(dynarmic_test_reader PRIVATE FMT_USE_USER_DEFINED_LIT
#
create_target_directory_groups(dynarmic_tests)
target_link_libraries(dynarmic_tests PRIVATE dynarmic Catch2::Catch2WithMain fmt::fmt merry::mcl unordered_dense::unordered_dense)
target_link_libraries(dynarmic_tests PRIVATE dynarmic Catch2::Catch2WithMain fmt::fmt merry::mcl)
if (BOOST_NO_HEADERS)
target_link_libraries(dynarmic_tests PRIVATE Boost::variant Boost::icl Boost::pool)
else()
@@ -47,6 +47,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
INSERT(Settings, login_share_applet_mode, tr("Login share"), QString());
INSERT(Settings, wifi_web_auth_applet_mode, tr("Wifi web auth"), QString());
INSERT(Settings, my_page_applet_mode, tr("My page"), QString());
INSERT(Settings, splay_applet_mode, tr("Splay"), QString());
INSERT(Settings, enable_overlay, tr("Enable Overlay Applet"), QString());
// Audio
+1 -7
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
@@ -42,8 +39,7 @@ public:
static constexpr u64 BASE_PAGE_SIZE = 1ULL << BASE_PAGE_BITS;
explicit BufferBase(VAddr cpu_addr_, u64 size_bytes_)
: cpu_addr_cached{static_cast<DAddr>(cpu_addr_)}, cpu_addr{cpu_addr_},
size_bytes{size_bytes_} {}
: cpu_addr{cpu_addr_}, size_bytes{size_bytes_} {}
explicit BufferBase(NullBufferParams) {}
@@ -101,8 +97,6 @@ public:
return cpu_addr;
}
DAddr cpu_addr_cached = 0;
/// Returns the offset relative to the given CPU address
/// @pre IsInBounds returns true
[[nodiscard]] u32 Offset(VAddr other_cpu_addr) const noexcept {
+34 -83
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
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -382,10 +382,6 @@ void BufferCache<P>::BindHostComputeBuffers() {
BindHostComputeUniformBuffers();
BindHostComputeStorageBuffers();
BindHostComputeTextureBuffers();
if (any_buffer_uploaded) {
runtime.PostCopyBarrier();
any_buffer_uploaded = false;
}
}
template <class P>
@@ -767,85 +763,45 @@ void BufferCache<P>::BindHostIndexBuffer() {
}
}
template <class P>
void BufferCache<P>::BindHostVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size,
u32 stride) {
if constexpr (IS_OPENGL) {
runtime.BindVertexBuffer(index, buffer, offset, size, stride);
} else {
runtime.BindVertexBuffer(index, buffer.Handle(), offset, size, stride);
}
}
template <class P>
Binding& BufferCache<P>::VertexBufferSlot(u32 index) {
ASSERT(index < NUM_VERTEX_BUFFERS);
return v_buffer[index];
}
template <class P>
const Binding& BufferCache<P>::VertexBufferSlot(u32 index) const {
ASSERT(index < NUM_VERTEX_BUFFERS);
return v_buffer[index];
}
template <class P>
void BufferCache<P>::UpdateVertexBufferSlot(u32 index, const Binding& binding) {
Binding& slot = VertexBufferSlot(index);
if (slot.device_addr != binding.device_addr || slot.size != binding.size) {
++vertex_buffers_serial;
}
slot = binding;
if (binding.buffer_id != NULL_BUFFER_ID && binding.size != 0) {
enabled_vertex_buffers_mask |= (1u << index);
} else {
enabled_vertex_buffers_mask &= ~(1u << index);
}
}
template <class P>
void BufferCache<P>::BindHostVertexBuffers() {
HostBindings<typename P::Buffer> host_bindings;
bool any_valid{false};
auto& flags = maxwell3d->dirty.flags;
u32 enabled_mask = enabled_vertex_buffers_mask;
HostBindings<Buffer> bindings{};
u32 last_index = std::numeric_limits<u32>::max();
const auto flush_bindings = [&]() {
if (bindings.buffers.empty()) {
return;
}
bindings.max_index = bindings.min_index + static_cast<u32>(bindings.buffers.size());
runtime.BindVertexBuffers(bindings);
bindings = HostBindings<Buffer>{};
last_index = std::numeric_limits<u32>::max();
};
while (enabled_mask != 0) {
const u32 index = std::countr_zero(enabled_mask);
enabled_mask &= (enabled_mask - 1);
const Binding& binding = VertexBufferSlot(index);
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
const Binding& binding = channel_state->vertex_buffers[index];
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer, binding.buffer_id);
SynchronizeBuffer(buffer, binding.device_addr, binding.size);
if (!flags[Dirty::VertexBuffer0 + index]) {
flush_bindings();
continue;
}
flags[Dirty::VertexBuffer0 + index] = false;
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
const u32 offset = buffer.Offset(binding.device_addr);
buffer.MarkUsage(offset, binding.size);
if (!bindings.buffers.empty() && index != last_index + 1) {
flush_bindings();
}
if (bindings.buffers.empty()) {
bindings.min_index = index;
}
bindings.buffers.push_back(&buffer);
bindings.offsets.push_back(offset);
bindings.sizes.push_back(binding.size);
bindings.strides.push_back(stride);
last_index = index;
host_bindings.min_index = (std::min)(host_bindings.min_index, index);
host_bindings.max_index = (std::max)(host_bindings.max_index, index);
any_valid = true;
}
if (any_valid) {
host_bindings.max_index++;
for (u32 index = host_bindings.min_index; index < host_bindings.max_index; index++) {
flags[Dirty::VertexBuffer0 + index] = false;
const Binding& binding = channel_state->vertex_buffers[index];
Buffer& buffer = slot_buffers[binding.buffer_id];
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
const u32 offset = buffer.Offset(binding.device_addr);
buffer.MarkUsage(offset, binding.size);
host_bindings.buffers.push_back(&buffer);
host_bindings.offsets.push_back(offset);
host_bindings.sizes.push_back(binding.size);
host_bindings.strides.push_back(stride);
}
runtime.BindVertexBuffers(host_bindings);
}
flush_bindings();
}
template <class P>
@@ -1249,20 +1205,17 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
u32 size = address_size; // TODO: Analyze stride and number of vertices
if (array.enable == 0 || size == 0 || !device_addr) {
channel_state->vertex_buffers[index] = NULL_BINDING;
UpdateVertexBufferSlot(index, NULL_BINDING);
return;
}
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || size >= 64_MiB) {
size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
}
const BufferId buffer_id = FindBuffer(*device_addr, size);
const Binding binding{
channel_state->vertex_buffers[index] = Binding{
.device_addr = *device_addr,
.size = size,
.buffer_id = buffer_id,
};
channel_state->vertex_buffers[index] = binding;
UpdateVertexBufferSlot(index, binding);
}
template <class P>
@@ -1575,12 +1528,12 @@ void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
template <class P>
bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) {
upload_copies.clear();
boost::container::small_vector<BufferCopy, 4> copies;
u64 total_size_bytes = 0;
u64 largest_copy = 0;
const DAddr buffer_start = buffer.cpu_addr_cached;
DAddr buffer_start = buffer.CpuAddr();
memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
upload_copies.push_back(BufferCopy{
copies.push_back(BufferCopy{
.src_offset = total_size_bytes,
.dst_offset = device_addr_out - buffer_start,
.size = range_size,
@@ -1591,9 +1544,8 @@ bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si
if (total_size_bytes == 0) {
return true;
}
const std::span<BufferCopy> copies_span(upload_copies.data(), upload_copies.size());
const std::span<BufferCopy> copies_span(copies.data(), copies.size());
UploadMemory(buffer, total_size_bytes, largest_copy, copies_span);
any_buffer_uploaded = true;
return false;
}
@@ -1783,7 +1735,6 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
auto& binding = channel_state->vertex_buffers[index];
if (binding.buffer_id == buffer_id) {
binding.buffer_id = BufferId{};
UpdateVertexBufferSlot(index, binding);
dirty_vertex_buffers.push_back(index);
}
}
@@ -320,7 +320,6 @@ public:
std::recursive_mutex mutex;
Runtime& runtime;
bool any_buffer_uploaded = false;
private:
template <typename Func>
@@ -373,8 +372,6 @@ private:
void BindHostTransformFeedbackBuffers();
void BindHostVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride);
void BindHostComputeUniformBuffers();
void BindHostComputeStorageBuffers();
@@ -456,12 +453,6 @@ private:
[[nodiscard]] bool HasFastUniformBufferBound(size_t stage, u32 binding_index) const noexcept;
[[nodiscard]] Binding& VertexBufferSlot(u32 index);
[[nodiscard]] const Binding& VertexBufferSlot(u32 index) const;
void UpdateVertexBufferSlot(u32 index, const Binding& binding);
void ClearDownload(DAddr base_addr, u64 size);
void InlineMemoryImplementation(DAddr dest_address, size_t copy_size,
@@ -481,12 +472,6 @@ private:
u32 last_index_count = 0;
u32 enabled_vertex_buffers_mask = 0;
u64 vertex_buffers_serial = 0;
std::array<Binding, 32> v_buffer{};
boost::container::small_vector<BufferCopy, 4> upload_copies;
MemoryTracker memory_tracker;
Common::RangeSet<DAddr> uncommitted_gpu_modified_ranges;
Common::RangeSet<DAddr> gpu_modified_ranges;
+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 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -92,7 +89,7 @@ struct CommandDataContainer {
/// Struct used to synchronize the GPU thread
struct SynchState final {
using CommandQueue = Common::SPSCQueue<CommandDataContainer>;
using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
std::mutex write_lock;
CommandQueue queue;
u64 last_fence{};
@@ -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 2021 yuzu Emulator Project
@@ -189,10 +189,6 @@ void ComputePipeline::Configure() {
buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers);
buffer_cache.runtime.SetImagePointers(textures.data(), images.data());
buffer_cache.BindHostComputeBuffers();
if (buffer_cache.any_buffer_uploaded) {
buffer_cache.runtime.PostCopyBarrier();
buffer_cache.any_buffer_uploaded = false;
}
const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers +
num_image_buffers};
@@ -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 2021 yuzu Emulator Project
@@ -558,10 +558,6 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
if (image_binding != 0) {
glBindImageTextures(0, image_binding, images.data());
}
if (buffer_cache.any_buffer_uploaded) {
buffer_cache.runtime.PostCopyBarrier();
buffer_cache.any_buffer_uploaded = false;
}
return true;
}
@@ -12,14 +12,12 @@
#include "shader_recompiler/shader_info.h"
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/surface.h"
#include "video_core/texture_cache/types.h"
#include "video_core/vulkan_common/vulkan_device.h"
namespace Vulkan {
using Shader::Backend::SPIRV::NUM_TEXTURE_AND_IMAGE_SCALING_WORDS;
using VideoCore::Surface::IsPixelFormatInteger;
class DescriptorLayoutBuilder {
public:
@@ -193,14 +191,10 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
ImageView& image_view{texture_cache.GetImageView(image_view_id)};
const VkImageView vk_image_view{image_view.Handle(desc.type)};
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
// Integer formats don't support VK_FILTER_LINEAR in Vulkan.
const bool needs_nearest{sampler.HasLinearFilter() &&
IsPixelFormatInteger(image_view.format)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
const VkSampler vk_sampler{needs_nearest ? sampler.HandleWithNearestFilter()
: use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
: sampler.Handle()};
const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
: sampler.Handle()};
guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler);
rescaling.PushTexture(texture_cache.IsRescaling(image_view));
}
@@ -203,10 +203,6 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
buffer_cache.UpdateComputeBuffers();
buffer_cache.BindHostComputeBuffers();
if (buffer_cache.any_buffer_uploaded) {
buffer_cache.runtime.PostCopyBarrier();
buffer_cache.any_buffer_uploaded = false;
}
RescalingPushConstant rescaling;
const VideoCommon::SamplerId* samplers_it{samplers.data()};
@@ -496,10 +496,6 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
if constexpr (Spec::enabled_stages[4]) {
prepare_stage(4);
}
if (buffer_cache.any_buffer_uploaded) {
buffer_cache.runtime.PostCopyBarrier();
buffer_cache.any_buffer_uploaded = false;
}
texture_cache.UpdateRenderTargets(false);
texture_cache.CheckFeedbackLoop(views);
ConfigureDraw(rescaling, render_area);
@@ -38,7 +38,6 @@ namespace Vulkan {
using Tegra::Engines::Fermi2D;
using Tegra::Texture::SwizzleSource;
using Tegra::Texture::TextureFilter;
using Tegra::Texture::TextureMipmapFilter;
using VideoCommon::BufferImageCopy;
using VideoCommon::ImageFlagBits;
@@ -2357,35 +2356,6 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
if (max_anisotropy > max_anisotropy_default) {
sampler_default_anisotropy = create_sampler(max_anisotropy_default);
}
// Create a nearest-filter fallback for integer format image views.
// but Vulkan requires the format to support linear filtering.
const bool is_mag_linear = tsc.mag_filter == TextureFilter::Linear;
const bool is_min_linear = tsc.min_filter == TextureFilter::Linear;
has_linear_filter = is_mag_linear || is_min_linear;
if (has_linear_filter) {
sampler_nearest = device.GetLogical().CreateSampler(VkSamplerCreateInfo{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.pNext = pnext,
.flags = 0,
.magFilter = VK_FILTER_NEAREST,
.minFilter = VK_FILTER_NEAREST,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
.mipLodBias = tsc.LodBias(),
.anisotropyEnable = VK_FALSE,
.maxAnisotropy = 1.0f,
.compareEnable = tsc.depth_compare_enabled,
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(),
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(),
.borderColor = has_custom_border_colors ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT
: ConvertBorderColor(color),
.unnormalizedCoordinates = VK_FALSE,
});
}
}
Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers,
@@ -408,19 +408,9 @@ public:
return static_cast<bool>(sampler_default_anisotropy);
}
[[nodiscard]] bool HasLinearFilter() const noexcept {
return has_linear_filter;
}
[[nodiscard]] VkSampler HandleWithNearestFilter() const noexcept {
return sampler_nearest ? *sampler_nearest : *sampler;
}
private:
vk::Sampler sampler;
vk::Sampler sampler_default_anisotropy;
vk::Sampler sampler_nearest;
bool has_linear_filter = false;
};
struct TextureCacheParams {
+34 -80
View File
@@ -291,59 +291,55 @@ void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) {
return;
}
if (render_targets_serial == last_feedback_loop_serial &&
texture_bindings_serial == last_feedback_texture_serial) {
if (last_feedback_loop_result) {
runtime.BarrierFeedbackLoop();
}
return;
}
if (rt_active_mask == 0) {
last_feedback_loop_serial = render_targets_serial;
last_feedback_texture_serial = texture_bindings_serial;
last_feedback_loop_result = false;
return;
}
const u32 depth_bit = 1u << NUM_RT;
const bool depth_active = (rt_active_mask & depth_bit) != 0;
const bool requires_barrier = [&] {
for (const auto& view : views) {
if (!view.id) {
continue;
}
{
bool is_continue = false;
for (size_t i = 0; i < 8; ++i)
is_continue |= (rt_active_mask & (1u << i)) && view.id == render_targets.color_buffer_ids[i];
if (is_continue)
continue;
bool is_render_target = false;
for (const auto& ct_view_id : render_targets.color_buffer_ids) {
if (ct_view_id && ct_view_id == view.id) {
is_render_target = true;
break;
}
}
if (depth_active && view.id == render_targets.depth_buffer_id)
if (!is_render_target && render_targets.depth_buffer_id == view.id) {
is_render_target = true;
}
if (is_render_target) {
continue;
const ImageId view_image_id = slot_image_views[view.id].image_id;
{
bool is_continue = false;
for (size_t i = 0; i < 8; ++i)
is_continue |= (rt_active_mask & (1u << i)) && view_image_id == rt_image_id[i];
if (is_continue)
continue;
}
if (depth_active && view_image_id == rt_depth_image_id) {
return true;
auto& image_view = slot_image_views[view.id];
for (const auto& ct_view_id : render_targets.color_buffer_ids) {
if (!ct_view_id) {
continue;
}
auto& ct_view = slot_image_views[ct_view_id];
if (image_view.image_id == ct_view.image_id) {
return true;
}
}
if (render_targets.depth_buffer_id) {
auto& zt_view = slot_image_views[render_targets.depth_buffer_id];
if (image_view.image_id == zt_view.image_id) {
return true;
}
}
}
return false;
}();
last_feedback_loop_serial = render_targets_serial;
last_feedback_texture_serial = texture_bindings_serial;
last_feedback_loop_result = requires_barrier;
if (requires_barrier) {
runtime.BarrierFeedbackLoop();
}
@@ -403,19 +399,13 @@ void TextureCache<P>::SynchronizeGraphicsDescriptors() {
const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
const u32 tic_limit = maxwell3d->regs.tex_header.limit;
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
bool bindings_changed = false;
if (channel_state->graphics_sampler_table.Synchronize(maxwell3d->regs.tex_sampler.Address(),
tsc_limit)) {
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
bindings_changed = true;
}
if (channel_state->graphics_image_table.Synchronize(maxwell3d->regs.tex_header.Address(),
tic_limit)) {
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
bindings_changed = true;
}
if (bindings_changed) {
++texture_bindings_serial;
}
}
@@ -425,18 +415,12 @@ void TextureCache<P>::SynchronizeComputeDescriptors() {
const u32 tic_limit = kepler_compute->regs.tic.limit;
const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit;
const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address();
bool bindings_changed = false;
if (channel_state->compute_sampler_table.Synchronize(tsc_gpu_addr, tsc_limit)) {
channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
bindings_changed = true;
}
if (channel_state->compute_image_table.Synchronize(kepler_compute->regs.tic.Address(),
tic_limit)) {
channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
bindings_changed = true;
}
if (bindings_changed) {
++texture_bindings_serial;
}
}
@@ -550,7 +534,6 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
return;
}
const VideoCommon::RenderTargets previous_render_targets = render_targets;
const bool rescaled = RescaleRenderTargets();
if (is_rescaling != rescaled) {
flags[Dirty::RescaleViewports] = true;
@@ -566,21 +549,6 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id));
rt_active_mask = 0;
rt_image_id = {};
for (size_t i = 0; i < rt_image_id.size(); ++i) {
if (ImageViewId const view = render_targets.color_buffer_ids[i]; view) {
rt_active_mask |= 1u << i;
rt_image_id[i] = slot_image_views[view].image_id;
}
}
if (depth_buffer_id) {
rt_active_mask |= (1u << NUM_RT);
rt_depth_image_id = slot_image_views[depth_buffer_id].image_id;
} else {
rt_depth_image_id = ImageId{};
}
for (size_t index = 0; index < NUM_RT; ++index) {
render_targets.draw_buffers[index] = static_cast<u8>(maxwell3d->regs.rt_control.Map(index));
}
@@ -596,22 +564,12 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
};
render_targets.is_rescaled = is_rescaling;
if (render_targets != previous_render_targets) {
++render_targets_serial;
}
flags[Dirty::DepthBiasGlobal] = true;
}
template <class P>
typename P::Framebuffer* TextureCache<P>::GetFramebuffer() {
if (last_framebuffer_id && last_framebuffer_serial == render_targets_serial) {
return &slot_framebuffers[last_framebuffer_id];
}
const FramebufferId framebuffer_id = GetFramebufferId(render_targets);
last_framebuffer_id = framebuffer_id;
last_framebuffer_serial = render_targets_serial;
return &slot_framebuffers[framebuffer_id];
return &slot_framebuffers[GetFramebufferId(render_targets)];
}
template <class P>
@@ -2652,10 +2610,6 @@ void TextureCache<P>::RemoveFramebuffers(std::span<const ImageViewId> removed_vi
if (it->first.Contains(removed_views)) {
auto framebuffer_id = it->second;
ASSERT(framebuffer_id);
if (framebuffer_id == last_framebuffer_id) {
last_framebuffer_id = {};
last_framebuffer_serial = 0;
}
sentenced_framebuffers.Push(std::move(slot_framebuffers[framebuffer_id]));
it = framebuffers.erase(it);
} else {
@@ -455,16 +455,6 @@ private:
std::deque<TextureCacheGPUMap> gpu_page_table_storage;
RenderTargets render_targets;
u64 render_targets_serial = 0;
u32 rt_active_mask = 0;
std::array<ImageId, 8> rt_image_id{};
ImageId rt_depth_image_id{};
u64 texture_bindings_serial = 0;
u64 last_feedback_loop_serial = 0;
u64 last_feedback_texture_serial = 0;
bool last_feedback_loop_result = false;
FramebufferId last_framebuffer_id{};
u64 last_framebuffer_serial = 0;
ankerl::unordered_dense::map<RenderTargets, FramebufferId> framebuffers;
ankerl::unordered_dense::map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
+5 -1
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -63,7 +66,8 @@ void ConfigureApplets::Setup(const ConfigurationShared::Builder& builder) {
setting->Id() == Settings::values.shop_applet_mode.Id() ||
setting->Id() == Settings::values.login_share_applet_mode.Id() ||
setting->Id() == Settings::values.wifi_web_auth_applet_mode.Id() ||
setting->Id() == Settings::values.my_page_applet_mode.Id()) {
setting->Id() == Settings::values.my_page_applet_mode.Id() ||
setting->Id() == Settings::values.splay_applet_mode.Id()) {
widget->setHidden(true);
}
+6
View File
@@ -189,6 +189,7 @@
<addaction name="action_Launch_MiiEdit"/>
<addaction name="action_Launch_Controller"/>
<addaction name="action_Launch_PhotoViewer"/>
<addaction name="action_Launch_Splay"/>
</widget>
<widget class="QMenu" name="menuTAS">
<property name="title">
@@ -465,6 +466,11 @@
<string>&amp;Mii Editor</string>
</property>
</action>
<action name="action_Launch_Splay">
<property name="text">
<string>&amp;Splay</string>
</property>
</action>
<action name="action_Configure_Tas">
<property name="text">
<string>&amp;Configure TAS...</string>
+7 -2
View File
@@ -1700,6 +1700,9 @@ void MainWindow::ConnectMenuEvents() {
connect_menu(ui->action_Launch_QLaunch, [this]{
LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::QLaunch), std::nullopt);
});
connect_menu(ui->action_Launch_Splay, [this]{
LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::Splay), std::nullopt);
});
// Tools (cabinet)
connect_menu(ui->action_Launch_Cabinet_Nickname_Owner, [this]{
LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::Cabinet), {Service::NFP::CabinetMode::StartNicknameAndOwnerSettings});
@@ -1762,7 +1765,8 @@ void MainWindow::UpdateMenuState() {
ui->action_Launch_Cabinet_Formatter,
ui->action_Launch_MiiEdit,
ui->action_Launch_QLaunch,
ui->action_Launch_Controller
ui->action_Launch_Controller,
ui->action_Launch_Splay
};
for (QAction* action : running_actions) {
@@ -2142,7 +2146,7 @@ void MainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletPa
game_list->hide();
game_list_placeholder->hide();
}
status_bar_update_timer.start(500);
status_bar_update_timer.start(250);
renderer_status_button->setDisabled(true);
refresh_button->setDisabled(true);
@@ -4101,6 +4105,7 @@ void MainWindow::LaunchFirmwareApplet(u64 raw_program_id, std::optional<Service:
case AppletProgramId::LoginShare: return AppletId::LoginShare;
case AppletProgramId::WebAuth: return AppletId::WebAuth;
case AppletProgramId::MyPage: return AppletId::MyPage;
case AppletProgramId::Splay: return AppletId::Splay;
default: return AppletId::None;
}
}(); applet_id != Service::AM::AppletId::None) {