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.
master
Lioncash 2019-11-26 14:10:49 +07:00
parent fc7d0a17b6
commit 536fc7f0ea
24 changed files with 108 additions and 61 deletions

@ -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;