Skip to content

Commit cc2a3dd

Browse files
author
N3xoX1
committed
Implement void Core::Memory::HandleRasterizerWrite(VAddr v_address, size_t size)
1 parent b6aec6c commit cc2a3dd

12 files changed

Lines changed: 97 additions & 9 deletions

File tree

src/nxemu-module-spec/base.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
enum
1818
{
1919
MODULE_LOADER_SPECS_VERSION = 0x0106,
20-
MODULE_VIDEO_SPECS_VERSION = 0x0103,
20+
MODULE_VIDEO_SPECS_VERSION = 0x0104,
2121
MODULE_CPU_SPECS_VERSION = 0x0102,
22-
MODULE_OPERATING_SYSTEM_SPECS_VERSION = 0x0105,
22+
MODULE_OPERATING_SYSTEM_SPECS_VERSION = 0x0106,
2323
};
2424

2525
enum MODULE_TYPE : uint16_t

src/nxemu-module-spec/operating_system.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,15 @@ __interface ICacheInvalidator
7070

7171
__interface IOperatingSystem
7272
{
73-
bool Initialize(void) = 0;
73+
bool Initialize() = 0;
7474
bool CreateApplicationProcess(uint64_t codeSize, const IProgramMetadata & metaData, uint64_t & baseAddress, uint64_t & processID, bool is_hbl) = 0;
7575
void StartApplicationProcess(int32_t priority, int64_t stackSize, uint32_t version, StorageId baseGameStorageId, StorageId updateStorageId, uint8_t * nacpData, uint32_t nacpDataLen) = 0;
7676
bool LoadModule(const IModuleInfo & module, uint64_t baseAddress) = 0;
77-
IDeviceMemory & DeviceMemory(void) = 0;
77+
IDeviceMemory & DeviceMemory() = 0;
7878
void KeyboardKeyPress(int modifier, int keyIndex, int keyCode) = 0;
7979
void KeyboardKeyRelease(int modifier, int keyIndex, int keyCode) = 0;
8080
void GatherGPUDirtyMemory(ICacheInvalidator * invalidator) = 0;
81+
void GameFrameEnd() = 0;
8182
};
8283

8384
EXPORT IOperatingSystem * CALL CreateOperatingSystem(ISwitchSystem & system);

src/nxemu-module-spec/video.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ __interface IChannelState
3535
void Release() = 0;
3636
};
3737

38+
typedef void (*DeviceMemoryOperation)(uint64_t device_address, void* user_data);
39+
3840
__interface IVideo
3941
{
4042
bool Initialize(void) = 0;
@@ -48,6 +50,8 @@ __interface IVideo
4850
void UpdateFramebufferLayout(uint32_t width, uint32_t height) = 0;
4951
IChannelState * AllocateChannel() = 0;
5052
void PushGPUEntries(int32_t bindId, const uint64_t * commandList, uint32_t commandListSize, const uint32_t * prefetchCommandlist, uint32_t prefetchCommandlistSize) = 0;
53+
void ApplyOpOnDeviceMemoryPointer(const uint8_t * pointer, uint32_t * scratchBuffer, size_t scratchBufferSize, DeviceMemoryOperation operation, void * userData) = 0;
54+
bool OnCPUWrite(uint64_t addr, uint64_t size) = 0;
5155
};
5256

5357
EXPORT IVideo * CALL CreateVideo(IRenderWindow & RenderWindow, ISwitchSystem & System);

src/nxemu-os/core/core.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ bool System::IsPoweredOn() const {
274274
return impl->is_powered_on.load(std::memory_order::relaxed);
275275
}
276276

277+
size_t System::GetCurrentHostThreadID() const {
278+
return impl->kernel.GetCurrentHostThreadID();
279+
}
280+
277281
std::span<GPUDirtyMemoryManager> System::GetGPUDirtyMemoryManager() {
278282
return impl->gpu_dirty_memory_managers;
279283
}

src/nxemu-os/core/hle/kernel/k_process.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa
322322

323323
// Ensure our memory is initialized.
324324
m_memory.SetCurrentPageTable(*this);
325+
m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager());
325326

326327
// Ensure we can insert the code region.
327328
R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize,
@@ -418,6 +419,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params,
418419

419420
// Ensure our memory is initialized.
420421
m_memory.SetCurrentPageTable(*this);
422+
m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager());
421423

422424
// Ensure we can insert the code region.
423425
R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code),

src/nxemu-os/core/memory.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "core/hle/kernel/k_page_table.h"
2424
#include "core/hle/kernel/k_process.h"
2525
#include "core/memory.h"
26+
#include <nxemu-module-spec/video.h>
2627

