Compare commits

..

6 Commits

Author SHA1 Message Date
e9d7bd2534 Android 190 2024-01-12 01:00:45 +00:00
57c6d95eb5 Merge yuzu-emu#12642 2024-01-12 01:00:45 +00:00
b83c362cc9 Merge yuzu-emu#12612 2024-01-12 01:00:45 +00:00
0d8ce6cc50 Merge yuzu-emu#12610 2024-01-12 01:00:45 +00:00
67b104dc5a Merge yuzu-emu#12605 2024-01-12 01:00:45 +00:00
8f979a3153 Merge yuzu-emu#12579 2024-01-12 01:00:45 +00:00
28 changed files with 190 additions and 393 deletions

View File

@ -1,11 +1,10 @@
| Pull Request | Commit | Title | Author | Merged? | | Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----| |----|----|----|----|----|
| [12579](https://github.com/yuzu-emu/yuzu-android//pull/12579) | [`66ae60a9e`](https://github.com/yuzu-emu/yuzu-android//pull/12579/files) | Core: Implement Device Mapping & GPU SMMU | [FernandoS27](https://github.com/FernandoS27/) | Yes | | [12579](https://github.com/yuzu-emu/yuzu-android//pull/12579) | [`66ae60a9e`](https://github.com/yuzu-emu/yuzu-android//pull/12579/files) | Core: Implement Device Mapping & GPU SMMU | [FernandoS27](https://github.com/FernandoS27/) | Yes |
| [12605](https://github.com/yuzu-emu/yuzu-android//pull/12605) | [`0683fb5a7`](https://github.com/yuzu-emu/yuzu-android//pull/12605/files) | service: hid: Create abstracted pad structure | [german77](https://github.com/german77/) | Yes |
| [12610](https://github.com/yuzu-emu/yuzu-android//pull/12610) | [`200b371d1`](https://github.com/yuzu-emu/yuzu-android//pull/12610/files) | server_manager: respond to session close correctly | [liamwhite](https://github.com/liamwhite/) | Yes | | [12610](https://github.com/yuzu-emu/yuzu-android//pull/12610) | [`200b371d1`](https://github.com/yuzu-emu/yuzu-android//pull/12610/files) | server_manager: respond to session close correctly | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12611](https://github.com/yuzu-emu/yuzu-android//pull/12611) | [`2f0b57ca1`](https://github.com/yuzu-emu/yuzu-android//pull/12611/files) | kernel: fix resource management issues | [liamwhite](https://github.com/liamwhite/) | Yes | | [12612](https://github.com/yuzu-emu/yuzu-android//pull/12612) | [`aae9eea53`](https://github.com/yuzu-emu/yuzu-android//pull/12612/files) | fsp-srv: use program registry for SetCurrentProcess | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12612](https://github.com/yuzu-emu/yuzu-android//pull/12612) | [`76880b84f`](https://github.com/yuzu-emu/yuzu-android//pull/12612/files) | fsp-srv: use program registry for SetCurrentProcess | [liamwhite](https://github.com/liamwhite/) | Yes | | [12642](https://github.com/yuzu-emu/yuzu-android//pull/12642) | [`d3ba6b334`](https://github.com/yuzu-emu/yuzu-android//pull/12642/files) | android: Refactor list adapters | [t895](https://github.com/t895/) | Yes |
| [12652](https://github.com/yuzu-emu/yuzu-android//pull/12652) | [`2a0d707ce`](https://github.com/yuzu-emu/yuzu-android//pull/12652/files) | shader_recompiler: emulate 8-bit and 16-bit storage writes with cas loop | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12659](https://github.com/yuzu-emu/yuzu-android//pull/12659) | [`d94097478`](https://github.com/yuzu-emu/yuzu-android//pull/12659/files) | audio: fetch process object from handle table | [liamwhite](https://github.com/liamwhite/) | Yes |
End of merge log. You can find the original README.md below the break. End of merge log. You can find the original README.md below the break.

View File

@ -11,8 +11,6 @@
#include "core/guest_memory.h" #include "core/guest_memory.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/hle/kernel/k_process.h"
namespace AudioCore { namespace AudioCore {
using namespace std::literals; using namespace std::literals;
@ -28,7 +26,7 @@ DeviceSession::~DeviceSession() {
} }
Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_format_, Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_format_,
u16 channel_count_, size_t session_id_, Kernel::KProcess* handle_, u16 channel_count_, size_t session_id_, u32 handle_,
u64 applet_resource_user_id_, Sink::StreamType type_) { u64 applet_resource_user_id_, Sink::StreamType type_) {
if (stream) { if (stream) {
Finalize(); Finalize();
@ -39,7 +37,6 @@ Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_for
channel_count = channel_count_; channel_count = channel_count_;
session_id = session_id_; session_id = session_id_;
handle = handle_; handle = handle_;
handle->Open();
applet_resource_user_id = applet_resource_user_id_; applet_resource_user_id = applet_resource_user_id_;
if (type == Sink::StreamType::In) { if (type == Sink::StreamType::In) {
@ -58,11 +55,6 @@ void DeviceSession::Finalize() {
sink->CloseStream(stream); sink->CloseStream(stream);
stream = nullptr; stream = nullptr;
} }
if (handle) {
handle->Close();
handle = nullptr;
}
} }
void DeviceSession::Start() { void DeviceSession::Start() {
@ -100,7 +92,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
stream->AppendBuffer(new_buffer, tmp_samples); stream->AppendBuffer(new_buffer, tmp_samples);
} else { } else {
Core::Memory::CpuGuestMemory<s16, Core::Memory::GuestMemoryFlags::UnsafeRead> samples( Core::Memory::CpuGuestMemory<s16, Core::Memory::GuestMemoryFlags::UnsafeRead> samples(
handle->GetMemory(), buffer.samples, buffer.size / sizeof(s16)); system.ApplicationMemory(), buffer.samples, buffer.size / sizeof(s16));
stream->AppendBuffer(new_buffer, samples); stream->AppendBuffer(new_buffer, samples);
} }
} }
@ -109,7 +101,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const { void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
if (type == Sink::StreamType::In) { if (type == Sink::StreamType::In) {
auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))}; auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
handle->GetMemory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size); system.ApplicationMemory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
} }
} }

View File

