GPU: Refactor synchronization on Async GPU

This commit is contained in:
Fernando Sahmkow 2020-02-16 09:51:37 -04:00
parent a60a22d9c2
commit da8f17715d
11 changed files with 56 additions and 7 deletions

View file

@ -32,6 +32,7 @@ void DmaPusher::DispatchCalls() {
} }
} }
gpu.FlushCommands(); gpu.FlushCommands();
gpu.SyncGuestHost();
} }
bool DmaPusher::Step() { bool DmaPusher::Step() {

View file

@ -403,9 +403,13 @@ void Maxwell3D::ProcessQueryGet() {
"Units other than CROP are unimplemented"); "Units other than CROP are unimplemented");
switch (regs.query.query_get.operation) { switch (regs.query.query_get.operation) {
case Regs::QueryOperation::Release: case Regs::QueryOperation::Release: {
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); rasterizer.FlushCommands();
rasterizer.SyncGuestHost();
const u64 result = regs.query.query_sequence;
StampQueryResult(result, regs.query.query_get.short_query == 0);
break; break;
}
case Regs::QueryOperation::Acquire: case Regs::QueryOperation::Acquire:
// TODO(Blinkhawk): Under this operation, the GPU waits for the CPU to write a value that // TODO(Blinkhawk): Under this operation, the GPU waits for the CPU to write a value that
// matches the current payload. // matches the current payload.

View file

@ -142,6 +142,9 @@ void GPU::FlushCommands() {
renderer->Rasterizer().FlushCommands(); renderer->Rasterizer().FlushCommands();
} }
void GPU::SyncGuestHost() {
renderer->Rasterizer().SyncGuestHost();
}
// Note that, traditionally, methods are treated as 4-byte addressable locations, and hence // Note that, traditionally, methods are treated as 4-byte addressable locations, and hence
// their numbers are written down multiplied by 4 in Docs. Here we are not multiply by 4. // their numbers are written down multiplied by 4 in Docs. Here we are not multiply by 4.
// So the values you see in docs might be multiplied by 4. // So the values you see in docs might be multiplied by 4.

View file

@ -156,6 +156,7 @@ public:
void CallMethod(const MethodCall& method_call); void CallMethod(const MethodCall& method_call);
void FlushCommands(); void FlushCommands();
void SyncGuestHost();
/// Returns a reference to the Maxwell3D GPU engine. /// Returns a reference to the Maxwell3D GPU engine.
Engines::Maxwell3D& Maxwell3D(); Engines::Maxwell3D& Maxwell3D();

View file

@ -40,7 +40,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Core::Frontend::Graphic
} else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) { } else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) {
renderer.Rasterizer().FlushRegion(data->addr, data->size); renderer.Rasterizer().FlushRegion(data->addr, data->size);
} else if (const auto data = std::get_if<InvalidateRegionCommand>(&next.data)) { } else if (const auto data = std::get_if<InvalidateRegionCommand>(&next.data)) {
renderer.Rasterizer().InvalidateRegion(data->addr, data->size); renderer.Rasterizer().OnCPUWrite(data->addr, data->size);
} else if (std::holds_alternative<EndProcessingCommand>(next.data)) { } else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
return; return;
} else { } else {
@ -82,12 +82,12 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) {
} }
void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {
system.Renderer().Rasterizer().InvalidateRegion(addr, size); system.Renderer().Rasterizer().OnCPUWrite(addr, size);
} }
void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
// Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
InvalidateRegion(addr, size); system.Renderer().Rasterizer().OnCPUWrite(addr, size);
} }
void ThreadManager::WaitIdle() const { void ThreadManager::WaitIdle() const {

View file

@ -58,6 +58,12 @@ public:
/// Notify rasterizer that any caches of the specified region should be invalidated /// Notify rasterizer that any caches of the specified region should be invalidated
virtual void InvalidateRegion(VAddr addr, u64 size) = 0; virtual void InvalidateRegion(VAddr addr, u64 size) = 0;
/// Notify rasterizer that any caches of the specified region are desync with guest
virtual void OnCPUWrite(VAddr addr, u64 size) = 0;
/// Sync memory between guest and host.
virtual void SyncGuestHost() = 0;
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
/// and invalidated /// and invalidated
virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0; virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0;

View file

@ -660,6 +660,22 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
query_cache.InvalidateRegion(addr, size); query_cache.InvalidateRegion(addr, size);
} }
void RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
if (!addr || !size) {
return;
}
texture_cache.OnCPUWrite(addr, size);
shader_cache.InvalidateRegion(addr, size);
buffer_cache.InvalidateRegion(addr, size);
}
void RasterizerOpenGL::SyncGuestHost() {
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
texture_cache.SyncGuestHost();
// buffer_cache.SyncGuestHost();
}
void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
if (Settings::IsGPULevelExtreme()) { if (Settings::IsGPULevelExtreme()) {
FlushRegion(addr, size); FlushRegion(addr, size);

View file

@ -67,6 +67,8 @@ public:
void FlushAll() override; void FlushAll() override;
void FlushRegion(VAddr addr, u64 size) override; void FlushRegion(VAddr addr, u64 size) override;
void InvalidateRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override;
void OnCPUWrite(VAddr addr, u64 size) override;
void SyncGuestHost() override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void FlushCommands() override; void FlushCommands() override;
void TickFrame() override; void TickFrame() override;

View file

@ -524,6 +524,20 @@ void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size) {
query_cache.InvalidateRegion(addr, size); query_cache.InvalidateRegion(addr, size);
} }
void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) {
if (!addr || !size) {
return;
}
texture_cache.OnCPUWrite(addr, size);
pipeline_cache.InvalidateRegion(addr, size);
buffer_cache.InvalidateRegion(addr, size);
}
void RasterizerVulkan::SyncGuestHost() {
texture_cache.SyncGuestHost();
// buffer_cache.SyncGuestHost();
}
void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) { void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) {
FlushRegion(addr, size); FlushRegion(addr, size);
InvalidateRegion(addr, size); InvalidateRegion(addr, size);

View file

@ -119,6 +119,8 @@ public:
void FlushAll() override; void FlushAll() override;
void FlushRegion(VAddr addr, u64 size) override; void FlushRegion(VAddr addr, u64 size) override;
void InvalidateRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override;
void OnCPUWrite(VAddr addr, u64 size) override;
void SyncGuestHost() override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override; void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
void FlushCommands() override; void FlushCommands() override;
void TickFrame() override; void TickFrame() override;

View file

@ -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}; std::lock_guard lock{mutex};
for (const auto& surface : GetSurfacesInRegion(addr, size)) { for (const auto& surface : GetSurfacesInRegion(addr, size)) {
@ -549,7 +549,7 @@ private:
} }
const auto& final_params = new_surface->GetSurfaceParams(); const auto& final_params = new_surface->GetSurfaceParams();
if (cr_params.type != final_params.type) { if (cr_params.type != final_params.type) {
if (Settings::values.use_accurate_gpu_emulation) { if (Settings::IsGPULevelExtreme()) {
BufferCopy(current_surface, new_surface); BufferCopy(current_surface, new_surface);
} }
} else { } else {