aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/buffer_cache/buffer_cache.h
diff options
context:
space:
mode:
authorxbzk <xbzk@eden-emu.dev>2025-12-26 04:54:14 +0100
committercrueter <crueter@eden-emu.dev>2025-12-26 04:54:14 +0100
commitcfae726289e38008ace558ab8bd42fd5189a3ab6 (patch)
tree7c101c36af785bde13850f8f221278a3ee4158f3 /src/video_core/buffer_cache/buffer_cache.h
parentbb94cff886a7379a89a997d307093169b5b757c9 (diff)
[video_core] nvn descriptor layout fix (#3206)
Yxzx presumes this: // The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size. But in MCI i`ve discovered that there are no sizes, both registers are GPU addresses (hence the 2.8gb allocation, it was an address actually) Method could be much simpler but for safety i`ve routed both old and new worlds. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3206 Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com> Reviewed-by: Lizzie <lizzie@eden-emu.dev> Co-authored-by: xbzk <xbzk@eden-emu.dev> Co-committed-by: xbzk <xbzk@eden-emu.dev>
Diffstat (limited to 'src/video_core/buffer_cache/buffer_cache.h')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h19
1 files changed, 12 insertions, 7 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 39c56fb33f..5b5dc1c219 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1705,21 +1705,26 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
return NULL_BINDING;
}
+ // xbzk: New size logic. Fixes MCI.
+ // If ever the * comment below prove wrong, the 'if' block may be removed.
const auto size = [&]() {
const bool is_nvn_cbuf = cbuf_index == 0;
- // The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
if (is_nvn_cbuf) {
- const u32 ssbo_size = gpu_memory->Read<u32>(ssbo_addr + 8);
- if (ssbo_size != 0) {
- return ssbo_size;
+ // * The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
+ const u64 next_qword = gpu_memory->Read<u64>(ssbo_addr + 8);
+ const u32 upper_32 = static_cast<u32>(next_qword >> 32);
+ // Hardware-based detection: GPU addresses have non-zero upper bits
+ if (upper_32 == 0) {
+ // This is a size field, not a GPU address
+ return static_cast<u32>(next_qword); // Return lower_32
}
}
- // Other titles (notably Doom Eternal) may use STG/LDG on buffer addresses in custom defined
- // cbufs, which do not store the sizes adjacent to the addresses, so use the fully
- // mapped buffer size for now.
+ // Fall through: either not NVN cbuf (Doom Eternal & +), or NVN but ssbo_addr+8 is a GPU address (MCI)
const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
+ // Cap at 8MB to prevent allocator overflow from misinterpreted addresses
return (std::min)(memory_layout_size, static_cast<u32>(8_MiB));
}();
+
// Alignment only applies to the offset of the buffer
const u32 alignment = runtime.GetStorageBufferAlignment();
const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment);