diff options
| author | xbzk <xbzk@eden-emu.dev> | 2026-09-24 18:44:14 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-09-24 18:44:14 +0200 |
| commit | dbeb73ee011416cffc6c203945f5ccc6b90621f6 (patch) | |
| tree | 43d3674029e1756dfbab6554c853d8a371570240 /src/video_core/buffer_cache | |
| parent | cb73a4dcc7710a7fea1643797b17e39858f4ae6a (diff) | |
[video_core] cpu buffer fix + kepler uploads / maxwell macro dirty tracking fixes (#4473)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
Aimed to fix two known UE5 crashes: Kepler uploads and Maxwell macros, both caused by CPU/GPU races due dirty tracking issues.
Kepler ComputeInline: preserved dirty tracking across dma continuations and async readback.
Maxwell macros: preserved gpu owned subranges during page granular cpu uploads.
DiscardWrite: stopped clearing neighboring macro arguments by rounding up ranges.
DMA Step: improved continuation aware dirty sampling.
To the Ender Magnolia crew (maybe 1 or 2 persons): This will fix the dash crash, and the random / shackled beast vaper crashes.
There are some more UE5 issues to go next.
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4473
Reviewed-by: lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src/video_core/buffer_cache')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 4c345dd213..576f20c4e7 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -121,7 +121,7 @@ void BufferCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size template <class P> void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) { - if (memory_tracker.IsRegionGpuModified(device_addr, size)) { + if (IsRegionGpuModified(device_addr, size)) { ClearDownload(device_addr, size); gpu_modified_ranges.Subtract(device_addr, size); } @@ -311,11 +311,8 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer( MarkWrittenBuffer(buffer_id, device_addr, size); break; case ObtainBufferOperation::DiscardWrite: { - const DAddr device_addr_start = Common::AlignDown(device_addr, 64); - const DAddr device_addr_end = Common::AlignUp(device_addr + size, 64); - const size_t new_size = device_addr_end - device_addr_start; - ClearDownload(device_addr_start, new_size); - gpu_modified_ranges.Subtract(device_addr_start, new_size); + ClearDownload(device_addr, size); + gpu_modified_ranges.Subtract(device_addr, size); break; } default: @@ -1742,14 +1739,24 @@ bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si u64 total_size_bytes = 0; u64 largest_copy = 0; const DAddr buffer_start = buffer.cpu_addr_cached; - memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) { + const auto add_upload = [&](DAddr start, DAddr end) { + if (start == end) return; + const u64 range_size = end - start; upload_copies.push_back(BufferCopy{ .src_offset = total_size_bytes, - .dst_offset = device_addr_out - buffer_start, + .dst_offset = start - buffer_start, .size = range_size, }); total_size_bytes += range_size; largest_copy = (std::max)(largest_copy, range_size); + }; + memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) { + DAddr upload_start = device_addr_out; + gpu_modified_ranges.ForEachInRange(device_addr_out, range_size, [&](DAddr gpu_start, DAddr gpu_end) { + add_upload(upload_start, gpu_start); + upload_start = gpu_end; + }); + add_upload(upload_start, device_addr_out + range_size); }); if (total_size_bytes == 0) { return true; |
