summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2020-04-15 22:36:14 +0200
committerFernando Sahmkow <fsahmkow27@gmail.com>2020-04-22 17:36:18 +0200
commit0649f0590047e8cc0b16a10dec5eb74938fef718 (patch)
treeb56cf7fb42c31f0012b063d356dc2b1eb1126a42
parentOpenGL: Guarantee writes to Buffers. (diff)
downloadyuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.gz
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.bz2
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.lz
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.xz
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.tar.zst
yuzu-0649f0590047e8cc0b16a10dec5eb74938fef718.zip
-rw-r--r--src/video_core/fence_manager.h18
-rw-r--r--src/video_core/query_cache.h50
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.h7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp6
5 files changed, 77 insertions, 12 deletions
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h
index 417cb113f..99a138b5b 100644
--- a/src/video_core/fence_manager.h
+++ b/src/video_core/fence_manager.h
@@ -49,15 +49,17 @@ protected:
bool is_stubbed;
};
-template <typename TFence, typename TTextureCache, typename TTBufferCache>
+template <typename TFence, typename TTextureCache, typename TTBufferCache, typename TQueryCache>
class FenceManager {
public:
void SignalSemaphore(GPUVAddr addr, u32 value) {
TryReleasePendingFences();
bool should_flush = texture_cache.HasUncommitedFlushes();
should_flush |= buffer_cache.HasUncommitedFlushes();
+ should_flush |= query_cache.HasUncommitedFlushes();
texture_cache.CommitAsyncFlushes();
buffer_cache.CommitAsyncFlushes();
+ query_cache.CommitAsyncFlushes();
TFence new_fence = CreateFence(addr, value, !should_flush);
fences.push(new_fence);
QueueFence(new_fence);
@@ -71,8 +73,10 @@ public:
TryReleasePendingFences();
bool should_flush = texture_cache.HasUncommitedFlushes();
should_flush |= buffer_cache.HasUncommitedFlushes();
+ should_flush |= query_cache.HasUncommitedFlushes();
texture_cache.CommitAsyncFlushes();
buffer_cache.CommitAsyncFlushes();
+ query_cache.CommitAsyncFlushes();
TFence new_fence = CreateFence(value, !should_flush);
fences.push(new_fence);
QueueFence(new_fence);
@@ -87,11 +91,13 @@ public:
TFence& current_fence = fences.front();
bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
+ should_wait |= query_cache.ShouldWaitAsyncFlushes();
if (should_wait) {
WaitFence(current_fence);
}
texture_cache.PopAsyncFlushes();
buffer_cache.PopAsyncFlushes();
+ query_cache.PopAsyncFlushes();
auto& gpu{system.GPU()};
if (current_fence->IsSemaphore()) {
auto& memory_manager{gpu.MemoryManager()};
@@ -105,9 +111,10 @@ public:
protected:
FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
- TTextureCache& texture_cache, TTBufferCache& buffer_cache)
- : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{
- buffer_cache} {}
+ TTextureCache& texture_cache, TTBufferCache& buffer_cache,
+ TQueryCache& query_cache)
+ : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache},
+ buffer_cache{buffer_cache}, query_cache{query_cache} {}
virtual TFence CreateFence(u32 value, bool is_stubbed) = 0;
virtual TFence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) = 0;
@@ -119,6 +126,7 @@ protected:
VideoCore::RasterizerInterface& rasterizer;
TTextureCache& texture_cache;
TTBufferCache& buffer_cache;
+ TQueryCache& query_cache;
private:
void TryReleasePendingFences() {
@@ -126,11 +134,13 @@ private:
TFence& current_fence = fences.front();
bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
+ should_wait |= query_cache.ShouldWaitAsyncFlushes();
if (should_wait && !IsFenceSignaled(current_fence)) {
return;
}
texture_cache.PopAsyncFlushes();
buffer_cache.PopAsyncFlushes();
+ query_cache.PopAsyncFlushes();
auto& gpu{system.GPU()};
if (current_fence->IsSemaphore()) {
auto& memory_manager{gpu.MemoryManager()};
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 5ea2b01f2..1b1c23995 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -12,6 +12,7 @@
#include <mutex>
#include <optional>
#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "common/assert.h"
@@ -130,6 +131,7 @@ public:
}
query->BindCounter(Stream(type).Current(), timestamp);
+ AsyncFlushQuery(cpu_addr);
}
/// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch.
@@ -170,6 +172,44 @@ public:
return streams[static_cast<std::size_t>(type)];
}
+ void CommitAsyncFlushes() {
+ commited_flushes.push_back(uncommited_flushes);
+ uncommited_flushes.reset();
+ }
+
+ bool HasUncommitedFlushes() {
+ if (uncommited_flushes) {
+ return true;
+ }
+ return false;
+ }
+
+ bool ShouldWaitAsyncFlushes() {
+ if (commited_flushes.empty()) {
+ return false;
+ }
+ auto& flush_list = commited_flushes.front();
+ if (!flush_list) {
+ return false;
+ }
+ return true;
+ }
+
+ void PopAsyncFlushes() {
+ if (commited_flushes.empty()) {
+ return;
+ }
+ auto& flush_list = commited_flushes.front();
+ if (!flush_list) {
+ commited_flushes.pop_front();
+ return;
+ }
+ for (VAddr query_address : *flush_list) {
+ FlushAndRemoveRegion(query_address, 4);
+ }
+ commited_flushes.pop_front();
+ }
+
protected:
std::array<QueryPool, VideoCore::NumQueryTypes> query_pools;
@@ -224,6 +264,13 @@ private:
return found != std::end(contents) ? &*found : nullptr;
}
+ void AsyncFlushQuery(VAddr addr) {
+ if (!uncommited_flushes) {
+ uncommited_flushes = std::make_shared<std::unordered_set<VAddr>>();
+ }
+ uncommited_flushes->insert(addr);
+ }
+
static constexpr std::uintptr_t PAGE_SIZE = 4096;
static constexpr unsigned PAGE_SHIFT = 12;
@@ -235,6 +282,9 @@ private:
std::unordered_map<u64, std::vector<CachedQuery>> cached_queries;
std::array<CounterStream, VideoCore::NumQueryTypes> streams;
+
+ std::shared_ptr<std::unordered_set<VAddr>> uncommited_flushes{};
+ std::list<std::shared_ptr<std::unordered_set<VAddr>>> commited_flushes;
};
template <class QueryCache, class HostCounter>
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp
index 579c03a1e..aa57a0ae0 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp
@@ -44,9 +44,11 @@ void GLInnerFence::Wait() {
;
}
-FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
- TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache)
- : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {}
+FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system,
+ VideoCore::RasterizerInterface& rasterizer,
+ TextureCacheOpenGL& texture_cache,
+ OGLBufferCache& buffer_cache, QueryCache& query_cache)
+ : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache, query_cache) {}
Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) {
return std::make_shared<GLInnerFence>(value, is_stubbed);
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h
index ba48d2f84..c76e69cb8 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.h
+++ b/src/video_core/renderer_opengl/gl_fence_manager.h
@@ -10,6 +10,7 @@
#include "common/common_types.h"
#include "video_core/fence_manager.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
+#include "video_core/renderer_opengl/gl_query_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_texture_cache.h"
@@ -32,12 +33,14 @@ private:
};
using Fence = std::shared_ptr<GLInnerFence>;
-using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache>;
+using GenericFenceManager =
+ VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache, QueryCache>;
class FenceManagerOpenGL final : public GenericFenceManager {
public:
FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
- TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache);
+ TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache,
+ QueryCache& query_cache);
protected:
Fence CreateFence(u32 value, bool is_stubbed) override;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index bc57d396e..6d3b5f3f4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -101,9 +101,9 @@ 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}, fence_manager{system, *this,
- texture_cache,
- buffer_cache} {
+ buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{
+ system, *this, texture_cache,
+ buffer_cache, query_cache} {
CheckExtensions();
}