diff options
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | 1 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | 5 | ||||
-rw-r--r-- | src/video_core/memory_manager.cpp | 19 | ||||
-rw-r--r-- | src/video_core/memory_manager.h | 8 | ||||
-rw-r--r-- | src/video_core/rasterizer_interface.h | 6 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 20 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 2 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 20 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 2 |
11 files changed, 89 insertions, 3 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 6c1edce331..4f42fffcb2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -68,6 +68,7 @@ void nvhost_nvdec::OnOpen(DeviceFD fd) {} void nvhost_nvdec::OnClose(DeviceFD fd) { LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); system.GPU().ClearCdmaInstance(); + system.GPU().MemoryManager().InvalidateQueuedCaches(); } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 98e6296f1e..1375689e7c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -198,7 +198,13 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec return NvResult::InvalidState; } if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { - gpu.MemoryManager().Unmap(object->dma_map_addr, *size); + if (vic_device) { + // UnmapVicFrame defers texture_cache invalidation of the frame address until + // the stream is over + gpu.MemoryManager().UnmapVicFrame(object->dma_map_addr, *size); + } else { + gpu.MemoryManager().Unmap(object->dma_map_addr, *size); + } } else { // This occurs quite frequently, however does not seem to impact functionality LOG_DEBUG(Service_NVDRV, "invalid offset=0x{:X} dma=0x{:X}", object->addr, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index da10f5f412..46c81f9067 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -160,6 +160,7 @@ protected: s32_le nvmap_fd{}; u32_le submit_timeout{}; + bool vic_device{}; std::shared_ptr<nvmap> nvmap_dev; SyncpointManager& syncpoint_manager; std::array<u32, MaxSyncPoints> device_syncpoints{}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 21d101e8a6..64aa7b06f1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -12,8 +12,9 @@ namespace Service::Nvidia::Devices { nvhost_vic::nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, SyncpointManager& syncpoint_manager_) - : nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {} - + : nvhost_nvdec_common(system_, std::move(nvmap_dev_), syncpoint_manager_) { + vic_device = true; +} nvhost_vic::~nvhost_vic() = default; NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index eb58ac6b6c..76492a103b 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -114,6 +114,25 @@ void MemoryManager::TryUnlockPage(PageEntry page_entry, std::size_t size) { .IsSuccess()); } +void MemoryManager::UnmapVicFrame(GPUVAddr gpu_addr, std::size_t size) { + if (!size) { + return; + } + + const std::optional<VAddr> cpu_addr = GpuToCpuAddress(gpu_addr); + ASSERT(cpu_addr); + rasterizer->InvalidateExceptTextureCache(*cpu_addr, size); + cache_invalidate_queue.push_back({*cpu_addr, size}); + + UpdateRange(gpu_addr, PageEntry::State::Unmapped, size); +} + +void MemoryManager::InvalidateQueuedCaches() { + for (const auto& entry : cache_invalidate_queue) { + rasterizer->InvalidateTextureCache(entry.first, entry.second); + } + cache_invalidate_queue.clear(); +} PageEntry MemoryManager::GetPageEntry(GPUVAddr gpu_addr) const { return page_table[PageEntryIndex(gpu_addr)]; } diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index b3538d503d..5d6c196fa3 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -123,6 +123,14 @@ public: [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align); void Unmap(GPUVAddr gpu_addr, std::size_t size); + /** + * Some Decoded NVDEC frames require that texture cache does not get invalidated. + * UnmapVicFrame defers the texture cache invalidation until the stream ends + * by invoking InvalidateQueuedCaches to invalidate all frame texture caches. + */ + void UnmapVicFrame(GPUVAddr gpu_addr, std::size_t size); + void InvalidateQueuedCaches(); + private: [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const; void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 50491b7586..afc7ff4ae1 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -69,6 +69,12 @@ public: /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory virtual void FlushRegion(VAddr addr, u64 size) = 0; + /// Notify rasterizer to flush the texture cache to Switch memory + virtual void InvalidateExceptTextureCache(VAddr addr, u64 size) = 0; + + /// Notify rasterizer to invalidate the texture cache + virtual void InvalidateTextureCache(VAddr addr, u64 size) = 0; + /// Check if the the specified memory area requires flushing to CPU Memory. virtual bool MustFlushRegion(VAddr addr, u64 size) = 0; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a5dbb9adfd..b387f29439 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -544,6 +544,26 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { query_cache.FlushRegion(addr, size); } +void RasterizerOpenGL::InvalidateExceptTextureCache(VAddr addr, u64 size) { + if (addr == 0 || size == 0) { + return; + } + shader_cache.InvalidateRegion(addr, size); + { + std::scoped_lock lock{buffer_cache.mutex}; + buffer_cache.WriteMemory(addr, size); + } + query_cache.InvalidateRegion(addr, size); +} + +void RasterizerOpenGL::InvalidateTextureCache(VAddr addr, u64 size) { + if (addr == 0 || size == 0) { + return; + } + std::scoped_lock lock{texture_cache.mutex}; + texture_cache.UnmapMemory(addr, size); +} + bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size) { std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; if (!Settings::IsGPULevelHigh()) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 3745cf6379..9730544d9c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -74,6 +74,8 @@ public: void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; void FlushAll() override; void FlushRegion(VAddr addr, u64 size) override; + void InvalidateExceptTextureCache(VAddr addr, u64 size) override; + void InvalidateTextureCache(VAddr addr, u64 size) override; bool MustFlushRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override; void OnCPUWrite(VAddr addr, u64 size) override; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index e9a0e78118..ea47ac5fc6 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -493,6 +493,26 @@ void RasterizerVulkan::FlushRegion(VAddr addr, u64 size) { query_cache.FlushRegion(addr, size); } +void Vulkan::RasterizerVulkan::InvalidateExceptTextureCache(VAddr addr, u64 size) { + if (addr == 0 || size == 0) { + return; + } + pipeline_cache.InvalidateRegion(addr, size); + { + std::scoped_lock lock{buffer_cache.mutex}; + buffer_cache.WriteMemory(addr, size); + } + query_cache.InvalidateRegion(addr, size); +} + +void Vulkan::RasterizerVulkan::InvalidateTextureCache(VAddr addr, u64 size) { + if (addr == 0 || size == 0) { + return; + } + std::scoped_lock lock{texture_cache.mutex}; + texture_cache.UnmapMemory(addr, size); +} + bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size) { std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex}; if (!Settings::IsGPULevelHigh()) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 235afc6f3b..d8b5bf0fcb 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -66,6 +66,8 @@ public: void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; void FlushAll() override; void FlushRegion(VAddr addr, u64 size) override; + void InvalidateExceptTextureCache(VAddr addr, u64 size) override; + void InvalidateTextureCache(VAddr addr, u64 size) override; bool MustFlushRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override; void OnCPUWrite(VAddr addr, u64 size) override; |