diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/video_core/fence_manager.h | 97 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_fence_manager.cpp | 55 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_fence_manager.h | 47 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 2 |
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 | |||
| 23 | engines/shader_bytecode.h | 23 | engines/shader_bytecode.h |
| 24 | engines/shader_header.h | 24 | engines/shader_header.h |
| 25 | engines/shader_type.h | 25 | engines/shader_type.h |
| 26 | fence_manager.h | ||
| 26 | gpu.cpp | 27 | gpu.cpp |
| 27 | gpu.h | 28 | gpu.h |
| 28 | gpu_asynch.cpp | 29 | gpu_asynch.cpp |
| @@ -51,6 +52,8 @@ add_library(video_core STATIC | |||
| 51 | renderer_opengl/gl_buffer_cache.h | 52 | renderer_opengl/gl_buffer_cache.h |
| 52 | renderer_opengl/gl_device.cpp | 53 | renderer_opengl/gl_device.cpp |
| 53 | renderer_opengl/gl_device.h | 54 | renderer_opengl/gl_device.h |
| 55 | renderer_opengl/gl_fence_manager.cpp | ||
| 56 | renderer_opengl/gl_fence_manager.h | ||
| 54 | renderer_opengl/gl_framebuffer_cache.cpp | 57 | renderer_opengl/gl_framebuffer_cache.cpp |
| 55 | renderer_opengl/gl_framebuffer_cache.h | 58 | renderer_opengl/gl_framebuffer_cache.h |
| 56 | renderer_opengl/gl_rasterizer.cpp | 59 | 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 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <algorithm> | ||
| 8 | #include <array> | ||
| 9 | #include <queue> | ||
| 10 | #include <memory> | ||
| 11 | |||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "core/core.h" | ||
| 15 | #include "core/memory.h" | ||
| 16 | #include "core/settings.h" | ||
| 17 | #include "video_core/gpu.h" | ||
| 18 | #include "video_core/memory_manager.h" | ||
| 19 | #include "video_core/rasterizer_interface.h" | ||
| 20 | |||
| 21 | namespace VideoCommon { | ||
| 22 | |||
| 23 | class FenceBase { | ||
| 24 | public: | ||
| 25 | FenceBase(GPUVAddr address, u32 payload) : address{address}, payload{payload} {} | ||
| 26 | |||
| 27 | constexpr GPUVAddr GetAddress() const { | ||
| 28 | return address; | ||
| 29 | } | ||
| 30 | |||
| 31 | constexpr u32 GetPayload() const { | ||
| 32 | return payload; | ||
| 33 | } | ||
| 34 | |||
| 35 | private: | ||
| 36 | GPUVAddr address; | ||
| 37 | u32 payload; | ||
| 38 | }; | ||
| 39 | |||
| 40 | template <typename TFence, typename TTextureCache> | ||
| 41 | class FenceManager { | ||
| 42 | public: | ||
| 43 | void SignalFence(GPUVAddr addr, u32 value) { | ||
| 44 | TryReleasePendingFences(); | ||
| 45 | TFence new_fence = CreateFence(addr, value); | ||
| 46 | QueueFence(new_fence); | ||
| 47 | fences.push(new_fence); | ||
| 48 | texture_cache.CommitAsyncFlushes(); | ||
| 49 | rasterizer.FlushCommands(); | ||
| 50 | rasterizer.SyncGuestHost(); | ||
| 51 | } | ||
| 52 | |||
| 53 | void WaitPendingFences() { | ||
| 54 | while (!fences.empty()) { | ||
| 55 | TFence& current_fence = fences.front(); | ||
| 56 | WaitFence(current_fence); | ||
| 57 | texture_cache.PopAsyncFlushes(); | ||
| 58 | auto& gpu{system.GPU()}; | ||
| 59 | auto& memory_manager{gpu.MemoryManager()}; | ||
| 60 | memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||
| 61 | fences.pop(); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | protected: | ||
| 66 | FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | ||
| 67 | TTextureCache& texture_cache) | ||
| 68 | : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache} {} | ||
| 69 | |||
| 70 | virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0; | ||
| 71 | virtual void QueueFence(TFence& fence) = 0; | ||
| 72 | virtual bool IsFenceSignaled(TFence& fence) = 0; | ||
| 73 | virtual void WaitFence(TFence& fence) = 0; | ||
| 74 | |||
| 75 | Core::System& system; | ||
| 76 | VideoCore::RasterizerInterface& rasterizer; | ||
| 77 | TTextureCache& texture_cache; | ||
| 78 | |||
| 79 | private: | ||
| 80 | void TryReleasePendingFences() { | ||
| 81 | while (!fences.empty()) { | ||
| 82 | TFence& current_fence = fences.front(); | ||
| 83 | if (!IsFenceSignaled(current_fence)) { | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | texture_cache.PopAsyncFlushes(); | ||
| 87 | auto& gpu{system.GPU()}; | ||
| 88 | auto& memory_manager{gpu.MemoryManager()}; | ||
| 89 | memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload()); | ||
| 90 | fences.pop(); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | std::queue<TFence> fences; | ||
| 95 | }; | ||
| 96 | |||
| 97 | } // 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 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | |||
| 7 | #include "video_core/renderer_opengl/gl_fence_manager.h" | ||
| 8 | |||
| 9 | namespace OpenGL { | ||
| 10 | |||
| 11 | GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload) | ||
| 12 | : VideoCommon::FenceBase(address, payload), sync_object{} {} | ||
| 13 | |||
| 14 | GLInnerFence::~GLInnerFence() = default; | ||
| 15 | |||
| 16 | void GLInnerFence::Queue() { | ||
| 17 | ASSERT(sync_object.handle == 0); | ||
| 18 | sync_object.Create(); | ||
| 19 | } | ||
| 20 | |||
| 21 | bool GLInnerFence::IsSignaled() const { | ||
| 22 | ASSERT(sync_object.handle != 0); | ||
| 23 | GLsizei length; | ||
| 24 | GLint sync_status; | ||
| 25 | glGetSynciv(sync_object.handle, GL_SYNC_STATUS, sizeof(GLint), &length, &sync_status); | ||
| 26 | return sync_status == GL_SIGNALED; | ||
| 27 | } | ||
| 28 | |||
| 29 | void GLInnerFence::Wait() { | ||
| 30 | ASSERT(sync_object.handle != 0); | ||
| 31 | while (glClientWaitSync(sync_object.handle, 0, 1000) == GL_TIMEOUT_EXPIRED) | ||
| 32 | ; | ||
| 33 | } | ||
| 34 | |||
| 35 | FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | ||
| 36 | TextureCacheOpenGL& texture_cache) | ||
| 37 | : GenericFenceManager(system, rasterizer, texture_cache) {} | ||
| 38 | |||
| 39 | Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) { | ||
| 40 | return std::make_shared<GLInnerFence>(addr, value); | ||
| 41 | } | ||
| 42 | |||
| 43 | void FenceManagerOpenGL::QueueFence(Fence& fence) { | ||
| 44 | fence->Queue(); | ||
| 45 | } | ||
| 46 | |||
| 47 | bool FenceManagerOpenGL::IsFenceSignaled(Fence& fence) { | ||
| 48 | return fence->IsSignaled(); | ||
| 49 | } | ||
| 50 | |||
| 51 | void FenceManagerOpenGL::WaitFence(Fence& fence) { | ||
| 52 | fence->Wait(); | ||
| 53 | } | ||
| 54 | |||
| 55 | } // 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 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <glad/glad.h> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "video_core/fence_manager.h" | ||
| 12 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 13 | #include "video_core/renderer_opengl/gl_texture_cache.h" | ||
| 14 | |||
| 15 | namespace OpenGL { | ||
| 16 | |||
| 17 | class GLInnerFence : public VideoCommon::FenceBase { | ||
| 18 | public: | ||
| 19 | GLInnerFence(GPUVAddr address, u32 payload); | ||
| 20 | ~GLInnerFence(); | ||
| 21 | |||
| 22 | void Queue(); | ||
| 23 | |||
| 24 | bool IsSignaled() const; | ||
| 25 | |||
| 26 | void Wait(); | ||
| 27 | |||
| 28 | private: | ||
| 29 | OGLSync sync_object; | ||
| 30 | }; | ||
| 31 | |||
| 32 | using Fence = std::shared_ptr<GLInnerFence>; | ||
| 33 | using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL>; | ||
| 34 | |||
| 35 | class FenceManagerOpenGL final : public GenericFenceManager { | ||
| 36 | public: | ||
| 37 | FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | ||
| 38 | TextureCacheOpenGL& texture_cache); | ||
| 39 | |||
| 40 | protected: | ||
| 41 | Fence CreateFence(GPUVAddr addr, u32 value) override; | ||
| 42 | void QueueFence(Fence& fence) override; | ||
| 43 | bool IsFenceSignaled(Fence& fence) override; | ||
| 44 | void WaitFence(Fence& fence) override; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // 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 | |||
| 101 | : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, | 101 | : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, |
| 102 | shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, | 102 | shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, |
| 103 | screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, | 103 | screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, |
| 104 | buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} { | 104 | buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{system, *this, |
| 105 | texture_cache} { | ||
| 105 | CheckExtensions(); | 106 | CheckExtensions(); |
| 106 | } | 107 | } |
| 107 | 108 | ||
| @@ -677,31 +678,11 @@ void RasterizerOpenGL::SyncGuestHost() { | |||
| 677 | } | 678 | } |
| 678 | 679 | ||
| 679 | void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) { | 680 | void RasterizerOpenGL::SignalFence(GPUVAddr addr, u32 value) { |
| 680 | if (!fences.empty()) { | 681 | fence_manager.SignalFence(addr, value); |
| 681 | const std::pair<GPUVAddr, u32>& current_fence = fences.front(); | ||
| 682 | const auto [address, payload] = current_fence; | ||
| 683 | texture_cache.PopAsyncFlushes(); | ||
| 684 | auto& gpu{system.GPU()}; | ||
| 685 | auto& memory_manager{gpu.MemoryManager()}; | ||
| 686 | memory_manager.Write<u32>(address, payload); | ||
| 687 | fences.pop_front(); | ||
| 688 | } | ||
| 689 | fences.emplace_back(addr, value); | ||
| 690 | texture_cache.CommitAsyncFlushes(); | ||
| 691 | FlushCommands(); | ||
| 692 | SyncGuestHost(); | ||
| 693 | } | 682 | } |
| 694 | 683 | ||
| 695 | void RasterizerOpenGL::ReleaseFences() { | 684 | void RasterizerOpenGL::ReleaseFences() { |
| 696 | while (!fences.empty()) { | 685 | fence_manager.WaitPendingFences(); |
| 697 | const std::pair<GPUVAddr, u32>& current_fence = fences.front(); | ||
| 698 | const auto [address, payload] = current_fence; | ||
| 699 | texture_cache.PopAsyncFlushes(); | ||
| 700 | auto& gpu{system.GPU()}; | ||
| 701 | auto& memory_manager{gpu.MemoryManager()}; | ||
| 702 | memory_manager.Write<u32>(address, payload); | ||
| 703 | fences.pop_front(); | ||
| 704 | } | ||
| 705 | } | 686 | } |
| 706 | 687 | ||
| 707 | void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 688 | 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 @@ | |||
| 23 | #include "video_core/rasterizer_interface.h" | 23 | #include "video_core/rasterizer_interface.h" |
| 24 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 24 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 25 | #include "video_core/renderer_opengl/gl_device.h" | 25 | #include "video_core/renderer_opengl/gl_device.h" |
| 26 | #include "video_core/renderer_opengl/gl_fence_manager.h" | ||
| 26 | #include "video_core/renderer_opengl/gl_framebuffer_cache.h" | 27 | #include "video_core/renderer_opengl/gl_framebuffer_cache.h" |
| 27 | #include "video_core/renderer_opengl/gl_query_cache.h" | 28 | #include "video_core/renderer_opengl/gl_query_cache.h" |
| 28 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 29 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -226,6 +227,7 @@ private: | |||
| 226 | SamplerCacheOpenGL sampler_cache; | 227 | SamplerCacheOpenGL sampler_cache; |
| 227 | FramebufferCacheOpenGL framebuffer_cache; | 228 | FramebufferCacheOpenGL framebuffer_cache; |
| 228 | QueryCache query_cache; | 229 | QueryCache query_cache; |
| 230 | FenceManagerOpenGL fence_manager; | ||
| 229 | 231 | ||
| 230 | Core::System& system; | 232 | Core::System& system; |
| 231 | ScreenInfo& screen_info; | 233 | ScreenInfo& screen_info; |