#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_BUFFERCACHE_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_BUFFERCACHE_H_ #include "common/abi.h" #include "common/common.h" #include "common/slotVector.h" #include "graphics/host_gpu/memoryTracker.h" #include "graphics/host_gpu/rangeSet.h" #include "graphics/host_gpu/renderer/cache/streamBuffer.h" #include #include #include #include namespace Libs::Graphics { struct GraphicContext; class CommandScheduler; class TextureCache; using BufferId = Common::SlotId; inline constexpr BufferId NULL_BUFFER_ID {0}; class BufferCache { public: static constexpr uint64_t CACHING_PAGE_SIZE = 16ull * 1024ull; BufferCache(GraphicContext& graphics, CommandScheduler& scheduler, PageManager& page_manager, TextureCache& texture_cache); ~BufferCache(); KYTY_CLASS_NO_COPY(BufferCache); void InvalidateMemory(uint64_t vaddr, uint64_t size); void ReadMemory(uint64_t vaddr, uint64_t size, bool is_write = false); void UnmapMemory(uint64_t vaddr, uint64_t size); [[nodiscard]] Buffer& GetBuffer(BufferId id) { return m_slot_buffers[id]; } [[nodiscard]] BufferId FindBuffer(uint64_t vaddr, uint64_t size); [[nodiscard]] std::pair ObtainBuffer(uint64_t vaddr, uint64_t size, bool is_written, bool is_texel_buffer = false, BufferId id = {}); [[nodiscard]] StreamBuffer& GetUtilityBuffer(MemoryUsage usage) noexcept { switch (usage) { case MemoryUsage::Upload: return m_staging_buffer; case MemoryUsage::Stream: return m_stream_buffer; case MemoryUsage::Download: return m_download_buffer; case MemoryUsage::DeviceLocal: return m_device_buffer; } EXIT("BufferCache: invalid utility-buffer usage\n"); } [[nodiscard]] const Buffer* GetGdsBuffer() const noexcept { return &m_gds_buffer; } [[nodiscard]] std::pair ObtainBufferForImage(uint64_t vaddr, uint64_t size); void FillBuffer(uint64_t vaddr, uint64_t size, uint32_t value, bool is_gds); void CopyBuffer(uint64_t dst_vaddr, uint64_t src_vaddr, uint64_t size, bool dst_gds, bool src_gds); // Cache-index and exact dirty-range queries require GPU-thread serialization. [[nodiscard]] bool IsRegionRegistered(uint64_t vaddr, uint64_t size); [[nodiscard]] bool HasGpuDirtyBytes(uint64_t vaddr, uint64_t size); [[nodiscard]] bool IsRegionCpuModified(uint64_t vaddr, uint64_t size); [[nodiscard]] bool IsRegionGpuModified(uint64_t vaddr, uint64_t size); void RunGarbageCollector(); private: friend struct BufferCacheTestAccess; struct DownloadCopy; struct DownloadRange; static constexpr uint64_t DOWNLOAD_ALIGNMENT = 64; [[nodiscard]] static constexpr uint64_t AlignDownload(uint64_t size) noexcept { return (size + DOWNLOAD_ALIGNMENT - 1) & ~(DOWNLOAD_ALIGNMENT - 1); } [[nodiscard]] static std::pair DownloadEnvelope(const DownloadCopy& copy); void WriteDataBuffer(Buffer& buffer, uint64_t address, const void* source, uint64_t size); void Unregister(BufferId id); void DeleteBuffer(BufferId id); [[nodiscard]] bool SynchronizeBuffer(Buffer& buffer, uint64_t vaddr, uint64_t size, bool is_written, bool is_texel_buffer); [[nodiscard]] vk::Buffer UploadCopies(Buffer& buffer, std::span copies, uint64_t total_size); [[nodiscard]] bool SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uint64_t size); [[nodiscard]] std::vector RecordDownloads(std::span copies); void PublishDownloads(std::span downloads); void QueueGarbageDownload(std::span copies, BufferId id, uint64_t address, uint64_t size); void WriteHostMemory(uint64_t vaddr, std::span data); void ReadMemoryOnGpu(uint64_t vaddr, uint64_t size, bool is_write); GraphicContext& m_graphics; CommandScheduler& m_scheduler; Buffer m_gds_buffer; Common::SlotVector m_slot_buffers; std::map m_buffers; RangeSet m_gpu_modified_ranges; MemoryTracker m_memory_tracker; StreamBuffer m_staging_buffer; StreamBuffer m_stream_buffer; StreamBuffer m_download_buffer; StreamBuffer m_device_buffer; TextureCache& m_texture_cache; uint64_t m_total_used_memory = 0; uint64_t m_trigger_gc_memory = 1ull * 1024 * 1024 * 1024; uint64_t m_critical_gc_memory = 2ull * 1024 * 1024 * 1024; uint64_t m_gc_tick = 0; }; } // namespace Libs::Graphics #endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_BUFFERCACHE_H_