Compare commits

...

46 Commits

Author SHA1 Message Date
Morph 2df2b3719a renderers: Log total pipeline count 2021-09-14 13:18:26 -04:00
bunnei 081ccc6441 Merge pull request #7009 from ameerj/main_process_cleanup
core: Destroy main_process during shutdown
2021-09-13 23:32:43 -07:00
ameerj 67f7a6c398 core: Destroy main_process during shutdown
The main_process was never being cleaned up, causing a noticeable memory leak after subsequent launches. This change cleans up the memory during Core Shutdown, mitigating the leak.
2021-09-13 23:44:52 -04:00
Morph d86a9b9a4b Merge pull request #6943 from FernandoS27/omae-wa-mou-shindeiru
Vulkan: Disable VK_EXT_SAMPLER_FILTER_MINMAX in GCN AMD
2021-09-13 17:33:15 -04:00
Fernando Sahmkow 7a712da2b3 Vulkan: Disable VK_EXT_SAMPLER_FILTER_MINMAX in GCN AMD since it's broken. 2021-09-13 23:29:57 +02:00
Morph 62e88d0e74 Merge pull request #7006 from FernandoS27/a-motherfucking-driver
Vulkan: Blacklist Int8Float16 Extension on AMD on driver 21.9.1
2021-09-13 17:25:56 -04:00
Mai M edf3da346f Merge pull request #7005 from Morph1984/enum-bitwise-shift-ops
common_funcs: Add enum flag bitwise shift operator overloads
2021-09-13 17:21:22 -04:00
Morph fde9b84b21 Merge pull request #6944 from FernandoS27/dear-drunk-me
Vulkan/Descriptors: Increase sets per pool on AMD propietary driver.
2021-09-13 17:20:07 -04:00
Fernando Sahmkow e7c8a0bb23 Vulkan: Blacklist Int8Float16 Extension on AMD on driver 21.9.1 2021-09-13 23:17:37 +02:00
Fernando S 1bb28dfe2c Merge pull request #7001 from ameerj/wario-fix
vk_rasterizer: Fix dynamic StencilOp updating when two faces are enabled
2021-09-13 23:16:59 +02:00
Fernando Sahmkow e7ca37b1e5 Vulkan/Descriptors: Increase sets per pool on AMFD propietary driver. 2021-09-13 23:09:18 +02:00
Morph 3512cae623 common_funcs: Add enum flag bitwise shift operator overloads
This adds bitwise shift operator overloads (<<, >>, <<=, >>=) in the macro DECLARE_ENUM_FLAG_OPERATORS(type)
2021-09-13 16:01:20 -04:00
Ameer J d180fd7c36 Merge pull request #7000 from Morph1984/create-dir-comment
FS: Mark recursive CreateDirectory as inaccurate and temporary
2021-09-12 21:06:52 -04:00
Mai M e4318d2207 Merge pull request #7002 from ameerj/vk-state-unused
vk_state_tracker: Remove unused function
2021-09-12 17:31:56 -04:00
ameerj 8e289ade15 vk_state_tracker: Remove unused function 2021-09-12 15:28:24 -04:00
Morph 727f607e00 FS: Mark recursive CreateDirectory as inaccurate and temporary 2021-09-12 14:06:01 -04:00
Morph 9248442bb2 Merge pull request #6948 from ameerj/amd-warp-fix
shaders: Fix warp instructions on 64-thread warp devices
2021-09-12 13:53:29 -04:00
Morph 4ab549e62a Merge pull request #6975 from ogniK5377/acc-async-ctx
account: EnsureTokenIdCacheAsync
2021-09-12 12:03:10 -04:00
Morph f0f416e85c Merge pull request #6974 from ogniK5377/fs-recursive-createdir
FS: Recursively create directories for CreateDirectory
2021-09-12 12:02:39 -04:00
Morph 9907302465 Merge pull request #6997 from ameerj/stop-emulation-confirmation
main: Apply confirm exit setting in exit locked scenarios
2021-09-12 12:01:57 -04:00
Morph 3428232bca Merge pull request #6992 from german77/brains
hid/am: Stub SetTouchScreenConfiguration and implement GetNotificationStorageChannelEvent
2021-09-12 12:01:43 -04:00
Morph 74030eb427 Merge pull request #6987 from Morph1984/common-error
common: Move error handling functions out of common_funcs
2021-09-12 12:01:23 -04:00
Morph 47b6f522bd Merge pull request #6986 from Morph1984/version-update
api_version: Update and add AtmosphereTargetFirmware
2021-09-12 12:01:11 -04:00
ameerj 188cf1aed2 main: Apply confirm exit setting in exit locked scenarios
Some titles set an exit lock through HLE, which prompts an exit confirmation when stopping emulation if the system is locked.
This change allows bypassing this confirmation if the setting to confirm exits has been disabled by the user.
2021-09-12 00:31:32 -04:00
Morph e67463df24 shader_environment: Add missing <algorithm> include 2021-09-11 17:19:16 -04:00
Morph 63b4c8f9f7 vk_descriptor_pool: Add missing <algorithm> include 2021-09-11 17:19:16 -04:00
Morph 76abf55f25 slot_vector: Add missing <algorithm> include 2021-09-11 17:19:15 -04:00
Morph 554c46d186 video_core/memory_manager: Add missing <algorithm> include 2021-09-11 17:19:15 -04:00
Morph 6f307f1521 kernel: Add missing <functional> include 2021-09-11 17:19:15 -04:00
Morph 4a6a73e887 file_sys/kernel_executable: Add missing <string> include 2021-09-11 17:19:14 -04:00
Morph ae028ddf22 codec: Add missing <string_view> include 2021-09-11 17:19:14 -04:00
Morph eb1e3f19bb common_funcs: Replace <algorithm> with <iterator> 2021-09-11 17:19:14 -04:00
Morph 290afc00d3 common: Move error handling to error.cpp/h
This allows us to avoid implicitly including <string> every time common_funcs.h is included.
2021-09-11 17:19:14 -04:00
german77 9bddcdac69 am: Implement GetNotificationStorageChannelEvent 2021-09-10 12:24:50 -05:00
german77 a7bbd37f81 hid: Stub SetTouchScreenConfiguration 2021-09-10 12:24:28 -05:00
Morph c9710f6c78 api_version: Update and add AtmosphereTargetFirmware 2021-09-10 01:10:47 -04:00
Chloe 005b0e68db Addressed issues
Co-authored-by: Mai M. <mathew1800@gmail.com>
2021-09-09 03:00:08 +10:00
Chloe Marcec 543081e4a1 Mark is_complete as atomic 2021-09-09 00:10:52 +10:00
Chloe Marcec 89958e27aa Addressed issues 2021-09-09 00:09:04 +10:00
Chloe Marcec 9141816b10 address name shadowing with system 2021-09-06 22:13:51 +10:00
Chloe Marcec 4e2aa50cef account: EnsureTokenIdCacheAsync
Closes #2547, #6946
2021-09-06 21:16:21 +10:00
Chloe Marcec 0b891c9245 FS: Recursively create directories for CreateDirectory
Originally we only created the parent directory, this caused issues for creating directories which also contained subdirectories, eg `/Folder1/Folder2`

