mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-26 04:16:18 +00:00
texture_cache: Basic handling of partially resident images (#3066)
* texture_cache: Avoid gpu tracking assert on sparse image At the moment just take the easy way of creating the entire image normally and uploading unmapped subresources are zero * tile_manager: Downgrade assert to error * fix macos
This commit is contained in:
parent
12f4a8f073
commit
d7051f15f4
5 changed files with 69 additions and 2 deletions
|
@ -660,6 +660,9 @@ int PS4_SYSV_ABI sceKernelSetPrtAperture(int id, VAddr address, size_t size) {
|
|||
"PRT aperture id = {}, address = {:#x}, size = {:#x} is set but not used", id,
|
||||
address, size);
|
||||
|
||||
auto* memory = Core::Memory::Instance();
|
||||
memory->SetPrtArea(id, address, size);
|
||||
|
||||
PrtApertures[id] = {address, size};
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,46 @@ u64 MemoryManager::ClampRangeSize(VAddr virtual_addr, u64 size) {
|
|||
return clamped_size;
|
||||
}
|
||||
|
||||
void MemoryManager::SetPrtArea(u32 id, VAddr address, u64 size) {
|
||||
PrtArea& area = prt_areas[id];
|
||||
if (area.mapped) {
|
||||
rasterizer->UnmapMemory(area.start, area.end - area.start);
|
||||
}
|
||||
|
||||
area.start = address;
|
||||
area.end = address + size;
|
||||
area.mapped = true;
|
||||
|
||||
// Pretend the entire PRT area is mapped to avoid GPU tracking errors.
|
||||
// The caches will use CopySparseMemory to fetch data which avoids unmapped areas.
|
||||
rasterizer->MapMemory(address, size);
|
||||
}
|
||||
|
||||
void MemoryManager::CopySparseMemory(VAddr virtual_addr, u8* dest, u64 size) {
|
||||
const bool is_sparse = std::ranges::any_of(
|
||||
prt_areas, [&](const PrtArea& area) { return area.Overlaps(virtual_addr, size); });
|
||||
if (!is_sparse) {
|
||||
std::memcpy(dest, std::bit_cast<const u8*>(virtual_addr), size);
|
||||
return;
|
||||
}
|
||||
|
||||
auto vma = FindVMA(virtual_addr);
|
||||
ASSERT_MSG(vma->second.Contains(virtual_addr, 0),
|
||||
"Attempted to access invalid GPU address {:#x}", virtual_addr);
|
||||
while (size) {
|
||||
u64 copy_size = std::min<u64>(vma->second.size - (virtual_addr - vma->first), size);
|
||||
if (vma->second.IsFree()) {
|
||||
std::memset(dest, 0, copy_size);
|
||||
} else {
|
||||
std::memcpy(dest, std::bit_cast<const u8*>(virtual_addr), copy_size);
|
||||
}
|
||||
size -= copy_size;
|
||||
virtual_addr += copy_size;
|
||||
dest += copy_size;
|
||||
++vma;
|
||||
}
|
||||
}
|
||||
|
||||
bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 num_bytes) {
|
||||
const VAddr virtual_addr = std::bit_cast<VAddr>(address);
|
||||
const auto& vma = FindVMA(virtual_addr)->second;
|
||||
|
|
|
@ -172,6 +172,10 @@ public:
|
|||
|
||||
u64 ClampRangeSize(VAddr virtual_addr, u64 size);
|
||||
|
||||
void SetPrtArea(u32 id, VAddr address, u64 size);
|
||||
|
||||
void CopySparseMemory(VAddr source, u8* dest, u64 size);
|
||||
|
||||
bool TryWriteBacking(void* address, const void* data, u32 num_bytes);
|
||||
|
||||
void SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1, bool use_extended_mem2);
|
||||
|
@ -275,6 +279,18 @@ private:
|
|||
size_t pool_budget{};
|
||||
Vulkan::Rasterizer* rasterizer{};
|
||||
|
||||
struct PrtArea {
|
||||
VAddr start;
|
||||
VAddr end;
|
||||
bool mapped;
|
||||
|
||||
bool Overlaps(VAddr test_address, u64 test_size) const {
|
||||
const VAddr overlap_end = test_address + test_size;
|
||||
return start < overlap_end && test_address < end;
|
||||
}
|
||||
};
|
||||
std::array<PrtArea, 3> prt_areas{};
|
||||
|
||||
friend class ::Core::Devtools::Widget::MemoryMapViewer;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue