From f52ea7bddb8bba61a8b62f836742093e3e03c11e Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Fri, 29 Jul 2022 20:02:47 +0100 Subject: [PATCH] Make deferred draw and constant buffer updates reentrant-safe At some point we will call Submit within draws or constant buffer updates, to avoid any infinite recursion mark draw/cbuf pending as false before performing any operation --- .../main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp | 11 ++++++----- .../main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h | 5 ++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index f316cd49..344b0c7f 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -19,12 +19,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d { void Maxwell3D::FlushDeferredDraw() { if (deferredDraw.pending) { + deferredDraw.pending = false; + if (deferredDraw.indexed) context.DrawIndexed(deferredDraw.drawCount, deferredDraw.drawFirst, deferredDraw.instanceCount, deferredDraw.drawBaseVertex); else context.Draw(deferredDraw.drawCount, deferredDraw.drawFirst, deferredDraw.instanceCount); - deferredDraw.pending = false; deferredDraw.instanceCount = 1; } } @@ -55,7 +56,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { #undef CBUF_UPDATE_CALLBACKS default: // When a method other than constant buffer update is called submit our submit the previously built-up update as a batch - context.ConstantBufferUpdate(std::move(batchConstantBufferUpdate.buffer), batchConstantBufferUpdate.startOffset); + context.ConstantBufferUpdate(batchConstantBufferUpdate.buffer, batchConstantBufferUpdate.Invalidate()); batchConstantBufferUpdate.Reset(); break; // Continue on here to handle the actual method } @@ -771,12 +772,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d { } void Maxwell3D::FlushEngineState() { + FlushDeferredDraw(); + if (batchConstantBufferUpdate.Active()) { - context.ConstantBufferUpdate(std::move(batchConstantBufferUpdate.buffer), batchConstantBufferUpdate.startOffset); + context.ConstantBufferUpdate(batchConstantBufferUpdate.buffer, batchConstantBufferUpdate.Invalidate()); batchConstantBufferUpdate.Reset(); } - - FlushDeferredDraw(); } __attribute__((always_inline)) void Maxwell3D::CallMethod(u32 method, u32 argument) { diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index f24c3851..c238d3a3 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -31,9 +31,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d { return startOffset != std::numeric_limits::max(); } + u32 Invalidate() { + return std::exchange(startOffset, std::numeric_limits::max()); + } + void Reset() { buffer.clear(); - startOffset = std::numeric_limits::max(); } } batchConstantBufferUpdate; //!< Holds state for updating constant buffer data in a batch rather than word by word