QueryCache: Implement Async Flushes.

This commit is contained in:
Fernando Sahmkow 2020-04-15 16:36:14 -04:00
parent 131b342130
commit 0649f05900
5 changed files with 77 additions and 12 deletions

View File

@ -49,15 +49,17 @@ protected:
bool is_stubbed; bool is_stubbed;
}; };
template <typename TFence, typename TTextureCache, typename TTBufferCache> template <typename TFence, typename TTextureCache, typename TTBufferCache, typename TQueryCache>
class FenceManager { class FenceManager {
public: public:
void SignalSemaphore(GPUVAddr addr, u32 value) { void SignalSemaphore(GPUVAddr addr, u32 value) {
TryReleasePendingFences(); TryReleasePendingFences();
bool should_flush = texture_cache.HasUncommitedFlushes(); bool should_flush = texture_cache.HasUncommitedFlushes();
should_flush |= buffer_cache.HasUncommitedFlushes(); should_flush |= buffer_cache.HasUncommitedFlushes();
should_flush |= query_cache.HasUncommitedFlushes();
texture_cache.CommitAsyncFlushes(); texture_cache.CommitAsyncFlushes();
buffer_cache.CommitAsyncFlushes(); buffer_cache.CommitAsyncFlushes();
query_cache.CommitAsyncFlushes();
TFence new_fence = CreateFence(addr, value, !should_flush); TFence new_fence = CreateFence(addr, value, !should_flush);
fences.push(new_fence); fences.push(new_fence);
QueueFence(new_fence); QueueFence(new_fence);
@ -71,8 +73,10 @@ public:
TryReleasePendingFences(); TryReleasePendingFences();
bool should_flush = texture_cache.HasUncommitedFlushes(); bool should_flush = texture_cache.HasUncommitedFlushes();
should_flush |= buffer_cache.HasUncommitedFlushes(); should_flush |= buffer_cache.HasUncommitedFlushes();
should_flush |= query_cache.HasUncommitedFlushes();
texture_cache.CommitAsyncFlushes(); texture_cache.CommitAsyncFlushes();
buffer_cache.CommitAsyncFlushes(); buffer_cache.CommitAsyncFlushes();
query_cache.CommitAsyncFlushes();
TFence new_fence = CreateFence(value, !should_flush); TFence new_fence = CreateFence(value, !should_flush);
fences.push(new_fence); fences.push(new_fence);
QueueFence(new_fence); QueueFence(new_fence);
@ -87,11 +91,13 @@ public:
TFence& current_fence = fences.front(); TFence& current_fence = fences.front();
bool should_wait = texture_cache.ShouldWaitAsyncFlushes(); bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
should_wait |= buffer_cache.ShouldWaitAsyncFlushes(); should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
should_wait |= query_cache.ShouldWaitAsyncFlushes();
if (should_wait) { if (should_wait) {
WaitFence(current_fence); WaitFence(current_fence);
} }
texture_cache.PopAsyncFlushes(); texture_cache.PopAsyncFlushes();
buffer_cache.PopAsyncFlushes(); buffer_cache.PopAsyncFlushes();
query_cache.PopAsyncFlushes();
auto& gpu{system.GPU()}; auto& gpu{system.GPU()};
if (current_fence->IsSemaphore()) { if (current_fence->IsSemaphore()) {
auto& memory_manager{gpu.MemoryManager()}; auto& memory_manager{gpu.MemoryManager()};
@ -105,9 +111,10 @@ public:
protected: protected:
FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer, FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
TTextureCache& texture_cache, TTBufferCache& buffer_cache) TTextureCache& texture_cache, TTBufferCache& buffer_cache,
: system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{ TQueryCache& query_cache)
buffer_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(u32 value, bool is_stubbed) = 0;
virtual TFence CreateFence(GPUVAddr addr, 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; VideoCore::RasterizerInterface& rasterizer;
TTextureCache& texture_cache; TTextureCache& texture_cache;
TTBufferCache& buffer_cache; TTBufferCache& buffer_cache;
TQueryCache& query_cache;
private: private:
void TryReleasePendingFences() { void TryReleasePendingFences() {
@ -126,11 +134,13 @@ private:
TFence& current_fence = fences.front(); TFence& current_fence = fences.front();
bool should_wait = texture_cache.ShouldWaitAsyncFlushes(); bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
should_wait |= buffer_cache.ShouldWaitAsyncFlushes(); should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
should_wait |= query_cache.ShouldWaitAsyncFlushes();
if (should_wait && !IsFenceSignaled(current_fence)) { if (should_wait && !IsFenceSignaled(current_fence)) {
return; return;
} }
texture_cache.PopAsyncFlushes(); texture_cache.PopAsyncFlushes();
buffer_cache.PopAsyncFlushes(); buffer_cache.PopAsyncFlushes();
query_cache.PopAsyncFlushes();
auto& gpu{system.GPU()}; auto& gpu{system.GPU()};
if (current_fence->IsSemaphore()) { if (current_fence->IsSemaphore()) {
auto& memory_manager{gpu.MemoryManager()}; auto& memory_manager{gpu.MemoryManager()};

View File

@ -12,6 +12,7 @@
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
#include "common/assert.h" #include "common/assert.h"
@ -130,6 +131,7 @@ public:
} }
query->BindCounter(Stream(type).Current(), timestamp); query->BindCounter(Stream(type).Current(), timestamp);
AsyncFlushQuery(cpu_addr);
} }
/// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. /// 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)]; 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: protected:
std::array<QueryPool, VideoCore::NumQueryTypes> query_pools; std::array<QueryPool, VideoCore::NumQueryTypes> query_pools;
@ -224,6 +264,13 @@ private:
return found != std::end(contents) ? &*found : nullptr; 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 std::uintptr_t PAGE_SIZE = 4096;
static constexpr unsigned PAGE_SHIFT = 12; static constexpr unsigned PAGE_SHIFT = 12;
@ -235,6 +282,9 @@ private:
std::unordered_map<u64, std::vector<CachedQuery>> cached_queries; std::unordered_map<u64, std::vector<CachedQuery>> cached_queries;
std::array<CounterStream, VideoCore::NumQueryTypes> streams; 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> template <class QueryCache, class HostCounter>

View File

@ -44,9 +44,11 @@ void GLInnerFence::Wait() {
; ;
} }
FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system,
TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache) VideoCore::RasterizerInterface& rasterizer,
: GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {} 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) { Fence FenceManagerOpenGL::CreateFence(u32 value, bool is_stubbed) {
return std::make_shared<GLInnerFence>(value, is_stubbed); return std::make_shared<GLInnerFence>(value, is_stubbed);

View File

@ -10,6 +10,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/fence_manager.h" #include "video_core/fence_manager.h"
#include "video_core/renderer_opengl/gl_buffer_cache.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_resource_manager.h"
#include "video_core/renderer_opengl/gl_texture_cache.h" #include "video_core/renderer_opengl/gl_texture_cache.h"
@ -32,12 +33,14 @@ private:
}; };
using Fence = std::shared_ptr<GLInnerFence>; 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 { class FenceManagerOpenGL final : public GenericFenceManager {
public: public:
FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache); TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache,
QueryCache& query_cache);
protected: protected:
Fence CreateFence(u32 value, bool is_stubbed) override; Fence CreateFence(u32 value, bool is_stubbed) override;

View File

@ -101,9 +101,9 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
: RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker},
shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system},
screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker},
buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{system, *this, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE}, fence_manager{
texture_cache, system, *this, texture_cache,
buffer_cache} { buffer_cache, query_cache} {
CheckExtensions(); CheckExtensions();
} }