#[BUG] Rewind Allocator in FixedRateCatchUpManager

1 messages · Page 1 of 1 (latest)

devout beacon
#
            public bool ShouldGroupUpdate(ComponentSystemGroup group)
            {
                float worldMaximumDeltaTime = group.World.MaximumDeltaTime;
                float maximumDeltaTime = math.max(worldMaximumDeltaTime, m_FixedTimestep);

                // if this is true, means we're being called a second or later time in a loop
                if (m_DidPushTime)
                {
                    group.World.PopTime();
                    group.World.RestoreGroupAllocator(m_OldGroupAllocators);
                }
                else
                {
                    m_MaxFinalElapsedTime = m_LastFixedUpdateTime + maximumDeltaTime;
                }

                var finalElapsedTime = math.min(m_MaxFinalElapsedTime, group.World.Time.ElapsedTime);
                if (m_FixedUpdateCount == 0)
                {
                    // First update should always occur at t=0
                }
                else if (finalElapsedTime - m_LastFixedUpdateTime >= m_FixedTimestep)
                {
                    // Advance the timestep and update the system group
                    m_LastFixedUpdateTime += m_FixedTimestep;
                }
                else
                {
                    // No update is necessary at this time.
                    m_DidPushTime = false;
                    return false;
                }

                m_FixedUpdateCount++;

                group.World.PushTime(new TimeData(
                    elapsedTime: m_LastFixedUpdateTime,
                    deltaTime: m_FixedTimestep));

                m_DidPushTime = true;

                m_OldGroupAllocators = group.World.CurrentGroupAllocators;
                group.World.SetGroupAllocator(group.RateGroupAllocators);
                return true;
            }```
#

Everytime fixed update runs it calls

m_DidPushTime = true;
m_OldGroupAllocators = group.World.CurrentGroupAllocators;
group.World.SetGroupAllocator(group.RateGroupAllocators);
return true;```
#

The next call restores the old allocator

// if this is true, means we're being called a second or later time in a loop
if (m_DidPushTime)
{
    group.World.PopTime();
    group.World.RestoreGroupAllocator(m_OldGroupAllocators);
}```
#

RestoreGroupAllocator

        internal void RestoreGroupAllocator(DoubleRewindableAllocators* oldGroupAllocators)
        {
            // Group allocators provided
            if (oldGroupAllocators != null)
            {
                // Not the same as the old rate group allocator
                if (DoubleUpdateAllocators != oldGroupAllocators)
                {
                    DoubleUpdateAllocators->Update();
                }
                DoubleUpdateAllocators = oldGroupAllocators;
                return;
            }
        }```
does the Update which 
> Update the double rewindable allocators, switch Pointer to another allocator and rewind the newly switched allocator.
#

rolls back the old allocator and switches them

#

But rewind allocator only supports 2 ticks

#

Therefore in a sync less environment (which I have enforced)
If your fixed update runs 3+ times a frame you start rewinding frames that could still be running

#

(Now to be clear, I am probably the only person in the world who this affects because currently fixed updates annoyingly forces a sync between ticks but I've 'fixed' this limitation)

#
public bool ShouldGroupUpdate(ComponentSystemGroup group)
{
    float worldMaximumDeltaTime = group.World.MaximumDeltaTime;
    float maximumDeltaTime = math.max(worldMaximumDeltaTime, m_FixedTimestep);

    // if this is true, means we're being called a second or later time in a loop
    if (m_DidPushTime)
    {
        group.World.PopTime();
    }
    else
    {
        m_MaxFinalElapsedTime = m_LastFixedUpdateTime + maximumDeltaTime;
    }

    var finalElapsedTime = math.min(m_MaxFinalElapsedTime, group.World.Time.ElapsedTime);
    if (m_FixedUpdateCount == 0)
    {
        // First update should always occur at t=0
    }
    else if (finalElapsedTime - m_LastFixedUpdateTime >= m_FixedTimestep)
    {
        // Advance the timestep and update the system group
        m_LastFixedUpdateTime += m_FixedTimestep;
    }
    else
    {
        if (m_DidPushTime)
        {
            m_DidPushTime = false;
            group.World.RestoreGroupAllocator(m_OldGroupAllocators);
        }
        
        // No update is necessary at this time.
        return false;
    }

    m_FixedUpdateCount++;

    group.World.PushTime(new TimeData(
        elapsedTime: m_LastFixedUpdateTime,
        deltaTime: m_FixedTimestep));

    if (!m_DidPushTime)
    {
        m_DidPushTime = true;

        m_OldGroupAllocators = group.World.CurrentGroupAllocators;
        group.World.SetGroupAllocator(group.RateGroupAllocators);
    }

    return true;
}```
I've fixed it by making it only set/restore at start/end of the update
devout beacon
#

netcode NetcodePredictionFixedRateManager/NetcodeServerRateManager/NetcodeClientPredictionRateManager etc seems to have the same problem

errant bronze
devout beacon
#

This 'bug' really only effects me

devout beacon
#

[BUG] Rewind Allocator in FixedRateCatchUpManager