Repository navigation
Pipeline Collect ahead of Execute with a lock-free triple buffer - #96
Merged
Merged
Conversation
Collect and Execute used to run strictly lockstep: the main thread would only gather a frame's render data after the render thread finished the previous one, and vice versa, serialized through a pair of AutoResetEvents. That meant the render thread was always idle while Collect ran and vice versa, with no overlap possible. Collect() now hands its output to the render thread through a new TripleBuffer<T>, a lock-free SPSC latest-wins primitive: the writer never blocks, the reader always gets the most recently completed write, and a stale batch that falls behind is skipped and disposed rather than executed out of order. The render thread's AutoResetEvent is now purely a wake signal, not a backpressure gate. WindowRenderer selects its frame slot at collect time (_framesCollected) instead of at execute-completion time, so two in-flight collected batches never alias the same Frame.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Collect()and the render thread'sExecute()used to serialize through a pair ofAutoResetEvents, so each was idle while the other ran. Now Collect runs ahead freely; the render thread'sAutoResetEventis purely a wake signal, not a backpressure gate.TripleBuffer<T>(Engine/Rin.Core/Shared/Threading/TripleBuffer.cs): a lock-free single-producer/single-consumer "latest wins" primitive. The writer never blocks, the reader always gets the most recently completed write, and a batch that falls behind before ever being read is reported back to the writer so it can be disposed instead of executed stale and out of order.WindowRenderer: frame-slot selection used to be keyed off_framesRendered(incremented only after GPU submission completes), which could let two in-flight collected batches reference the sameFrameonce Collect runs ahead of Execute. It now selects the slot at collect time via a new_framesCollectedcounter.VulkanGraphicsModule, since a futureIRenderDataimplementation may hold a disposable resource (IRenderDataitself isn'tIDisposabletoday).Test plan
dotnet build Engine/Rin.Graphics.Vulkan/Rin.Graphics.Vulkan.csproj -c Debug— builds cleandotnet test Engine/Rin.Core.Tests/Rin.Core.Tests.csproj --filter "FullyQualifiedName~TripleBufferTests"— 6/6 passing