#Burst Loop Investigation

1 messages · Page 1 of 1 (latest)

deft quarry
#

ok it's much weirder than i expected

#
public static TData Calculate<T, TData>(this ref DataHeader<TData> header, in EntityContext entityContext, ref T context)
    where T : unmanaged, IContext<T>
    where TData : unmanaged
{
    return (DataType)header.Type switch
    {
        DataType.Default => default,
        DataType.ScalarConstant => ScalarConstant.Calculate<T, TData>(ref Data<ScalarConstantData<TData>>(ref header)),
        DataType.ScalarAdd => As(ScalarAdd.Calculate(ref Data<ScalarAddData>(ref header), in entityContext, ref context)),
        DataType.ScalarMultiply => As(ScalarMultiply.Calculate(ref Data<ScalarMultiplyData>(ref header), in entityContext, ref context)),
        DataType.QualifierAllOrNothing => As(QualifierAllOrNothing.Calculate(ref Data<QualifierAllOrNothingData>(ref header), in entityContext, ref context)),
        // DataType.QualifierMinimumOrNothing => As(QualifierMinimumOrNothing.Calculate(ref Data<QualifierMinimumOrNothingData>(ref header), in entityContext, ref context)),
        // DataType.QualifierSumAllAboveThreshold => As(QualifierSumAllAboveThreshold.Calculate(ref Data<QualifierSumAllAboveThresholdData>(ref header), in entityContext, ref context)),
        // DataType.QualifierSumAll => As(QualifierSumAll.Calculate(ref Data<QualifierSumAllData>(ref header), in entityContext, ref context)),
        DataType.QualifierSumWhileAboveThreshold => As(QualifierSumWhileAboveThreshold.Calculate(ref Data<QualifierSumWhileAboveThresholdData>(ref header), in entityContext, ref context)),
        _ => context.DataGenerated(ref header, in entityContext, ref context),
    };

    static TData As<TFrom>(TFrom from)
        where TFrom : unmanaged
    {
        return *(TData*)&from;
    }

    static ref TD Data<TD>(ref DataHeader<TData> header)
        where TD : unmanaged
    {
        return ref UnsafeUtility.AsRef<TD>((byte*)UnsafeUtility.AddressOf(ref header) + sizeof(DataHeader<TData>));
    }
}```
#

the 3 comment out lines are busted

#

the rest work fine

#

for example this works

    public struct QualifierSumWhileAboveThresholdData
    {
        internal BlobArray<BlobPtr<DataHeader<float>>> Scorers;
        internal BlobPtr<DataHeader<float>> Threshold;
    }

    /// <summary> Qualifier that sums all scores until one is no longer above the threshold then stops. </summary>
    public static class QualifierSumWhileAboveThreshold
    {
        [DataNode((int)DataType.QualifierSumWhileAboveThreshold)]
        public static float Calculate<T>(ref QualifierSumWhileAboveThresholdData data, in EntityContext entityContext, ref T context)
            where T : unmanaged, IContext<T>
        {
            var sum = 0f;
            var threshold = data.Threshold.Value.Calculate(in entityContext, ref context);

            for (var i = 0; i < data.Scorers.Length; i++)
            {
                var score = data.Scorers[i].Value.Calculate(in entityContext, ref context);
                if (score <= threshold)
                {
                    return sum;
                }

                sum += score;
            }

            return sum;
        }
    }```
#

while this is busted and never finishes compiling

public struct QualifierSumAllAboveThresholdData
{
    internal BlobArray<BlobPtr<DataHeader<float>>> Scorers;
    internal BlobPtr<DataHeader<float>> Threshold;
}

/// <summary> Qualifier that sums all scores above the threshold. </summary>
public static class QualifierSumAllAboveThreshold
{
    [DataNode((int)DataType.QualifierSumAllAboveThreshold)]
    public static float Calculate<T>(ref QualifierSumAllAboveThresholdData data, in EntityContext entityContext, ref T context)
        where T : unmanaged, IContext<T>
    {
        var sum = 0f;
        var threshold = data.Threshold.Value.Calculate(in entityContext, ref context);

        for (var i = 0; i < data.Scorers.Length; i++)
        {
            var score = data.Scorers[i].Value.Calculate(in entityContext, ref context);
            if (score > threshold)
            {
                sum += score;
            }
        }

        return sum;
    }
}```
#

they're near identical

deft quarry
#
    [BurstCompile]
    public partial struct TestSystemJob : IJobEntity
    {
        public void Execute(ref TestComponent component)
        {
            var context = new TestContext();
            component.Result = component.Blob.Value.Calculate(default, ref context);
        }
    }

    public struct TestContext : IContext<TestContext>
    {
        public DynamicUntypedHashMap<short> GetState(int index)
        {
            return default;
        }
    }

    public struct TestComponent : IComponentData
    {
        public BlobAssetReference<DataHeader<float>> Blob;
        public float Result;
    }```

well i've got standalone project repro down to this + 1 library assembly (rest deleted)
I don't seem to be able to reduce it anymore easily
#

so hopefully that'll be small enough

uneven bramble
#

i bet it'll be fine

deft quarry
runic nest
#

nice! great that you found it

deft quarry
#

well i didn't really find it as much as i'd like as it's still a, what the hell is going on

#

but i'm hoping it's enough that someone at unity can find it

#

it's actually kind of blocking me

#

i was hoping i could have at least found a workaround

uneven bramble
#

burst maven has picked it up

deft quarry
#

QA confirmed it which is always a relief that it isn't some local problem

deft quarry
#

ok, after a bunch of trial and error I actually found a workaround

#

but it makes the original being busted even more confusing

#

replacing the above shown method

public static TData Calculate<T, TData>(this ref DataHeader<TData> header, in EntityContext entityContext, ref T context)
    where T : unmanaged, IContext<T>
    where TData : unmanaged
{```
with
```cs
        public static TData Calculate<T, TData>(this ref DataHeader<TData> header, in EntityContext entityContext, ref T context)
            where T : unmanaged, IContext<T>
            where TData : unmanaged
        {
            return UnsafeUtility.As<DataHeader<TData>, DataHeader>(ref header).Calculate<T, TData>(entityContext, ref context);
        }

        private static TData Calculate<T, TData>(this ref DataHeader header, in EntityContext entityContext, ref T context)
            where T : unmanaged, IContext<T>
            where TData : unmanaged```
#

solves the issue

#

basically removing the generic header struct from the actual switch statement method

#

the actual generic struct has no generic fields or anything in it, it's purely there for some graph type safety in authoring

    public struct DataHeader<T> : INode
        where T : unmanaged
    {
        /// <summary> The unique data type. </summary>
        public int Type;
        internal int TypeHash;
    }
    public struct DataHeader
    {
        /// <summary> The unique data type. </summary>
        public int Type;
        internal int TypeHash;
    }```
#

very odd