summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp4
-rw-r--r--src/core/device_memory_manager.inc91
-rw-r--r--src/core/hle/service/nvdrv/core/heap_mapper.cpp3
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h38
5 files changed, 94 insertions, 46 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 56d76e136..d6193e7e9 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -295,7 +295,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
- config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
+ if (Settings::values.cpuopt_unsafe_ignore_global_monitor.GetValue()) {
+ config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
+ }
}
// Paranoia mode for debugging optimizations
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index c40ff6b83..2d676cf52 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -348,7 +348,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
config.unsafe_optimizations = true;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
config.fastmem_address_space_bits = 64;
- config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
+ if (Settings::values.cpuopt_unsafe_ignore_global_monitor.GetValue()) {
+ config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
+ }
}
// Paranoia mode for debugging optimizations
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
index ebb9d8b1a..a3adaeda5 100644
--- a/src/core/device_memory_manager.inc
+++ b/src/core/device_memory_manager.inc
@@ -16,6 +16,7 @@
#include "core/device_memory.h"
#include "core/device_memory_manager.h"
#include "core/memory.h"
+#include "hle/kernel/board/nintendo/nx/k_system_control.h"
namespace Core {
@@ -28,21 +29,24 @@ public:
void GatherValues(u32 start_entry, Common::ScratchBuffer<u32>& buffer) {
buffer.resize(8);
- buffer.resize(0);
- size_t index = 0;
- const auto add_value = [&](u32 value) {
- buffer.resize(index + 1);
+ const auto add_value = [&buffer](u32 value, size_t index) {
+ if (buffer.size() < index + 1) {
+ buffer.resize(index + 8);
+ }
buffer[index++] = value;
+ return index;
};
+ size_t index = 0;
u32 iter_entry = start_entry;
Entry* current = &storage[iter_entry - 1];
- add_value(current->value);
+ index = add_value(current->value, index);
while (current->next_entry != 0) {
iter_entry = current->next_entry;
current = &storage[iter_entry - 1];
- add_value(current->value);
+ index = add_value(current->value, index);
}
+ buffer.resize(index);
}
u32 Register(u32 value) {
@@ -163,11 +167,9 @@ template <typename Traits>
DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_)
: physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())},
device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS),
- compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
- Settings::MemoryLayout::Memory_4Gb
- ? physical_min_bits
- : physical_max_bits) -
- Memory::YUZU_PAGEBITS)),
+ compressed_device_addr(Common::AlignUp(
+ Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize(),
+ Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS),
continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS),
cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) {
impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>();
@@ -179,11 +181,9 @@ DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memo
continuity_tracker[i] = 1;
cpu_backing_address[i] = 0;
}
- const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
- Settings::MemoryLayout::Memory_4Gb
- ? physical_min_bits
- : physical_max_bits) -
- Memory::YUZU_PAGEBITS);
+ const size_t total_phys = Common::AlignUp(
+ Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize(),
+ Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
for (size_t i = 0; i < total_phys; i++) {
compressed_device_addr[i] = 0;
}
@@ -257,6 +257,7 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
auto phys_addr = compressed_physical_ptr[start_page_d + i];
compressed_physical_ptr[start_page_d + i] = 0;
cpu_backing_address[start_page_d + i] = 0;
+ continuity_tracker[start_page_d + i] = 1;
if (phys_addr != 0) [[likely]] {
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] {
@@ -273,6 +274,16 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG;
}
}
+ if (start_page_d > 0) {
+ for (size_t p = start_page_d; p > 0; p--) {
+ size_t prev_page = p - 1;
+ if (prev_page + continuity_tracker[prev_page] > start_page_d) {
+ continuity_tracker[prev_page] = static_cast<u32>(start_page_d - prev_page);
+ } else {
+ break;
+ }
+ }
+ }
}
template <typename Traits>
void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
@@ -287,7 +298,7 @@ void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtu
const VAddr new_vaddress = virtual_address + index * Memory::YUZU_PAGESIZE;
const uintptr_t new_ptr = reinterpret_cast<uintptr_t>(
process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress)));
- if (new_ptr + page_size == last_ptr) {
+ if (new_ptr != 0 && last_ptr != 0 && new_ptr + page_size == last_ptr) {
page_count++;
} else {
page_count = 1;
@@ -386,26 +397,39 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
std::size_t page_offset = addr & Memory::YUZU_PAGEMASK;
while (remaining_size) {
- const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]);
- const std::size_t copy_amount =
- std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
- const auto current_vaddr =
- static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
- SCOPE_EXIT{
- page_index += next_pages;
- page_offset = 0;
- increment(copy_amount);
- remaining_size -= copy_amount;
- };
-
auto phys_addr = compressed_physical_ptr[page_index];
if (phys_addr == 0) {
+ size_t unmapped_pages = 1;
+ while ((unmapped_pages << Memory::YUZU_PAGEBITS) - page_offset < remaining_size &&
+ compressed_physical_ptr[page_index + unmapped_pages] == 0) {
+ unmapped_pages++;
+ }
+ const std::size_t copy_amount =
+ std::min((unmapped_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
+ const auto current_vaddr =
+ static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
on_unmapped(copy_amount, current_vaddr);
+ page_index += unmapped_pages;
+ page_offset = 0;
+ increment(copy_amount);
+ remaining_size -= copy_amount;
continue;
}
+
+ size_t next_pages = std::max<size_t>(1, static_cast<std::size_t>(continuity_tracker[page_index]));
+ if (compressed_physical_ptr[page_index + next_pages - 1] == 0) {
+ next_pages = 1;
+ }
+ const std::size_t copy_amount =
+ std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
auto* mem_ptr = GetPointerFromRaw<u8>(
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
on_memory(copy_amount, mem_ptr);
+
+ page_index += next_pages;
+ page_offset = 0;
+ increment(copy_amount);
+ remaining_size -= copy_amount;
}
}
@@ -419,13 +443,10 @@ void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, s
WalkBlock(
address, size,
[&](size_t copy_amount, DAddr current_vaddr) {
- // Fill unmapped memory with a known pattern instead of zeros
- constexpr u8 UNMAPPED_MEMORY_PATTERN = 0xCC;
- std::memset(dest_pointer, UNMAPPED_MEMORY_PATTERN, copy_amount);
+ std::memset(dest_pointer, 0, copy_amount);
LOG_DEBUG(HW_Memory,
- "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}). "
- "Filling with pattern 0x{:02X}",
- current_vaddr, address, size, UNMAPPED_MEMORY_PATTERN);
+ "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
+ current_vaddr, address, size);
},
[&](size_t copy_amount, const u8* const src_ptr) {
if (src_ptr) {
diff --git a/src/core/hle/service/nvdrv/core/heap_mapper.cpp b/src/core/hle/service/nvdrv/core/heap_mapper.cpp
index af17e3e85..3f2418771 100644
--- a/src/core/hle/service/nvdrv/core/heap_mapper.cpp
+++ b/src/core/hle/service/nvdrv/core/heap_mapper.cpp
@@ -51,7 +51,8 @@ DAddr HeapMapper::Map(VAddr start, size_t size) {
m_internal->m_temporary_set.ForEach([this](VAddr start_addr, VAddr end_addr) {
const size_t sub_size = end_addr - start_addr;
const size_t offset = start_addr - m_vaddress;
- m_internal->m_device_memory.Map(m_daddress + offset, m_vaddress + offset, sub_size, m_asid);
+ m_internal->m_device_memory.Map(m_daddress + offset, m_vaddress + offset, sub_size,
+ m_asid, true);
});
// Add the mapping range to the split map, to register the map and overlaps.
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 7351e2fc3..87dda9a9b 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1513,6 +1513,27 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
if constexpr (USE_MEMORY_MAPS) {
auto upload_staging = runtime.UploadStagingBuffer(total_size_bytes);
const std::span<u8> staging_pointer = upload_staging.mapped_span;
+ if (staging_pointer.size() < total_size_bytes) {
+ LOG_ERROR(HW_Memory,
+ "BufferCache rejected short mapped upload staging allocation: "
+ "buffer_base=0x{:016X} buffer_size={} staging_size={} total_size={}",
+ buffer.CpuAddr(), buffer.SizeBytes(), staging_pointer.size(), total_size_bytes);
+ return;
+ }
+ for (const BufferCopy& copy : copies) {
+ if (copy.src_offset > staging_pointer.size() ||
+ copy.size > staging_pointer.size() - copy.src_offset ||
+ copy.dst_offset > buffer.SizeBytes() ||
+ copy.size > buffer.SizeBytes() - copy.dst_offset) {
+ LOG_ERROR(HW_Memory,
+ "BufferCache rejected out-of-bounds mapped upload: buffer_base=0x{:016X} "
+ "buffer_size={} staging_size={} total_size={} src_offset={} dst_offset={} "
+ "copy_size={}",
+ buffer.CpuAddr(), buffer.SizeBytes(), staging_pointer.size(),
+ total_size_bytes, copy.src_offset, copy.dst_offset, copy.size);
+ return;
+ }
+ }
for (BufferCopy& copy : copies) {
u8* const src_pointer = staging_pointer.data() + copy.src_offset;
const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
@@ -1782,15 +1803,16 @@ TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr,
template <class P>
std::span<const u8> BufferCache<P>::ImmediateBufferWithData(DAddr device_addr, size_t size) {
- u8* const base_pointer = device_memory.GetPointer<u8>(device_addr);
- if (IsRangeGranular(device_addr, size) ||
- base_pointer + size == device_memory.GetPointer<u8>(device_addr + size)) {
- return std::span(base_pointer, size);
- } else {
- const std::span<u8> span = ImmediateBuffer(size);
- device_memory.ReadBlockUnsafe(device_addr, span.data(), size);
- return span;
+ if (IsRangeGranular(device_addr, size)) {
+ if (u8* const base_pointer = device_memory.GetPointer<u8>(device_addr)) {
+ return std::span(base_pointer, size);
+ }
+ } else if (u8* const span_pointer = device_memory.GetSpan(device_addr, size)) {
+ return std::span(span_pointer, size);
}
+ const std::span<u8> span = ImmediateBuffer(size);
+ device_memory.ReadBlockUnsafe(device_addr, span.data(), size);
+ return span;
}
template <class P>