summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/memory_manager.cpp74
-rw-r--r--src/video_core/memory_manager.h5
2 files changed, 32 insertions, 47 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index dce00e829..055c79a8e 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -265,7 +265,8 @@ size_t MemoryManager::BytesToMapEnd(GPUVAddr gpu_addr) const noexcept {
265 return it->second - (gpu_addr - it->first); 265 return it->second - (gpu_addr - it->first);
266} 266}
267 267
268void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const { 268void MemoryManager::ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size,
269 bool is_safe) const {
269 std::size_t remaining_size{size}; 270 std::size_t remaining_size{size};
270 std::size_t page_index{gpu_src_addr >> page_bits}; 271 std::size_t page_index{gpu_src_addr >> page_bits};
271 std::size_t page_offset{gpu_src_addr & page_mask}; 272 std::size_t page_offset{gpu_src_addr & page_mask};
@@ -276,11 +277,15 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
276 277
277 if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) { 278 if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) {
278 const auto src_addr{*page_addr + page_offset}; 279 const auto src_addr{*page_addr + page_offset};
279 280 if (is_safe) {
280 // Flush must happen on the rasterizer interface, such that memory is always synchronous 281 // Flush must happen on the rasterizer interface, such that memory is always
281 // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. 282 // synchronous when it is read (even when in asynchronous GPU mode).
282 rasterizer->FlushRegion(src_addr, copy_amount); 283 // Fixes Dead Cells title menu.
284 rasterizer->FlushRegion(src_addr, copy_amount);
285 }
283 system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); 286 system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
287 } else {
288 std::memset(dest_buffer, 0, copy_amount);
284 } 289 }
285 290
286 page_index++; 291 page_index++;
@@ -290,31 +295,17 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
290 } 295 }
291} 296}
292 297
298void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const {
299 ReadBlockImpl(gpu_src_addr, dest_buffer, size, true);
300}
301
293void MemoryManager::ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer, 302void MemoryManager::ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer,
294 const std::size_t size) const { 303 const std::size_t size) const {
295 std::size_t remaining_size{size}; 304 ReadBlockImpl(gpu_src_addr, dest_buffer, size, false);
296 std::size_t page_index{gpu_src_addr >> page_bits};
297 std::size_t page_offset{gpu_src_addr & page_mask};
298
299 while (remaining_size > 0) {
300 const std::size_t copy_amount{
301 std::min(static_cast<std::size_t>(page_size) - page_offset, remaining_size)};
302
303 if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) {
304 const auto src_addr{*page_addr + page_offset};
305 system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
306 } else {
307 std::memset(dest_buffer, 0, copy_amount);
308 }
309
310 page_index++;
311 page_offset = 0;
312 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
313 remaining_size -= copy_amount;
314 }
315} 305}
316 306
317void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size) { 307void MemoryManager::WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size,
308 bool is_safe) {
318 std::size_t remaining_size{size}; 309 std::size_t remaining_size{size};
319 std::size_t page_index{gpu_dest_addr >> page_bits}; 310 std::size_t page_index{gpu_dest_addr >> page_bits};
320 std::size_t page_offset{gpu_dest_addr & page_mask}; 311 std::size_t page_offset{gpu_dest_addr & page_mask};
@@ -326,9 +317,11 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
326 if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) { 317 if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) {
327 const auto dest_addr{*page_addr + page_offset}; 318 const auto dest_addr{*page_addr + page_offset};
328 319
329 // Invalidate must happen on the rasterizer interface, such that memory is always 320 if (is_safe) {
330 // synchronous when it is written (even when in asynchronous GPU mode). 321 // Invalidate must happen on the rasterizer interface, such that memory is always
331 rasterizer->InvalidateRegion(dest_addr, copy_amount); 322 // synchronous when it is written (even when in asynchronous GPU mode).
323 rasterizer->InvalidateRegion(dest_addr, copy_amount);
324 }
332 system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); 325 system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
333 } 326 }
334 327
@@ -339,26 +332,13 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
339 } 332 }
340} 333}
341 334
335void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size) {
336 WriteBlockImpl(gpu_dest_addr, src_buffer, size, true);
337}
338
342void MemoryManager::WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer, 339void MemoryManager::WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer,
343 std::size_t size) { 340 std::size_t size) {
344 std::size_t remaining_size{size}; 341 WriteBlockImpl(gpu_dest_addr, src_buffer, size, false);
345 std::size_t page_index{gpu_dest_addr >> page_bits};
346 std::size_t page_offset{gpu_dest_addr & page_mask};
347
348 while (remaining_size > 0) {
349 const std::size_t copy_amount{
350 std::min(static_cast<std::size_t>(page_size) - page_offset, remaining_size)};
351
352 if (const auto page_addr{GpuToCpuAddress(page_index << page_bits)}; page_addr) {
353 const auto dest_addr{*page_addr + page_offset};
354 system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
355 }
356
357 page_index++;
358 page_offset = 0;
359 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
360 remaining_size -= copy_amount;
361 }
362} 342}
363 343
364void MemoryManager::FlushRegion(GPUVAddr gpu_addr, size_t size) const { 344void MemoryManager::FlushRegion(GPUVAddr gpu_addr, size_t size) const {
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 99d13e7f6..38d8d9d74 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -155,6 +155,11 @@ private:
155 155
156 void FlushRegion(GPUVAddr gpu_addr, size_t size) const; 156 void FlushRegion(GPUVAddr gpu_addr, size_t size) const;
157 157
158 void ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size,
159 bool is_safe) const;
160 void WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size,
161 bool is_safe);
162
158 [[nodiscard]] static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { 163 [[nodiscard]] static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) {
159 return (gpu_addr >> page_bits) & page_table_mask; 164 return (gpu_addr >> page_bits) & page_table_mask;
160 } 165 }