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.
This commit is contained in:
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;
|
||||||
|
|
Reference in New Issue