core: Prepare various classes for memory read/write migration
Amends a few interfaces to be able to handle the migration over to the new Memory class by passing the class by reference as a function parameter where necessary. Notably, within the filesystem services, this eliminates two ReadBlock() calls by using the helper functions of HLERequestContext to do that for us.pull/3169/head
parent
fc7d0a17b6
commit
536fc7f0ea
|
|
@ -36,9 +36,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetWaveIndex(std::size_t index);
|
void SetWaveIndex(std::size_t index);
|
||||||
std::vector<s16> DequeueSamples(std::size_t sample_count);
|
std::vector<s16> DequeueSamples(std::size_t sample_count, Memory::Memory& memory);
|
||||||
void UpdateState();
|
void UpdateState();
|
||||||
void RefreshBuffer();
|
void RefreshBuffer(Memory::Memory& memory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_in_use{};
|
bool is_in_use{};
|
||||||
|
|
@ -66,17 +66,18 @@ public:
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateState();
|
void UpdateState(Memory::Memory& memory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EffectOutStatus out_status{};
|
EffectOutStatus out_status{};
|
||||||
EffectInStatus info{};
|
EffectInStatus info{};
|
||||||
};
|
};
|
||||||
AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params,
|
AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Memory::Memory& memory_,
|
||||||
|
AudioRendererParameter params,
|
||||||
std::shared_ptr<Kernel::WritableEvent> buffer_event,
|
std::shared_ptr<Kernel::WritableEvent> buffer_event,
|
||||||
std::size_t instance_number)
|
std::size_t instance_number)
|
||||||
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
|
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
|
||||||
effects(params.effect_count) {
|
effects(params.effect_count), memory{memory_} {
|
||||||
|
|
||||||
audio_out = std::make_unique<AudioCore::AudioOut>();
|
audio_out = std::make_unique<AudioCore::AudioOut>();
|
||||||
stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
|
stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
|
||||||
|
|
@ -162,7 +163,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& effect : effects) {
|
for (auto& effect : effects) {
|
||||||
effect.UpdateState();
|
effect.UpdateState(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release previous buffers and queue next ones for playback
|
// Release previous buffers and queue next ones for playback
|
||||||
|
|
@ -206,13 +207,14 @@ void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) {
|
||||||
is_refresh_pending = true;
|
is_refresh_pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count) {
|
std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count,
|
||||||
|
Memory::Memory& memory) {
|
||||||
if (!IsPlaying()) {
|
if (!IsPlaying()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_refresh_pending) {
|
if (is_refresh_pending) {
|
||||||
RefreshBuffer();
|
RefreshBuffer(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t max_size{samples.size() - offset};
|
const std::size_t max_size{samples.size() - offset};
|
||||||
|
|
@ -256,7 +258,7 @@ void AudioRenderer::VoiceState::UpdateState() {
|
||||||
is_in_use = info.is_in_use;
|
is_in_use = info.is_in_use;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioRenderer::VoiceState::RefreshBuffer() {
|
void AudioRenderer::VoiceState::RefreshBuffer(Memory::Memory& memory) {
|
||||||
std::vector<s16> new_samples(info.wave_buffer[wave_index].buffer_sz / sizeof(s16));
|
std::vector<s16> new_samples(info.wave_buffer[wave_index].buffer_sz / sizeof(s16));
|
||||||
Memory::ReadBlock(info.wave_buffer[wave_index].buffer_addr, new_samples.data(),
|
Memory::ReadBlock(info.wave_buffer[wave_index].buffer_addr, new_samples.data(),
|
||||||
info.wave_buffer[wave_index].buffer_sz);
|
info.wave_buffer[wave_index].buffer_sz);
|
||||||
|
|
@ -307,7 +309,7 @@ void AudioRenderer::VoiceState::RefreshBuffer() {
|
||||||
is_refresh_pending = false;
|
is_refresh_pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioRenderer::EffectState::UpdateState() {
|
void AudioRenderer::EffectState::UpdateState(Memory::Memory& memory) {
|
||||||
if (info.is_new) {
|
if (info.is_new) {
|
||||||
out_status.state = EffectStatus::New;
|
out_status.state = EffectStatus::New;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -340,7 +342,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
|
||||||
std::size_t offset{};
|
std::size_t offset{};
|
||||||
s64 samples_remaining{BUFFER_SIZE};
|
s64 samples_remaining{BUFFER_SIZE};
|
||||||
while (samples_remaining > 0) {
|
while (samples_remaining > 0) {
|
||||||
const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)};
|
const std::vector<s16> samples{voice.DequeueSamples(samples_remaining, memory)};
|
||||||
|
|
||||||
if (samples.empty()) {
|
if (samples.empty()) {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@ namespace Kernel {
|
||||||
class WritableEvent;
|
class WritableEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace AudioCore {
|
namespace AudioCore {
|
||||||
|
|
||||||
class AudioOut;
|
class AudioOut;
|
||||||
|
|
@ -217,7 +221,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
|
||||||
|
|
||||||
class AudioRenderer {
|
class AudioRenderer {
|
||||||
public:
|
public:
|
||||||
AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params,
|
AudioRenderer(Core::Timing::CoreTiming& core_timing, Memory::Memory& memory_,
|
||||||
|
AudioRendererParameter params,
|
||||||
std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number);
|
std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number);
|
||||||
~AudioRenderer();
|
~AudioRenderer();
|
||||||
|
|
||||||
|
|
@ -238,7 +243,8 @@ private:
|
||||||
std::vector<VoiceState> voices;
|
std::vector<VoiceState> voices;
|
||||||
std::vector<EffectState> effects;
|
std::vector<EffectState> effects;
|
||||||
std::unique_ptr<AudioOut> audio_out;
|
std::unique_ptr<AudioOut> audio_out;
|
||||||
AudioCore::StreamPtr stream;
|
StreamPtr stream;
|
||||||
|
Memory::Memory& memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AudioCore
|
} // namespace AudioCore
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr u64 ELF_DYNAMIC_TAG_NULL = 0;
|
constexpr u64 ELF_DYNAMIC_TAG_NULL = 0;
|
||||||
|
|
@ -156,7 +155,7 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<VAddr, std::string> modules;
|
std::map<VAddr, std::string> modules;
|
||||||
auto& loader{System::GetInstance().GetAppLoader()};
|
auto& loader{system.GetAppLoader()};
|
||||||
if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
|
if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,13 @@ enum class VMAPermission : u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
|
||||||
/// Generic ARMv8 CPU interface
|
/// Generic ARMv8 CPU interface
|
||||||
class ARM_Interface : NonCopyable {
|
class ARM_Interface : NonCopyable {
|
||||||
public:
|
public:
|
||||||
virtual ~ARM_Interface() {}
|
explicit ARM_Interface(System& system_) : system{system_} {}
|
||||||
|
virtual ~ARM_Interface() = default;
|
||||||
|
|
||||||
struct ThreadContext {
|
struct ThreadContext {
|
||||||
std::array<u64, 31> cpu_registers;
|
std::array<u64, 31> cpu_registers;
|
||||||
|
|
@ -163,6 +165,10 @@ public:
|
||||||
/// fp+0 : pointer to previous frame record
|
/// fp+0 : pointer to previous frame record
|
||||||
/// fp+8 : value of lr for frame
|
/// fp+8 : value of lr for frame
|
||||||
void LogBacktrace() const;
|
void LogBacktrace() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// System context that this ARM interface is running under.
|
||||||
|
System& system;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ public:
|
||||||
explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
|
explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
|
||||||
|
|
||||||
u8 MemoryRead8(u64 vaddr) override {
|
u8 MemoryRead8(u64 vaddr) override {
|
||||||
|
auto& s = parent.system;
|
||||||
return Memory::Read8(vaddr);
|
return Memory::Read8(vaddr);
|
||||||
}
|
}
|
||||||
u16 MemoryRead16(u64 vaddr) override {
|
u16 MemoryRead16(u64 vaddr) override {
|
||||||
|
|
@ -171,9 +172,10 @@ void ARM_Dynarmic::Step() {
|
||||||
|
|
||||||
ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
|
ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||||
std::size_t core_index)
|
std::size_t core_index)
|
||||||
: cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
|
: ARM_Interface{system},
|
||||||
core_index{core_index}, system{system},
|
cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
|
||||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
core_index{core_index}, exclusive_monitor{
|
||||||
|
dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
||||||
|
|
||||||
ARM_Dynarmic::~ARM_Dynarmic() = default;
|
ARM_Dynarmic::~ARM_Dynarmic() = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ private:
|
||||||
ARM_Unicorn inner_unicorn;
|
ARM_Unicorn inner_unicorn;
|
||||||
|
|
||||||
std::size_t core_index;
|
std::size_t core_index;
|
||||||
System& system;
|
|
||||||
DynarmicExclusiveMonitor& exclusive_monitor;
|
DynarmicExclusiveMonitor& exclusive_monitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM_Unicorn::ARM_Unicorn(System& system) : system{system} {
|
ARM_Unicorn::ARM_Unicorn(System& system) : ARM_Interface{system} {
|
||||||
CHECKED(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
|
CHECKED(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
|
||||||
|
|
||||||
auto fpv = 3 << 20;
|
auto fpv = 3 << 20;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ private:
|
||||||
static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data);
|
static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data);
|
||||||
|
|
||||||
uc_engine* uc{};
|
uc_engine* uc{};
|
||||||
System& system;
|
|
||||||
GDBStub::BreakpointAddress last_bkpt{};
|
GDBStub::BreakpointAddress last_bkpt{};
|
||||||
bool last_bkpt_hit = false;
|
bool last_bkpt_hit = false;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ ClientSession::~ClientSession() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode ClientSession::SendSyncRequest(Thread* thread) {
|
ResultCode ClientSession::SendSyncRequest(Thread* thread, Memory::Memory& memory) {
|
||||||
// Signal the server session that new data is available
|
// Signal the server session that new data is available
|
||||||
if (auto server = parent->server.lock()) {
|
if (auto server = parent->server.lock()) {
|
||||||
return server->HandleSyncRequest(SharedFrom(thread));
|
return server->HandleSyncRequest(SharedFrom(thread), memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_SESSION_CLOSED_BY_REMOTE;
|
return ERR_SESSION_CLOSED_BY_REMOTE;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@
|
||||||
|
|
||||||
union ResultCode;
|
union ResultCode;
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class KernelCore;
|
class KernelCore;
|
||||||
|
|
@ -37,7 +41,7 @@ public:
|
||||||
return HANDLE_TYPE;
|
return HANDLE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SendSyncRequest(Thread* thread);
|
ResultCode SendSyncRequest(Thread* thread, Memory::Memory& memory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The parent session, which links to the server endpoint.
|
/// The parent session, which links to the server endpoint.
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,8 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
|
ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
|
||||||
|
Memory::Memory& memory) {
|
||||||
// The ServerSession received a sync request, this means that there's new data available
|
// The ServerSession received a sync request, this means that there's new data available
|
||||||
// from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
|
// from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
|
||||||
// similar.
|
// similar.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
#include "core/hle/kernel/wait_object.h"
|
#include "core/hle/kernel/wait_object.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class ClientPort;
|
class ClientPort;
|
||||||
|
|
@ -85,10 +89,13 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a sync request from the emulated application.
|
* Handle a sync request from the emulated application.
|
||||||
|
*
|
||||||
* @param thread Thread that initiated the request.
|
* @param thread Thread that initiated the request.
|
||||||
|
* @param memory Memory context to handle the sync request under.
|
||||||
|
*
|
||||||
* @returns ResultCode from the operation.
|
* @returns ResultCode from the operation.
|
||||||
*/
|
*/
|
||||||
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread);
|
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread, Memory::Memory& memory);
|
||||||
|
|
||||||
bool ShouldWait(const Thread* thread) const override;
|
bool ShouldWait(const Thread* thread) const override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||||
|
|
||||||
// TODO(Subv): svcSendSyncRequest should put the caller thread to sleep while the server
|
// TODO(Subv): svcSendSyncRequest should put the caller thread to sleep while the server
|
||||||
// responds and cause a reschedule.
|
// responds and cause a reschedule.
|
||||||
return session->SendSyncRequest(system.CurrentScheduler().GetCurrentThread());
|
return session->SendSyncRequest(system.CurrentScheduler().GetCurrentThread(), system.Memory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ID for the specified thread.
|
/// Get the ID for the specified thread.
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,9 @@ public:
|
||||||
|
|
||||||
system_event =
|
system_event =
|
||||||
Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
|
Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
|
||||||
renderer = std::make_unique<AudioCore::AudioRenderer>(
|
renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), system.Memory(),
|
||||||
system.CoreTiming(), audren_params, system_event.writable, instance_number);
|
audren_params, system_event.writable,
|
||||||
|
instance_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -391,13 +391,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenameFile(Kernel::HLERequestContext& ctx) {
|
void RenameFile(Kernel::HLERequestContext& ctx) {
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer = ctx.ReadBuffer(0);
|
||||||
buffer.resize(ctx.BufferDescriptorX()[0].Size());
|
|
||||||
Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
|
|
||||||
const std::string src_name = Common::StringFromBuffer(buffer);
|
const std::string src_name = Common::StringFromBuffer(buffer);
|
||||||
|
|
||||||
buffer.resize(ctx.BufferDescriptorX()[1].Size());
|
buffer = ctx.ReadBuffer(1);
|
||||||
Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
|
|
||||||
const std::string dst_name = Common::StringFromBuffer(buffer);
|
const std::string dst_name = Common::StringFromBuffer(buffer);
|
||||||
|
|
||||||
LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name);
|
LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ namespace Service::LM {
|
||||||
|
|
||||||
class ILogger final : public ServiceFramework<ILogger> {
|
class ILogger final : public ServiceFramework<ILogger> {
|
||||||
public:
|
public:
|
||||||
ILogger(Manager& manager) : ServiceFramework("ILogger"), manager(manager) {
|
explicit ILogger(Manager& manager_, Memory::Memory& memory_)
|
||||||
|
: ServiceFramework("ILogger"), manager{manager_}, memory{memory_} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ILogger::Log, "Log"},
|
{0, &ILogger::Log, "Log"},
|
||||||
{1, &ILogger::SetDestination, "SetDestination"},
|
{1, &ILogger::SetDestination, "SetDestination"},
|
||||||
|
|
@ -74,11 +75,13 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager& manager;
|
Manager& manager;
|
||||||
|
Memory::Memory& memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LM final : public ServiceFramework<LM> {
|
class LM final : public ServiceFramework<LM> {
|
||||||
public:
|
public:
|
||||||
explicit LM(Manager& manager) : ServiceFramework{"lm"}, manager(manager) {
|
explicit LM(Manager& manager_, Memory::Memory& memory_)
|
||||||
|
: ServiceFramework{"lm"}, manager{manager_}, memory{memory_} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &LM::OpenLogger, "OpenLogger"},
|
{0, &LM::OpenLogger, "OpenLogger"},
|
||||||
|
|
@ -94,14 +97,16 @@ private:
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushIpcInterface<ILogger>(manager);
|
rb.PushIpcInterface<ILogger>(manager, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager& manager;
|
Manager& manager;
|
||||||
|
Memory::Memory& memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system) {
|
void InstallInterfaces(Core::System& system) {
|
||||||
std::make_shared<LM>(system.GetLogManager())->InstallAsService(system.ServiceManager());
|
std::make_shared<LM>(system.GetLogManager(), system.Memory())
|
||||||
|
->InstallAsService(system.ServiceManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::LM
|
} // namespace Service::LM
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ json GetFullDataAuto(const std::string& timestamp, u64 title_id, Core::System& s
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool read_value, typename DescriptorType>
|
template <bool read_value, typename DescriptorType>
|
||||||
json GetHLEBufferDescriptorData(const std::vector<DescriptorType>& buffer) {
|
json GetHLEBufferDescriptorData(const std::vector<DescriptorType>& buffer, Memory::Memory& memory) {
|
||||||
auto buffer_out = json::array();
|
auto buffer_out = json::array();
|
||||||
for (const auto& desc : buffer) {
|
for (const auto& desc : buffer) {
|
||||||
auto entry = json{
|
auto entry = json{
|
||||||
|
|
@ -167,7 +167,7 @@ json GetHLEBufferDescriptorData(const std::vector<DescriptorType>& buffer) {
|
||||||
return buffer_out;
|
return buffer_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
json GetHLERequestContextData(Kernel::HLERequestContext& ctx) {
|
json GetHLERequestContextData(Kernel::HLERequestContext& ctx, Memory::Memory& memory) {
|
||||||
json out;
|
json out;
|
||||||
|
|
||||||
auto cmd_buf = json::array();
|
auto cmd_buf = json::array();
|
||||||
|
|
@ -177,10 +177,10 @@ json GetHLERequestContextData(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
out["command_buffer"] = std::move(cmd_buf);
|
out["command_buffer"] = std::move(cmd_buf);
|
||||||
|
|
||||||
out["buffer_descriptor_a"] = GetHLEBufferDescriptorData<true>(ctx.BufferDescriptorA());
|
out["buffer_descriptor_a"] = GetHLEBufferDescriptorData<true>(ctx.BufferDescriptorA(), memory);
|
||||||
out["buffer_descriptor_b"] = GetHLEBufferDescriptorData<false>(ctx.BufferDescriptorB());
|
out["buffer_descriptor_b"] = GetHLEBufferDescriptorData<false>(ctx.BufferDescriptorB(), memory);
|
||||||
out["buffer_descriptor_c"] = GetHLEBufferDescriptorData<false>(ctx.BufferDescriptorC());
|
out["buffer_descriptor_c"] = GetHLEBufferDescriptorData<false>(ctx.BufferDescriptorC(), memory);
|
||||||
out["buffer_descriptor_x"] = GetHLEBufferDescriptorData<true>(ctx.BufferDescriptorX());
|
out["buffer_descriptor_x"] = GetHLEBufferDescriptorData<true>(ctx.BufferDescriptorX(), memory);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u
|
||||||
const auto title_id = system.CurrentProcess()->GetTitleID();
|
const auto title_id = system.CurrentProcess()->GetTitleID();
|
||||||
auto out = GetFullDataAuto(timestamp, title_id, system);
|
auto out = GetFullDataAuto(timestamp, title_id, system);
|
||||||
|
|
||||||
auto function_out = GetHLERequestContextData(ctx);
|
auto function_out = GetHLERequestContextData(ctx, system.Memory());
|
||||||
function_out["command_id"] = command_id;
|
function_out["command_id"] = command_id;
|
||||||
function_out["function_name"] = name;
|
function_out["function_name"] = name;
|
||||||
function_out["service_name"] = service_name;
|
function_out["service_name"] = service_name;
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,11 @@
|
||||||
#include "core/tools/freezer.h"
|
#include "core/tools/freezer.h"
|
||||||
|
|
||||||
namespace Tools {
|
namespace Tools {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 60);
|
constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 60);
|
||||||
|
|
||||||
u64 MemoryReadWidth(u32 width, VAddr addr) {
|
u64 MemoryReadWidth(Memory::Memory& memory, u32 width, VAddr addr) {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case 1:
|
case 1:
|
||||||
return Memory::Read8(addr);
|
return Memory::Read8(addr);
|
||||||
|
|
@ -32,7 +31,7 @@ u64 MemoryReadWidth(u32 width, VAddr addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryWriteWidth(u32 width, VAddr addr, u64 value) {
|
void MemoryWriteWidth(Memory::Memory& memory, u32 width, VAddr addr, u64 value) {
|
||||||
switch (width) {
|
switch (width) {
|
||||||
case 1:
|
case 1:
|
||||||
Memory::Write8(addr, static_cast<u8>(value));
|
Memory::Write8(addr, static_cast<u8>(value));
|
||||||
|
|
@ -53,7 +52,8 @@ void MemoryWriteWidth(u32 width, VAddr addr, u64 value) {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
Freezer::Freezer(Core::Timing::CoreTiming& core_timing) : core_timing(core_timing) {
|
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Memory::Memory& memory_)
|
||||||
|
: core_timing{core_timing_}, memory{memory_} {
|
||||||
event = Core::Timing::CreateEvent(
|
event = Core::Timing::CreateEvent(
|
||||||
"MemoryFreezer::FrameCallback",
|
"MemoryFreezer::FrameCallback",
|
||||||
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
|
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
|
||||||
|
|
@ -89,7 +89,7 @@ void Freezer::Clear() {
|
||||||
u64 Freezer::Freeze(VAddr address, u32 width) {
|
u64 Freezer::Freeze(VAddr address, u32 width) {
|
||||||
std::lock_guard lock{entries_mutex};
|
std::lock_guard lock{entries_mutex};
|
||||||
|
|
||||||
const auto current_value = MemoryReadWidth(width, address);
|
const auto current_value = MemoryReadWidth(memory, width, address);
|
||||||
entries.push_back({address, width, current_value});
|
entries.push_back({address, width, current_value});
|
||||||
|
|
||||||
LOG_DEBUG(Common_Memory,
|
LOG_DEBUG(Common_Memory,
|
||||||
|
|
@ -169,7 +169,7 @@ void Freezer::FrameCallback(u64 userdata, s64 cycles_late) {
|
||||||
LOG_DEBUG(Common_Memory,
|
LOG_DEBUG(Common_Memory,
|
||||||
"Enforcing memory freeze at address={:016X}, value={:016X}, width={:02X}",
|
"Enforcing memory freeze at address={:016X}, value={:016X}, width={:02X}",
|
||||||
entry.address, entry.value, entry.width);
|
entry.address, entry.value, entry.width);
|
||||||
MemoryWriteWidth(entry.width, entry.address, entry.value);
|
MemoryWriteWidth(memory, entry.width, entry.address, entry.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS - cycles_late, event);
|
core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS - cycles_late, event);
|
||||||
|
|
@ -181,7 +181,7 @@ void Freezer::FillEntryReads() {
|
||||||
LOG_DEBUG(Common_Memory, "Updating memory freeze entries to current values.");
|
LOG_DEBUG(Common_Memory, "Updating memory freeze entries to current values.");
|
||||||
|
|
||||||
for (auto& entry : entries) {
|
for (auto& entry : entries) {
|
||||||
entry.value = MemoryReadWidth(entry.width, entry.address);
|
entry.value = MemoryReadWidth(memory, entry.width, entry.address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ class CoreTiming;
|
||||||
struct EventType;
|
struct EventType;
|
||||||
} // namespace Core::Timing
|
} // namespace Core::Timing
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Tools {
|
namespace Tools {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -34,7 +38,7 @@ public:
|
||||||
u64 value;
|
u64 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Freezer(Core::Timing::CoreTiming& core_timing);
|
explicit Freezer(Core::Timing::CoreTiming& core_timing_, Memory::Memory& memory_);
|
||||||
~Freezer();
|
~Freezer();
|
||||||
|
|
||||||
// Enables or disables the entire memory freezer.
|
// Enables or disables the entire memory freezer.
|
||||||
|
|
@ -78,6 +82,7 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<Core::Timing::EventType> event;
|
std::shared_ptr<Core::Timing::EventType> event;
|
||||||
Core::Timing::CoreTiming& core_timing;
|
Core::Timing::CoreTiming& core_timing;
|
||||||
|
Memory::Memory& memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tools
|
} // namespace Tools
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
RasterizerAccelerated::RasterizerAccelerated() = default;
|
RasterizerAccelerated::RasterizerAccelerated(Memory::Memory& cpu_memory_)
|
||||||
|
: cpu_memory{cpu_memory_} {}
|
||||||
|
|
||||||
RasterizerAccelerated::~RasterizerAccelerated() = default;
|
RasterizerAccelerated::~RasterizerAccelerated() = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,16 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
|
/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
|
||||||
class RasterizerAccelerated : public RasterizerInterface {
|
class RasterizerAccelerated : public RasterizerInterface {
|
||||||
public:
|
public:
|
||||||
explicit RasterizerAccelerated();
|
explicit RasterizerAccelerated(Memory::Memory& cpu_memory_);
|
||||||
~RasterizerAccelerated() override;
|
~RasterizerAccelerated() override;
|
||||||
|
|
||||||
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
|
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
|
||||||
|
|
@ -24,8 +28,9 @@ public:
|
||||||
private:
|
private:
|
||||||
using CachedPageMap = boost::icl::interval_map<u64, int>;
|
using CachedPageMap = boost::icl::interval_map<u64, int>;
|
||||||
CachedPageMap cached_pages;
|
CachedPageMap cached_pages;
|
||||||
|
|
||||||
std::mutex pages_mutex;
|
std::mutex pages_mutex;
|
||||||
|
|
||||||
|
Memory::Memory& cpu_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,9 @@ std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer,
|
||||||
|
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
||||||
ScreenInfo& info)
|
ScreenInfo& info)
|
||||||
: texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device},
|
: RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device},
|
||||||
system{system}, screen_info{info}, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} {
|
shader_cache{*this, system, emu_window, device}, system{system}, screen_info{info},
|
||||||
|
buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} {
|
||||||
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
||||||
state.draw.shader_program = 0;
|
state.draw.shader_program = 0;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,11 @@ CachedBufferEntry::CachedBufferEntry(VAddr cpu_addr, std::size_t size, u64 offse
|
||||||
alignment{alignment} {}
|
alignment{alignment} {}
|
||||||
|
|
||||||
VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager,
|
VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager,
|
||||||
|
Memory::Memory& cpu_memory_,
|
||||||
VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
|
VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
|
||||||
VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size)
|
VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size)
|
||||||
: RasterizerCache{rasterizer}, tegra_memory_manager{tegra_memory_manager} {
|
: RasterizerCache{rasterizer}, tegra_memory_manager{tegra_memory_manager}, cpu_memory{
|
||||||
|
cpu_memory_} {
|
||||||
const auto usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
const auto usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
||||||
vk::BufferUsageFlagBits::eIndexBuffer |
|
vk::BufferUsageFlagBits::eIndexBuffer |
|
||||||
vk::BufferUsageFlagBits::eUniformBuffer;
|
vk::BufferUsageFlagBits::eUniformBuffer;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
#include "video_core/renderer_vulkan/declarations.h"
|
#include "video_core/renderer_vulkan/declarations.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
|
|
||||||
|
namespace Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class MemoryManager;
|
class MemoryManager;
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +62,7 @@ private:
|
||||||
|
|
||||||
class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> {
|
class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> {
|
||||||
public:
|
public:
|
||||||
explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager,
|
explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, Memory::Memory& cpu_memory_,
|
||||||
VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
|
VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
|
||||||
VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size);
|
VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size);
|
||||||
~VKBufferCache();
|
~VKBufferCache();
|
||||||
|
|
@ -92,6 +96,7 @@ private:
|
||||||
void AlignBuffer(std::size_t alignment);
|
void AlignBuffer(std::size_t alignment);
|
||||||
|
|
||||||
Tegra::MemoryManager& tegra_memory_manager;
|
Tegra::MemoryManager& tegra_memory_manager;
|
||||||
|
Memory::Memory& cpu_memory;
|
||||||
|
|
||||||
std::unique_ptr<VKStreamBuffer> stream_buffer;
|
std::unique_ptr<VKStreamBuffer> stream_buffer;
|
||||||
vk::Buffer buffer_handle;
|
vk::Buffer buffer_handle;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue