Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix increased CPU/energy impact while backgrounded #6451

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions osu.Framework/Allocation/TripleBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ namespace osu.Framework.Allocation
internal class TripleBuffer<T>
where T : class
{
/// <summary>
/// The default amount of time (in milliseconds) to wait for a write to occur during <see cref="GetForRead"/>.
/// </summary>
public const int DEFAULT_READ_TIMEOUT = 100;

private const int buffer_count = 3;
private const long read_timeout_milliseconds = 100;

private readonly Buffer[] buffers = new Buffer[buffer_count];

private readonly Stopwatch stopwatch = new Stopwatch();

private int writeIndex;
Expand All @@ -32,25 +35,36 @@ public TripleBuffer()
buffers[i] = new Buffer(i, finishUsage);
}

/// <summary>
/// Retrieves a buffer to be written to.
/// </summary>
/// <returns>The buffer.</returns>
public Buffer GetForWrite()
{
Buffer usage = buffers[writeIndex];
usage.LastUsage = UsageType.Write;
return usage;
}

public Buffer? GetForRead()
/// <summary>
/// Attempts to retrieve a buffer to read.
/// </summary>
/// <param name="timeout">Amount of time (in milliseconds) to wait for a buffer to be written.</param>
/// <returns>An available buffer to be read, or <c>null</c> if no buffer has been written.</returns>
public Buffer? GetForRead(int timeout = DEFAULT_READ_TIMEOUT)
{
stopwatch.Restart();

do
while (true)
{
flip(ref readIndex);

// This should really never happen, but prevents a potential infinite loop if the usage can never be retrieved.
if (stopwatch.ElapsedMilliseconds > read_timeout_milliseconds)
if (buffers[readIndex].LastUsage != UsageType.Read)
break;

if (timeout == 0 || stopwatch.ElapsedMilliseconds > timeout)
return null;
} while (buffers[readIndex].LastUsage == UsageType.Read);
}

Buffer usage = buffers[readIndex];

Expand Down
2 changes: 1 addition & 1 deletion osu.Framework/Platform/GameHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ protected virtual void DrawFrame()
Renderer.WaitUntilNextFrameReady();

didRenderFrame = false;
buffer = drawRoots.GetForRead();
buffer = drawRoots.GetForRead(IsActive.Value ? TripleBuffer<DrawNode>.DEFAULT_READ_TIMEOUT : 0);
}

if (buffer == null)
Expand Down
Loading