diff options
Diffstat (limited to 'src/core/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 514ba0d66..257406f09 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <span> | ||
| 6 | 7 | ||
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 8 | #include "common/atomic_ops.h" | 9 | #include "common/atomic_ops.h" |
| @@ -13,6 +14,7 @@ | |||
| 13 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/device_memory.h" | 16 | #include "core/device_memory.h" |
| 17 | #include "core/gpu_dirty_memory_manager.h" | ||
| 16 | #include "core/hardware_properties.h" | 18 | #include "core/hardware_properties.h" |
| 17 | #include "core/hle/kernel/k_page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 18 | #include "core/hle/kernel/k_process.h" | 20 | #include "core/hle/kernel/k_process.h" |
| @@ -678,7 +680,7 @@ struct Memory::Impl { | |||
| 678 | LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, | 680 | LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, |
| 679 | GetInteger(vaddr), static_cast<u64>(data)); | 681 | GetInteger(vaddr), static_cast<u64>(data)); |
| 680 | }, | 682 | }, |
| 681 | [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(T)); }); | 683 | [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); }); |
| 682 | if (ptr) { | 684 | if (ptr) { |
| 683 | std::memcpy(ptr, &data, sizeof(T)); | 685 | std::memcpy(ptr, &data, sizeof(T)); |
| 684 | } | 686 | } |
| @@ -692,7 +694,7 @@ struct Memory::Impl { | |||
| 692 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}", | 694 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}", |
| 693 | sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data)); | 695 | sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data)); |
| 694 | }, | 696 | }, |
| 695 | [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(T)); }); | 697 | [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); }); |
| 696 | if (ptr) { | 698 | if (ptr) { |
| 697 | const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); | 699 | const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); |
| 698 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); | 700 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); |
| @@ -707,7 +709,7 @@ struct Memory::Impl { | |||
| 707 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}", | 709 | LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}", |
| 708 | GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0])); | 710 | GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0])); |
| 709 | }, | 711 | }, |
| 710 | [&]() { system.GPU().InvalidateRegion(GetInteger(vaddr), sizeof(u128)); }); | 712 | [&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); }); |
| 711 | if (ptr) { | 713 | if (ptr) { |
| 712 | const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); | 714 | const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); |
| 713 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); | 715 | return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); |
| @@ -717,7 +719,7 @@ struct Memory::Impl { | |||
| 717 | 719 | ||
| 718 | void HandleRasterizerDownload(VAddr address, size_t size) { | 720 | void HandleRasterizerDownload(VAddr address, size_t size) { |
| 719 | const size_t core = system.GetCurrentHostThreadID(); | 721 | const size_t core = system.GetCurrentHostThreadID(); |
| 720 | auto& current_area = rasterizer_areas[core]; | 722 | auto& current_area = rasterizer_read_areas[core]; |
| 721 | const VAddr end_address = address + size; | 723 | const VAddr end_address = address + size; |
| 722 | if (current_area.start_address <= address && end_address <= current_area.end_address) | 724 | if (current_area.start_address <= address && end_address <= current_area.end_address) |
| 723 | [[likely]] { | 725 | [[likely]] { |
| @@ -726,9 +728,31 @@ struct Memory::Impl { | |||
| 726 | current_area = system.GPU().OnCPURead(address, size); | 728 | current_area = system.GPU().OnCPURead(address, size); |
| 727 | } | 729 | } |
| 728 | 730 | ||
| 729 | Common::PageTable* current_page_table = nullptr; | 731 | void HandleRasterizerWrite(VAddr address, size_t size) { |
| 730 | std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> rasterizer_areas{}; | 732 | const size_t core = system.GetCurrentHostThreadID(); |
| 733 | auto& current_area = rasterizer_write_areas[core]; | ||
| 734 | VAddr subaddress = address >> YUZU_PAGEBITS; | ||
| 735 | bool do_collection = current_area.last_address == subaddress; | ||
| 736 | if (!do_collection) [[unlikely]] { | ||
| 737 | do_collection = system.GPU().OnCPUWrite(address, size); | ||
| 738 | if (!do_collection) { | ||
| 739 | return; | ||
| 740 | } | ||
| 741 | current_area.last_address = subaddress; | ||
| 742 | } | ||
| 743 | gpu_dirty_managers[core].Collect(address, size); | ||
| 744 | } | ||
| 745 | |||
| 746 | struct GPUDirtyState { | ||
| 747 | VAddr last_address; | ||
| 748 | }; | ||
| 749 | |||
| 731 | Core::System& system; | 750 | Core::System& system; |
| 751 | Common::PageTable* current_page_table = nullptr; | ||
| 752 | std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> | ||
| 753 | rasterizer_read_areas{}; | ||
| 754 | std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; | ||
| 755 | std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; | ||
| 732 | }; | 756 | }; |
| 733 | 757 | ||
| 734 | Memory::Memory(Core::System& system_) : system{system_} { | 758 | Memory::Memory(Core::System& system_) : system{system_} { |
| @@ -876,6 +900,10 @@ void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) | |||
| 876 | impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); | 900 | impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); |
| 877 | } | 901 | } |
| 878 | 902 | ||
| 903 | void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { | ||
| 904 | impl->gpu_dirty_managers = managers; | ||
| 905 | } | ||
| 906 | |||
| 879 | Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { | 907 | Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { |
| 880 | return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); | 908 | return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); |
| 881 | } | 909 | } |