From 084ceb925acad470b69467d64e4dfbb3bd7ef3f1 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 18 Feb 2020 16:51:42 -0400 Subject: UI: Replasce accurate GPU option for GPU Accuracy Level --- src/video_core/texture_cache/texture_cache.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 69ca08fd1..7432691d1 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -417,7 +417,7 @@ private: **/ RecycleStrategy PickStrategy(std::vector& overlaps, const SurfaceParams& params, const GPUVAddr gpu_addr, const MatchTopologyResult untopological) { - if (Settings::values.use_accurate_gpu_emulation) { + if (Settings::IsGPULevelExtreme()) { return RecycleStrategy::Flush; } // 3D Textures decision @@ -461,7 +461,7 @@ private: } switch (PickStrategy(overlaps, params, gpu_addr, untopological)) { case RecycleStrategy::Ignore: { - return InitializeSurface(gpu_addr, params, Settings::values.use_accurate_gpu_emulation); + return InitializeSurface(gpu_addr, params, Settings::IsGPULevelExtreme()); } case RecycleStrategy::Flush: { std::sort(overlaps.begin(), overlaps.end(), @@ -598,7 +598,7 @@ private: if (passed_tests == 0) { return {}; // In Accurate GPU all tests should pass, else we recycle - } else if (Settings::values.use_accurate_gpu_emulation && passed_tests != overlaps.size()) { + } else if (Settings::IsGPULevelExtreme() && passed_tests != overlaps.size()) { return {}; } for (const auto& surface : overlaps) { @@ -668,7 +668,7 @@ private: for (const auto& surface : overlaps) { if (!surface->MatchTarget(params.target)) { if (overlaps.size() == 1 && surface->GetCpuAddr() == cpu_addr) { - if (Settings::values.use_accurate_gpu_emulation) { + if (Settings::IsGPULevelExtreme()) { return std::nullopt; } Unregister(surface); -- cgit v1.2.3 From a60a22d9c284537be2e3a6a89b8afb37e6f0c510 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 16 Feb 2020 09:33:03 -0400 Subject: Texture Cache: Implement OnCPUWrite and SyncGuestHost --- src/video_core/texture_cache/surface_base.h | 18 +++++++++++ src/video_core/texture_cache/texture_cache.h | 48 ++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 3 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index c5ab21f56..79e10ffbb 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -192,6 +192,22 @@ public: index = index_; } + void SetMemoryMarked(bool is_memory_marked_) { + is_memory_marked = is_memory_marked_; + } + + bool IsMemoryMarked() const { + return is_memory_marked; + } + + void SetSyncPending(bool is_sync_pending_) { + is_sync_pending = is_sync_pending_; + } + + bool IsSyncPending() const { + return is_sync_pending; + } + void MarkAsPicked(bool is_picked_) { is_picked = is_picked_; } @@ -303,6 +319,8 @@ private: bool is_target{}; bool is_registered{}; bool is_picked{}; + bool is_memory_marked{}; + bool is_sync_pending{}; u32 index{NO_RT}; u64 modification_tick{}; }; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 7432691d1..441fda53d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -62,6 +63,30 @@ public: } } + void OnCPUWrite(CacheAddr addr, std::size_t size) { + std::lock_guard lock{mutex}; + + for (const auto& surface : GetSurfacesInRegion(addr, size)) { + if (surface->IsMemoryMarked()) { + Unmark(surface); + surface->SetSyncPending(true); + marked_for_unregister.emplace_back(surface); + } + } + } + + void SyncGuestHost() { + std::lock_guard lock{mutex}; + + for (const auto& surface : marked_for_unregister) { + if (surface->IsRegistered()) { + surface->SetSyncPending(false); + Unregister(surface); + } + } + marked_for_unregister.clear(); + } + /** * Guarantees that rendertargets don't unregister themselves if the * collide. Protection is currently only done on 3D slices. @@ -85,7 +110,9 @@ public: return a->GetModificationTick() < b->GetModificationTick(); }); for (const auto& surface : surfaces) { + mutex.unlock(); FlushSurface(surface); + mutex.lock(); } } @@ -345,9 +372,20 @@ protected: surface->SetCpuAddr(*cpu_addr); RegisterInnerCache(surface); surface->MarkAsRegistered(true); + surface->SetMemoryMarked(true); rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); } + void Unmark(TSurface surface) { + if (!surface->IsMemoryMarked()) { + return; + } + const std::size_t size = surface->GetSizeInBytes(); + const VAddr cpu_addr = surface->GetCpuAddr(); + rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); + surface->SetMemoryMarked(false); + } + void Unregister(TSurface surface) { if (guard_render_targets && surface->IsProtected()) { return; @@ -355,9 +393,11 @@ protected: if (!guard_render_targets && surface->IsRenderTarget()) { ManageRenderTargetUnregister(surface); } - const std::size_t size = surface->GetSizeInBytes(); - const VAddr cpu_addr = surface->GetCpuAddr(); - rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); + Unmark(surface); + if (surface->IsSyncPending()) { + marked_for_unregister.remove(surface); + surface->SetSyncPending(false); + } UnregisterInnerCache(surface); surface->MarkAsRegistered(false); ReserveSurface(surface->GetSurfaceParams(), surface); @@ -1150,6 +1190,8 @@ private: std::unordered_map invalid_cache; std::vector invalid_memory; + std::list marked_for_unregister; + StagingCache staging_cache; std::recursive_mutex mutex; }; -- cgit v1.2.3 From da8f17715dbdc7eec92f5f0c11c968a51b86cab4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 16 Feb 2020 09:51:37 -0400 Subject: GPU: Refactor synchronization on Async GPU --- src/video_core/texture_cache/texture_cache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 441fda53d..c23b9f9b9 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -63,7 +63,7 @@ public: } } - void OnCPUWrite(CacheAddr addr, std::size_t size) { + void OnCPUWrite(VAddr addr, std::size_t size) { std::lock_guard lock{mutex}; for (const auto& surface : GetSurfacesInRegion(addr, size)) { @@ -549,7 +549,7 @@ private: } const auto& final_params = new_surface->GetSurfaceParams(); if (cr_params.type != final_params.type) { - if (Settings::values.use_accurate_gpu_emulation) { + if (Settings::IsGPULevelExtreme()) { BufferCopy(current_surface, new_surface); } } else { -- cgit v1.2.3 From ed7e9657120faea849af2933e539c72bc961c2a9 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 16 Feb 2020 17:13:19 -0400 Subject: TextureCache: Flush linear textures after finishing rendering. --- src/video_core/texture_cache/texture_cache.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index c23b9f9b9..d8c8390bb 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -233,8 +233,14 @@ public: auto surface_view = GetSurface(gpu_addr, *cpu_addr, SurfaceParams::CreateForFramebuffer(system, index), true); - if (render_targets[index].target) - render_targets[index].target->MarkAsRenderTarget(false, NO_RT); + if (render_targets[index].target) { + auto& surface = render_targets[index].target; + surface->MarkAsRenderTarget(false, NO_RT); + const auto& cr_params = surface->GetSurfaceParams(); + if (!cr_params.is_tiled) { + FlushSurface(surface); + } + } render_targets[index].target = surface_view.first; render_targets[index].view = surface_view.second; if (render_targets[index].target) -- cgit v1.2.3 From 487379c593bcaf3787ede187c5d44f7923b54dc9 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 17 Feb 2020 18:10:23 -0400 Subject: OpenGL: Implement Fencing backend. --- src/video_core/texture_cache/texture_cache.h | 32 +++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index d8c8390bb..6629c59ed 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -238,7 +238,7 @@ public: surface->MarkAsRenderTarget(false, NO_RT); const auto& cr_params = surface->GetSurfaceParams(); if (!cr_params.is_tiled) { - FlushSurface(surface); + AsyncFlushSurface(surface); } } render_targets[index].target = surface_view.first; @@ -317,6 +317,26 @@ public: return ++ticks; } + void CommitAsyncFlushes() { + commited_flushes.push_back(uncommited_flushes); + uncommited_flushes.reset(); + } + + void PopAsyncFlushes() { + if (commited_flushes.empty()) { + return; + } + auto& flush_list = commited_flushes.front(); + if (!flush_list) { + commited_flushes.pop_front(); + return; + } + for (TSurface& surface : *flush_list) { + FlushSurface(surface); + } + commited_flushes.pop_front(); + } + protected: explicit TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer, bool is_astc_supported) @@ -1152,6 +1172,13 @@ private: TView view; }; + void AsyncFlushSurface(TSurface& surface) { + if (!uncommited_flushes) { + uncommited_flushes = std::make_shared>(); + } + uncommited_flushes->push_back(surface); + } + VideoCore::RasterizerInterface& rasterizer; FormatLookupTable format_lookup_table; @@ -1198,6 +1225,9 @@ private: std::list marked_for_unregister; + std::shared_ptr> uncommited_flushes{}; + std::list>> commited_flushes; + StagingCache staging_cache; std::recursive_mutex mutex; }; -- cgit v1.2.3 From 57fdbd9b8992de4eaf2b262e6a2cece43c141894 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 17 Feb 2020 22:15:43 -0400 Subject: FenceManager: Implement should wait. --- src/video_core/texture_cache/texture_cache.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 6629c59ed..04fe69c11 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -322,6 +322,17 @@ public: 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; -- cgit v1.2.3 From 165ae823f522aa981129927f42e76763a9fa6006 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 17 Feb 2020 22:29:04 -0400 Subject: ThreadManager: Sync async reads on accurate gpu. --- src/video_core/texture_cache/texture_cache.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 04fe69c11..e251a30c3 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -116,6 +116,21 @@ public: } } + bool MustFlushRegion(VAddr addr, std::size_t size) { + std::lock_guard lock{mutex}; + + auto surfaces = GetSurfacesInRegion(addr, size); + if (surfaces.empty()) { + return false; + } + for (const auto& surface : surfaces) { + if (surface->IsModified()) { + return true; + } + } + return false; + } + TView GetTextureSurface(const Tegra::Texture::TICEntry& tic, const VideoCommon::Shader::Sampler& entry) { std::lock_guard lock{mutex}; -- cgit v1.2.3 From e84eb64e511cd4699cc2371744fccd24628c0749 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 18 Feb 2020 11:26:31 -0400 Subject: Rasterizer: Disable fence managing in synchronous gpu. --- src/video_core/texture_cache/texture_cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index e251a30c3..e1a1edbd2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -252,7 +252,7 @@ public: auto& surface = render_targets[index].target; surface->MarkAsRenderTarget(false, NO_RT); const auto& cr_params = surface->GetSurfaceParams(); - if (!cr_params.is_tiled) { + if (!cr_params.is_tiled && Settings::values.use_asynchronous_gpu_emulation) { AsyncFlushSurface(surface); } } -- cgit v1.2.3 From b7bc3c25496849661846f2fe42f591f2a81fbc87 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 19 Feb 2020 13:40:37 -0400 Subject: FenceManager: Manage syncpoints and rename fences to semaphores. --- src/video_core/texture_cache/texture_cache.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index e1a1edbd2..f3ca1ffd1 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -337,6 +337,13 @@ public: uncommited_flushes.reset(); } + bool HasUncommitedFlushes() { + if (uncommited_flushes) { + return true; + } + return false; + } + bool ShouldWaitAsyncFlushes() { if (commited_flushes.empty()) { return false; -- cgit v1.2.3 From f616dc0b591b783b3fb75ca89633f1c26cce05a9 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 16 Apr 2020 12:29:53 -0400 Subject: Address Feedback. --- src/video_core/texture_cache/texture_cache.h | 50 ++++++++++------------------ 1 file changed, 18 insertions(+), 32 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index f3ca1ffd1..1148c3a34 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -120,15 +120,8 @@ public: std::lock_guard lock{mutex}; auto surfaces = GetSurfacesInRegion(addr, size); - if (surfaces.empty()) { - return false; - } - for (const auto& surface : surfaces) { - if (surface->IsModified()) { - return true; - } - } - return false; + return std::any_of(surfaces.begin(), surfaces.end(), + [](const TSurface& surface) { return surface->IsModified(); }); } TView GetTextureSurface(const Tegra::Texture::TICEntry& tic, @@ -333,41 +326,34 @@ public: } void CommitAsyncFlushes() { - commited_flushes.push_back(uncommited_flushes); - uncommited_flushes.reset(); + committed_flushes.push_back(uncommitted_flushes); + uncommitted_flushes.reset(); } - bool HasUncommitedFlushes() { - if (uncommited_flushes) { - return true; - } - return false; + bool HasUncommittedFlushes() const { + return uncommitted_flushes != nullptr; } - bool ShouldWaitAsyncFlushes() { - if (commited_flushes.empty()) { - return false; - } - auto& flush_list = commited_flushes.front(); - if (!flush_list) { + bool ShouldWaitAsyncFlushes() const { + if (committed_flushes.empty()) { return false; } - return true; + return committed_flushes.front() != nullptr; } void PopAsyncFlushes() { - if (commited_flushes.empty()) { + if (committed_flushes.empty()) { return; } - auto& flush_list = commited_flushes.front(); + auto& flush_list = committed_flushes.front(); if (!flush_list) { - commited_flushes.pop_front(); + committed_flushes.pop_front(); return; } for (TSurface& surface : *flush_list) { FlushSurface(surface); } - commited_flushes.pop_front(); + committed_flushes.pop_front(); } protected: @@ -1206,10 +1192,10 @@ private: }; void AsyncFlushSurface(TSurface& surface) { - if (!uncommited_flushes) { - uncommited_flushes = std::make_shared>(); + if (!uncommitted_flushes) { + uncommitted_flushes = std::make_shared>(); } - uncommited_flushes->push_back(surface); + uncommitted_flushes->push_back(surface); } VideoCore::RasterizerInterface& rasterizer; @@ -1258,8 +1244,8 @@ private: std::list marked_for_unregister; - std::shared_ptr> uncommited_flushes{}; - std::list>> commited_flushes; + std::shared_ptr> uncommitted_flushes{}; + std::list>> committed_flushes; StagingCache staging_cache; std::recursive_mutex mutex; -- cgit v1.2.3 From 4e37f1b1130b083b42f21029155e5a2e4e9a9eb3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 22 Apr 2020 11:14:40 -0400 Subject: Address Feedback. --- src/video_core/texture_cache/texture_cache.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src/video_core/texture_cache') diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 1148c3a34..cf6bd005a 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -68,7 +68,7 @@ public: for (const auto& surface : GetSurfacesInRegion(addr, size)) { if (surface->IsMemoryMarked()) { - Unmark(surface); + UnmarkMemory(surface); surface->SetSyncPending(true); marked_for_unregister.emplace_back(surface); } @@ -119,8 +119,8 @@ public: bool MustFlushRegion(VAddr addr, std::size_t size) { std::lock_guard lock{mutex}; - auto surfaces = GetSurfacesInRegion(addr, size); - return std::any_of(surfaces.begin(), surfaces.end(), + const auto surfaces = GetSurfacesInRegion(addr, size); + return std::any_of(surfaces.cbegin(), surfaces.cend(), [](const TSurface& surface) { return surface->IsModified(); }); } @@ -335,10 +335,7 @@ public: } bool ShouldWaitAsyncFlushes() const { - if (committed_flushes.empty()) { - return false; - } - return committed_flushes.front() != nullptr; + return !committed_flushes.empty() && committed_flushes.front() != nullptr; } void PopAsyncFlushes() { @@ -421,7 +418,7 @@ protected: rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1); } - void Unmark(TSurface surface) { + void UnmarkMemory(TSurface surface) { if (!surface->IsMemoryMarked()) { return; } @@ -438,7 +435,7 @@ protected: if (!guard_render_targets && surface->IsRenderTarget()) { ManageRenderTargetUnregister(surface); } - Unmark(surface); + UnmarkMemory(surface); if (surface->IsSyncPending()) { marked_for_unregister.remove(surface); surface->SetSyncPending(false); -- cgit v1.2.3