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
This commit is contained in:
Billy Laws 2022-07-29 20:02:47 +01:00
parent dbb684835f
commit f52ea7bddb
2 changed files with 10 additions and 6 deletions

View File

@ -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) {

View File

@ -31,9 +31,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
return startOffset != std::numeric_limits<u32>::max();
}
u32 Invalidate() {
return std::exchange(startOffset, std::numeric_limits<u32>::max());
}
void Reset() {
buffer.clear();
startOffset = std::numeric_limits<u32>::max();
}
} batchConstantBufferUpdate; //!< Holds state for updating constant buffer data in a batch rather than word by word