Compare commits
3 Commits
true-eds
...
memsetopsy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
518b806473 | ||
|
|
8f6e23bba0 | ||
|
|
cfae726289 |
@@ -219,11 +219,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClearBackingRegion(size_t physical_offset, size_t length) {
|
|
||||||
// TODO: This does not seem to be possible on Windows.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnableDirectMappedAddress() {
|
void EnableDirectMappedAddress() {
|
||||||
// TODO
|
// TODO
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@@ -617,24 +612,6 @@ public:
|
|||||||
ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
|
ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClearBackingRegion(size_t physical_offset, size_t length) {
|
|
||||||
#ifdef __linux__
|
|
||||||
// Only incur syscall cost IF memset would be slower (theshold = 16MiB)
|
|
||||||
// TODO(lizzie): Smarter way to dynamically get this threshold (broadwell != raptor lake) for example
|
|
||||||
if (length >= 2097152UL * 8) {
|
|
||||||
// Set MADV_REMOVE on backing map to destroy it instantly.
|
|
||||||
// This also deletes the area from the backing file.
|
|
||||||
int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
|
|
||||||
ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnableDirectMappedAddress() {
|
void EnableDirectMappedAddress() {
|
||||||
virtual_base = nullptr;
|
virtual_base = nullptr;
|
||||||
}
|
}
|
||||||
@@ -762,9 +739,7 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, MemoryPermission
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) {
|
void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) {
|
||||||
if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) {
|
std::memset(backing_base + physical_offset, fill_value, length);
|
||||||
std::memset(backing_base + physical_offset, fill_value, length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostMemory::EnableDirectMappedAddress() {
|
void HostMemory::EnableDirectMappedAddress() {
|
||||||
|
|||||||
@@ -1705,21 +1705,26 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
|
|||||||
return NULL_BINDING;
|
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 auto size = [&]() {
|
||||||
const bool is_nvn_cbuf = cbuf_index == 0;
|
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) {
|
if (is_nvn_cbuf) {
|
||||||
const u32 ssbo_size = gpu_memory->Read<u32>(ssbo_addr + 8);
|
// * The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
|
||||||
if (ssbo_size != 0) {
|
const u64 next_qword = gpu_memory->Read<u64>(ssbo_addr + 8);
|
||||||
return ssbo_size;
|
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
|
// Fall through: either not NVN cbuf (Doom Eternal & +), or NVN but ssbo_addr+8 is a GPU address (MCI)
|
||||||
// cbufs, which do not store the sizes adjacent to the addresses, so use the fully
|
|
||||||
// mapped buffer size for now.
|
|
||||||
const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
|
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));
|
return (std::min)(memory_layout_size, static_cast<u32>(8_MiB));
|
||||||
}();
|
}();
|
||||||
|
|
||||||
// Alignment only applies to the offset of the buffer
|
// Alignment only applies to the offset of the buffer
|
||||||
const u32 alignment = runtime.GetStorageBufferAlignment();
|
const u32 alignment = runtime.GetStorageBufferAlignment();
|
||||||
const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment);
|
const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment);
|
||||||
|
|||||||
Reference in New Issue
Block a user