summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2020-02-18 01:19:26 +0100
committerFernando Sahmkow <fsahmkow27@gmail.com>2020-04-22 17:36:10 +0200
commit1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1 (patch)
treed0c9926af3f60d35e3cf06f52e114e57fefea4b8
parentOpenGL: Implement Fencing backend. (diff)
downloadyuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.tar
yuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.tar.gz
yuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.tar.bz2
yuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.tar.lz
yuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.tar.xz
yuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.tar.zst
yuzu-1f345ebe3a5501b50f26f0c5c21cac5d55dd79c1.zip
-rw-r--r--src/video_core/CMakeLists.txt3
-rw-r--r--src/video_core/fence_manager.h97
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.cpp55
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.h47
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp27
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h2
6 files changed, 208 insertions, 23 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 258d58eba..9a3f568f9 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -23,6 +23,7 @@ add_library(video_core STATIC
engines/shader_bytecode.h
engines/shader_header.h
engines/shader_type.h
+ fence_manager.h
gpu.cpp
gpu.h
gpu_asynch.cpp
@@ -51,6 +52,8 @@ add_library(video_core STATIC
renderer_opengl/gl_buffer_cache.h
renderer_opengl/gl_device.cpp
renderer_opengl/gl_device.h
+ renderer_opengl/gl_fence_manager.cpp
+ renderer_opengl/gl_fence_manager.h
renderer_opengl/gl_framebuffer_cache.cpp
renderer_opengl/gl_framebuffer_cache.h
renderer_opengl/gl_rasterizer.cpp
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 <algorithm>
+#include <array>
+#include <queue>
+#include <memory>
+
+#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 <typename TFence, typename TTextureCache>
+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<u32>(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<u32>(current_fence->GetAddress(), current_fence->GetPayload());
+ fences.pop();
+ }
+ }
+
+ std::queue<TFence> fences;
+};
+
+} // namespace VideoCommon
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp
new file mode 100644
index 000000000..4517ef150
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp
@@ -0,0 +1,55 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+
+#include "video_core/renderer_opengl/gl_fence_manager.h"
+
+namespace OpenGL {
+
+GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload)
+ : VideoCommon::FenceBase(address, payload), sync_object{} {}
+
+GLInnerFence::~GLInnerFence() = default;
+
+void GLInnerFence::Queue() {
+ ASSERT(sync_object.handle == 0);
+ sync_object.Create();
+}
+
+bool GLInnerFence::IsSignaled() const {
+ ASSERT(sync_object.handle != 0);
+ GLsizei length;
+ GLint sync_status;
+ glGetSynciv(sync_object.handle, GL_SYNC_STATUS, sizeof(GLint), &length, &sync_status);
+ return sync_status == GL_SIGNALED;
+}
+
+void GLInnerFence::Wait() {
+ ASSERT(sync_object.handle != 0);
+ while (glClientWaitSync(sync_object.handle, 0, 1000) == GL_TIMEOUT_EXPIRED)
+ ;
+}
+
+FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
+ TextureCacheOpenGL& texture_cache)
+ : GenericFenceManager(system, rasterizer, texture_cache) {}
+
+Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) {
+ return std::make_shared<GLInnerFence>(addr, value);
+}
+
+void FenceManagerOpenGL::QueueFence(Fence& fence) {
+ fence->Queue();
+}
+
+bool FenceManagerOpenGL::IsFenceSignaled(Fence& fence) {
+ return fence->IsSignaled();
+}
+
+void FenceManagerOpenGL::WaitFence(Fence& fence) {
+ fence->Wait();
+}
+
+} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h
new file mode 100644
index 000000000..3cfa8b1d0
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_fence_manager.h
@@ -0,0 +1,47 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <glad/glad.h>
+
+#include "common/common_types.h"
+#include "video_core/fence_manager.h"
+#include "video_core/renderer_opengl/gl_resource_manager.h"
+#include "video_core/renderer_opengl/gl_texture_cache.h"
+
+namespace OpenGL {
+
+class GLInnerFence : public VideoCommon::FenceBase {
+public:
+ GLInnerFence(GPUVAddr address, u32 payload);
+ ~GLInnerFence();
+
+ void Queue();
+
+ bool IsSignaled() const;
+
+ void Wait();
+
+private:
+ OGLSync sync_object;
+};
+
+using Fence = std::shared_ptr<GLInnerFence>;
+using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL>;
+
+class FenceManagerOpenGL final : public GenericFenceManager {
+public:
+ FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
+ TextureCacheOpenGL& texture_cache);
+
+protected:
+ Fence CreateFence(GPUVAddr addr, u32 value) override;
+ void QueueFence(Fence& fence) override;
+ bool IsFenceSignaled(Fence& fence) override;
+ void WaitFence(Fence& fence) override;
+};
+
+} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 93bb33e8c..35bed444f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -101,7 +101,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
: RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker},
shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system},
screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker},
- buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} {
+ buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{system, *this,
+ texture_cache} {
CheckExtensions();
}
@@ -677,31 +678,11 @@ void RasterizerOpenGL::SyncGuestHost() {
}
void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) {
- if (!fences.empty()) {
- const std::pair<GPUVAddr, u32>& current_fence = fences.front();
- const auto [address, payload] = current_fence;
- texture_cache.PopAsyncFlushes();
- auto& gpu{system.GPU()};
- auto& memory_manager{gpu.MemoryManager()};
- memory_manager.Write<u32>(address, payload);
- fences.pop_front();
- }
- fences.emplace_back(addr, value);
- texture_cache.CommitAsyncFlushes();
- FlushCommands();
- SyncGuestHost();
+ fence_manager.SignalFence(addr, value);
}
void RasterizerOpenGL::ReleaseFences() {
- while (!fences.empty()) {
- const std::pair<GPUVAddr, u32>& current_fence = fences.front();
- const auto [address, payload] = current_fence;
- texture_cache.PopAsyncFlushes();
- auto& gpu{system.GPU()};
- auto& memory_manager{gpu.MemoryManager()};
- memory_manager.Write<u32>(address, payload);
- fences.pop_front();
- }
+ fence_manager.WaitPendingFences();
}
void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 486a154ad..6d173a922 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -23,6 +23,7 @@
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_device.h"
+#include "video_core/renderer_opengl/gl_fence_manager.h"
#include "video_core/renderer_opengl/gl_framebuffer_cache.h"
#include "video_core/renderer_opengl/gl_query_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
@@ -226,6 +227,7 @@ private:
SamplerCacheOpenGL sampler_cache;
FramebufferCacheOpenGL framebuffer_cache;
QueryCache query_cache;
+ FenceManagerOpenGL fence_manager;
Core::System& system;
ScreenInfo& screen_info;