Merge pull request #3905 from FernandoS27/vulkan-fix

Correct a series of crashes and intructions on Async GPU and Vulkan Pipeline
This commit is contained in:
bunnei 2020-05-24 15:23:38 -04:00 committed by GitHub
commit 1adabdac7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 7 deletions

View file

@ -56,9 +56,27 @@ public:
last_modified_ticks = cache.GetModifiedTicks(); last_modified_ticks = cache.GetModifiedTicks();
} }
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;
}
private: private:
bool is_registered{}; ///< Whether the object is currently registered with the cache bool is_registered{}; ///< Whether the object is currently registered with the cache
bool is_dirty{}; ///< Whether the object is dirty (out of sync with guest memory) bool is_dirty{}; ///< Whether the object is dirty (out of sync with guest memory)
bool is_memory_marked{}; ///< Whether the object is marking rasterizer memory.
bool is_sync_pending{}; ///< Whether the object is pending deletion.
u64 last_modified_ticks{}; ///< When the object was last modified, used for in-order flushing u64 last_modified_ticks{}; ///< When the object was last modified, used for in-order flushing
VAddr cpu_addr{}; ///< Cpu address memory, unique from emulated virtual address space VAddr cpu_addr{}; ///< Cpu address memory, unique from emulated virtual address space
}; };
@ -94,6 +112,30 @@ public:
} }
} }
void OnCPUWrite(VAddr addr, std::size_t size) {
std::lock_guard lock{mutex};
for (const auto& object : GetSortedObjectsFromRegion(addr, size)) {
if (object->IsRegistered()) {
UnmarkMemory(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();
}
/// Invalidates everything in the cache /// Invalidates everything in the cache
void InvalidateAll() { void InvalidateAll() {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
@ -120,19 +162,32 @@ protected:
interval_cache.add({GetInterval(object), ObjectSet{object}}); interval_cache.add({GetInterval(object), ObjectSet{object}});
map_cache.insert({object->GetCpuAddr(), object}); map_cache.insert({object->GetCpuAddr(), object});
rasterizer.UpdatePagesCachedCount(object->GetCpuAddr(), object->GetSizeInBytes(), 1); rasterizer.UpdatePagesCachedCount(object->GetCpuAddr(), object->GetSizeInBytes(), 1);
object->SetMemoryMarked(true);
} }
/// Unregisters an object from the cache /// Unregisters an object from the cache
virtual void Unregister(const T& object) { virtual void Unregister(const T& object) {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
UnmarkMemory(object);
object->SetIsRegistered(false); object->SetIsRegistered(false);
rasterizer.UpdatePagesCachedCount(object->GetCpuAddr(), object->GetSizeInBytes(), -1); if (object->IsSyncPending()) {
marked_for_unregister.remove(object);
object->SetSyncPending(false);
}
const VAddr addr = object->GetCpuAddr(); const VAddr addr = object->GetCpuAddr();
interval_cache.subtract({GetInterval(object), ObjectSet{object}}); interval_cache.subtract({GetInterval(object), ObjectSet{object}});
map_cache.erase(addr); map_cache.erase(addr);
} }
void UnmarkMemory(const T& object) {
if (!object->IsMemoryMarked()) {
return;
}
rasterizer.UpdatePagesCachedCount(object->GetCpuAddr(), object->GetSizeInBytes(), -1);
object->SetMemoryMarked(false);
}
/// Returns a ticks counter used for tracking when cached objects were last modified /// Returns a ticks counter used for tracking when cached objects were last modified
u64 GetModifiedTicks() { u64 GetModifiedTicks() {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
@ -194,4 +249,5 @@ private:
IntervalCache interval_cache; ///< Cache of objects IntervalCache interval_cache; ///< Cache of objects
u64 modified_ticks{}; ///< Counter of cache state ticks, used for in-order flushing u64 modified_ticks{}; ///< Counter of cache state ticks, used for in-order flushing
VideoCore::RasterizerInterface& rasterizer; VideoCore::RasterizerInterface& rasterizer;
std::list<T> marked_for_unregister;
}; };

View file

@ -727,15 +727,15 @@ void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
return; return;
} }
texture_cache.OnCPUWrite(addr, size); texture_cache.OnCPUWrite(addr, size);
shader_cache.InvalidateRegion(addr, size); shader_cache.OnCPUWrite(addr, size);
buffer_cache.OnCPUWrite(addr, size); buffer_cache.OnCPUWrite(addr, size);
query_cache.InvalidateRegion(addr, size);
} }
void RasterizerOpenGL::SyncGuestHost() { void RasterizerOpenGL::SyncGuestHost() {
MICROPROFILE_SCOPE(OpenGL_CacheManagement); MICROPROFILE_SCOPE(OpenGL_CacheManagement);
texture_cache.SyncGuestHost(); texture_cache.SyncGuestHost();
buffer_cache.SyncGuestHost(); buffer_cache.SyncGuestHost();
shader_cache.SyncGuestHost();
} }
void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) { void RasterizerOpenGL::SignalSemaphore(GPUVAddr addr, u32 value) {

View file

@ -329,8 +329,7 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
const GPUVAddr gpu_addr = GetShaderAddress(system, program_enum); const GPUVAddr gpu_addr = GetShaderAddress(system, program_enum);
const auto cpu_addr = memory_manager.GpuToCpuAddress(gpu_addr); const auto cpu_addr = memory_manager.GpuToCpuAddress(gpu_addr);
ASSERT(cpu_addr); const auto shader = cpu_addr ? TryGet(*cpu_addr) : null_shader;
const auto shader = TryGet(*cpu_addr);
ASSERT(shader); ASSERT(shader);
const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5 const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5

View file

@ -532,14 +532,14 @@ void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) {
return; return;
} }
texture_cache.OnCPUWrite(addr, size); texture_cache.OnCPUWrite(addr, size);
pipeline_cache.InvalidateRegion(addr, size); pipeline_cache.OnCPUWrite(addr, size);
buffer_cache.OnCPUWrite(addr, size); buffer_cache.OnCPUWrite(addr, size);
query_cache.InvalidateRegion(addr, size);
} }
void RasterizerVulkan::SyncGuestHost() { void RasterizerVulkan::SyncGuestHost() {
texture_cache.SyncGuestHost(); texture_cache.SyncGuestHost();
buffer_cache.SyncGuestHost(); buffer_cache.SyncGuestHost();
pipeline_cache.SyncGuestHost();
} }
void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) { void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) {