6 changed files with 208 additions and 23 deletions
-
3src/video_core/CMakeLists.txt
-
97src/video_core/fence_manager.h
-
55src/video_core/renderer_opengl/gl_fence_manager.cpp
-
47src/video_core/renderer_opengl/gl_fence_manager.h
-
27src/video_core/renderer_opengl/gl_rasterizer.cpp
-
2src/video_core/renderer_opengl/gl_rasterizer.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 |
||||
@ -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
|
||||
@ -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 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue