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
2728namespace 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+
9881037Result Memory::InvalidateDataCache (Common::ProcessAddress dest_addr, const std::size_t size) {
9891038 return impl->InvalidateDataCache (dest_addr, size);
9901039}
0 commit comments