forked from ShuriZma/suyu
GPU: Refactor synchronization on Async GPU
This commit is contained in:
parent
a60a22d9c2
commit
da8f17715d
|
@ -32,6 +32,7 @@ void DmaPusher::DispatchCalls() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gpu.FlushCommands();
|
gpu.FlushCommands();
|
||||||
|
gpu.SyncGuestHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DmaPusher::Step() {
|
bool DmaPusher::Step() {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue