From 1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 17 Feb 2020 20:19:26 -0400 Subject: GPU: Implement a Fence Manager. --- src/video_core/fence_manager.h | 97 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/video_core/fence_manager.h (limited to 'src/video_core/fence_manager.h') diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h new file mode 100644 index 000000000..19cec0f66 --- /dev/null +++ b/src/video_core/fence_manager.h @@ -0,0 +1,97 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include + +#include "common/assert.h" +#include "common/common_types.h" +#include "core/core.h" +#include "core/memory.h" +#include "core/settings.h" +#include "video_core/gpu.h" +#include "video_core/memory_manager.h" +#include "video_core/rasterizer_interface.h" + +namespace VideoCommon { + +class FenceBase { +public: + FenceBase(GPUVAddr address, u32 payload) : address{address}, payload{payload} {} + + constexpr GPUVAddr GetAddress() const { + return address; + } + + constexpr u32 GetPayload() const { + return payload; + } + +private: + GPUVAddr address; + u32 payload; +}; + +template +class FenceManager { +public: + void SignalFence(GPUVAddr addr, u32 value) { + TryReleasePendingFences(); + TFence new_fence = CreateFence(addr, value); + QueueFence(new_fence); + fences.push(new_fence); + texture_cache.CommitAsyncFlushes(); + rasterizer.FlushCommands(); + rasterizer.SyncGuestHost(); + } + + void WaitPendingFences() { + while (!fences.empty()) { + TFence& current_fence = fences.front(); + WaitFence(current_fence); + texture_cache.PopAsyncFlushes(); + auto& gpu{system.GPU()}; + auto& memory_manager{gpu.MemoryManager()}; + memory_manager.Write(current_fence->GetAddress(), current_fence->GetPayload()); + fences.pop(); + } + } + +protected: + FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer, + TTextureCache& texture_cache) + : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache} {} + + virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0; + virtual void QueueFence(TFence& fence) = 0; + virtual bool IsFenceSignaled(TFence& fence) = 0; + virtual void WaitFence(TFence& fence) = 0; + + Core::System& system; + VideoCore::RasterizerInterface& rasterizer; + TTextureCache& texture_cache; + +private: + void TryReleasePendingFences() { + while (!fences.empty()) { + TFence& current_fence = fences.front(); + if (!IsFenceSignaled(current_fence)) { + return; + } + texture_cache.PopAsyncFlushes(); + auto& gpu{system.GPU()}; + auto& memory_manager{gpu.MemoryManager()}; + memory_manager.Write(current_fence->GetAddress(), current_fence->GetPayload()); + fences.pop(); + } + } + + std::queue fences; +}; + +} // namespace VideoCommon -- cgit v1.2.3