@ -20,10 +20,6 @@ struct EventType;
} // namespace Timing } // namespace Timing
} // namespace Core } // namespace Core
namespace Kernel {
class KProcess;
} // namespace Kernel
namespace AudioCore { namespace AudioCore {
namespace Sink { namespace Sink {
@ -48,13 +44,13 @@ public:
* @param sample_format - Sample format for this device's output. * @param sample_format - Sample format for this device's output.
* @param channel_count - Number of channels for this device (2 or 6). * @param channel_count - Number of channels for this device (2 or 6).
* @param session_id - This session's id. * @param session_id - This session's id.
* @param handle - Process handle for this device session. * @param handle - Handle for this device session (unused).
* @param applet_resource_user_id - Applet resource user id for this device session (unused). * @param applet_resource_user_id - Applet resource user id for this device session (unused).
* @param type - Type of this stream (Render, In, Out). * @param type - Type of this stream (Render, In, Out).
* @return Result code for this call. * @return Result code for this call.
*/ */
Result Initialize(std::string_view name, SampleFormat sample_format, u16 channel_count, Result Initialize(std::string_view name, SampleFormat sample_format, u16 channel_count,
size_t session_id, Kernel::KProcess* handle, u64 applet_resource_user_id, size_t session_id, u32 handle, u64 applet_resource_user_id,
Sink::StreamType type); Sink::StreamType type);
/** /**
@ -141,8 +137,8 @@ private:
u16 channel_count{}; u16 channel_count{};
/// Session id of this device session /// Session id of this device session
size_t session_id{}; size_t session_id{};
/// Process handle of device memory owner /// Handle of this device session
Kernel::KProcess* handle{}; u32 handle{};
/// Applet resource user id of this device session /// Applet resource user id of this device session
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Total number of samples played by this device session /// Total number of samples played by this device session

View File

@ -57,7 +57,7 @@ Result System::IsConfigValid(const std::string_view device_name,
} }
Result System::Initialize(std::string device_name, const AudioInParameter& in_params, Result System::Initialize(std::string device_name, const AudioInParameter& in_params,
Kernel::KProcess* handle_, const u64 applet_resource_user_id_) { const u32 handle_, const u64 applet_resource_user_id_) {
auto result{IsConfigValid(device_name, in_params)}; auto result{IsConfigValid(device_name, in_params)};
if (result.IsError()) { if (result.IsError()) {
return result; return result;

View File

@ -19,8 +19,7 @@ class System;
namespace Kernel { namespace Kernel {
class KEvent; class KEvent;
class KProcess; }
} // namespace Kernel
namespace AudioCore::AudioIn { namespace AudioCore::AudioIn {
@ -94,12 +93,12 @@ public:
* *
* @param device_name - The name of the requested input device. * @param device_name - The name of the requested input device.
* @param in_params - Input parameters, see AudioInParameter. * @param in_params - Input parameters, see AudioInParameter.
* @param handle - Process handle. * @param handle - Unused.
* @param applet_resource_user_id - Unused. * @param applet_resource_user_id - Unused.
* @return Result code. * @return Result code.
*/ */
Result Initialize(std::string device_name, const AudioInParameter& in_params, Result Initialize(std::string device_name, const AudioInParameter& in_params, u32 handle,
Kernel::KProcess* handle, u64 applet_resource_user_id); u64 applet_resource_user_id);
/** /**
* Start this system. * Start this system.
@ -245,8 +244,8 @@ public:
private: private:
/// Core system /// Core system
Core::System& system; Core::System& system;
/// Process handle /// (Unused)
Kernel::KProcess* handle{}; u32 handle{};
/// (Unused) /// (Unused)
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Buffer event, signalled when a buffer is ready /// Buffer event, signalled when a buffer is ready

View File

@ -48,8 +48,8 @@ Result System::IsConfigValid(std::string_view device_name,
return Service::Audio::ResultInvalidChannelCount; return Service::Audio::ResultInvalidChannelCount;
} }
Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle_,
Kernel::KProcess* handle_, u64 applet_resource_user_id_) { u64 applet_resource_user_id_) {
auto result = IsConfigValid(device_name, in_params); auto result = IsConfigValid(device_name, in_params);
if (result.IsError()) { if (result.IsError()) {
return result; return result;

View File

@ -19,8 +19,7 @@ class System;
namespace Kernel { namespace Kernel {
class KEvent; class KEvent;
class KProcess; }
} // namespace Kernel
namespace AudioCore::AudioOut { namespace AudioCore::AudioOut {
@ -85,12 +84,12 @@ public:
* *
* @param device_name - The name of the requested output device. * @param device_name - The name of the requested output device.
* @param in_params - Input parameters, see AudioOutParameter. * @param in_params - Input parameters, see AudioOutParameter.
* @param handle - Process handle. * @param handle - Unused.
* @param applet_resource_user_id - Unused. * @param applet_resource_user_id - Unused.
* @return Result code. * @return Result code.
*/ */
Result Initialize(std::string device_name, const AudioOutParameter& in_params, Result Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle,
Kernel::KProcess* handle, u64 applet_resource_user_id); u64 applet_resource_user_id);
/** /**
* Start this system. * Start this system.
@ -229,8 +228,8 @@ public:
private: private:
/// Core system /// Core system
Core::System& system; Core::System& system;
/// Process handle /// (Unused)
Kernel::KProcess* handle{}; u32 handle{};
/// (Unused) /// (Unused)
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Buffer event, signalled when a buffer is ready /// Buffer event, signalled when a buffer is ready

View File

@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/page_table.h" #include "common/page_table.h"
#include "common/scope_exit.h"
namespace Common { namespace Common {
@ -12,10 +11,29 @@ PageTable::~PageTable() noexcept = default;
bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context, bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context,
Common::ProcessAddress address) const { Common::ProcessAddress address) const {
out_context->next_offset = GetInteger(address); // Setup invalid defaults.
out_context->next_page = address / page_size; out_entry->phys_addr = 0;
out_entry->block_size = page_size;
out_context->next_page = 0;
return this->ContinueTraversal(out_entry, out_context); // Validate that we can read the actual entry.
const auto page = address / page_size;
if (page >= backing_addr.size()) {
return false;
}
// Validate that the entry is mapped.
const auto phys_addr = backing_addr[page];
if (phys_addr == 0) {
return false;
}
// Populate the results.
out_entry->phys_addr = phys_addr + GetInteger(address);
out_context->next_page = page + 1;
out_context->next_offset = GetInteger(address) + page_size;
return true;
} }
bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const { bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const {
@ -23,12 +41,6 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c
out_entry->phys_addr = 0; out_entry->phys_addr = 0;
out_entry->block_size = page_size; out_entry->block_size = page_size;
// Regardless of whether the page was mapped, advance on exit.
SCOPE_EXIT({
context->next_page += 1;
context->next_offset += page_size;
});
// Validate that we can read the actual entry. // Validate that we can read the actual entry.
const auto page = context->next_page; const auto page = context->next_page;
if (page >= backing_addr.size()) { if (page >= backing_addr.size()) {
@ -43,6 +55,8 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c
// Populate the results. // Populate the results.
out_entry->phys_addr = phys_addr + context->next_offset; out_entry->phys_addr = phys_addr + context->next_offset;
context->next_page = page + 1;
context->next_offset += page_size;
return true; return true;
} }

View File

@ -114,7 +114,7 @@ public:
} }
Kernel::KThread* GetActiveThread() override { Kernel::KThread* GetActiveThread() override {
return state->active_thread.GetPointerUnsafe(); return state->active_thread;
} }
private: private:
@ -147,14 +147,11 @@ private:
std::scoped_lock lk{connection_lock}; std::scoped_lock lk{connection_lock};
// Find the process we are going to debug.
SetDebugProcess();
// Ensure everything is stopped. // Ensure everything is stopped.
PauseEmulation(); PauseEmulation();
// Set up the new frontend. // Set up the new frontend.
frontend = std::make_unique<GDBStub>(*this, system, debug_process.GetPointerUnsafe()); frontend = std::make_unique<GDBStub>(*this, system);
// Set the new state. This will tear down any existing state. // Set the new state. This will tear down any existing state.
state = ConnectionState{ state = ConnectionState{
@ -197,20 +194,15 @@ private:
UpdateActiveThread(); UpdateActiveThread();
if (state->info.type == SignalType::Watchpoint) { if (state->info.type == SignalType::Watchpoint) {
frontend->Watchpoint(std::addressof(*state->active_thread), frontend->Watchpoint(state->active_thread, *state->info.watchpoint);
*state->info.watchpoint);
} else { } else {
frontend->Stopped(std::addressof(*state->active_thread)); frontend->Stopped(state->active_thread);
} }
break; break;
case SignalType::ShuttingDown: case SignalType::ShuttingDown:
frontend->ShuttingDown(); frontend->ShuttingDown();
// Release members.
state->active_thread.Reset(nullptr);
debug_process.Reset(nullptr);
// Wait for emulation to shut down gracefully now. // Wait for emulation to shut down gracefully now.
state->signal_pipe.close(); state->signal_pipe.close();
state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); state->client_socket.shutdown(boost::asio::socket_base::shutdown_both);
@ -230,7 +222,7 @@ private:
stopped = true; stopped = true;
PauseEmulation(); PauseEmulation();
UpdateActiveThread(); UpdateActiveThread();
frontend->Stopped(state->active_thread.GetPointerUnsafe()); frontend->Stopped(state->active_thread);
break; break;
} }
case DebuggerAction::Continue: case DebuggerAction::Continue:
@ -240,7 +232,7 @@ private:
MarkResumed([&] { MarkResumed([&] {
state->active_thread->SetStepState(Kernel::StepState::StepPending); state->active_thread->SetStepState(Kernel::StepState::StepPending);
state->active_thread->Resume(Kernel::SuspendType::Debug); state->active_thread->Resume(Kernel::SuspendType::Debug);
ResumeEmulation(state->active_thread.GetPointerUnsafe()); ResumeEmulation(state->active_thread);
}); });
break; break;
case DebuggerAction::StepThreadLocked: { case DebuggerAction::StepThreadLocked: {
@ -263,7 +255,6 @@ private:
} }
void PauseEmulation() { void PauseEmulation() {
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()}; Kernel::KScopedSchedulerLock sl{system.Kernel()};
// Put all threads to sleep on next scheduler round. // Put all threads to sleep on next scheduler round.
@ -273,9 +264,6 @@ private:
} }
void ResumeEmulation(Kernel::KThread* except = nullptr) { void ResumeEmulation(Kernel::KThread* except = nullptr) {
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
// Wake up all threads. // Wake up all threads.
for (auto& thread : ThreadList()) { for (auto& thread : ThreadList()) {
if (std::addressof(thread) == except) { if (std::addressof(thread) == except) {
@ -289,16 +277,15 @@ private:
template <typename Callback> template <typename Callback>
void MarkResumed(Callback&& cb) { void MarkResumed(Callback&& cb) {
Kernel::KScopedSchedulerLock sl{system.Kernel()};
stopped = false; stopped = false;
cb(); cb();
} }
void UpdateActiveThread() { void UpdateActiveThread() {
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
auto& threads{ThreadList()}; auto& threads{ThreadList()};
for (auto& thread : threads) { for (auto& thread : threads) {
if (std::addressof(thread) == state->active_thread.GetPointerUnsafe()) { if (std::addressof(thread) == state->active_thread) {
// Thread is still alive, no need to update. // Thread is still alive, no need to update.
return; return;
} }
@ -306,18 +293,12 @@ private:
state->active_thread = std::addressof(threads.front()); state->active_thread = std::addressof(threads.front());
} }
private:
void SetDebugProcess() {
debug_process = std::move(system.Kernel().GetProcessList().back());
}
Kernel::KProcess::ThreadList& ThreadList() { Kernel::KProcess::ThreadList& ThreadList() {
return debug_process->GetThreadList(); return system.ApplicationProcess()->GetThreadList();
} }
private: private:
System& system; System& system;
Kernel::KScopedAutoObject<Kernel::KProcess> debug_process;
std::unique_ptr<DebuggerFrontend> frontend; std::unique_ptr<DebuggerFrontend> frontend;
boost::asio::io_context io_context; boost::asio::io_context io_context;
@ -329,7 +310,7 @@ private:
boost::process::async_pipe signal_pipe; boost::process::async_pipe signal_pipe;
SignalInfo info; SignalInfo info;
Kernel::KScopedAutoObject<Kernel::KThread> active_thread; Kernel::KThread* active_thread;
std::array<u8, 4096> client_data; std::array<u8, 4096> client_data;
bool pipe_data; bool pipe_data;
}; };

View File

@ -108,9 +108,9 @@ static std::string EscapeXML(std::string_view data) {
return escaped; return escaped;
} }
GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_, Kernel::KProcess* debug_process_) GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_)
: DebuggerFrontend(backend_), system{system_}, debug_process{debug_process_} { : DebuggerFrontend(backend_), system{system_} {
if (GetProcess()->Is64Bit()) { if (system.ApplicationProcess()->Is64Bit()) {
arch = std::make_unique<GDBStubA64>(); arch = std::make_unique<GDBStubA64>();
} else { } else {
arch = std::make_unique<GDBStubA32>(); arch = std::make_unique<GDBStubA32>();
@ -276,7 +276,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
std::vector<u8> mem(size); std::vector<u8> mem(size);
if (GetMemory().ReadBlock(addr, mem.data(), size)) { if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
// Restore any bytes belonging to replaced instructions. // Restore any bytes belonging to replaced instructions.
auto it = replaced_instructions.lower_bound(addr); auto it = replaced_instructions.lower_bound(addr);
for (; it != replaced_instructions.end() && it->first < addr + size; it++) { for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
@ -310,8 +310,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
const auto mem_substr{std::string_view(command).substr(mem_sep)}; const auto mem_substr{std::string_view(command).substr(mem_sep)};
const auto mem{Common::HexStringToVector(mem_substr, false)}; const auto mem{Common::HexStringToVector(mem_substr, false)};
if (GetMemory().WriteBlock(addr, mem.data(), size)) { if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) {
Core::InvalidateInstructionCacheRange(GetProcess(), addr, size); Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, size);
SendReply(GDB_STUB_REPLY_OK); SendReply(GDB_STUB_REPLY_OK);
} else { } else {
SendReply(GDB_STUB_REPLY_ERR); SendReply(GDB_STUB_REPLY_ERR);
@ -353,7 +353,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
if (!GetMemory().IsValidVirtualAddressRange(addr, size)) { if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
SendReply(GDB_STUB_REPLY_ERR); SendReply(GDB_STUB_REPLY_ERR);
return; return;
} }
@ -362,20 +362,22 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
switch (type) { switch (type) {
case BreakpointType::Software: case BreakpointType::Software:
replaced_instructions[addr] = GetMemory().Read32(addr); replaced_instructions[addr] = system.ApplicationMemory().Read32(addr);
GetMemory().Write32(addr, arch->BreakpointInstruction()); system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction());
Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32)); Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32));
success = true; success = true;
break; break;
case BreakpointType::WriteWatch: case BreakpointType::WriteWatch:
success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
Kernel::DebugWatchpointType::Write);
break; break;
case BreakpointType::ReadWatch: case BreakpointType::ReadWatch:
success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
Kernel::DebugWatchpointType::Read);
break; break;
case BreakpointType::AccessWatch: case BreakpointType::AccessWatch:
success = success = system.ApplicationProcess()->InsertWatchpoint(
GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break; break;
case BreakpointType::Hardware: case BreakpointType::Hardware:
default: default:
@ -398,7 +400,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
if (!GetMemory().IsValidVirtualAddressRange(addr, size)) { if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
SendReply(GDB_STUB_REPLY_ERR); SendReply(GDB_STUB_REPLY_ERR);
return; return;
} }
@ -409,22 +411,24 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
case BreakpointType::Software: { case BreakpointType::Software: {
const auto orig_insn{replaced_instructions.find(addr)}; const auto orig_insn{replaced_instructions.find(addr)};
if (orig_insn != replaced_instructions.end()) { if (orig_insn != replaced_instructions.end()) {
GetMemory().Write32(addr, orig_insn->second); system.ApplicationMemory().Write32(addr, orig_insn->second);
Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32)); Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32));
replaced_instructions.erase(addr); replaced_instructions.erase(addr);
success = true; success = true;
} }
break; break;
} }
case BreakpointType::WriteWatch: case BreakpointType::WriteWatch:
success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
Kernel::DebugWatchpointType::Write);
break; break;
case BreakpointType::ReadWatch: case BreakpointType::ReadWatch:
success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
Kernel::DebugWatchpointType::Read);
break; break;
case BreakpointType::AccessWatch: case BreakpointType::AccessWatch:
success = success = system.ApplicationProcess()->RemoveWatchpoint(
GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break; break;
case BreakpointType::Hardware: case BreakpointType::Hardware:
default: default:
@ -462,10 +466,10 @@ void GDBStub::HandleQuery(std::string_view command) {
const auto target_xml{arch->GetTargetXML()}; const auto target_xml{arch->GetTargetXML()};
SendReply(PaginateBuffer(target_xml, command.substr(30))); SendReply(PaginateBuffer(target_xml, command.substr(30)));
} else if (command.starts_with("Offsets")) { } else if (command.starts_with("Offsets")) {
const auto main_offset = Core::FindMainModuleEntrypoint(GetProcess()); const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess());
SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset))); SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset)));
} else if (command.starts_with("Xfer:libraries:read::")) { } else if (command.starts_with("Xfer:libraries:read::")) {
auto modules = Core::FindModules(GetProcess()); auto modules = Core::FindModules(system.ApplicationProcess());
std::string buffer; std::string buffer;
buffer += R"(<?xml version="1.0"?>)"; buffer += R"(<?xml version="1.0"?>)";
@ -479,7 +483,7 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply(PaginateBuffer(buffer, command.substr(21))); SendReply(PaginateBuffer(buffer, command.substr(21)));
} else if (command.starts_with("fThreadInfo")) { } else if (command.starts_with("fThreadInfo")) {
// beginning of list // beginning of list
const auto& threads = GetProcess()->GetThreadList(); const auto& threads = system.ApplicationProcess()->GetThreadList();
std::vector<std::string> thread_ids; std::vector<std::string> thread_ids;
for (const auto& thread : threads) { for (const auto& thread : threads) {
thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId())); thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId()));
@ -493,7 +497,7 @@ void GDBStub::HandleQuery(std::string_view command) {
buffer += R"(<?xml version="1.0"?>)"; buffer += R"(<?xml version="1.0"?>)";
buffer += "<threads>"; buffer += "<threads>";
const auto& threads = GetProcess()->GetThreadList(); const auto& threads = system.ApplicationProcess()->GetThreadList();
for (const auto& thread : threads) { for (const auto& thread : threads) {
auto thread_name{Core::GetThreadName(&thread)}; auto thread_name{Core::GetThreadName(&thread)};
if (!thread_name) { if (!thread_name) {
@ -609,7 +613,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()}; std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
std::string reply; std::string reply;
auto* process = GetProcess(); auto* process = system.ApplicationProcess();
auto& page_table = process->GetPageTable(); auto& page_table = process->GetPageTable();
const char* commands = "Commands:\n" const char* commands = "Commands:\n"
@ -710,7 +714,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
} }
Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
auto& threads{GetProcess()->GetThreadList()}; auto& threads{system.ApplicationProcess()->GetThreadList()};
for (auto& thread : threads) { for (auto& thread : threads) {
if (thread.GetThreadId() == thread_id) { if (thread.GetThreadId() == thread_id) {
return std::addressof(thread); return std::addressof(thread);
@ -779,12 +783,4 @@ void GDBStub::SendStatus(char status) {
backend.WriteToClient(buf); backend.WriteToClient(buf);
} }
Kernel::KProcess* GDBStub::GetProcess() {
return debug_process;
}
Core::Memory::Memory& GDBStub::GetMemory() {
return GetProcess()->GetMemory();
}
} // namespace Core } // namespace Core

View File

@ -12,22 +12,13 @@
#include "core/debugger/debugger_interface.h" #include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub_arch.h" #include "core/debugger/gdbstub_arch.h"
namespace Kernel {
class KProcess;
}
namespace Core::Memory {
class Memory;
}
namespace Core { namespace Core {
class System; class System;
class GDBStub : public DebuggerFrontend { class GDBStub : public DebuggerFrontend {
public: public:
explicit GDBStub(DebuggerBackend& backend, Core::System& system, explicit GDBStub(DebuggerBackend& backend, Core::System& system);
Kernel::KProcess* debug_process);
~GDBStub() override; ~GDBStub() override;
void Connected() override; void Connected() override;
@ -51,12 +42,8 @@ private:
void SendReply(std::string_view data); void SendReply(std::string_view data);
void SendStatus(char status); void SendStatus(char status);
Kernel::KProcess* GetProcess();
Core::Memory::Memory& GetMemory();
private: private:
Core::System& system; Core::System& system;
Kernel::KProcess* debug_process;
std::unique_ptr<GDBStubArch> arch; std::unique_ptr<GDBStubArch> arch;
std::vector<char> current_command; std::vector<char> current_command;
std::map<VAddr, u32> replaced_instructions; std::map<VAddr, u32> replaced_instructions;

View File

@ -28,14 +28,14 @@ Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd,
} }
void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager,
BlockCallback&& block_callback) { HostUnmapCallback&& host_unmap_callback) {
// Erase every block until we have none left. // Erase every block until we have none left.
auto it = m_memory_block_tree.begin(); auto it = m_memory_block_tree.begin();
while (it != m_memory_block_tree.end()) { while (it != m_memory_block_tree.end()) {
KMemoryBlock* block = std::addressof(*it); KMemoryBlock* block = std::addressof(*it);
it = m_memory_block_tree.erase(it); it = m_memory_block_tree.erase(it);
block_callback(block->GetAddress(), block->GetSize());
slab_manager->Free(block); slab_manager->Free(block);
host_unmap_callback(block->GetAddress(), block->GetSize());
} }
ASSERT(m_memory_block_tree.empty()); ASSERT(m_memory_block_tree.empty());

View File

@ -85,11 +85,11 @@ public:
public: public:
KMemoryBlockManager(); KMemoryBlockManager();
using BlockCallback = std::function<void(Common::ProcessAddress, u64)>; using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>;
Result Initialize(KProcessAddress st, KProcessAddress nd, Result Initialize(KProcessAddress st, KProcessAddress nd,
KMemoryBlockSlabManager* slab_manager); KMemoryBlockSlabManager* slab_manager);
void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback); void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback);
iterator end() { iterator end() {
return m_memory_block_tree.end(); return m_memory_block_tree.end();

View File

@ -431,43 +431,15 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool
m_memory_block_slab_manager)); m_memory_block_slab_manager));
} }
Result KPageTableBase::FinalizeProcess() {
// Only process tables should be finalized.
ASSERT(!this->IsKernel());
// NOTE: Here Nintendo calls an unknown OnFinalize function.
// this->OnFinalize();
// NOTE: Here Nintendo calls a second unknown OnFinalize function.
// this->OnFinalize2();
// NOTE: Here Nintendo does a page table walk to discover heap pages to free.
// We will use the block manager finalization below to free them.
R_SUCCEED();
}
void KPageTableBase::Finalize() { void KPageTableBase::Finalize() {
this->FinalizeProcess(); auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) {
if (Settings::IsFastmemEnabled()) {
auto BlockCallback = [&](KProcessAddress addr, u64 size) {
if (m_impl->fastmem_arena) {
m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false);
} }
// Get physical pages.
KPageGroup pg(m_kernel, m_block_info_manager);
this->MakePageGroup(pg, addr, size / PageSize);
// Free the pages.
pg.CloseAndReset();
}; };
// Finalize memory blocks. // Finalize memory blocks.
{ m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback));
KScopedLightLock lk(m_general_lock);
m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(BlockCallback));
}
// Free any unsafe mapped memory. // Free any unsafe mapped memory.
if (m_mapped_unsafe_physical_memory) { if (m_mapped_unsafe_physical_memory) {

View File

@ -241,7 +241,6 @@ public:
KResourceLimit* resource_limit, Core::Memory::Memory& memory, KResourceLimit* resource_limit, Core::Memory::Memory& memory,
KProcessAddress aslr_space_start); KProcessAddress aslr_space_start);
Result FinalizeProcess();
void Finalize(); void Finalize();
bool IsKernel() const { bool IsKernel() const {

View File

@ -172,12 +172,6 @@ void KProcess::Finalize() {
m_resource_limit->Close(); m_resource_limit->Close();
} }
// Clear expensive resources, as the destructor is not called for guest objects.
for (auto& interface : m_arm_interfaces) {
interface.reset();
}
m_exclusive_monitor.reset();
// Perform inherited finalization. // Perform inherited finalization.
KSynchronizationObject::Finalize(); KSynchronizationObject::Finalize();
} }

View File

@ -112,14 +112,7 @@ struct KernelCore::Impl {
old_process->Close(); old_process->Close();
} }
{ process_list.clear();
std::scoped_lock lk{process_list_lock};
for (auto* const process : process_list) {
process->Terminate();
process->Close();
}
process_list.clear();
}
next_object_id = 0; next_object_id = 0;
next_kernel_process_id = KProcess::InitialProcessIdMin; next_kernel_process_id = KProcess::InitialProcessIdMin;
@ -777,7 +770,6 @@ struct KernelCore::Impl {
std::atomic<u64> next_thread_id{1}; std::atomic<u64> next_thread_id{1};
// Lists all processes that exist in the current session. // Lists all processes that exist in the current session.
std::mutex process_list_lock;
std::vector<KProcess*> process_list; std::vector<KProcess*> process_list;
std::atomic<KProcess*> application_process{}; std::atomic<KProcess*> application_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
@ -877,19 +869,9 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
} }
void KernelCore::AppendNewProcess(KProcess* process) { void KernelCore::AppendNewProcess(KProcess* process) {
process->Open();
std::scoped_lock lk{impl->process_list_lock};
impl->process_list.push_back(process); impl->process_list.push_back(process);
} }
void KernelCore::RemoveProcess(KProcess* process) {
std::scoped_lock lk{impl->process_list_lock};
if (std::erase(impl->process_list, process)) {
process->Close();
}
}
void KernelCore::MakeApplicationProcess(KProcess* process) { void KernelCore::MakeApplicationProcess(KProcess* process) {
impl->MakeApplicationProcess(process); impl->MakeApplicationProcess(process);
} }
@ -902,15 +884,8 @@ const KProcess* KernelCore::ApplicationProcess() const {
return impl->application_process; return impl->application_process;
} }
std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() { const std::vector<KProcess*>& KernelCore::GetProcessList() const {
std::list<KScopedAutoObject<KProcess>> processes; return impl->process_list;
std::scoped_lock lk{impl->process_list_lock};
for (auto* const process : impl->process_list) {
processes.emplace_back(process);
}
return processes;
} }
Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() {

View File

@ -5,7 +5,6 @@
#include <array> #include <array>
#include <functional> #include <functional>
#include <list>
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -117,9 +116,8 @@ public:
/// Retrieves a shared pointer to the system resource limit instance. /// Retrieves a shared pointer to the system resource limit instance.
KResourceLimit* GetSystemResourceLimit(); KResourceLimit* GetSystemResourceLimit();
/// Adds/removes the given pointer to an internal list of active processes. /// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(KProcess* process); void AppendNewProcess(KProcess* process);
void RemoveProcess(KProcess* process);
/// Makes the given process the new application process. /// Makes the given process the new application process.
void MakeApplicationProcess(KProcess* process); void MakeApplicationProcess(KProcess* process);
@ -131,7 +129,7 @@ public:
const KProcess* ApplicationProcess() const; const KProcess* ApplicationProcess() const;
/// Retrieves the list of processes. /// Retrieves the list of processes.
std::list<KScopedAutoObject<KProcess>> GetProcessList(); const std::vector<KProcess*>& GetProcessList() const;
/// Gets the sole instance of the global scheduler /// Gets the sole instance of the global scheduler
Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); Kernel::GlobalSchedulerContext& GlobalSchedulerContext();

View File

@ -74,15 +74,13 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
} }
auto& memory = GetCurrentMemory(kernel); auto& memory = GetCurrentMemory(kernel);
auto process_list = kernel.GetProcessList(); const auto& process_list = kernel.GetProcessList();
auto it = process_list.begin();
const auto num_processes = process_list.size(); const auto num_processes = process_list.size();
const auto copy_amount = const auto copy_amount =
std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) { for (std::size_t i = 0; i < copy_amount; ++i) {
memory.Write64(out_process_ids, (*it)->GetProcessId()); memory.Write64(out_process_ids, process_list[i]->GetProcessId());
out_process_ids += sizeof(u64); out_process_ids += sizeof(u64);
} }

View File

@ -18,11 +18,11 @@ using namespace AudioCore::AudioIn;
class IAudioIn final : public ServiceFramework<IAudioIn> { class IAudioIn final : public ServiceFramework<IAudioIn> {
public: public:
explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id, explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioInParameter& in_params, const std::string& device_name, const AudioInParameter& in_params, u32 handle,
Kernel::KProcess* handle, u64 applet_resource_user_id) u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioIn"}, : ServiceFramework{system_, "IAudioIn"},
service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")}, service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")},
process{handle}, impl{std::make_shared<In>(system_, manager, event, session_id)} { impl{std::make_shared<In>(system_, manager, event, session_id)} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IAudioIn::GetAudioInState, "GetAudioInState"}, {0, &IAudioIn::GetAudioInState, "GetAudioInState"},
@ -45,8 +45,6 @@ public:
RegisterHandlers(functions); RegisterHandlers(functions);
process->Open();
if (impl->GetSystem() if (impl->GetSystem()
.Initialize(device_name, in_params, handle, applet_resource_user_id) .Initialize(device_name, in_params, handle, applet_resource_user_id)
.IsError()) { .IsError()) {
@ -57,7 +55,6 @@ public:
~IAudioIn() override { ~IAudioIn() override {
impl->Free(); impl->Free();
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close();
} }
[[nodiscard]] std::shared_ptr<In> GetImpl() { [[nodiscard]] std::shared_ptr<In> GetImpl() {
@ -199,7 +196,6 @@ private:
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event; Kernel::KEvent* event;
Kernel::KProcess* process;
std::shared_ptr<AudioCore::AudioIn::In> impl; std::shared_ptr<AudioCore::AudioIn::In> impl;
Common::ScratchBuffer<u64> released_buffer; Common::ScratchBuffer<u64> released_buffer;
}; };
@ -271,14 +267,6 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
auto device_name = Common::StringFromBuffer(device_name_data); auto device_name = Common::StringFromBuffer(device_name_data);
auto handle{ctx.GetCopyHandle(0)}; auto handle{ctx.GetCopyHandle(0)};
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
if (process.IsNull()) {
LOG_ERROR(Service_Audio, "Failed to get process handle");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultUnknown);
return;
}
std::scoped_lock l{impl->mutex}; std::scoped_lock l{impl->mutex};
auto link{impl->LinkToManager()}; auto link{impl->LinkToManager()};
if (link.IsError()) { if (link.IsError()) {
@ -299,9 +287,8 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
auto audio_in = auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params, in_params, handle, applet_resource_user_id);
process.GetPointerUnsafe(), applet_resource_user_id);
impl->sessions[new_session_id] = audio_in->GetImpl(); impl->sessions[new_session_id] = audio_in->GetImpl();
impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
@ -331,14 +318,6 @@ void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
auto device_name = Common::StringFromBuffer(device_name_data); auto device_name = Common::StringFromBuffer(device_name_data);
auto handle{ctx.GetCopyHandle(0)}; auto handle{ctx.GetCopyHandle(0)};
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
if (process.IsNull()) {
LOG_ERROR(Service_Audio, "Failed to get process handle");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultUnknown);
return;
}
std::scoped_lock l{impl->mutex}; std::scoped_lock l{impl->mutex};
auto link{impl->LinkToManager()}; auto link{impl->LinkToManager()};
if (link.IsError()) { if (link.IsError()) {
@ -359,9 +338,8 @@ void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
auto audio_in = auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params, in_params, handle, applet_resource_user_id);
process.GetPointerUnsafe(), applet_resource_user_id);
impl->sessions[new_session_id] = audio_in->GetImpl(); impl->sessions[new_session_id] = audio_in->GetImpl();
impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;

View File

@ -26,10 +26,9 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
public: public:
explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
size_t session_id, const std::string& device_name, size_t session_id, const std::string& device_name,
const AudioOutParameter& in_params, Kernel::KProcess* handle, const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id)
u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")}, process{handle}, event{service_context.CreateEvent("AudioOutEvent")},
impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
// clang-format off // clang-format off
@ -51,14 +50,11 @@ public:
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
process->Open();
} }
~IAudioOut() override { ~IAudioOut() override {
impl->Free(); impl->Free();
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close();
} }
[[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() { [[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
@ -210,7 +206,6 @@ private:
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event; Kernel::KEvent* event;
Kernel::KProcess* process;
std::shared_ptr<AudioCore::AudioOut::Out> impl; std::shared_ptr<AudioCore::AudioOut::Out> impl;
Common::ScratchBuffer<u64> released_buffer; Common::ScratchBuffer<u64> released_buffer;
}; };
@ -262,14 +257,6 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
auto device_name = Common::StringFromBuffer(device_name_data); auto device_name = Common::StringFromBuffer(device_name_data);
auto handle{ctx.GetCopyHandle(0)}; auto handle{ctx.GetCopyHandle(0)};
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
if (process.IsNull()) {
LOG_ERROR(Service_Audio, "Failed to get process handle");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultUnknown);
return;
}
auto link{impl->LinkToManager()}; auto link{impl->LinkToManager()};
if (link.IsError()) { if (link.IsError()) {
LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager"); LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager");
@ -289,11 +276,10 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
auto audio_out = auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name,
std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params, in_params, handle, applet_resource_user_id);
process.GetPointerUnsafe(), applet_resource_user_id); result = audio_out->GetImpl()->GetSystem().Initialize(device_name, in_params, handle,
result = audio_out->GetImpl()->GetSystem().Initialize( applet_resource_user_id);
device_name, in_params, process.GetPointerUnsafe(), applet_resource_user_id);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!"); LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};

View File

@ -15,10 +15,9 @@
namespace Service::Glue { namespace Service::Glue {
namespace { namespace {
std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id) { std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) {
auto list = system.Kernel().GetProcessList(); const auto& list = system.Kernel().GetProcessList();
const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) {
const auto iter = std::find_if(list.begin(), list.end(), [&process_id](auto& process) {
return process->GetProcessId() == process_id; return process->GetProcessId() == process_id;
}); });

View File

@ -22,10 +22,12 @@ void LoopProcess(Core::System& system) {
std::shared_ptr<HidFirmwareSettings> firmware_settings = std::shared_ptr<HidFirmwareSettings> firmware_settings =
std::make_shared<HidFirmwareSettings>(); std::make_shared<HidFirmwareSettings>();
// TODO: Remove this hack when am is emulated properly. // TODO: Remove this hack until this service is emulated properly.
resource_manager->Initialize(); const auto process_list = system.Kernel().GetProcessList();
resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), if (!process_list.empty()) {
true); resource_manager->Initialize();
resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
}
server_manager->RegisterNamedService( server_manager->RegisterNamedService(
"hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings));

View File

@ -22,26 +22,27 @@ constexpr Result ResultProcessNotFound{ErrorModule::PM, 1};
constexpr u64 NO_PROCESS_FOUND_PID{0}; constexpr u64 NO_PROCESS_FOUND_PID{0};
using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>; std::optional<Kernel::KProcess*> SearchProcessList(
const std::vector<Kernel::KProcess*>& process_list,
template <typename F> std::function<bool(Kernel::KProcess*)> predicate) {
Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(ProcessList& process_list,
F&& predicate) {
const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate);
if (iter == process_list.end()) { if (iter == process_list.end()) {
return nullptr; return std::nullopt;
} }
return iter->GetPointerUnsafe(); return *iter;
} }
void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { void GetApplicationPidGeneric(HLERequestContext& ctx,
auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); const std::vector<Kernel::KProcess*>& process_list) {
const auto process = SearchProcessList(process_list, [](const auto& proc) {
return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin;
});
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId()); rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID);
} }
} // Anonymous namespace } // Anonymous namespace
@ -79,7 +80,8 @@ private:
class DebugMonitor final : public ServiceFramework<DebugMonitor> { class DebugMonitor final : public ServiceFramework<DebugMonitor> {
public: public:
explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} { explicit DebugMonitor(Core::System& system_)
: ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "GetJitDebugProcessIdList"}, {0, nullptr, "GetJitDebugProcessIdList"},
@ -104,11 +106,12 @@ private:
LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
auto list = kernel.GetProcessList(); const auto process =
auto process = SearchProcessList( SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) {
list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); return proc->GetProgramId() == program_id;
});
if (process.IsNull()) { if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound); rb.Push(ResultProcessNotFound);
return; return;
@ -116,13 +119,12 @@ private:
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(process->GetProcessId()); rb.Push((*process)->GetProcessId());
} }
void GetApplicationProcessId(HLERequestContext& ctx) { void GetApplicationProcessId(HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called"); LOG_DEBUG(Service_PM, "called");
auto list = kernel.GetProcessList(); GetApplicationPidGeneric(ctx, kernel.GetProcessList());
GetApplicationPidGeneric(ctx, list);
} }
void AtmosphereGetProcessInfo(HLERequestContext& ctx) { void AtmosphereGetProcessInfo(HLERequestContext& ctx) {
@ -133,10 +135,11 @@ private:
LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
auto list = kernel.GetProcessList(); const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) {
auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); return proc->GetProcessId() == pid;
});
if (process.IsNull()) { if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound); rb.Push(ResultProcessNotFound);
return; return;
@ -156,7 +159,7 @@ private:
OverrideStatus override_status{}; OverrideStatus override_status{};
ProgramLocation program_location{ ProgramLocation program_location{
.program_id = process->GetProgramId(), .program_id = (*process)->GetProgramId(),
.storage_id = 0, .storage_id = 0,
}; };
@ -166,11 +169,14 @@ private:
rb.PushRaw(program_location); rb.PushRaw(program_location);
rb.PushRaw(override_status); rb.PushRaw(override_status);
} }
const Kernel::KernelCore& kernel;
}; };
class Info final : public ServiceFramework<Info> { class Info final : public ServiceFramework<Info> {
public: public:
explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} { explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_)
: ServiceFramework{system_, "pm:info"}, process_list{process_list_} {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &Info::GetProgramId, "GetProgramId"}, {0, &Info::GetProgramId, "GetProgramId"},
{65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"},
@ -187,11 +193,11 @@ private:
LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id);
auto list = kernel.GetProcessList(); const auto process = SearchProcessList(process_list, [process_id](const auto& proc) {
auto process = SearchProcessList( return proc->GetProcessId() == process_id;
list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); });
if (process.IsNull()) { if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound); rb.Push(ResultProcessNotFound);
return; return;
@ -199,7 +205,7 @@ private:
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(process->GetProgramId()); rb.Push((*process)->GetProgramId());
} }
void AtmosphereGetProcessId(HLERequestContext& ctx) { void AtmosphereGetProcessId(HLERequestContext& ctx) {
@ -208,11 +214,11 @@ private:
LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
auto list = system.Kernel().GetProcessList(); const auto process = SearchProcessList(process_list, [program_id](const auto& proc) {
auto process = SearchProcessList( return proc->GetProgramId() == program_id;
list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); });
if (process.IsNull()) { if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound); rb.Push(ResultProcessNotFound);
return; return;
@ -220,13 +226,16 @@ private:
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(process->GetProcessId()); rb.Push((*process)->GetProcessId());
} }
const std::vector<Kernel::KProcess*>& process_list;
}; };
class Shell final : public ServiceFramework<Shell> { class Shell final : public ServiceFramework<Shell> {
public: public:
explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} { explicit Shell(Core::System& system_)
: ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "LaunchProgram"}, {0, nullptr, "LaunchProgram"},
@ -248,9 +257,10 @@ public:
private: private:
void GetApplicationProcessIdForShell(HLERequestContext& ctx) { void GetApplicationProcessIdForShell(HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called"); LOG_DEBUG(Service_PM, "called");
auto list = kernel.GetProcessList(); GetApplicationPidGeneric(ctx, kernel.GetProcessList());
GetApplicationPidGeneric(ctx, list);
} }
const Kernel::KernelCore& kernel;
}; };
void LoopProcess(Core::System& system) { void LoopProcess(Core::System& system) {
@ -258,7 +268,8 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system)); server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system));
server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system));
server_manager->RegisterNamedService("pm:info", std::make_shared<Info>(system)); server_manager->RegisterNamedService(
"pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList()));
server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system));
ServerManager::RunServer(std::move(server_manager)); ServerManager::RunServer(std::move(server_manager));
} }

View File

@ -275,12 +275,12 @@ AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::KProcess& process, Core::S
return {ResultStatus::ErrorLoadingNRO, {}}; return {ResultStatus::ErrorLoadingNRO, {}};
} }
u64 program_id{}; if (romfs != nullptr) {
ReadProgramId(program_id); system.GetFileSystemController().RegisterProcess(
system.GetFileSystemController().RegisterProcess( process.GetProcessId(), {},
process.GetProcessId(), program_id, std::make_unique<FileSys::RomFSFactory>(*this, system.GetContentProvider(),
std::make_unique<FileSys::RomFSFactory>(*this, system.GetContentProvider(), system.GetFileSystemController()));
system.GetFileSystemController())); }
is_loaded = true; is_loaded = true;
return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority, return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority,

View File

@ -65,14 +65,6 @@ void WriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value&
WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32), WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32),
&StorageDefinitions::U32, index_offset); &StorageDefinitions::U32, index_offset);
} }
void WriteStorageByCasLoop(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value, Id bit_offset, Id bit_count) {
const Id pointer{StoragePointer(ctx, binding, offset, ctx.storage_types.U32, sizeof(u32),
&StorageDefinitions::U32)};
ctx.OpFunctionCall(ctx.TypeVoid(), ctx.write_storage_cas_loop_func, pointer, value, bit_offset,
bit_count);
}
} // Anonymous namespace } // Anonymous namespace
void EmitLoadGlobalU8(EmitContext&) { void EmitLoadGlobalU8(EmitContext&) {
@ -227,42 +219,26 @@ Id EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Valu
void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) { Id value) {
if (ctx.profile.support_int8) { WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8,
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8, sizeof(u8), &StorageDefinitions::U8);
sizeof(u8), &StorageDefinitions::U8);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset8(offset), ctx.Const(8u));
}
} }
void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) { Id value) {
if (ctx.profile.support_int8) { WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8,
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8, sizeof(s8), &StorageDefinitions::S8);
sizeof(s8), &StorageDefinitions::S8);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset8(offset), ctx.Const(8u));
}
} }
void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) { Id value) {
if (ctx.profile.support_int16) { WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16,
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16, sizeof(u16), &StorageDefinitions::U16);
sizeof(u16), &StorageDefinitions::U16);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset16(offset), ctx.Const(16u));
}
} }
void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
Id value) { Id value) {
if (ctx.profile.support_int16) { WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16,
WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16, sizeof(s16), &StorageDefinitions::S16);
sizeof(s16), &StorageDefinitions::S16);
} else {
WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset16(offset), ctx.Const(16u));
}
} }
void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,

View File

@ -480,7 +480,6 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
DefineTextures(program.info, texture_binding, bindings.texture_scaling_index); DefineTextures(program.info, texture_binding, bindings.texture_scaling_index);
DefineImages(program.info, image_binding, bindings.image_scaling_index); DefineImages(program.info, image_binding, bindings.image_scaling_index);
DefineAttributeMemAccess(program.info); DefineAttributeMemAccess(program.info);
DefineWriteStorageCasLoopFunction(program.info);
DefineGlobalMemoryFunctions(program.info); DefineGlobalMemoryFunctions(program.info);
DefineRescalingInput(program.info); DefineRescalingInput(program.info);
DefineRenderArea(program.info); DefineRenderArea(program.info);
@ -878,56 +877,6 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
} }
} }
void EmitContext::DefineWriteStorageCasLoopFunction(const Info& info) {
if (profile.support_int8 && profile.support_int16) {
return;
}
if (!info.uses_int8 && !info.uses_int16) {
return;
}
AddCapability(spv::Capability::VariablePointersStorageBuffer);
const Id ptr_type{TypePointer(spv::StorageClass::StorageBuffer, U32[1])};
const Id func_type{TypeFunction(void_id, ptr_type, U32[1], U32[1], U32[1])};
const Id func{OpFunction(void_id, spv::FunctionControlMask::MaskNone, func_type)};
const Id pointer{OpFunctionParameter(ptr_type)};
const Id value{OpFunctionParameter(U32[1])};
const Id bit_offset{OpFunctionParameter(U32[1])};
const Id bit_count{OpFunctionParameter(U32[1])};
AddLabel();
const Id scope_device{Const(1u)};
const Id ordering_relaxed{u32_zero_value};
const Id body_label{OpLabel()};
const Id continue_label{OpLabel()};
const Id endloop_label{OpLabel()};
const Id beginloop_label{OpLabel()};
OpBranch(beginloop_label);
AddLabel(beginloop_label);
OpLoopMerge(endloop_label, continue_label, spv::LoopControlMask::MaskNone);
OpBranch(body_label);
AddLabel(body_label);
const Id expected_value{OpLoad(U32[1], pointer)};
const Id desired_value{OpBitFieldInsert(U32[1], expected_value, value, bit_offset, bit_count)};
const Id actual_value{OpAtomicCompareExchange(U32[1], pointer, scope_device, ordering_relaxed,
ordering_relaxed, desired_value, expected_value)};
const Id store_successful{OpIEqual(U1, expected_value, actual_value)};
OpBranchConditional(store_successful, endloop_label, continue_label);
AddLabel(endloop_label);
OpReturn();
AddLabel(continue_label);
OpBranch(beginloop_label);
OpFunctionEnd();
write_storage_cas_loop_func = func;
}
void EmitContext::DefineGlobalMemoryFunctions(const Info& info) { void EmitContext::DefineGlobalMemoryFunctions(const Info& info) {
if (!info.uses_global_memory || !profile.support_int64) { if (!info.uses_global_memory || !profile.support_int64) {
return; return;

View File

@ -325,8 +325,6 @@ public:
Id f32x2_min_cas{}; Id f32x2_min_cas{};
Id f32x2_max_cas{}; Id f32x2_max_cas{};
Id write_storage_cas_loop_func{};
Id load_global_func_u32{}; Id load_global_func_u32{};
Id load_global_func_u32x2{}; Id load_global_func_u32x2{};
Id load_global_func_u32x4{}; Id load_global_func_u32x4{};
@ -374,7 +372,6 @@ private:
void DefineTextures(const Info& info, u32& binding, u32& scaling_index); void DefineTextures(const Info& info, u32& binding, u32& scaling_index);
void DefineImages(const Info& info, u32& binding, u32& scaling_index); void DefineImages(const Info& info, u32& binding, u32& scaling_index);
void DefineAttributeMemAccess(const Info& info); void DefineAttributeMemAccess(const Info& info);
void DefineWriteStorageCasLoopFunction(const Info& info);
void DefineGlobalMemoryFunctions(const Info& info); void DefineGlobalMemoryFunctions(const Info& info);
void DefineRescalingInput(const Info& info); void DefineRescalingInput(const Info& info);
void DefineRescalingInputPushConstant(); void DefineRescalingInputPushConstant();