diff options
Diffstat (limited to 'src/core')
30 files changed, 197 insertions, 145 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 6dda20faa..eba2177d1 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -36,7 +36,8 @@ #include "frontend/applets/software_keyboard.h" #include "frontend/applets/web_browser.h" #include "video_core/debug_utils/debug_utils.h" -#include "video_core/gpu.h" +#include "video_core/gpu_asynch.h" +#include "video_core/gpu_synch.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" @@ -129,10 +130,16 @@ struct System::Impl { return ResultStatus::ErrorVideoCore; } - gpu_core = std::make_unique<Tegra::GPU>(system, renderer->Rasterizer()); + is_powered_on = true; + + if (Settings::values.use_asynchronous_gpu_emulation) { + gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer); + } else { + gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer); + } cpu_core_manager.Initialize(system); - is_powered_on = true; + LOG_DEBUG(Core, "Initialized OK"); // Reset counters and set time origin to current frame @@ -183,13 +190,13 @@ struct System::Impl { void Shutdown() { // Log last frame performance stats - auto perf_results = GetAndResetPerfStats(); - Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", - perf_results.emulation_speed * 100.0); - Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", - perf_results.game_fps); - Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", - perf_results.frametime * 1000.0); + const auto perf_results = GetAndResetPerfStats(); + telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", + perf_results.emulation_speed * 100.0); + telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", + perf_results.game_fps); + telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", + perf_results.frametime * 1000.0); is_powered_on = false; diff --git a/src/core/core.h b/src/core/core.h index d720013f7..ba76a41d8 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -293,10 +293,6 @@ inline ARM_Interface& CurrentArmInterface() { return System::GetInstance().CurrentArmInterface(); } -inline TelemetrySession& Telemetry() { - return System::GetInstance().TelemetrySession(); -} - inline Kernel::Process* CurrentProcess() { return System::GetInstance().CurrentProcess(); } diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 54aa21a3a..1eefed6d0 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -11,6 +11,7 @@ #endif #include "core/arm/exclusive_monitor.h" #include "core/arm/unicorn/arm_unicorn.h" +#include "core/core.h" #include "core/core_cpu.h" #include "core/core_timing.h" #include "core/hle/kernel/scheduler.h" @@ -49,9 +50,9 @@ bool CpuBarrier::Rendezvous() { return false; } -Cpu::Cpu(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor, - CpuBarrier& cpu_barrier, std::size_t core_index) - : cpu_barrier{cpu_barrier}, core_timing{core_timing}, core_index{core_index} { +Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, + std::size_t core_index) + : cpu_barrier{cpu_barrier}, core_timing{system.CoreTiming()}, core_index{core_index} { if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 arm_interface = std::make_unique<ARM_Dynarmic>(core_timing, exclusive_monitor, core_index); @@ -63,7 +64,7 @@ Cpu::Cpu(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor, arm_interface = std::make_unique<ARM_Unicorn>(core_timing); } - scheduler = std::make_unique<Kernel::Scheduler>(*arm_interface); + scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface); } Cpu::~Cpu() = default; diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index e2204c6b0..7589beb8c 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h @@ -15,6 +15,10 @@ namespace Kernel { class Scheduler; } +namespace Core { +class System; +} + namespace Core::Timing { class CoreTiming; } @@ -45,8 +49,8 @@ private: class Cpu { public: - Cpu(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor, - CpuBarrier& cpu_barrier, std::size_t core_index); + Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, + std::size_t core_index); ~Cpu(); void RunLoop(bool tight_loop = true); diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp index 2ddb3610d..93bc5619c 100644 --- a/src/core/cpu_core_manager.cpp +++ b/src/core/cpu_core_manager.cpp @@ -27,8 +27,7 @@ void CpuCoreManager::Initialize(System& system) { exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size()); for (std::size_t index = 0; index < cores.size(); ++index) { - cores[index] = - std::make_unique<Cpu>(system.CoreTiming(), *exclusive_monitor, *barrier, index); + cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); } // Create threads for CPU cores 1-3, and build thread_to_cpu map diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index ed84197b3..455d1f346 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -4,10 +4,10 @@ #pragma once +#include "common/bit_field.h" +#include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" -#include "core/hle/kernel/errors.h" -#include "core/memory.h" namespace IPC { diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 90f276ee8..079283830 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -350,7 +350,7 @@ public: template <class T> std::shared_ptr<T> PopIpcInterface() { ASSERT(context->Session()->IsDomain()); - ASSERT(context->GetDomainMessageHeader()->input_object_count > 0); + ASSERT(context->GetDomainMessageHeader().input_object_count > 0); return context->GetDomainRequestHandler<T>(Pop<u32>() - 1); } }; diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 704e82824..c17baa50a 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -17,21 +17,11 @@ ClientSession::~ClientSession() { // This destructor will be called automatically when the last ClientSession handle is closed by // the emulated application. - // Local references to ServerSession and SessionRequestHandler are necessary to guarantee they + // A local reference to the ServerSession is necessary to guarantee it // will be kept alive until after ClientDisconnected() returns. SharedPtr<ServerSession> server = parent->server; if (server) { - std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler; - if (hle_handler) - hle_handler->ClientDisconnected(server); - - // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set - // their WaitSynchronization result to 0xC920181A. - - // Clean up the list of client threads with pending requests, they are unneeded now that the - // client endpoint is closed. - server->pending_requesting_threads.clear(); - server->currently_handling = nullptr; + server->ClientDisconnected(); } parent->client = nullptr; diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index 4c18de69c..b1f39aad7 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -36,14 +36,15 @@ public: ResultCode SendSyncRequest(SharedPtr<Thread> thread); - std::string name; ///< Name of client port (optional) +private: + explicit ClientSession(KernelCore& kernel); + ~ClientSession() override; /// The parent session, which links to the server endpoint. std::shared_ptr<Session> parent; -private: - explicit ClientSession(KernelCore& kernel); - ~ClientSession() override; + /// Name of the client session (optional) + std::string name; }; } // namespace Kernel diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 5dd855db8..fe710eb6e 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -86,7 +86,7 @@ HLERequestContext::~HLERequestContext() = default; void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming) { IPC::RequestParser rp(src_cmdbuf); - command_header = std::make_shared<IPC::CommandHeader>(rp.PopRaw<IPC::CommandHeader>()); + command_header = rp.PopRaw<IPC::CommandHeader>(); if (command_header->type == IPC::CommandType::Close) { // Close does not populate the rest of the IPC header @@ -95,8 +95,7 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ // If handle descriptor is present, add size of it if (command_header->enable_handle_descriptor) { - handle_descriptor_header = - std::make_shared<IPC::HandleDescriptorHeader>(rp.PopRaw<IPC::HandleDescriptorHeader>()); + handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); if (handle_descriptor_header->send_current_pid) { rp.Skip(2, false); } @@ -140,16 +139,15 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ // If this is an incoming message, only CommandType "Request" has a domain header // All outgoing domain messages have the domain header, if only incoming has it if (incoming || domain_message_header) { - domain_message_header = - std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>()); + domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); } else { - if (Session()->IsDomain()) + if (Session()->IsDomain()) { LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); + } } } - data_payload_header = - std::make_shared<IPC::DataPayloadHeader>(rp.PopRaw<IPC::DataPayloadHeader>()); + data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); data_payload_offset = rp.GetCurrentOffset(); @@ -264,11 +262,11 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) { // Write the domain objects to the command buffer, these go after the raw untranslated data. // TODO(Subv): This completely ignores C buffers. std::size_t domain_offset = size - domain_message_header->num_objects; - auto& request_handlers = server_session->domain_request_handlers; - for (auto& object : domain_objects) { - request_handlers.emplace_back(object); - dst_cmdbuf[domain_offset++] = static_cast<u32_le>(request_handlers.size()); + for (const auto& object : domain_objects) { + server_session->AppendDomainRequestHandler(object); + dst_cmdbuf[domain_offset++] = + static_cast<u32_le>(server_session->NumDomainRequestHandlers()); } } diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index cb1c5aff3..2bdd9f02c 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -6,6 +6,7 @@ #include <array> #include <memory> +#include <optional> #include <string> #include <type_traits> #include <vector> @@ -15,6 +16,8 @@ #include "core/hle/ipc.h" #include "core/hle/kernel/object.h" +union ResultCode; + namespace Service { class ServiceFrameworkBase; } @@ -166,12 +169,12 @@ public: return buffer_c_desciptors; } - const IPC::DomainMessageHeader* GetDomainMessageHeader() const { - return domain_message_header.get(); + const IPC::DomainMessageHeader& GetDomainMessageHeader() const { + return domain_message_header.value(); } bool HasDomainMessageHeader() const { - return domain_message_header != nullptr; + return domain_message_header.has_value(); } /// Helper function to read a buffer using the appropriate buffer descriptor @@ -208,14 +211,12 @@ public: template <typename T> SharedPtr<T> GetCopyObject(std::size_t index) { - ASSERT(index < copy_objects.size()); - return DynamicObjectCast<T>(copy_objects[index]); + return DynamicObjectCast<T>(copy_objects.at(index)); } template <typename T> SharedPtr<T> GetMoveObject(std::size_t index) { - ASSERT(index < move_objects.size()); - return DynamicObjectCast<T>(move_objects[index]); + return DynamicObjectCast<T>(move_objects.at(index)); } void AddMoveObject(SharedPtr<Object> object) { @@ -232,7 +233,7 @@ public: template <typename T> std::shared_ptr<T> GetDomainRequestHandler(std::size_t index) const { - return std::static_pointer_cast<T>(domain_request_handlers[index]); + return std::static_pointer_cast<T>(domain_request_handlers.at(index)); } void SetDomainRequestHandlers( @@ -272,10 +273,10 @@ private: boost::container::small_vector<SharedPtr<Object>, 8> copy_objects; boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; - std::shared_ptr<IPC::CommandHeader> command_header; - std::shared_ptr<IPC::HandleDescriptorHeader> handle_descriptor_header; - std::shared_ptr<IPC::DataPayloadHeader> data_payload_header; - std::shared_ptr<IPC::DomainMessageHeader> domain_message_header; + std::optional<IPC::CommandHeader> command_header; + std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; + std::optional<IPC::DataPayloadHeader> data_payload_header; + std::optional<IPC::DomainMessageHeader> domain_message_header; std::vector<IPC::BufferDescriptorX> buffer_x_desciptors; std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 44f30d070..5fccfd9f4 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -19,7 +19,8 @@ namespace Kernel { std::mutex Scheduler::scheduler_mutex; -Scheduler::Scheduler(Core::ARM_Interface& cpu_core) : cpu_core(cpu_core) {} +Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core) + : cpu_core{cpu_core}, system{system} {} Scheduler::~Scheduler() { for (auto& thread : thread_list) { @@ -61,7 +62,7 @@ Thread* Scheduler::PopNextReadyThread() { void Scheduler::SwitchContext(Thread* new_thread) { Thread* const previous_thread = GetCurrentThread(); - Process* const previous_process = Core::CurrentProcess(); + Process* const previous_process = system.Kernel().CurrentProcess(); UpdateLastContextSwitchTime(previous_thread, previous_process); @@ -94,8 +95,8 @@ void Scheduler::SwitchContext(Thread* new_thread) { auto* const thread_owner_process = current_thread->GetOwnerProcess(); if (previous_process != thread_owner_process) { - Core::System::GetInstance().Kernel().MakeCurrentProcess(thread_owner_process); - SetCurrentPageTable(&Core::CurrentProcess()->VMManager().page_table); + system.Kernel().MakeCurrentProcess(thread_owner_process); + SetCurrentPageTable(&thread_owner_process->VMManager().page_table); } cpu_core.LoadContext(new_thread->GetContext()); @@ -111,7 +112,7 @@ void Scheduler::SwitchContext(Thread* new_thread) { void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) { const u64 prev_switch_ticks = last_context_switch_time; - const u64 most_recent_switch_ticks = Core::System::GetInstance().CoreTiming().GetTicks(); + const u64 most_recent_switch_ticks = system.CoreTiming().GetTicks(); const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks; if (thread != nullptr) { @@ -223,8 +224,7 @@ void Scheduler::YieldWithLoadBalancing(Thread* thread) { // Take the first non-nullptr one for (unsigned cur_core = 0; cur_core < Core::NUM_CPU_CORES; ++cur_core) { const auto res = - Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread( - core, priority); + system.CpuCore(cur_core).Scheduler().GetNextSuggestedThread(core, priority); // If scheduler provides a suggested thread if (res != nullptr) { diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 97ced4dfc..1c5bf57d9 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -13,7 +13,8 @@ namespace Core { class ARM_Interface; -} +class System; +} // namespace Core namespace Kernel { @@ -21,7 +22,7 @@ class Process; class Scheduler final { public: - explicit Scheduler(Core::ARM_Interface& cpu_core); + explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core); ~Scheduler(); /// Returns whether there are any threads that are ready to run. @@ -162,6 +163,7 @@ private: Core::ARM_Interface& cpu_core; u64 last_context_switch_time = 0; + Core::System& system; static std::mutex scheduler_mutex; }; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 027434f92..4d8a337a7 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -63,42 +63,71 @@ void ServerSession::Acquire(Thread* thread) { pending_requesting_threads.pop_back(); } +void ServerSession::ClientDisconnected() { + // We keep a shared pointer to the hle handler to keep it alive throughout + // the call to ClientDisconnected, as ClientDisconnected invalidates the + // hle_handler member itself during the course of the function executing. + std::shared_ptr<SessionRequestHandler> handler = hle_handler; + if (handler) { + // Note that after this returns, this server session's hle_handler is + // invalidated (set to null). + handler->ClientDisconnected(this); + } + + // TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set + // their WaitSynchronization result to 0xC920181A. + + // Clean up the list of client threads with pending requests, they are unneeded now that the + // client endpoint is closed. + pending_requesting_threads.clear(); + currently_handling = nullptr; +} + +void ServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) { + domain_request_handlers.push_back(std::move(handler)); +} + +std::size_t ServerSession::NumDomainRequestHandlers() const { + return domain_request_handlers.size(); +} + ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { - auto* const domain_message_header = context.GetDomainMessageHeader(); - if (domain_message_header) { - // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs - context.SetDomainRequestHandlers(domain_request_handlers); - - // If there is a DomainMessageHeader, then this is CommandType "Request" - const u32 object_id{context.GetDomainMessageHeader()->object_id}; - switch (domain_message_header->command) { - case IPC::DomainMessageHeader::CommandType::SendMessage: - if (object_id > domain_request_handlers.size()) { - LOG_CRITICAL(IPC, - "object_id {} is too big! This probably means a recent service call " - "to {} needed to return a new interface!", - object_id, name); - UNREACHABLE(); - return RESULT_SUCCESS; // Ignore error if asserts are off - } - return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); - - case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { - LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); - - domain_request_handlers[object_id - 1] = nullptr; - - IPC::ResponseBuilder rb{context, 2}; - rb.Push(RESULT_SUCCESS); - return RESULT_SUCCESS; - } + if (!context.HasDomainMessageHeader()) { + return RESULT_SUCCESS; + } + + // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs + context.SetDomainRequestHandlers(domain_request_handlers); + + // If there is a DomainMessageHeader, then this is CommandType "Request" + const auto& domain_message_header = context.GetDomainMessageHeader(); + const u32 object_id{domain_message_header.object_id}; + switch (domain_message_header.command) { + case IPC::DomainMessageHeader::CommandType::SendMessage: + if (object_id > domain_request_handlers.size()) { + LOG_CRITICAL(IPC, + "object_id {} is too big! This probably means a recent service call " + "to {} needed to return a new interface!", + object_id, name); + UNREACHABLE(); + return RESULT_SUCCESS; // Ignore error if asserts are off } + return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); - LOG_CRITICAL(IPC, "Unknown domain command={}", - static_cast<int>(domain_message_header->command.Value())); - ASSERT(false); + case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { + LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); + + domain_request_handlers[object_id - 1] = nullptr; + + IPC::ResponseBuilder rb{context, 2}; + rb.Push(RESULT_SUCCESS); + return RESULT_SUCCESS; + } } + LOG_CRITICAL(IPC, "Unknown domain command={}", + static_cast<int>(domain_message_header.command.Value())); + ASSERT(false); return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index e0e9d64c8..aea4ccfeb 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -46,6 +46,14 @@ public: return HANDLE_TYPE; } + Session* GetParent() { + return parent.get(); + } + + const Session* GetParent() const { + return parent.get(); + } + using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>; /** @@ -78,23 +86,16 @@ public: void Acquire(Thread* thread) override; - std::string name; ///< The name of this session (optional) - std::shared_ptr<Session> parent; ///< The parent session, which links to the client endpoint. - std::shared_ptr<SessionRequestHandler> - hle_handler; ///< This session's HLE request handler (applicable when not a domain) + /// Called when a client disconnection occurs. + void ClientDisconnected(); - /// This is the list of domain request handlers (after conversion to a domain) - std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; - - /// List of threads that are pending a response after a sync request. This list is processed in - /// a LIFO manner, thus, the last request will be dispatched first. - /// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test. - std::vector<SharedPtr<Thread>> pending_requesting_threads; + /// Adds a new domain request handler to the collection of request handlers within + /// this ServerSession instance. + void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler); - /// Thread whose request is currently being handled. A request is considered "handled" when a - /// response is sent via svcReplyAndReceive. - /// TODO(Subv): Find a better name for this. - SharedPtr<Thread> currently_handling; + /// Retrieves the total number of domain request handlers that have been + /// appended to this ServerSession instance. + std::size_t NumDomainRequestHandlers() const; /// Returns true if the session has been converted to a domain, otherwise False bool IsDomain() const { @@ -129,8 +130,30 @@ private: /// object handle. ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); + /// The parent session, which links to the client endpoint. + std::shared_ptr<Session> parent; + + /// This session's HLE request handler (applicable when not a domain) + std::shared_ptr<SessionRequestHandler> hle_handler; + + /// This is the list of domain request handlers (after conversion to a domain) + std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; + + /// List of threads that are pending a response after a sync request. This list is processed in + /// a LIFO manner, thus, the last request will be dispatched first. + /// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test. + std::vector<SharedPtr<Thread>> pending_requesting_threads; + + /// Thread whose request is currently being handled. A request is considered "handled" when a + /// response is sent via svcReplyAndReceive. + /// TODO(Subv): Find a better name for this. + SharedPtr<Thread> currently_handling; + /// When set to True, converts the session to a domain at the end of the command bool convert_to_domain{}; + + /// The name of this session (optional) + std::string name; }; } // namespace Kernel diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 22d0c1dd5..62861da36 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -6,7 +6,6 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "core/core.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/shared_memory.h" @@ -34,8 +33,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, Process* owner_ shared_memory->backing_block_offset = 0; // Refresh the address mappings for the current process. - if (Core::CurrentProcess() != nullptr) { - Core::CurrentProcess()->VMManager().RefreshMemoryBlockMappings( + if (kernel.CurrentProcess() != nullptr) { + kernel.CurrentProcess()->VMManager().RefreshMemoryBlockMappings( shared_memory->backing_block.get()); } } else { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 75b88a333..7f5c0cc86 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -20,6 +20,7 @@ #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/mutex.h" diff --git a/src/core/hle/result.h b/src/core/hle/result.h index bfb77cc31..1ed144481 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -8,7 +8,6 @@ #include <utility> #include "common/assert.h" #include "common/bit_field.h" -#include "common/common_funcs.h" #include "common/common_types.h" // All the constants in this file come from http://switchbrew.org/index.php?title=Error_codes diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index f255f74b5..8c5bd6059 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -7,6 +7,7 @@ #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/software_keyboard.h" +#include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/software_keyboard.h" diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index efd5753a1..b93a30d28 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -9,10 +9,13 @@ #include <vector> #include "common/common_funcs.h" +#include "common/common_types.h" #include "common/swap.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" +union ResultCode; + namespace Service::AM::Applets { enum class KeysetDisable : u32 { diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index bbe813490..21f5e64c7 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -107,7 +107,9 @@ private: void StopAudioOut(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); - audio_core.StopStream(stream); + if (stream->IsPlaying()) { + audio_core.StopStream(stream); + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index dbe7ee6e8..20c7c39aa 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -36,7 +36,7 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 auto& instance = Core::System::GetInstance(); instance.GetPerfStats().EndGameFrame(); - instance.Renderer().SwapBuffers(framebuffer); + instance.GPU().SwapBuffers(framebuffer); } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 466db7ccd..a34b9e753 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -178,7 +178,7 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou auto& gpu = system_instance.GPU(); auto cpu_addr = gpu.MemoryManager().GpuToCpuAddress(params.offset); ASSERT(cpu_addr); - system_instance.Renderer().Rasterizer().FlushAndInvalidateRegion(*cpu_addr, itr->second.size); + gpu.FlushAndInvalidateRegion(*cpu_addr, itr->second.size); params.offset = gpu.MemoryManager().UnmapBuffer(params.offset, itr->second.size); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 0a650f36c..8ce7bc7a5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -136,16 +136,6 @@ u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector< return 0; } -static void PushGPUEntries(Tegra::CommandList&& entries) { - if (entries.empty()) { - return; - } - - auto& dma_pusher{Core::System::GetInstance().GPU().DmaPusher()}; - dma_pusher.Push(std::move(entries)); - dma_pusher.DispatchCalls(); -} - u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); @@ -163,7 +153,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], params.num_entries * sizeof(Tegra::CommandListHeader)); - PushGPUEntries(std::move(entries)); + Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); params.fence_out.id = 0; params.fence_out.value = 0; @@ -184,7 +174,7 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) Memory::ReadBlock(params.address, entries.data(), params.num_entries * sizeof(Tegra::CommandListHeader)); - PushGPUEntries(std::move(entries)); + Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries)); params.fence_out.id = 0; params.fence_out.value = 0; diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 56f31e2ac..fc496b654 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -186,7 +186,7 @@ void NVFlinger::Compose() { // There was no queued buffer to draw, render previous frame system_instance.GetPerfStats().EndGameFrame(); - system_instance.Renderer().SwapBuffers({}); + system_instance.GPU().SwapBuffers({}); continue; } diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index 74da4d5e6..e9ee73710 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp @@ -30,7 +30,7 @@ void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; rb.Push(RESULT_SUCCESS); - Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->parent->client}; + Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->GetParent()->client}; rb.PushMoveObjects(session); LOG_DEBUG(Service, "session={}", session->GetObjectId()); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ec279cef8..6591c45d2 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -356,16 +356,16 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { const VAddr overlap_end = std::min(end, region_end); const VAddr overlap_size = overlap_end - overlap_start; - auto& rasterizer = system_instance.Renderer().Rasterizer(); + auto& gpu = system_instance.GPU(); switch (mode) { case FlushMode::Flush: - rasterizer.FlushRegion(overlap_start, overlap_size); + gpu.FlushRegion(overlap_start, overlap_size); break; case FlushMode::Invalidate: - rasterizer.InvalidateRegion(overlap_start, overlap_size); + gpu.InvalidateRegion(overlap_start, overlap_size); break; case FlushMode::FlushAndInvalidate: - rasterizer.FlushAndInvalidateRegion(overlap_start, overlap_size); + gpu.FlushAndInvalidateRegion(overlap_start, overlap_size); break; } }; diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 2e232e1e7..6dd3139cc 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -91,7 +91,10 @@ void LogSettings() { LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor); LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit); LogSetting("Renderer_FrameLimit", Settings::values.frame_limit); + LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache); LogSetting("Renderer_UseAccurateGpuEmulation", Settings::values.use_accurate_gpu_emulation); + LogSetting("Renderer_UseAsynchronousGpuEmulation", + Settings::values.use_asynchronous_gpu_emulation); LogSetting("Audio_OutputEngine", Settings::values.sink_id); LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching); LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); diff --git a/src/core/settings.h b/src/core/settings.h index 7e76e0466..cdfb2f742 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -393,6 +393,7 @@ struct Values { u16 frame_limit; bool use_disk_shader_cache; bool use_accurate_gpu_emulation; + bool use_asynchronous_gpu_emulation; float bg_red; float bg_green; diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 58dfcc4df..e1db06811 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -162,6 +162,8 @@ TelemetrySession::TelemetrySession() { Settings::values.use_disk_shader_cache); AddField(Telemetry::FieldType::UserConfig, "Renderer_UseAccurateGpuEmulation", Settings::values.use_accurate_gpu_emulation); + AddField(Telemetry::FieldType::UserConfig, "Renderer_UseAsynchronousGpuEmulation", + Settings::values.use_asynchronous_gpu_emulation); AddField(Telemetry::FieldType::UserConfig, "System_UseDockedMode", Settings::values.use_docked_mode); } |