summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h50
-rw-r--r--src/video_core/fence_manager.h15
-rw-r--r--src/video_core/gpu_thread.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp3
6 files changed, 69 insertions, 10 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index df4c0211e..d72df90ef 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -21,6 +21,7 @@
#include "common/common_types.h"
#include "core/core.h"
#include "core/memory.h"
+#include "core/settings.h"
#include "video_core/buffer_cache/buffer_block.h"
#include "video_core/buffer_cache/map_interval.h"
#include "video_core/memory_manager.h"
@@ -80,6 +81,9 @@ public:
auto map = MapAddress(block, gpu_addr, cpu_addr, size);
if (is_written) {
map->MarkAsModified(true, GetModifiedTicks());
+ if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) {
+ AsyncFlushMap(map);
+ }
if (!map->IsWritten()) {
map->MarkAsWritten(true);
MarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1);
@@ -193,6 +197,39 @@ public:
marked_for_unregister.clear();
}
+ void CommitAsyncFlushes() {
+ commited_flushes.push_back(uncommited_flushes);
+ uncommited_flushes.reset();
+ }
+
+ 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 (MapInterval& map : *flush_list) {
+ if (map->IsRegistered()) {
+ FlushMap(map);
+ }
+ }
+ commited_flushes.pop_front();
+ }
+
virtual BufferType GetEmptyBuffer(std::size_t size) = 0;
protected:
@@ -316,6 +353,9 @@ private:
MapInterval new_map = CreateMap(new_start, new_end, new_gpu_addr);
if (modified_inheritance) {
new_map->MarkAsModified(true, GetModifiedTicks());
+ if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) {
+ AsyncFlushMap(new_map);
+ }
}
Register(new_map, write_inheritance);
return new_map;
@@ -502,6 +542,13 @@ private:
return false;
}
+ void AsyncFlushMap(MapInterval& map) {
+ if (!uncommited_flushes) {
+ uncommited_flushes = std::make_shared<std::list<MapInterval>>();
+ }
+ uncommited_flushes->push_back(map);
+ }
+
VideoCore::RasterizerInterface& rasterizer;
Core::System& system;
@@ -533,6 +580,9 @@ private:
std::vector<u8> staging_buffer;
std::list<MapInterval> marked_for_unregister;
+ std::shared_ptr<std::list<MapInterval>> uncommited_flushes{};
+ std::list<std::shared_ptr<std::list<MapInterval>>> commited_flushes;
+
std::recursive_mutex mutex;
};
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h
index 036f3996c..c4b190503 100644
--- a/src/video_core/fence_manager.h
+++ b/src/video_core/fence_manager.h
@@ -6,8 +6,8 @@
#include <algorithm>
#include <array>
-#include <queue>
#include <memory>
+#include <queue>
#include "common/assert.h"
#include "common/common_types.h"
@@ -37,7 +37,7 @@ private:
u32 payload;
};
-template <typename TFence, typename TTextureCache>
+template <typename TFence, typename TTextureCache, typename TTBufferCache>
class FenceManager {
public:
void SignalFence(GPUVAddr addr, u32 value) {
@@ -46,6 +46,7 @@ public:
QueueFence(new_fence);
fences.push(new_fence);
texture_cache.CommitAsyncFlushes();
+ buffer_cache.CommitAsyncFlushes();
rasterizer.FlushCommands();
rasterizer.SyncGuestHost();
}
@@ -54,10 +55,12 @@ public:
while (!fences.empty()) {
TFence& current_fence = fences.front();
bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
+ should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
if (should_wait) {
WaitFence(current_fence);
}
texture_cache.PopAsyncFlushes();
+ buffer_cache.PopAsyncFlushes();
auto& gpu{system.GPU()};
auto& memory_manager{gpu.MemoryManager()};
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
@@ -67,8 +70,9 @@ public:
protected:
FenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
- TTextureCache& texture_cache)
- : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache} {}
+ TTextureCache& texture_cache, TTBufferCache& buffer_cache)
+ : system{system}, rasterizer{rasterizer}, texture_cache{texture_cache}, buffer_cache{
+ buffer_cache} {}
virtual TFence CreateFence(GPUVAddr addr, u32 value) = 0;
virtual void QueueFence(TFence& fence) = 0;
@@ -78,16 +82,19 @@ protected:
Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
TTextureCache& texture_cache;
+ TTBufferCache& buffer_cache;
private:
void TryReleasePendingFences() {
while (!fences.empty()) {
TFence& current_fence = fences.front();
bool should_wait = texture_cache.ShouldWaitAsyncFlushes();
+ should_wait |= buffer_cache.ShouldWaitAsyncFlushes();
if (should_wait && !IsFenceSignaled(current_fence)) {
return;
}
texture_cache.PopAsyncFlushes();
+ buffer_cache.PopAsyncFlushes();
auto& gpu{system.GPU()};
auto& memory_manager{gpu.MemoryManager()};
memory_manager.Write<u32>(current_fence->GetAddress(), current_fence->GetPayload());
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 1c3ab2145..3e2be00e9 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -81,7 +81,7 @@ void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
}
void ThreadManager::FlushRegion(VAddr addr, u64 size) {
- if (!Settings::IsGPULevelExtreme()) {
+ if (!Settings::IsGPULevelHigh()) {
return;
}
if (system.Renderer().Rasterizer().MustFlushRegion(addr, size)) {
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp
index 4517ef150..69dd3211b 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp
@@ -33,8 +33,8 @@ void GLInnerFence::Wait() {
}
FenceManagerOpenGL::FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
- TextureCacheOpenGL& texture_cache)
- : GenericFenceManager(system, rasterizer, texture_cache) {}
+ TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache)
+ : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache) {}
Fence FenceManagerOpenGL::CreateFence(GPUVAddr addr, u32 value) {
return std::make_shared<GLInnerFence>(addr, value);
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h
index 3cfa8b1d0..b48d5eaa0 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.h
+++ b/src/video_core/renderer_opengl/gl_fence_manager.h
@@ -9,6 +9,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_resource_manager.h"
#include "video_core/renderer_opengl/gl_texture_cache.h"
@@ -30,12 +31,12 @@ private:
};
using Fence = std::shared_ptr<GLInnerFence>;
-using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL>;
+using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCacheOpenGL, OGLBufferCache>;
class FenceManagerOpenGL final : public GenericFenceManager {
public:
FenceManagerOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
- TextureCacheOpenGL& texture_cache);
+ TextureCacheOpenGL& texture_cache, OGLBufferCache& buffer_cache);
protected:
Fence CreateFence(GPUVAddr addr, u32 value) override;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index db7eae065..88914828c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -102,7 +102,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
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} {
+ texture_cache,
+ buffer_cache} {
CheckExtensions();
}