summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/memory_manager.cpp99
-rw-r--r--src/video_core/memory_manager.h2
-rw-r--r--src/video_core/rasterizer_accelerated.cpp10
-rw-r--r--src/video_core/rasterizer_accelerated.h6
4 files changed, 42 insertions, 75 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index a3389d0d2..fd49bc2a9 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -6,8 +6,8 @@
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/memory/page_table.h"
9#include "core/hle/kernel/process.h" 10#include "core/hle/kernel/process.h"
10#include "core/hle/kernel/vm_manager.h"
11#include "core/memory.h" 11#include "core/memory.h"
12#include "video_core/gpu.h" 12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h" 13#include "video_core/memory_manager.h"
@@ -17,10 +17,7 @@ namespace Tegra {
17 17
18MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer) 18MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
19 : rasterizer{rasterizer}, system{system} { 19 : rasterizer{rasterizer}, system{system} {
20 std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); 20 page_table.Resize(address_space_width, page_bits, false);
21 std::fill(page_table.attributes.begin(), page_table.attributes.end(),
22 Common::PageType::Unmapped);
23 page_table.Resize(address_space_width);
24 21
25 // Initialize the map with a single free region covering the entire managed space. 22 // Initialize the map with a single free region covering the entire managed space.
26 VirtualMemoryArea initial_vma; 23 VirtualMemoryArea initial_vma;
@@ -55,9 +52,9 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
55 52
56 MapBackingMemory(gpu_addr, system.Memory().GetPointer(cpu_addr), aligned_size, cpu_addr); 53 MapBackingMemory(gpu_addr, system.Memory().GetPointer(cpu_addr), aligned_size, cpu_addr);
57 ASSERT(system.CurrentProcess() 54 ASSERT(system.CurrentProcess()
58 ->VMManager() 55 ->PageTable()
59 .SetMemoryAttribute(cpu_addr, size, Kernel::MemoryAttribute::DeviceMapped, 56 .SetMemoryAttribute(cpu_addr, size, Kernel::Memory::MemoryAttribute::DeviceShared,
60 Kernel::MemoryAttribute::DeviceMapped) 57 Kernel::Memory::MemoryAttribute::DeviceShared)
61 .IsSuccess()); 58 .IsSuccess());
62 59
63 return gpu_addr; 60 return gpu_addr;
@@ -70,9 +67,9 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size)
70 67
71 MapBackingMemory(gpu_addr, system.Memory().GetPointer(cpu_addr), aligned_size, cpu_addr); 68 MapBackingMemory(gpu_addr, system.Memory().GetPointer(cpu_addr), aligned_size, cpu_addr);
72 ASSERT(system.CurrentProcess() 69 ASSERT(system.CurrentProcess()
73 ->VMManager() 70 ->PageTable()
74 .SetMemoryAttribute(cpu_addr, size, Kernel::MemoryAttribute::DeviceMapped, 71 .SetMemoryAttribute(cpu_addr, size, Kernel::Memory::MemoryAttribute::DeviceShared,
75 Kernel::MemoryAttribute::DeviceMapped) 72 Kernel::Memory::MemoryAttribute::DeviceShared)
76 .IsSuccess()); 73 .IsSuccess());
77 return gpu_addr; 74 return gpu_addr;
78} 75}
@@ -89,9 +86,10 @@ GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
89 86
90 UnmapRange(gpu_addr, aligned_size); 87 UnmapRange(gpu_addr, aligned_size);
91 ASSERT(system.CurrentProcess() 88 ASSERT(system.CurrentProcess()
92 ->VMManager() 89 ->PageTable()
93 .SetMemoryAttribute(cpu_addr.value(), size, Kernel::MemoryAttribute::DeviceMapped, 90 .SetMemoryAttribute(cpu_addr.value(), size,
94 Kernel::MemoryAttribute::None) 91 Kernel::Memory::MemoryAttribute::DeviceShared,
92 Kernel::Memory::MemoryAttribute::None)
95 .IsSuccess()); 93 .IsSuccess());
96 94
97 return gpu_addr; 95 return gpu_addr;
@@ -147,16 +145,8 @@ T MemoryManager::Read(GPUVAddr addr) const {
147 return value; 145 return value;
148 } 146 }
149 147
150 switch (page_table.attributes[addr >> page_bits]) { 148 UNREACHABLE();
151 case Common::PageType::Unmapped: 149
152 LOG_ERROR(HW_GPU, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, addr);
153 return 0;
154 case Common::PageType::Memory:
155 ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", addr);
156 break;
157 default:
158 UNREACHABLE();
159 }
160 return {}; 150 return {};
161} 151}
162 152
@@ -173,17 +163,7 @@ void MemoryManager::Write(GPUVAddr addr, T data) {
173 return; 163 return;
174 } 164 }
175 165
176 switch (page_table.attributes[addr >> page_bits]) { 166 UNREACHABLE();
177 case Common::PageType::Unmapped:
178 LOG_ERROR(HW_GPU, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8,
179 static_cast<u32>(data), addr);
180 return;
181 case Common::PageType::Memory:
182 ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", addr);
183 break;
184 default:
185 UNREACHABLE();
186 }
187} 167}
188 168
189template u8 MemoryManager::Read<u8>(GPUVAddr addr) const; 169template u8 MemoryManager::Read<u8>(GPUVAddr addr) const;
@@ -249,18 +229,11 @@ void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::s
249 const std::size_t copy_amount{ 229 const std::size_t copy_amount{
250 std::min(static_cast<std::size_t>(page_size) - page_offset, remaining_size)}; 230 std::min(static_cast<std::size_t>(page_size) - page_offset, remaining_size)};
251 231
252 switch (page_table.attributes[page_index]) { 232 const VAddr src_addr{page_table.backing_addr[page_index] + page_offset};
253 case Common::PageType::Memory: { 233 // Flush must happen on the rasterizer interface, such that memory is always synchronous
254 const VAddr src_addr{page_table.backing_addr[page_index] + page_offset}; 234 // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
255 // Flush must happen on the rasterizer interface, such that memory is always synchronous 235 rasterizer.FlushRegion(src_addr, copy_amount);
256 // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. 236 memory.ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
257 rasterizer.FlushRegion(src_addr, copy_amount);
258 memory.ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
259 break;
260 }
261 default:
262 UNREACHABLE();
263 }
264 237
265 page_index++; 238 page_index++;
266 page_offset = 0; 239 page_offset = 0;
@@ -305,18 +278,11 @@ void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const
305 const std::size_t copy_amount{ 278 const std::size_t copy_amount{
306 std::min(static_cast<std::size_t>(page_size) - page_offset, remaining_size)}; 279 std::min(static_cast<std::size_t>(page_size) - page_offset, remaining_size)};
307 280
308 switch (page_table.attributes[page_index]) { 281 const VAddr dest_addr{page_table.backing_addr[page_index] + page_offset};
309 case Common::PageType::Memory: { 282 // Invalidate must happen on the rasterizer interface, such that memory is always
310 const VAddr dest_addr{page_table.backing_addr[page_index] + page_offset}; 283 // synchronous when it is written (even when in asynchronous GPU mode).
311 // Invalidate must happen on the rasterizer interface, such that memory is always 284 rasterizer.InvalidateRegion(dest_addr, copy_amount);
312 // synchronous when it is written (even when in asynchronous GPU mode). 285 memory.WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
313 rasterizer.InvalidateRegion(dest_addr, copy_amount);
314 memory.WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
315 break;
316 }
317 default:
318 UNREACHABLE();
319 }
320 286
321 page_index++; 287 page_index++;
322 page_offset = 0; 288 page_offset = 0;
@@ -362,8 +328,8 @@ void MemoryManager::CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, const
362 328
363bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) { 329bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) {
364 const VAddr addr = page_table.backing_addr[gpu_addr >> page_bits]; 330 const VAddr addr = page_table.backing_addr[gpu_addr >> page_bits];
365 const std::size_t page = (addr & Memory::PAGE_MASK) + size; 331 const std::size_t page = (addr & Core::Memory::PAGE_MASK) + size;
366 return page <= Memory::PAGE_SIZE; 332 return page <= Core::Memory::PAGE_SIZE;
367} 333}
368 334
369void MemoryManager::MapPages(GPUVAddr base, u64 size, u8* memory, Common::PageType type, 335void MemoryManager::MapPages(GPUVAddr base, u64 size, u8* memory, Common::PageType type,
@@ -375,12 +341,13 @@ void MemoryManager::MapPages(GPUVAddr base, u64 size, u8* memory, Common::PageTy
375 ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", 341 ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
376 base + page_table.pointers.size()); 342 base + page_table.pointers.size());
377 343
378 std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type);
379
380 if (memory == nullptr) { 344 if (memory == nullptr) {
381 std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end, memory); 345 while (base != end) {
382 std::fill(page_table.backing_addr.begin() + base, page_table.backing_addr.begin() + end, 346 page_table.pointers[base] = nullptr;
383 backing_addr); 347 page_table.backing_addr[base] = 0;
348
349 base += 1;
350 }
384 } else { 351 } else {
385 while (base != end) { 352 while (base != end) {
386 page_table.pointers[base] = memory; 353 page_table.pointers[base] = memory;
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 0d9468535..0ddd52d5a 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -179,7 +179,7 @@ private:
179 /// End of address space, based on address space in bits. 179 /// End of address space, based on address space in bits.
180 static constexpr GPUVAddr address_space_end{1ULL << address_space_width}; 180 static constexpr GPUVAddr address_space_end{1ULL << address_space_width};
181 181
182 Common::BackingPageTable page_table{page_bits}; 182 Common::PageTable page_table;
183 VMAMap vma_map; 183 VMAMap vma_map;
184 VideoCore::RasterizerInterface& rasterizer; 184 VideoCore::RasterizerInterface& rasterizer;
185 185
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index d01db97da..53622ca05 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -23,15 +23,15 @@ constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
23 23
24} // Anonymous namespace 24} // Anonymous namespace
25 25
26RasterizerAccelerated::RasterizerAccelerated(Memory::Memory& cpu_memory_) 26RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_)
27 : cpu_memory{cpu_memory_} {} 27 : cpu_memory{cpu_memory_} {}
28 28
29RasterizerAccelerated::~RasterizerAccelerated() = default; 29RasterizerAccelerated::~RasterizerAccelerated() = default;
30 30
31void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 31void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
32 std::lock_guard lock{pages_mutex}; 32 std::lock_guard lock{pages_mutex};
33 const u64 page_start{addr >> Memory::PAGE_BITS}; 33 const u64 page_start{addr >> Core::Memory::PAGE_BITS};
34 const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS}; 34 const u64 page_end{(addr + size + Core::Memory::PAGE_SIZE - 1) >> Core::Memory::PAGE_BITS};
35 35
36 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to 36 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
37 // subtract after iterating 37 // subtract after iterating
@@ -44,8 +44,8 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
44 const auto interval = pair.first & pages_interval; 44 const auto interval = pair.first & pages_interval;
45 const int count = pair.second; 45 const int count = pair.second;
46 46
47 const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS; 47 const VAddr interval_start_addr = boost::icl::first(interval) << Core::Memory::PAGE_BITS;
48 const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS; 48 const VAddr interval_end_addr = boost::icl::last_next(interval) << Core::Memory::PAGE_BITS;
49 const u64 interval_size = interval_end_addr - interval_start_addr; 49 const u64 interval_size = interval_end_addr - interval_start_addr;
50 50
51 if (delta > 0 && count == delta) { 51 if (delta > 0 && count == delta) {
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
index 315798e7c..91866d7dd 100644
--- a/src/video_core/rasterizer_accelerated.h
+++ b/src/video_core/rasterizer_accelerated.h
@@ -11,7 +11,7 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
13 13
14namespace Memory { 14namespace Core::Memory {
15class Memory; 15class Memory;
16} 16}
17 17
@@ -20,7 +20,7 @@ namespace VideoCore {
20/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface. 20/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
21class RasterizerAccelerated : public RasterizerInterface { 21class RasterizerAccelerated : public RasterizerInterface {
22public: 22public:
23 explicit RasterizerAccelerated(Memory::Memory& cpu_memory_); 23 explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_);
24 ~RasterizerAccelerated() override; 24 ~RasterizerAccelerated() override;
25 25
26 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; 26 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
@@ -30,7 +30,7 @@ private:
30 CachedPageMap cached_pages; 30 CachedPageMap cached_pages;
31 std::mutex pages_mutex; 31 std::mutex pages_mutex;
32 32
33 Memory::Memory& cpu_memory; 33 Core::Memory::Memory& cpu_memory;
34}; 34};
35 35
36} // namespace VideoCore 36} // namespace VideoCore