#include "graphics/host_gpu/renderer/cache/gpuResourceManager.h" #include "common/assert.h" #include "graphics/guest_gpu/graphicsRun.h" #include "graphics/host_gpu/renderer/commandScheduler.h" namespace Libs::Graphics { GpuResourceManager::GpuResourceManager(GraphicContext& graphics, CommandScheduler& scheduler) : m_scheduler(scheduler), m_buffer_cache(graphics, scheduler, m_page_manager, m_texture_cache), m_texture_cache(graphics, scheduler, m_page_manager, m_buffer_cache) {} GpuResourceManager::~GpuResourceManager() = default; bool GpuResourceManager::HandleFault(PageFaultAccess access, uint64_t fault_vaddr) noexcept { constexpr uint64_t fault_size = 8; if (!IsMapped(fault_vaddr, fault_size)) { return false; } if (access == PageFaultAccess::Write) { m_buffer_cache.InvalidateMemory(fault_vaddr, fault_size); m_texture_cache.InvalidateMemory(fault_vaddr, fault_size); } else { m_buffer_cache.ReadMemory(fault_vaddr, fault_size); } return true; } bool GpuResourceManager::InvalidateMemory(uint64_t vaddr, uint64_t size) { if (!IsMapped(vaddr, size)) { return false; } m_buffer_cache.InvalidateMemory(vaddr, size); m_texture_cache.InvalidateMemory(vaddr, size); return true; } bool GpuResourceManager::IsMapped(uint64_t vaddr, uint64_t size) const noexcept { if (vaddr == 0 || size == 0 || vaddr >= TRACKER_ADDRESS_SIZE || size > TRACKER_ADDRESS_SIZE - vaddr) { return false; } std::shared_lock lock(m_mapped_ranges_mutex); return m_mapped_ranges.Contains(vaddr, size); } void GpuResourceManager::MapMemory(uint64_t vaddr, uint64_t size) { { std::lock_guard lock(m_mapped_ranges_mutex); m_mapped_ranges.Add(vaddr, size); } m_page_manager.OnGpuMap(vaddr, size); } void GpuResourceManager::UnmapMemory(uint64_t vaddr, uint64_t size) { if (CommandScheduler::InDeferredOperation()) { EXIT("unsupported memory unmap from an asynchronous GPU completion, " "addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n", vaddr, size); } const auto unmap = [this, vaddr, size] { if (m_scheduler.Active()) { const auto tick = m_scheduler.CurrentTick(); m_scheduler.FinishCurrent(); m_scheduler.WaitPriorityOperations(tick); } m_buffer_cache.UnmapMemory(vaddr, size); m_texture_cache.UnmapMemory(vaddr, size); m_page_manager.OnGpuUnmap(vaddr, size); std::lock_guard lock(m_mapped_ranges_mutex); m_mapped_ranges.Subtract(vaddr, size); }; if (m_gpu == nullptr) { unmap(); return; } m_gpu->SendCommandSync(unmap); } void GpuResourceManager::RunGarbageCollector() { m_texture_cache.ProcessDownloadImages(); m_texture_cache.RunGarbageCollector(); m_buffer_cache.RunGarbageCollector(); } } // namespace Libs::Graphics