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

Upgrading to Entities 1.0.16 #301

Merged
merged 22 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 21 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
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ The code is reasonably clean but documentation and examples are sparse. Feel fre
⚠️ We welcome PRs and bug reports but making this repo a public success is not our priority. No promises on when it will be addressed!

# Dependencies
- [Unity 2021.3.5+](https://unity.com/)
- [Unity 2022.3.15+](https://unity.com/)
- [anvil-csharp-core (main...usually 😬)](https://github.com/decline-cookies/anvil-csharp-core)
- [anvil-unity-core (main...usually 😬)](https://github.com/decline-cookies/anvil-unity-core)
- *DOTS Packages*
- [com.unity.entities (0.50.1-preview2)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.rendering.hybrid (0.50.0-preview.44)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.burst (1.6.4)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.collections (1.2.3)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.jobs (0.50.0-preview.9)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.mathematics (1.2.5)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.entities (1.0.16)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.entities.graphics (1.0.16)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.burst (1.8.11)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.collections (2.1.4)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)
- [com.unity.mathematics (1.2.6)](https://docs.unity3d.com/Packages/[email protected]/manual/index.html)

At this point in time, all DOTS related functionality is in this one repository. In the future, we may split the functionality into specialized repositories. Maintaining a repository per Unity DOTS package seems overly tedious at the moment.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ namespace Anvil.Unity.Collections
/// A collection of extension methods for <see cref="FixedList32Bytes{T}"/> (and friends) that require internal
/// access to function.
/// </summary>
[BurstCompatible]
public static unsafe class FixedListInternalExtension
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should put the [BurstCompile] attribute on this or in any place we've replaced the attribute?

OR

Since we're no longer using this attribute should we communicate methods/types that are/aren't burst compatible somehow? Our own attribute or maybe just comments?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's chat about this.

Putting [BurstCompile] won't do anything so I think that's confusing to add.

See: https://forum.unity.com/threads/when-where-and-why-to-put-burstcompile-with-mild-under-the-hood-explanation.1344539/ for more in-depth explanations for when to use the attributes.

A class/function etc isn't necessarily just Burst or not. It could be both depending on where you call it.

For example, if you called this FixedListInternalExtension.IndexOf from within a bursted job it would execute as Bursted code. Great.

But in the same runtime, if you called the same function FixedListInternalExtension.IndexOf from the main thread in OO land, it would just execute as regular non-bursted code.

The compiler would have generated two different lower level paths.

We could add in the updated test attribute of GenerateTestsForBurstCompatibility which replaces BurstCompatible but that also doesn't do anything unless you run the editor commands for generating tests for your code base and running them. There is also no replacement for NotBurstCompatible.

If we added our own attributes, that'd be fine, but again they can't really do anything. There's nothing we can use them for to check or gate or validate for.

Comments could be fine, but I'm not sure if it's worthwhile since it will depend on the context that you all it.

In my mind, based on how things work and the feedback we get from the IDE, there are the following scenarios:

  • Calling from Bursted Context
    • Calling code that can't be bursted: IDE will give you a warning, compiler will give you a Burst error.
      • This is great, prevents issues where you want to be bursted but messed up and didn't notice.
    • Calling code that can be bursted: All good, IDE will tell you that it's Bursted code.
  • Calling from Non Bursted Context
    • Doesn't matter what it is, the code will not be Bursted even if it has the BurstCompile attribute.

Given this, I'm not sure we need to communicate anything to the developer since really they just need to understand where they are calling from.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I misunderstood how [BurstCompile] worked. That's fine.

I think comments might be helpful. It's fair enough that the IDE will warn you when calling non-burstable code from a bursted context but it doesn't really help when you're writing bursted code and poking around the codebase to see what you can find. Until you type it out (or read the whole class) you won't know if a piece of existing functionality that you've found will be compatible.

Maybe that doesn't happen often enough to justify writing comments and I'm inventing work here but I feel like, while writing bursted code, I'm often asking myself "can I use this method/type?"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The counter-argument to comments is that it might be too general and the underlying code changes and whoever does that forgets to update the comment at the top of the file?

In the scenario you're describing, I feel like the effort to type it out (which is pretty fast with autocomplete) to get the Burst warning in the IDE is the same or less then opening things up and reading comments which would be more to maintain?

If we really wanted to signify to the developer that these are Burst safe things to use, I would argue that we should note that in the Class name or Method name instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try without the comments for now and see how it goes.

When I'm devising a solution I'm not going to type out and check every method/type as I go. I'm going to collect a path or collection of types that "will work" and then go to implement.

Adding burst to all the type and method names is insane but if you're considering that I'll just drop this topic. You've backed me away from the ledge...

{
/// <summary>
Expand Down Expand Up @@ -153,7 +152,6 @@ public static int IndexOf<TEnum, TUnderlying>(this in FixedList4096Bytes<TEnum>
/// /// <remarks>
/// This is a copy of <see cref="FixedList32Bytes{T}.Contains{T,U}"/> that supports <see cref="Enum"/> elements
/// </remarks>
[BurstCompatible(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
public static bool Contains<TEnum, TUnderlying>(this in FixedList32Bytes<TEnum> list, TUnderlying value)
where TEnum : unmanaged, Enum
where TUnderlying : unmanaged, IEquatable<TUnderlying>
Expand All @@ -174,7 +172,6 @@ public static bool Contains<TEnum, TUnderlying>(this in FixedList32Bytes<TEnum>
/// /// <remarks>
/// This is a copy of <see cref="FixedList32Bytes{T}.Contains{T,U}"/> that supports <see cref="Enum"/> elements
/// </remarks>
[BurstCompatible(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
public static bool Contains<TEnum, TUnderlying>(this in FixedList64Bytes<TEnum> list, TUnderlying value)
where TEnum : unmanaged, Enum
where TUnderlying : unmanaged, IEquatable<TUnderlying>
Expand All @@ -195,7 +192,6 @@ public static bool Contains<TEnum, TUnderlying>(this in FixedList64Bytes<TEnum>
/// /// <remarks>
/// This is a copy of <see cref="FixedList32Bytes{T}.Contains{T,U}"/> that supports <see cref="Enum"/> elements
/// </remarks>
[BurstCompatible(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
public static bool Contains<TEnum, TUnderlying>(this in FixedList128Bytes<TEnum> list, TUnderlying value)
where TEnum : unmanaged, Enum
where TUnderlying : unmanaged, IEquatable<TUnderlying>
Expand All @@ -216,7 +212,6 @@ public static bool Contains<TEnum, TUnderlying>(this in FixedList128Bytes<TEnum>
/// /// <remarks>
/// This is a copy of <see cref="FixedList32Bytes{T}.Contains{T,U}"/> that supports <see cref="Enum"/> elements
/// </remarks>
[BurstCompatible(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
public static bool Contains<TEnum, TUnderlying>(this in FixedList512Bytes<TEnum> list, TUnderlying value)
where TEnum : unmanaged, Enum
where TUnderlying : unmanaged, IEquatable<TUnderlying>
Expand All @@ -237,7 +232,6 @@ public static bool Contains<TEnum, TUnderlying>(this in FixedList512Bytes<TEnum>
/// /// <remarks>
/// This is a copy of <see cref="FixedList32Bytes{T}.Contains{T,U}"/> that supports <see cref="Enum"/> elements
/// </remarks>
[BurstCompatible(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
public static bool Contains<TEnum, TUnderlying>(this in FixedList4096Bytes<TEnum> list, TUnderlying value)
where TEnum : unmanaged, Enum
where TUnderlying : unmanaged, IEquatable<TUnderlying>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public static class NativeParallelHashMapInternalExtension
/// <typeparam name="TValue">The value type.</typeparam>
/// <returns>The <see cref="Allocator"/>.</returns>
public static Allocator GetAllocator<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> map)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
return map.m_HashMapData.GetAllocator();
}
Expand All @@ -34,8 +34,8 @@ public static Allocator GetAllocator<TKey, TValue>(this NativeParallelHashMap<TK
/// <typeparam name="TKey">The key type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
public static void GetKeyArray<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> map, NativeArray<TKey> result)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
map.m_HashMapData.GetKeyArray(result);
}
Expand All @@ -49,8 +49,8 @@ public static void GetKeyArray<TKey, TValue>(this NativeParallelHashMap<TKey, TV
/// <typeparam name="TKey">The key type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
public static void GetValueArray<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> map, NativeArray<TValue> result)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
map.m_HashMapData.GetValueArray(result);
}
Expand All @@ -64,8 +64,8 @@ public static void GetValueArray<TKey, TValue>(this NativeParallelHashMap<TKey,
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static void GetKeyValueArrays<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> map, NativeKeyValueArrays<TKey, TValue> result)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
map.m_HashMapData.GetKeyValueArrays(result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public static class UnsafeParallelHashMapInternalExtension
/// <typeparam name="TValue">The value type.</typeparam>
/// <returns>The <see cref="Allocator"/>.</returns>
public static Allocator GetAllocator<TKey, TValue>(this UnsafeParallelHashMap<TKey, TValue> map)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
return map.m_AllocatorLabel.ToAllocator;
}
Expand All @@ -35,8 +35,8 @@ public static Allocator GetAllocator<TKey, TValue>(this UnsafeParallelHashMap<TK
/// <typeparam name="TKey">The key type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
public static unsafe void GetKeyArray<TKey, TValue>(this UnsafeParallelHashMap<TKey, TValue> map, NativeArray<TKey> result)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
UnsafeParallelHashMapData.GetKeyArray(map.m_Buffer, result);
}
Expand All @@ -50,8 +50,8 @@ public static unsafe void GetKeyArray<TKey, TValue>(this UnsafeParallelHashMap<T
/// <typeparam name="TKey">The key type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
public static unsafe void GetValueArray<TKey, TValue>(this UnsafeParallelHashMap<TKey, TValue> map, NativeArray<TValue> result)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
UnsafeParallelHashMapData.GetValueArray(map.m_Buffer, result);
}
Expand All @@ -65,8 +65,8 @@ public static unsafe void GetValueArray<TKey, TValue>(this UnsafeParallelHashMap
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static unsafe void GetKeyValueArrays<TKey, TValue>(this UnsafeParallelHashMap<TKey, TValue> map, NativeKeyValueArrays<TKey, TValue> result)
where TKey : struct, IEquatable<TKey>
where TValue : struct
where TKey : unmanaged, IEquatable<TKey>
where TValue : unmanaged
{
UnsafeParallelHashMapData.GetKeyValueArrays(map.m_Buffer, result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
/// A collection of extension methods to help calculate and modify the dependencies on <see cref="ComponentType"/>s
/// directly.
/// </summary>
[BurstCompatible]
public static class ComponentTypeDependencyExtension
{
private static UnsafeList<int> s_WriteTypeList_ScratchPad;
private static UnsafeList<int> s_ReadTypeList_ScratchPad;
private static UnsafeList<TypeIndex> s_WriteTypeList_ScratchPad;
private static UnsafeList<TypeIndex> s_ReadTypeList_ScratchPad;

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Init()
Expand All @@ -24,13 +23,13 @@ private static void Init()
{
s_WriteTypeList_ScratchPad.Dispose();
}
s_WriteTypeList_ScratchPad = new UnsafeList<int>(0, Allocator.Persistent);
s_WriteTypeList_ScratchPad = new UnsafeList<TypeIndex>(0, Allocator.Persistent);

if (s_ReadTypeList_ScratchPad.IsCreated)
{
s_ReadTypeList_ScratchPad.Dispose();
}
s_ReadTypeList_ScratchPad = new UnsafeList<int>(0, Allocator.Persistent);
s_ReadTypeList_ScratchPad = new UnsafeList<TypeIndex>(0, Allocator.Persistent);
}


Expand All @@ -55,7 +54,6 @@ public static unsafe JobHandle GetDependency(this EntityManager manager, Compone
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
/// <param name="componentTypes">The component types to calculate the dependency of.</param>
/// <returns>The combined dependency for the component types</returns>
[NotBurstCompatible]
public static unsafe JobHandle GetDependency(this EntityManager manager, params ComponentType[] componentTypes)
{
return GetDependency(manager.GetCheckedEntityDataAccess()->DependencyManager, componentTypes);
Expand All @@ -70,7 +68,6 @@ public static unsafe JobHandle GetDependency(this EntityManager manager, params
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
/// <param name="componentTypes">The component types to calculate the dependency of.</param>
/// <returns>The combined dependency for the component types</returns>
[NotBurstCompatible]
public static unsafe JobHandle GetDependency<T>(this EntityManager manager, T componentTypes)
where T : class, IEnumerable<ComponentType>
{
Expand Down Expand Up @@ -110,7 +107,6 @@ public static unsafe JobHandle GetDependency(this ComponentType componentType, E
/// <param name="componentTypes">The component types to calculate the dependency of.</param>
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
/// <returns>The combined dependency for the component types</returns>
[NotBurstCompatible]
public static unsafe JobHandle GetDependency<T>(this T componentTypes, EntityManager manager)
where T : class, IEnumerable<ComponentType>
{
Expand All @@ -124,7 +120,6 @@ public static unsafe JobHandle GetDependency<T>(this T componentTypes, EntityMan
/// <param name="componentTypes">The component types to calculate the dependency of.</param>
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
/// <returns>The combined dependency for the component types</returns>
[NotBurstCompatible]
public static unsafe JobHandle GetDependency(this ref NativeArray<ComponentType> componentTypes, EntityManager manager)
{
return GetDependency(manager.GetCheckedEntityDataAccess()->DependencyManager, ref componentTypes);
Expand All @@ -151,7 +146,6 @@ public static unsafe void AddDependency(this EntityManager manager, JobHandle de
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
/// <param name="dependency">The handle that represents when the consuming job is complete.</param>
/// <param name="componentTypes">The component types to set the dependency of.</param>
[NotBurstCompatible]
public static unsafe void AddDependency(this EntityManager manager, JobHandle dependency, params ComponentType[] componentTypes)
{
AddDependency(manager.GetCheckedEntityDataAccess()->DependencyManager, dependency, componentTypes);
Expand All @@ -166,7 +160,6 @@ public static unsafe void AddDependency(this EntityManager manager, JobHandle de
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
/// <param name="dependency">The handle that represents when the consuming job is complete.</param>
/// <param name="componentTypes">The component types to set the dependency of.</param>
[NotBurstCompatible]
public static unsafe void AddDependency<T>(this EntityManager manager, JobHandle dependency, T componentTypes)
where T : class, IEnumerable<ComponentType>
{
Expand Down Expand Up @@ -206,7 +199,6 @@ public static unsafe void AddDependency(this ComponentType componentType, JobHan
/// <param name="componentTypes">The component types to set the dependency of.</param>
/// <param name="dependency">The handle that represents when the consuming job is complete.</param>
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
[NotBurstCompatible]
public static unsafe void AddDependency<T>(this T componentTypes, JobHandle dependency, EntityManager manager)
where T : class, IEnumerable<ComponentType>
{
Expand All @@ -220,7 +212,6 @@ public static unsafe void AddDependency<T>(this T componentTypes, JobHandle depe
/// <param name="componentTypes">The component types to set the dependency of.</param>
/// <param name="dependency">The handle that represents when the consuming job is complete.</param>
/// <param name="manager"> The <see cref="World"/>'s <see cref="EntityManager"/>.</param>
[NotBurstCompatible]
public static unsafe void AddDependency(this ref NativeArray<ComponentType> componentTypes, JobHandle dependency, EntityManager manager)
{
AddDependency(manager.GetCheckedEntityDataAccess()->DependencyManager, dependency, ref componentTypes);
Expand All @@ -235,15 +226,14 @@ private static unsafe JobHandle GetDependency(ComponentDependencyManager* depend
// 1. Get the pointer to the one type index.
// 2. Use the pointer for both the reader and writer parameters
// 3. Calculate the reader/writer count based on the component type's access mode.
int* typeIndexPtr = (int*)UnsafeUtility.AddressOf(ref componentType.TypeIndex);
TypeIndex* typeIndexPtr = (TypeIndex*)UnsafeUtility.AddressOf(ref componentType.TypeIndex);
int writerCount = componentType.AccessModeType == ComponentType.AccessMode.ReadWrite ? 1 : 0;
int readerCount = 1 - writerCount;

return dependencyManager
->GetDependency(typeIndexPtr, readerCount, typeIndexPtr, writerCount);
}

[NotBurstCompatible]
private static unsafe JobHandle GetDependency<T>(ComponentDependencyManager* dependencyManager, T componentTypes)
where T : class, IEnumerable<ComponentType>
{
Expand All @@ -266,15 +256,14 @@ private static unsafe void AddDependency(ComponentDependencyManager* dependencyM
// 1. Get the pointer to the one type index.
// 2. Use the pointer for both the reader and writer parameters
// 3. Calculate the reader/writer count based on the component type's access mode.
int* typeIndexPtr = (int*)UnsafeUtility.AddressOf(ref componentType.TypeIndex);
TypeIndex* typeIndexPtr = (TypeIndex*)UnsafeUtility.AddressOf(ref componentType.TypeIndex);
int writerCount = componentType.AccessModeType == ComponentType.AccessMode.ReadWrite ? 1 : 0;
int readerCount = 1 - writerCount;

dependencyManager
->AddDependency(typeIndexPtr, readerCount, typeIndexPtr, writerCount, dependency);
}

[NotBurstCompatible]
private static unsafe void AddDependency<T>(ComponentDependencyManager* dependencyManager, JobHandle dependency, T componentTypes)
where T : class, IEnumerable<ComponentType>
{
Expand All @@ -290,7 +279,6 @@ private static unsafe void AddDependency(ComponentDependencyManager* dependencyM
->AddDependency(s_ReadTypeList_ScratchPad.Ptr, s_ReadTypeList_ScratchPad.Length, s_WriteTypeList_ScratchPad.Ptr, s_WriteTypeList_ScratchPad.Length, dependency);
}

[NotBurstCompatible]
private static void BuildTypeLists<T>(T componentTypes)
where T : class, IEnumerable<ComponentType>
{
Expand All @@ -313,4 +301,4 @@ private static void BuildTypeLists(ref NativeArray<ComponentType> componentTypes
CalculateReaderWriterDependency.Add(componentType, ref s_ReadTypeList_ScratchPad, ref s_WriteTypeList_ScratchPad);
}
}
}
}
24 changes: 0 additions & 24 deletions Scripts/AssemblyInjections/Unity.Entities/WorldInternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,6 @@ namespace Anvil.Unity.DOTS.Entities
/// </summary>
public static class WorldInternal
{
/// <summary>
/// Dispatched after a world is created.
/// </summary>
/// <remarks>
/// This is a proxy for the internal <see cref="World.WorldCreated"/> static event that Unity has made internal.
/// </remarks>
public static event Action<World> OnWorldCreated
{
add => World.WorldCreated += value;
remove => World.WorldCreated -= value;
}

/// <summary>
/// Dispatched before a world is destroyed.
/// </summary>
/// <remarks>
/// This is a proxy for the internal <see cref="World.WorldDestroyed"/> static event that Unity has made internal.
/// </remarks>
public static event Action<World> OnWorldDestroyed
{
add => World.WorldDestroyed += value;
remove => World.WorldDestroyed -= value;
}

/// <summary>
/// Dispatched after a system is created.
/// </summary>
Expand Down
Loading