This allows the ultimate mod manager homebrew to at least boot
2021-09-06 19:35:55 +10:00
ameerj d956fb3c7c emit_glsl_warp: Fix shuffle ops for 64-thread warp sizes 2021-08-31 16:11:25 -04:00
ameerj 5b45dfe971 emit_glsl_warp: Fix ballot related ops for 64-thread warp sizes 2021-08-31 16:11:25 -04:00
ameerj a5d9dcf3d9 emit_spirv_warp: Fix shuffle ops for 64-thread warp sizes 2021-08-31 13:40:39 -04:00
ameerj 95213270ef emit_spirv_warp: Fix ballot related ops for 64-thread warp sizes 2021-08-31 13:40:12 -04:00
33 changed files with 462 additions and 130 deletions
+2 -1
View File
@@ -53,6 +53,8 @@ add_library(common STATIC
div_ceil.h
dynamic_library.cpp
dynamic_library.h
error.cpp
error.h
fiber.cpp
fiber.h
fs/file.cpp
@@ -88,7 +90,6 @@ add_library(common STATIC
microprofile.cpp
microprofile.h
microprofileui.h
misc.cpp
nvidia_flags.cpp
nvidia_flags.h
page_table.cpp
+17 -12
View File
@@ -4,9 +4,8 @@
#pragma once
#include <algorithm>
#include <array>
#include <string>
#include <iterator>
#if !defined(ARCHITECTURE_x86_64)
#include <cstdlib> // for exit
@@ -49,16 +48,6 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
#endif // _MSC_VER ndef
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.
// Defined in misc.cpp.
[[nodiscard]] std::string GetLastErrorMsg();
// Like GetLastErrorMsg(), but passing an explicit error code.
// Defined in misc.cpp.
[[nodiscard]] std::string NativeErrorToString(int e);
#define DECLARE_ENUM_FLAG_OPERATORS(type) \
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
@@ -72,6 +61,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) ^ static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator<<(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) << static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator>>(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) >> static_cast<T>(b)); \
} \
constexpr type& operator|=(type& a, type b) noexcept { \
a = a | b; \
return a; \
@@ -84,6 +81,14 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
a = a ^ b; \
return a; \
} \
constexpr type& operator<<=(type& a, type b) noexcept { \
a = a << b; \
return a; \
} \
constexpr type& operator>>=(type& a, type b) noexcept { \
a = a >> b; \
return a; \
} \
[[nodiscard]] constexpr type operator~(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(~static_cast<T>(key)); \
+5 -1
View File
@@ -10,7 +10,9 @@
#include <cstring>
#endif
#include "common/common_funcs.h"
#include "common/error.h"
namespace Common {
std::string NativeErrorToString(int e) {
#ifdef _WIN32
@@ -50,3 +52,5 @@ std::string GetLastErrorMsg() {
return NativeErrorToString(errno);
#endif
}
} // namespace Common
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
namespace Common {
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.
// Defined in error.cpp.
[[nodiscard]] std::string GetLastErrorMsg();
// Like GetLastErrorMsg(), but passing an explicit error code.
// Defined in error.cpp.
[[nodiscard]] std::string NativeErrorToString(int e);
} // namespace Common
+3 -3
View File
@@ -2,7 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/common_funcs.h"
#include <string>
#include "common/error.h"
#include "common/logging/log.h"
#include "common/thread.h"
#ifdef __APPLE__
@@ -21,8 +23,6 @@
#include <unistd.h>
#endif
#include <string>
#ifdef __FreeBSD__
#define cpu_set_t cpuset_t
#endif
+2
View File
@@ -263,6 +263,8 @@ add_library(core STATIC
hle/service/acc/acc_u0.h
hle/service/acc/acc_u1.cpp
hle/service/acc/acc_u1.h
hle/service/acc/async_context.cpp
hle/service/acc/async_context.h
hle/service/acc/errors.h
hle/service/acc/profile_manager.cpp
hle/service/acc/profile_manager.h
+12 -3
View File
@@ -83,6 +83,12 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
}
}
void KProcessDeleter(Kernel::KProcess* process) {
process->Destroy();
}
using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>;
} // Anonymous namespace
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
@@ -233,8 +239,8 @@ struct System::Impl {
}
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
auto main_process = Kernel::KProcess::Create(system.Kernel());
ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter};
ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main",
Kernel::KProcess::ProcessType::Userland)
.IsSuccess());
main_process->Open();
@@ -247,7 +253,7 @@ struct System::Impl {
static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.MakeCurrentProcess(main_process);
kernel.MakeCurrentProcess(main_process.get());
kernel.InitializeCores();
// Initialize cheat engine
@@ -316,6 +322,8 @@ struct System::Impl {
kernel.Shutdown();
memory.Reset();
applet_manager.ClearAll();
// TODO: The main process should be freed based on KAutoObject ref counting.
main_process.reset();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -374,6 +382,7 @@ struct System::Impl {
std::unique_ptr<Tegra::GPU> gpu_core;
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
std::unique_ptr<Core::DeviceMemory> device_memory;
KProcessPtr main_process{nullptr, KProcessDeleter};
Core::Memory::Memory memory;
CpuManager cpu_manager;
std::atomic_bool is_powered_on{};
+1
View File
@@ -5,6 +5,7 @@
#pragma once
#include <array>
#include <string>
#include <vector>
#include "common/common_funcs.h"
+12 -5
View File
@@ -28,13 +28,20 @@ constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0";
// Atmosphere version constants.
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 5;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 1;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 0;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 0;
constexpr u32 AtmosphereTargetFirmwareWithRevision(u8 major, u8 minor, u8 micro, u8 rev) {
return u32{major} << 24 | u32{minor} << 16 | u32{micro} << 8 | u32{rev};
}
constexpr u32 AtmosphereTargetFirmware(u8 major, u8 minor, u8 micro) {
return AtmosphereTargetFirmwareWithRevision(major, minor, micro, 0);
}
constexpr u32 GetTargetFirmware() {
return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
u32{HOS_VERSION_MICRO} << 8 | 0U;
return AtmosphereTargetFirmware(HOS_VERSION_MAJOR, HOS_VERSION_MINOR, HOS_VERSION_MICRO);
}
} // namespace HLE::ApiVersion
+1
View File
@@ -5,6 +5,7 @@
#pragma once
#include <array>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
+47 -19
View File
@@ -23,6 +23,7 @@
#include "core/hle/service/acc/acc_su.h"
#include "core/hle/service/acc/acc_u0.h"
#include "core/hle/service/acc/acc_u1.h"
#include "core/hle/service/acc/async_context.h"
#include "core/hle/service/acc/errors.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/glue/arp.h"
@@ -454,22 +455,6 @@ public:
: IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {}
};
class IAsyncContext final : public ServiceFramework<IAsyncContext> {
public:
explicit IAsyncContext(Core::System& system_) : ServiceFramework{system_, "IAsyncContext"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetSystemEvent"},
{1, nullptr, "Cancel"},
{2, nullptr, "HasDone"},
{3, nullptr, "GetResult"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class ISessionObject final : public ServiceFramework<ISessionObject> {
public:
explicit ISessionObject(Core::System& system_, Common::UUID)
@@ -504,16 +489,44 @@ public:
}
};
class EnsureTokenIdCacheAsyncInterface final : public IAsyncContext {
public:
explicit EnsureTokenIdCacheAsyncInterface(Core::System& system_) : IAsyncContext{system_} {
MarkComplete();
}
~EnsureTokenIdCacheAsyncInterface() = default;
void LoadIdTokenCache(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
protected:
bool IsComplete() const override {
return true;
}
void Cancel() override {}
ResultCode GetResult() const override {
return ResultSuccess;
}
};
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public:
explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_)
: ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} {
: ServiceFramework{system_, "IManagerForApplication"},
ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
user_id{user_id_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
{2, nullptr, "EnsureIdTokenCacheAsync"},
{3, nullptr, "LoadIdTokenCache"},
{2, &IManagerForApplication::EnsureIdTokenCacheAsync, "EnsureIdTokenCacheAsync"},
{3, &IManagerForApplication::LoadIdTokenCache, "LoadIdTokenCache"},
{130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"},
@@ -540,6 +553,20 @@ private:
rb.PushRaw<u64>(user_id.GetNintendoID());
}
void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface(ensure_token_id);
}
void LoadIdTokenCache(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
ensure_token_id->LoadIdTokenCache(ctx);
}
void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
@@ -562,6 +589,7 @@ private:
rb.Push(ResultSuccess);
}
std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
Common::UUID user_id{Common::INVALID_UUID};
};
@@ -0,0 +1,68 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/acc/async_context.h"
namespace Service::Account {
IAsyncContext::IAsyncContext(Core::System& system_)
: ServiceFramework{system_, "IAsyncContext"}, compeletion_event{system_.Kernel()} {
Kernel::KAutoObject::Create(std::addressof(compeletion_event));
compeletion_event.Initialize("IAsyncContext:CompletionEvent");
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"},
{1, &IAsyncContext::Cancel, "Cancel"},
{2, &IAsyncContext::HasDone, "HasDone"},
{3, &IAsyncContext::GetResult, "GetResult"},
};
// clang-format on
RegisterHandlers(functions);
}
void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(compeletion_event.GetReadableEvent());
}
void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
Cancel();
MarkComplete();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
is_complete.store(IsComplete());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(is_complete.load());
}
void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(GetResult());
}
void IAsyncContext::MarkComplete() {
is_complete.store(true);
compeletion_event.GetWritableEvent().Signal();
}
} // namespace Service::Account
+37
View File
@@ -0,0 +1,37 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <atomic>
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Account {
class IAsyncContext : public ServiceFramework<IAsyncContext> {
public:
explicit IAsyncContext(Core::System& system_);
void GetSystemEvent(Kernel::HLERequestContext& ctx);
void Cancel(Kernel::HLERequestContext& ctx);
void HasDone(Kernel::HLERequestContext& ctx);
void GetResult(Kernel::HLERequestContext& ctx);
protected:
virtual bool IsComplete() const = 0;
virtual void Cancel() = 0;
virtual ResultCode GetResult() const = 0;
void MarkComplete();
std::atomic<bool> is_complete{false};
Kernel::KEvent compeletion_event;
};
} // namespace Service::Account
+14 -2
View File
@@ -1270,7 +1270,8 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx)
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
: ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()},
friend_invitation_storage_channel_event{system.Kernel()},
health_warning_disappeared_system_event{system.Kernel()} {
notification_storage_channel_event{system.Kernel()}, health_warning_disappeared_system_event{
system.Kernel()} {
// clang-format off
static const FunctionInfo functions[] = {
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
@@ -1322,7 +1323,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
{150, nullptr, "GetNotificationStorageChannelEvent"},
{150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
{151, nullptr, "TryPopFromNotificationStorageChannel"},
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
{170, nullptr, "SetHdcpAuthenticationActivated"},
@@ -1340,11 +1341,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event));
Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event));
Kernel::KAutoObject::Create(std::addressof(notification_storage_channel_event));
Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event));
gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent");
friend_invitation_storage_channel_event.Initialize(
"IApplicationFunctions:FriendInvitationStorageChannelEvent");
notification_storage_channel_event.Initialize(
"IApplicationFunctions:NotificationStorageChannelEvent");
health_warning_disappeared_system_event.Initialize(
"IApplicationFunctions:HealthWarningDisappearedSystemEvent");
}
@@ -1762,6 +1766,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
rb.Push(ERR_NO_DATA_IN_CHANNEL);
}
void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(notification_storage_channel_event.GetReadableEvent());
}
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
+2
View File
@@ -295,6 +295,7 @@ private:
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx);
void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx);
void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx);
bool launch_popped_application_specific = false;
@@ -302,6 +303,7 @@ private:
s32 previous_program_index{-1};
Kernel::KEvent gpu_error_detected_event;
Kernel::KEvent friend_invitation_storage_channel_event;
Kernel::KEvent notification_storage_channel_event;
Kernel::KEvent health_warning_disappeared_system_event;
};
+18 -8
View File
@@ -97,14 +97,24 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
std::string path(Common::FS::SanitizePath(path_));
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) {
dir = backing;
}
auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path));
if (new_dir == nullptr) {
// TODO(DarkLordZach): Find a better error code for this
return ResultUnknown;
// NOTE: This is inaccurate behavior. CreateDirectory is not recursive.
// CreateDirectory should return PathNotFound if the parent directory does not exist.
// This is here temporarily in order to have UMM "work" in the meantime.
// TODO (Morph): Remove this when a hardware test verifies the correct behavior.
const auto components = Common::FS::SplitPathComponents(path);
std::string relative_path;
for (const auto& component : components) {
// Skip empty path components
if (component.empty()) {
continue;
}
relative_path = Common::FS::SanitizePath(relative_path + '/' + component);
auto new_dir = backing->CreateSubdirectory(relative_path);
if (new_dir == nullptr) {
// TODO(DarkLordZach): Find a better error code for this
return ResultUnknown;
}
}
return ResultSuccess;
}
@@ -15,6 +15,20 @@
namespace Service::HID {
class Controller_Touchscreen final : public ControllerBase {
public:
enum class TouchScreenModeForNx : u8 {
UseSystemSetting,
Finger,
Heat2,
};
struct TouchScreenConfigurationForNx {
TouchScreenModeForNx mode;
INSERT_PADDING_BYTES_NOINIT(0x7);
INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved
};
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
"TouchScreenConfigurationForNx is an invalid size");
explicit Controller_Touchscreen(Core::System& system_);
~Controller_Touchscreen() override;
+13 -1
View File
@@ -331,7 +331,7 @@ Hid::Hid(Core::System& system_)
{529, nullptr, "SetDisallowedPalmaConnection"},
{1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"},
{1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
{1002, nullptr, "SetTouchScreenConfiguration"},
{1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
{1003, nullptr, "IsFirmwareUpdateNeededForNotification"},
{2000, nullptr, "ActivateDigitizer"},
};
@@ -1631,6 +1631,18 @@ void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
.GetNpadCommunicationMode());
}
void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
touchscreen_mode.mode, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
class HidDbg final : public ServiceFramework<HidDbg> {
public:
explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} {
+1
View File
@@ -159,6 +159,7 @@ private:
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx);
enum class VibrationDeviceType : u32 {
Unknown = 0,
+3 -2
View File
@@ -7,7 +7,8 @@
#include <limits>
#include <utility>
#include <vector>
#include "common/common_funcs.h"
#include "common/error.h"
#ifdef _WIN32
#include <winsock2.h>
@@ -223,7 +224,7 @@ Errno GetAndLogLastError() {
if (err == Errno::AGAIN) {
return err;
}
LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e));
LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e));
return err;
}
@@ -11,6 +11,8 @@
namespace Shader::Backend::GLSL {
namespace {
constexpr char THREAD_ID[]{"gl_SubGroupInvocationARB"};
void SetInBoundsFlag(EmitContext& ctx, IR::Inst& inst) {
IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)};
if (!in_bounds) {
@@ -43,84 +45,100 @@ void UseShuffleNv(EmitContext& ctx, IR::Inst& inst, std::string_view shfl_op,
ctx.AddU32("{}={}({},{},{},shfl_in_bounds);", inst, shfl_op, value, index, width);
SetInBoundsFlag(ctx, inst);
}
std::string_view BallotIndex(EmitContext& ctx) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return ".x";
}
return "[gl_SubGroupInvocationARB>>5]";
}
std::string GetMask(EmitContext& ctx, std::string_view mask) {
const auto ballot_index{BallotIndex(ctx)};
return fmt::format("uint(uvec2({}){})", mask, ballot_index);
}
} // Anonymous namespace
void EmitLaneId(EmitContext& ctx, IR::Inst& inst) {
ctx.AddU32("{}=gl_SubGroupInvocationARB&31u;", inst);
ctx.AddU32("{}={}&31u;", inst, THREAD_ID);
}
void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, std::string_view pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
ctx.AddU1("{}=allInvocationsEqualARB({});", inst, pred);
} else {
const auto active_mask{fmt::format("uvec2(ballotARB(true))[gl_SubGroupInvocationARB]")};
const auto ballot{fmt::format("uvec2(ballotARB({}))[gl_SubGroupInvocationARB]", pred)};
ctx.AddU1("{}=({}&{})=={};", inst, ballot, active_mask, active_mask);
return;
}
const auto ballot_index{BallotIndex(ctx)};
const auto active_mask{fmt::format("uvec2(ballotARB(true)){}", ballot_index)};
const auto ballot{fmt::format("uvec2(ballotARB({})){}", pred, ballot_index)};
ctx.AddU1("{}=({}&{})=={};", inst, ballot, active_mask, active_mask);
}
void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, std::string_view pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
ctx.AddU1("{}=anyInvocationARB({});", inst, pred);
} else {
const auto active_mask{fmt::format("uvec2(ballotARB(true))[gl_SubGroupInvocationARB]")};
const auto ballot{fmt::format("uvec2(ballotARB({}))[gl_SubGroupInvocationARB]", pred)};
ctx.AddU1("{}=({}&{})!=0u;", inst, ballot, active_mask, active_mask);
return;
}
const auto ballot_index{BallotIndex(ctx)};
const auto active_mask{fmt::format("uvec2(ballotARB(true)){}", ballot_index)};
const auto ballot{fmt::format("uvec2(ballotARB({})){}", pred, ballot_index)};
ctx.AddU1("{}=({}&{})!=0u;", inst, ballot, active_mask, active_mask);
}
void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, std::string_view pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
ctx.AddU1("{}=allInvocationsEqualARB({});", inst, pred);
} else {
const auto active_mask{fmt::format("uvec2(ballotARB(true))[gl_SubGroupInvocationARB]")};
const auto ballot{fmt::format("uvec2(ballotARB({}))[gl_SubGroupInvocationARB]", pred)};
const auto value{fmt::format("({}^{})", ballot, active_mask)};
ctx.AddU1("{}=({}==0)||({}=={});", inst, value, value, active_mask);
return;
}
const auto ballot_index{BallotIndex(ctx)};
const auto active_mask{fmt::format("uvec2(ballotARB(true)){}", ballot_index)};
const auto ballot{fmt::format("uvec2(ballotARB({})){}", pred, ballot_index)};
const auto value{fmt::format("({}^{})", ballot, active_mask)};
ctx.AddU1("{}=({}==0)||({}=={});", inst, value, value, active_mask);
}
void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, std::string_view pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
ctx.AddU32("{}=uvec2(ballotARB({})).x;", inst, pred);
} else {
ctx.AddU32("{}=uvec2(ballotARB({}))[gl_SubGroupInvocationARB];", inst, pred);
}
const auto ballot_index{BallotIndex(ctx)};
ctx.AddU32("{}=uvec2(ballotARB({})){};", inst, pred, ballot_index);
}
void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) {
ctx.AddU32("{}=uint(gl_SubGroupEqMaskARB.x);", inst);
ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupEqMaskARB"));
}
void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) {
ctx.AddU32("{}=uint(gl_SubGroupLtMaskARB.x);", inst);
ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupLtMaskARB"));
}
void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) {
ctx.AddU32("{}=uint(gl_SubGroupLeMaskARB.x);", inst);
ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupLeMaskARB"));
}
void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) {
ctx.AddU32("{}=uint(gl_SubGroupGtMaskARB.x);", inst);
ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupGtMaskARB"));
}
void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) {
ctx.AddU32("{}=uint(gl_SubGroupGeMaskARB.x);", inst);
ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupGeMaskARB"));
}
void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value,
std::string_view index, std::string_view clamp,
std::string_view segmentation_mask) {
std::string_view index, std::string_view clamp, std::string_view seg_mask) {
if (ctx.profile.support_gl_warp_intrinsics) {
UseShuffleNv(ctx, inst, "shuffleNV", value, index, clamp, segmentation_mask);
UseShuffleNv(ctx, inst, "shuffleNV", value, index, clamp, seg_mask);
return;
}
const auto not_seg_mask{fmt::format("(~{})", segmentation_mask)};
const auto thread_id{"gl_SubGroupInvocationARB"};
const auto min_thread_id{ComputeMinThreadId(thread_id, segmentation_mask)};
const auto max_thread_id{ComputeMaxThreadId(min_thread_id, clamp, not_seg_mask)};
const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest};
const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"};
const auto upper_index{fmt::format("{}?{}+32:{}", is_upper_partition, index, index)};
const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)};
const auto lhs{fmt::format("({}&{})", index, not_seg_mask)};
const auto not_seg_mask{fmt::format("(~{})", seg_mask)};
const auto min_thread_id{ComputeMinThreadId(THREAD_ID, seg_mask)};
const auto max_thread_id{
ComputeMaxThreadId(min_thread_id, big_warp ? upper_clamp : clamp, not_seg_mask)};
const auto lhs{fmt::format("({}&{})", big_warp ? upper_index : index, not_seg_mask)};
const auto src_thread_id{fmt::format("({})|({})", lhs, min_thread_id)};
ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
@@ -128,29 +146,34 @@ void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value,
}
void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index,
std::string_view clamp, std::string_view segmentation_mask) {
std::string_view clamp, std::string_view seg_mask) {
if (ctx.profile.support_gl_warp_intrinsics) {
UseShuffleNv(ctx, inst, "shuffleUpNV", value, index, clamp, segmentation_mask);
UseShuffleNv(ctx, inst, "shuffleUpNV", value, index, clamp, seg_mask);
return;
}
const auto thread_id{"gl_SubGroupInvocationARB"};
const auto max_thread_id{GetMaxThreadId(thread_id, clamp, segmentation_mask)};
const auto src_thread_id{fmt::format("({}-{})", thread_id, index)};
const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest};
const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"};
const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)};
const auto max_thread_id{GetMaxThreadId(THREAD_ID, big_warp ? upper_clamp : clamp, seg_mask)};
const auto src_thread_id{fmt::format("({}-{})", THREAD_ID, index)};
ctx.Add("shfl_in_bounds=int({})>=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
}
void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value,
std::string_view index, std::string_view clamp,
std::string_view segmentation_mask) {
std::string_view index, std::string_view clamp, std::string_view seg_mask) {
if (ctx.profile.support_gl_warp_intrinsics) {
UseShuffleNv(ctx, inst, "shuffleDownNV", value, index, clamp, segmentation_mask);
UseShuffleNv(ctx, inst, "shuffleDownNV", value, index, clamp, seg_mask);
return;
}
const auto thread_id{"gl_SubGroupInvocationARB"};
const auto max_thread_id{GetMaxThreadId(thread_id, clamp, segmentation_mask)};
const auto src_thread_id{fmt::format("({}+{})", thread_id, index)};
const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest};
const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"};
const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)};
const auto max_thread_id{GetMaxThreadId(THREAD_ID, big_warp ? upper_clamp : clamp, seg_mask)};
const auto src_thread_id{fmt::format("({}+{})", THREAD_ID, index)};
ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
@@ -158,14 +181,17 @@ void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value,
void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value,
std::string_view index, std::string_view clamp,
std::string_view segmentation_mask) {
std::string_view seg_mask) {
if (ctx.profile.support_gl_warp_intrinsics) {
UseShuffleNv(ctx, inst, "shuffleXorNV", value, index, clamp, segmentation_mask);
UseShuffleNv(ctx, inst, "shuffleXorNV", value, index, clamp, seg_mask);
return;
}
const auto thread_id{"gl_SubGroupInvocationARB"};
const auto max_thread_id{GetMaxThreadId(thread_id, clamp, segmentation_mask)};
const auto src_thread_id{fmt::format("({}^{})", thread_id, index)};
const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest};
const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"};
const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)};
const auto max_thread_id{GetMaxThreadId(THREAD_ID, big_warp ? upper_clamp : clamp, seg_mask)};
const auto src_thread_id{fmt::format("({}^{})", THREAD_ID, index)};
ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
@@ -7,8 +7,13 @@
namespace Shader::Backend::SPIRV {
namespace {
Id GetThreadId(EmitContext& ctx) {
return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id);
}
Id WarpExtract(EmitContext& ctx, Id value) {
const Id local_index{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
const Id thread_id{GetThreadId(ctx)};
const Id local_index{ctx.OpShiftRightArithmetic(ctx.U32[1], thread_id, ctx.Const(5U))};
return ctx.OpVectorExtractDynamic(ctx.U32[1], value, local_index);
}
@@ -48,10 +53,17 @@ Id SelectValue(EmitContext& ctx, Id in_range, Id value, Id src_thread_id) {
return ctx.OpSelect(ctx.U32[1], in_range,
ctx.OpSubgroupReadInvocationKHR(ctx.U32[1], value, src_thread_id), value);
}
Id GetUpperClamp(EmitContext& ctx, Id invocation_id, Id clamp) {
const Id thirty_two{ctx.Const(32u)};
const Id is_upper_partition{ctx.OpSGreaterThanEqual(ctx.U1, invocation_id, thirty_two)};
const Id upper_clamp{ctx.OpIAdd(ctx.U32[1], thirty_two, clamp)};
return ctx.OpSelect(ctx.U32[1], is_upper_partition, upper_clamp, clamp);
}
} // Anonymous namespace
Id EmitLaneId(EmitContext& ctx) {
const Id id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
const Id id{GetThreadId(ctx)};
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return id;
}
@@ -123,7 +135,15 @@ Id EmitSubgroupGeMask(EmitContext& ctx) {
Id EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp,
Id segmentation_mask) {
const Id not_seg_mask{ctx.OpNot(ctx.U32[1], segmentation_mask)};
const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
const Id thread_id{GetThreadId(ctx)};
if (ctx.profile.warp_size_potentially_larger_than_guest) {
const Id thirty_two{ctx.Const(32u)};
const Id is_upper_partition{ctx.OpSGreaterThanEqual(ctx.U1, thread_id, thirty_two)};
const Id upper_index{ctx.OpIAdd(ctx.U32[1], thirty_two, index)};
const Id upper_clamp{ctx.OpIAdd(ctx.U32[1], thirty_two, clamp)};
index = ctx.OpSelect(ctx.U32[1], is_upper_partition, upper_index, index);
clamp = ctx.OpSelect(ctx.U32[1], is_upper_partition, upper_clamp, clamp);
}
const Id min_thread_id{ComputeMinThreadId(ctx, thread_id, segmentation_mask)};
const Id max_thread_id{ComputeMaxThreadId(ctx, min_thread_id, clamp, not_seg_mask)};
@@ -137,7 +157,10 @@ Id EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id cla
Id EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp,
Id segmentation_mask) {
const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
const Id thread_id{GetThreadId(ctx)};
if (ctx.profile.warp_size_potentially_larger_than_guest) {
clamp = GetUpperClamp(ctx, thread_id, clamp);
}
const Id max_thread_id{GetMaxThreadId(ctx, thread_id, clamp, segmentation_mask)};
const Id src_thread_id{ctx.OpISub(ctx.U32[1], thread_id, index)};
const Id in_range{ctx.OpSGreaterThanEqual(ctx.U1, src_thread_id, max_thread_id)};
@@ -148,7 +171,10 @@ Id EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp,
Id EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp,
Id segmentation_mask) {
const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
const Id thread_id{GetThreadId(ctx)};
if (ctx.profile.warp_size_potentially_larger_than_guest) {
clamp = GetUpperClamp(ctx, thread_id, clamp);
}
const Id max_thread_id{GetMaxThreadId(ctx, thread_id, clamp, segmentation_mask)};
const Id src_thread_id{ctx.OpIAdd(ctx.U32[1], thread_id, index)};
const Id in_range{ctx.OpSLessThanEqual(ctx.U1, src_thread_id, max_thread_id)};
@@ -159,7 +185,10 @@ Id EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clam
Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp,
Id segmentation_mask) {
const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
const Id thread_id{GetThreadId(ctx)};
if (ctx.profile.warp_size_potentially_larger_than_guest) {
clamp = GetUpperClamp(ctx, thread_id, clamp);
}
const Id max_thread_id{GetMaxThreadId(ctx, thread_id, clamp, segmentation_mask)};
const Id src_thread_id{ctx.OpBitwiseXor(ctx.U32[1], thread_id, index)};
const Id in_range{ctx.OpSLessThanEqual(ctx.U1, src_thread_id, max_thread_id)};
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include <string_view>
#include <queue>
#include "common/common_types.h"
#include "video_core/command_classes/nvdec_common.h"
+2
View File
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/alignment.h"
#include "common/assert.h"
#include "common/logging/log.h"
@@ -293,6 +293,8 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
}};
LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics);
LOG_INFO(Render_OpenGL, "Total Pipeline Count: {}", state.total);
std::unique_lock lock{state.mutex};
callback(VideoCore::LoadCallbackStage::Build, 0, state.total);
state.has_loaded = true;
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <mutex>
#include <span>
#include <vector>
@@ -18,7 +19,6 @@ namespace Vulkan {
// Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines
constexpr size_t SETS_GROW_RATE = 16;
constexpr s32 SCORE_THRESHOLD = 3;
constexpr u32 SETS_PER_POOL = 64;
struct DescriptorBank {
DescriptorBankInfo info;
@@ -58,11 +58,12 @@ static DescriptorBankInfo MakeBankInfo(std::span<const Shader::Info> infos) {
static void AllocatePool(const Device& device, DescriptorBank& bank) {
std::array<VkDescriptorPoolSize, 6> pool_sizes;
size_t pool_cursor{};
const u32 sets_per_pool = device.GetSetsPerPool();
const auto add = [&](VkDescriptorType type, u32 count) {
if (count > 0) {
pool_sizes[pool_cursor++] = {
.type = type,
.descriptorCount = count * SETS_PER_POOL,
.descriptorCount = count * sets_per_pool,
};
}
};
@@ -77,7 +78,7 @@ static void AllocatePool(const Device& device, DescriptorBank& bank) {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.pNext = nullptr,
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
.maxSets = SETS_PER_POOL,
.maxSets = sets_per_pool,
.poolSizeCount = static_cast<u32>(pool_cursor),
.pPoolSizes = std::data(pool_sizes),
}));
@@ -447,6 +447,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
VideoCommon::LoadPipelines(stop_loading, pipeline_cache_filename, CACHE_VERSION, load_compute,
load_graphics);
LOG_INFO(Render_Vulkan, "Total Pipeline Count: {}", state.total);
std::unique_lock lock{state.mutex};
callback(VideoCore::LoadCallbackStage::Build, 0, state.total);
state.has_loaded = true;
@@ -110,10 +110,6 @@ public:
return Exchange(Dirty::DepthTestEnable, false);
}
bool TouchDepthBoundsEnable() {
return Exchange(Dirty::DepthBoundsEnable, false);
}
bool TouchDepthWriteEnable() {
return Exchange(Dirty::DepthWriteEnable, false);
}
+1
View File
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <memory>
@@ -4,6 +4,7 @@
#pragma once
#include <algorithm>
#include <array>
#include <bit>
#include <concepts>
+33 -1
View File
@@ -243,6 +243,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
SetupFamilies(surface);
SetupFeatures();
SetupProperties();
CollectTelemetryParameters();
const auto queue_cis = GetDeviceQueueCreateInfos();
const std::vector extensions = LoadExtensions(surface != nullptr);
@@ -368,6 +369,18 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
};
SetNext(next, demote);
if (driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE) {
const u32 version = properties.driverVersion;
// Broken in this driver
if (version > VK_MAKE_API_VERSION(0, 2, 0, 193)) {
LOG_WARNING(Render_Vulkan, "AMD proprietary driver versions newer than 21.9.1 "
"(windows) / 0.2.0.194 (amdvlk) have "
"broken VkPhysicalDeviceFloat16Int8FeaturesKHR");
is_int8_supported = false;
is_float16_supported = false;
}
}
if (is_int8_supported || is_float16_supported) {
VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR,
@@ -560,7 +573,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
logical = vk::Device::Create(physical, queue_cis, extensions, first_next, dld);
CollectPhysicalMemoryInfo();
CollectTelemetryParameters();
CollectToolingInfo();
if (driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR) {
@@ -587,6 +599,26 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
ext_extended_dynamic_state = false;
}
}
sets_per_pool = 64;
if (driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE) {
// AMD drivers need a higher amount of Sets per Pool in certain circunstances like in XC2.
sets_per_pool = 96;
}
const bool is_amd = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY ||
driver_id == VK_DRIVER_ID_MESA_RADV ||
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
if (ext_sampler_filter_minmax && is_amd) {
// Disable ext_sampler_filter_minmax on AMD GCN4 and lower as it is broken.
if (!is_float16_supported) {
LOG_WARNING(
Render_Vulkan,
"Blacklisting AMD GCN4 and lower for VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME");
ext_sampler_filter_minmax = false;
}
}
if (ext_vertex_input_dynamic_state && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {
LOG_WARNING(Render_Vulkan, "Blacklisting Intel for VK_EXT_vertex_input_dynamic_state");
ext_vertex_input_dynamic_state = false;
@@ -323,6 +323,10 @@ public:
return device_access_memory;
}
u32 GetSetsPerPool() const {
return sets_per_pool;
}
private:
/// Checks if the physical device is suitable.
void CheckSuitability(bool requires_swapchain) const;
@@ -376,6 +380,7 @@ private:
VkShaderStageFlags guest_warp_stages{}; ///< Stages where the guest warp size can be forced.
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
u32 max_push_descriptors{}; ///< Maximum number of push descriptors
u32 sets_per_pool{}; ///< Sets per Description Pool
bool is_optimal_astc_supported{}; ///< Support for native ASTC.
bool is_float16_supported{}; ///< Support for float16 arithmetic.
bool is_int8_supported{}; ///< Support for int8 arithmetic.
+9 -11
View File
@@ -3174,12 +3174,11 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv
}
bool GMainWindow::ConfirmClose() {
if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) {
return true;
QMessageBox::StandardButton answer =
QMessageBox::question(this, tr("yuzu"), tr("Are you sure you want to close yuzu?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
}
const auto text = tr("Are you sure you want to close yuzu?");
const auto answer = QMessageBox::question(this, tr("yuzu"), text);
return answer != QMessageBox::No;
}
@@ -3261,14 +3260,13 @@ bool GMainWindow::ConfirmChangeGame() {
}
bool GMainWindow::ConfirmForceLockedExit() {
if (emu_thread == nullptr)
if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) {
return true;
}
const auto text = tr("The currently running application has requested yuzu to not exit.\n\n"
"Would you like to bypass this and exit anyway?");
const auto answer =
QMessageBox::question(this, tr("yuzu"),
tr("The currently running application has requested yuzu to not "
"exit.\n\nWould you like to bypass this and exit anyway?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
const auto answer = QMessageBox::question(this, tr("yuzu"), text);
return answer != QMessageBox::No;
}