2728
namespace Core::Memory {
2829

@@ -800,8 +801,51 @@ struct Memory::Impl {
800801
UNIMPLEMENTED();
801802
}
802803

804+
struct RasterizerWriteContext {
805+
Impl * impl;
806+
size_t core;
807+
size_t size;
808+
};
809+
810+
static void HandleRasterizerWriteCallback(uint64_t address, void * user_data)
811+
{
812+
RasterizerWriteContext & context = *((RasterizerWriteContext*)user_data);
813+
auto& current_area = context.impl->rasterizer_write_areas[context.core];
814+
PAddr subaddress = address >> YUZU_PAGEBITS;
815+
bool do_collection = current_area.last_address == subaddress;
816+
if (!do_collection) [[unlikely]] {
817+
do_collection = context.impl->system.GetVideo().OnCPUWrite(address, context.size);
818+
if (!do_collection) {
819+
return;
820+
}
821+
current_area.last_address = subaddress;
822+
}
823+
context.impl->gpu_dirty_managers[context.core].Collect(address, context.size);
824+
}
825+
803826
void HandleRasterizerWrite(VAddr v_address, size_t size) {
804-
UNIMPLEMENTED();
827+
const auto* p = GetPointerImpl(
828+
v_address, []() {}, []() {});
829+
constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
830+
const size_t core = std::min(system.GetCurrentHostThreadID(),
831+
sys_core); // any other calls threads go to syscore.
832+
833+
RasterizerWriteContext context;
834+
context.impl = this;
835+
context.core = core;
836+
context.size = size;
837+
838+
// Guard on sys_core;
839+
if (core == sys_core) [[unlikely]] {
840+
sys_core_guard.lock();
841+
}
842+
SCOPE_EXIT {
843+
if (core == sys_core) [[unlikely]] {
844+
sys_core_guard.unlock();
845+
}
846+
};
847+
848+
system.GetVideo().ApplyOpOnDeviceMemoryPointer(p, scratch_buffers[core].data(), scratch_buffers[core].size(), HandleRasterizerWriteCallback, &context);
805849
}
806850

807851
struct GPUDirtyState {
@@ -816,6 +860,7 @@ struct Memory::Impl {
816860
Common::PageTable* current_page_table = nullptr;
817861
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
818862
std::array<Common::ScratchBuffer<u32>, Core::Hardware::NUM_CPU_CORES> scratch_buffers{};
863+
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
819864
std::mutex sys_core_guard;
820865

821866
std::optional<Common::HeapTracker> heap_tracker;
@@ -985,6 +1030,10 @@ bool Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size)
9851030
return impl->ZeroBlock(dest_addr, size);
9861031
}
9871032

1033+
void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) {
1034+
impl->gpu_dirty_managers = managers;
1035+
}
1036+
9881037
Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
9891038
return impl->InvalidateDataCache(dest_addr, size);
9901039
}

src/nxemu-os/core/memory.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,8 @@ class Memory :
490490
*/
491491
void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug);
492492

493+
void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers);
494+
493495
bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size);
494496

495497
bool InvalidateSeparateHeap(void* fault_address);

src/nxemu-os/os_manager.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "core/hle/kernel/k_process.h"
44
#include "core/hle/service/am/applet_manager.h"
55
#include "core/hle/service/filesystem/filesystem.h"
6+
#include "core/perf_stats.h"
67
#include "yuzu_common/logging/backend.h"
78
#include "yuzu_common/settings.h"
89
#include "yuzu_common/settings_input.h"
@@ -149,4 +150,9 @@ void OSManager::KeyboardKeyRelease(int modifier, int keyIndex, int keyCode)
149150
void OSManager::GatherGPUDirtyMemory(ICacheInvalidator * invalidator)
150151
{
151152
m_coreSystem.GatherGPUDirtyMemory(invalidator);
152-
}
153+
}
154+
155+
void OSManager::GameFrameEnd()
156+
{
157+
m_coreSystem.GetPerfStats().EndGameFrame();
158+
}

src/nxemu-os/os_manager.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ class OSManager :
1212
void EmulationStarting();
1313

1414
// IOperatingSystem
15-
bool Initialize(void) override;
15+
bool Initialize() override;
1616
bool CreateApplicationProcess(uint64_t codeSize, const IProgramMetadata & metaData, uint64_t & baseAddress, uint64_t & processID, bool is_hbl) override;
1717
void StartApplicationProcess(int32_t priority, int64_t stackSize, uint32_t version, StorageId baseGameStorageId, StorageId updateStorageId, uint8_t * nacpData, uint32_t nacpDataLen) override;
1818
bool LoadModule(const IModuleInfo & module, uint64_t baseAddress) override;
19-
IDeviceMemory & DeviceMemory(void) override;
19+
IDeviceMemory & DeviceMemory() override;
2020
void KeyboardKeyPress(int modifier, int keyIndex, int keyCode) override;
2121
void KeyboardKeyRelease(int modifier, int keyIndex, int keyCode) override;
2222
void GatherGPUDirtyMemory(ICacheInvalidator * invalidator) override;
23+
void GameFrameEnd() override;
2324

2425
private:
2526
OSManager() = delete;

src/nxemu-video/video_manager.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,20 @@ void VideoManager::MemoryMap(uint64_t address, uint64_t virtualAddress, uint64_t
136136
{
137137
impl->m_host1x->MemoryManager().Map(address, virtualAddress, size, Core::Asid{asid}, track);
138138
}
139+
140+
void VideoManager::ApplyOpOnDeviceMemoryPointer(const uint8_t* pointer, uint32_t * scratchBuffer, size_t scratchBufferSize, DeviceMemoryOperation operation, void* userData)
141+
{
142+
Common::ScratchBuffer<u32> tempBuffer;
143+
tempBuffer.resize(scratchBufferSize);
144+
std::memcpy(tempBuffer.data(), scratchBuffer, scratchBufferSize * sizeof(uint32_t));
145+
146+
impl->m_host1x->MemoryManager().ApplyOpOnPointer(pointer, tempBuffer, [operation, userData](DAddr address) {
147+
operation(address, userData);
148+
});
149+
std::memcpy(scratchBuffer, tempBuffer.data(), tempBuffer.size() * sizeof(uint32_t));
150+
}
151+
152+
bool VideoManager::OnCPUWrite(uint64_t addr, uint64_t size)
153+
{
154+
return impl->m_gpuCore->OnCPUWrite(addr, size);
155+
}

0 commit comments

Comments
 (0)