From 8b1eb44b3ed5483071dc6754662a277b45e4a809 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 16 Feb 2020 10:08:07 -0400 Subject: BufferCache: Implement OnCPUWrite and SyncGuestHost --- src/video_core/buffer_cache/buffer_cache.h | 45 ++++++++++++++++++++++++++++-- src/video_core/buffer_cache/map_interval.h | 18 ++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 83e7a1cde..5b14d52e2 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -137,7 +138,9 @@ public: }); for (auto& object : objects) { if (object->IsModified() && object->IsRegistered()) { + mutex.unlock(); FlushMap(object); + mutex.lock(); } } } @@ -154,6 +157,30 @@ public: } } + void OnCPUWrite(VAddr addr, std::size_t size) { + std::lock_guard lock{mutex}; + + for (const auto& object : GetMapsInRange(addr, size)) { + if (object->IsMemoryMarked() && object->IsRegistered()) { + Unmark(object); + object->SetSyncPending(true); + marked_for_unregister.emplace_back(object); + } + } + } + + void SyncGuestHost() { + std::lock_guard lock{mutex}; + + for (const auto& object : marked_for_unregister) { + if (object->IsRegistered()) { + object->SetSyncPending(false); + Unregister(object); + } + } + marked_for_unregister.clear(); + } + virtual BufferType GetEmptyBuffer(std::size_t size) = 0; protected: @@ -196,17 +223,30 @@ protected: const IntervalType interval{new_map->GetStart(), new_map->GetEnd()}; mapped_addresses.insert({interval, new_map}); rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); + new_map->SetMemoryMarked(true); if (inherit_written) { MarkRegionAsWritten(new_map->GetStart(), new_map->GetEnd() - 1); new_map->MarkAsWritten(true); } } - /// Unregisters an object from the cache - void Unregister(MapInterval& map) { + void Unmark(const MapInterval& map) { + if (!map->IsMemoryMarked()) { + return; + } const std::size_t size = map->GetEnd() - map->GetStart(); rasterizer.UpdatePagesCachedCount(map->GetStart(), size, -1); + map->SetMemoryMarked(false); + } + + /// Unregisters an object from the cache + void Unregister(const MapInterval& map) { + Unmark(map); map->MarkAsRegistered(false); + if (map->IsSyncPending()) { + marked_for_unregister.remove(map); + map->SetSyncPending(false); + } if (map->IsWritten()) { UnmarkRegionAsWritten(map->GetStart(), map->GetEnd() - 1); } @@ -479,6 +519,7 @@ private: u64 modified_ticks = 0; std::vector staging_buffer; + std::list marked_for_unregister; std::recursive_mutex mutex; }; diff --git a/src/video_core/buffer_cache/map_interval.h b/src/video_core/buffer_cache/map_interval.h index b0956029d..29d8b26f3 100644 --- a/src/video_core/buffer_cache/map_interval.h +++ b/src/video_core/buffer_cache/map_interval.h @@ -46,6 +46,22 @@ public: return is_registered; } + 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; + } + VAddr GetStart() const { return start; } @@ -83,6 +99,8 @@ private: bool is_written{}; bool is_modified{}; bool is_registered{}; + bool is_memory_marked{}; + bool is_sync_pending{}; u64 ticks{}; }; -- 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/buffer_cache/buffer_cache.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 5b14d52e2..df4c0211e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -145,6 +145,18 @@ public: } } + bool MustFlushRegion(VAddr addr, std::size_t size) { + std::lock_guard lock{mutex}; + + std::vector objects = GetMapsInRange(addr, size); + for (auto& object : objects) { + if (object->IsModified() && object->IsRegistered()) { + return true; + } + } + return false; + } + /// Mark the specified region as being invalidated void InvalidateRegion(VAddr addr, u64 size) { std::lock_guard lock{mutex}; -- cgit v1.2.3 From b10db7e4a5f43414679b7969ea309b1829937a37 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 18 Feb 2020 17:20:39 -0400 Subject: FenceManager: Implement async buffer cache flushes on High settings --- src/video_core/buffer_cache/buffer_cache.h | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'src/video_core/buffer_cache') 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>(); + } + uncommited_flushes->push_back(map); + } + VideoCore::RasterizerInterface& rasterizer; Core::System& system; @@ -533,6 +580,9 @@ private: std::vector staging_buffer; std::list marked_for_unregister; + std::shared_ptr> uncommited_flushes{}; + std::list>> commited_flushes; + std::recursive_mutex mutex; }; -- cgit v1.2.3 From 96bb961a6485c2f5c8b7fb91aa0dd7eb24fa5e5d Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 19 Feb 2020 10:49:07 -0400 Subject: BufferCache: Refactor async managing. --- src/video_core/buffer_cache/buffer_cache.h | 31 +++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index d72df90ef..06fb931d7 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -82,7 +82,7 @@ public: if (is_written) { map->MarkAsModified(true, GetModifiedTicks()); if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) { - AsyncFlushMap(map); + MarkForAsyncFlush(map); } if (!map->IsWritten()) { map->MarkAsWritten(true); @@ -198,7 +198,23 @@ public: } void CommitAsyncFlushes() { - commited_flushes.push_back(uncommited_flushes); + if (uncommited_flushes) { + auto commit_list = std::make_shared>(); + for (auto& map : *uncommited_flushes) { + if (map->IsRegistered() && map->IsModified()) { + // TODO(Blinkhawk): Implement backend asynchronous flushing + // AsyncFlushMap(map) + commit_list->push_back(map); + } + } + if (!commit_list->empty()) { + commited_flushes.push_back(commit_list); + } else { + commited_flushes.emplace_back(); + } + } else { + commited_flushes.emplace_back(); + } uncommited_flushes.reset(); } @@ -224,6 +240,7 @@ public: } for (MapInterval& map : *flush_list) { if (map->IsRegistered()) { + // TODO(Blinkhawk): Replace this for reading the asynchronous flush FlushMap(map); } } @@ -354,7 +371,7 @@ private: if (modified_inheritance) { new_map->MarkAsModified(true, GetModifiedTicks()); if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) { - AsyncFlushMap(new_map); + MarkForAsyncFlush(new_map); } } Register(new_map, write_inheritance); @@ -542,11 +559,11 @@ private: return false; } - void AsyncFlushMap(MapInterval& map) { + void MarkForAsyncFlush(MapInterval& map) { if (!uncommited_flushes) { - uncommited_flushes = std::make_shared>(); + uncommited_flushes = std::make_shared>(); } - uncommited_flushes->push_back(map); + uncommited_flushes->insert(map); } VideoCore::RasterizerInterface& rasterizer; @@ -580,7 +597,7 @@ private: std::vector staging_buffer; std::list marked_for_unregister; - std::shared_ptr> uncommited_flushes{}; + std::shared_ptr> uncommited_flushes{}; std::list>> commited_flushes; std::recursive_mutex mutex; -- 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/buffer_cache/buffer_cache.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 06fb931d7..54c75ca4e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -229,6 +229,13 @@ public: return true; } + bool HasUncommitedFlushes() { + if (uncommited_flushes) { + return true; + } + return false; + } + void PopAsyncFlushes() { if (commited_flushes.empty()) { return; -- cgit v1.2.3 From b752faf2d3aae882a1a35a3aec393ef5765c035f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 16 Mar 2020 21:43:05 -0300 Subject: vk_fence_manager: Initial implementation --- src/video_core/buffer_cache/buffer_cache.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 54c75ca4e..372545080 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -19,6 +19,7 @@ #include "common/alignment.h" #include "common/common_types.h" +#include "common/logging/log.h" #include "core/core.h" #include "core/memory.h" #include "core/settings.h" -- 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/buffer_cache/buffer_cache.h | 56 ++++++++++++------------------ 1 file changed, 23 insertions(+), 33 deletions(-) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 372545080..f3aa35295 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -154,12 +154,9 @@ public: std::lock_guard lock{mutex}; std::vector objects = GetMapsInRange(addr, size); - for (auto& object : objects) { - if (object->IsModified() && object->IsRegistered()) { - return true; - } - } - return false; + return std::any_of(objects.begin(), objects.end(), [](const MapInterval& map) { + return map->IsModified() && map->IsRegistered(); + }); } /// Mark the specified region as being invalidated @@ -199,9 +196,9 @@ public: } void CommitAsyncFlushes() { - if (uncommited_flushes) { + if (uncommitted_flushes) { auto commit_list = std::make_shared>(); - for (auto& map : *uncommited_flushes) { + for (auto& map : *uncommitted_flushes) { if (map->IsRegistered() && map->IsModified()) { // TODO(Blinkhawk): Implement backend asynchronous flushing // AsyncFlushMap(map) @@ -209,41 +206,34 @@ public: } } if (!commit_list->empty()) { - commited_flushes.push_back(commit_list); + committed_flushes.push_back(commit_list); } else { - commited_flushes.emplace_back(); + committed_flushes.emplace_back(); } } else { - commited_flushes.emplace_back(); + committed_flushes.emplace_back(); } - uncommited_flushes.reset(); + uncommitted_flushes.reset(); } - 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; } - bool HasUncommitedFlushes() { - if (uncommited_flushes) { - return true; - } - return false; + bool HasUncommittedFlushes() const { + return uncommitted_flushes != 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 (MapInterval& map : *flush_list) { @@ -252,7 +242,7 @@ public: FlushMap(map); } } - commited_flushes.pop_front(); + committed_flushes.pop_front(); } virtual BufferType GetEmptyBuffer(std::size_t size) = 0; @@ -568,10 +558,10 @@ private: } void MarkForAsyncFlush(MapInterval& map) { - if (!uncommited_flushes) { - uncommited_flushes = std::make_shared>(); + if (!uncommitted_flushes) { + uncommitted_flushes = std::make_shared>(); } - uncommited_flushes->insert(map); + uncommitted_flushes->insert(map); } VideoCore::RasterizerInterface& rasterizer; @@ -605,8 +595,8 @@ private: std::vector staging_buffer; std::list marked_for_unregister; - std::shared_ptr> uncommited_flushes{}; - std::list>> commited_flushes; + std::shared_ptr> uncommitted_flushes{}; + std::list>> committed_flushes; 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/buffer_cache/buffer_cache.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src/video_core/buffer_cache') diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index f3aa35295..510f11089 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -153,8 +153,8 @@ public: bool MustFlushRegion(VAddr addr, std::size_t size) { std::lock_guard lock{mutex}; - std::vector objects = GetMapsInRange(addr, size); - return std::any_of(objects.begin(), objects.end(), [](const MapInterval& map) { + const std::vector objects = GetMapsInRange(addr, size); + return std::any_of(objects.cbegin(), objects.cend(), [](const MapInterval& map) { return map->IsModified() && map->IsRegistered(); }); } @@ -176,7 +176,7 @@ public: for (const auto& object : GetMapsInRange(addr, size)) { if (object->IsMemoryMarked() && object->IsRegistered()) { - Unmark(object); + UnmarkMemory(object); object->SetSyncPending(true); marked_for_unregister.emplace_back(object); } @@ -217,10 +217,7 @@ public: } bool ShouldWaitAsyncFlushes() const { - if (committed_flushes.empty()) { - return false; - } - return committed_flushes.front() != nullptr; + return !committed_flushes.empty() && committed_flushes.front() != nullptr; } bool HasUncommittedFlushes() const { @@ -294,7 +291,7 @@ protected: } } - void Unmark(const MapInterval& map) { + void UnmarkMemory(const MapInterval& map) { if (!map->IsMemoryMarked()) { return; } @@ -305,7 +302,7 @@ protected: /// Unregisters an object from the cache void Unregister(const MapInterval& map) { - Unmark(map); + UnmarkMemory(map); map->MarkAsRegistered(false); if (map->IsSyncPending()) { marked_for_unregister.remove(map); -- cgit v1.2.3