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

Fixes issue with headless mode #6

Merged
merged 3 commits into from
Dec 30, 2023
Merged

Fixes issue with headless mode #6

merged 3 commits into from
Dec 30, 2023

Conversation

Delsin-Yu
Copy link
Contributor

@Delsin-Yu Delsin-Yu commented Dec 5, 2023

Fixes #5

Currently, some APIs inside GDTask rely on the Engine.GetFramesDrawn() API, which always returns 0 when Engine runs with --disable-render-loop, this PR replaces all usage mentioned with Engine.GetProcessFrames(), which works regardless whether the render loop is enabled.
This API is also a better candidate for Unity's Time.frameCount API.

However, Engine.GetProcessFrames() returns ulong, which does not have -1 as a fallback value, I have replaced all -1s with 0ul as a compromise, this could be an issue for some edge cases. Currently, I can pass the builtin test, but I think further tests are required.

// UniTask: PlayerLoopTimer.cs, line 159

protected override bool MoveNextCore()
{
    if (elapsed == 0.0f)
    {
        if (initialFrame == Time.frameCount)
        {
            return true;
        }
    }

    elapsed += Time.deltaTime;
    if (elapsed >= interval)
    {
        return false;
    }

    return true;
}

protected override void ResetCore(TimeSpan? interval)
{
    this.elapsed = 0.0f;
    this.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
    if (interval != null)
    {
        this.interval = (float)interval.Value.TotalSeconds;
    }
}
// GDTask: PlayerLoopTimer.cs, line 155

protected override bool MoveNextCore()
{
    if (elapsed == 0.0)
    {
        if (initialFrame == Engine.GetProcessFrames())
        {
            return true;
        }
    }

    elapsed += GDTaskPlayerLoopAutoload.Global.DeltaTime;
    if (elapsed >= interval)
    {
        return false;
    }

    return true;
}

protected override void ResetCore(TimeSpan? interval)
{
    this.elapsed = 0.0;
    this.initialFrame = GDTaskPlayerLoopAutoload.IsMainThread ? Engine.GetProcessFrames() : 0ul;
    if (interval != null)
    {
        this.interval = (float)interval.Value.TotalSeconds;
    }
}

@Delsin-Yu
Copy link
Contributor Author

Delsin-Yu commented Dec 5, 2023

Addresses gdtask-no-yield
image

@Atlinx
Copy link
Member

Atlinx commented Dec 20, 2023

I think the purpose of the -1 was to ensure non-main-thread tasks relied on manual interval-based ticking instead of the engine's process/update frames. Maybe we could set a boolean flag that marks if a loop timer is in the main thread or not. Then we could try something like:

// PlayerLoopTimer.cs

protected override bool MoveNextCore()
{
    if (elapsed == 0.0f)
    {
        if (isMainThread && initialFrame == Engine.GetProcessFrames()) // Check the flag
        {
            return true;
        }
    }
    ...
}

protected override void ResetCore(TimeSpan? interval)
{
    this.elapsed = 0.0;
    this.isMainThread = GDTaskPlayerLoopAutoload.IsMainThread; // Set the flag
    this.initialFrame = Engine.GetProcessFrames();
    if (interval != null)
    {
        this.interval = (float)interval.Value.TotalSeconds;
    }
}

@Atlinx Atlinx merged commit 8bb9680 into Fractural:4.x Dec 30, 2023
1 check failed
@Atlinx
Copy link
Member

Atlinx commented Dec 30, 2023

Thanks for the PR! ❤️

@Atlinx Atlinx mentioned this pull request Dec 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants