#Chunk Support for DynamicBuffers

1 messages · Page 1 of 1 (latest)

pseudo cobalt
#

Has Unity said anything about adding support for “Chunk DynamicBuffers”?

…meaning DynamicBuffers that live on the chunk, the same way Chunk ComponentData do?

I can’t think of a technical reason why that couldn’t work. I hope it’s current absence is just a casualty of prioritization, rather than a philosophical stance by the DOTS team.

Chunk components are great, but there’s a lot you can’t do with them.

daring moat
#

it has been asked before but we didn't get a clear answer. i also think that would be really helpful to have as a feature. if you don't go overboard you can implement fields with an index accessor. you can also allocate an array and store the pointer but that has the obvious problem of the chunk lifecycle that suddenly has to be managed and is quite difficult to get right. maybe that's one of the reasons unity hasn't dealt with it yet.

thorn zinc
#

oh i looked at how chunk components work as part of my virtual chunk stuff i've been working on and i didn't really see a reason why buffers on chunks couldn't work (and wasn't already supported just missing API.)

#

a quick extension method later and

#
    public partial struct TestBufferSystem : ISystem
    {
        private Entity entity;

        public void OnCreate(ref SystemState state)
        {
            entity = state.EntityManager.CreateEntity();
            state.EntityManager.AddComponent(entity, ComponentType.ChunkComponent<TestChunkBuffer>());

            var buffer = state.EntityManager.GetChunkBuffer<TestChunkBuffer>(entity);
            buffer.Add(new TestChunkBuffer { Value = 2 });
        }

        public void OnUpdate(ref SystemState state)
        {
            var buffer = state.EntityManager.GetChunkBuffer<TestChunkBuffer>(entity);
            Debug.Log($"{buffer.Length}");
        }
    }```
#

it seems to work fine

#

chunk components are just stored on a separate entity

#

not sure about safety and all that jazz, not knowledge enough with it yet

#

i suspect safety handles aren't really setup for the buffers maybe?

#

exploring this is on my todo list

#

because if i can safely get a dynamic buffer on a chunk meta entity

#

i can use my existing dynamichashmap/dynamicmultihashmap as well

#

for hashmap support

thorn zinc
#
        public static DynamicBuffer<T> GetChunkBuffer<T>(this EntityManager em, Entity entity) where T : unmanaged, IBufferElementData
        {
            var store = em.GetCheckedEntityDataAccess()->EntityComponentStore;
            store->AssertEntitiesExist(&entity, 1);
            var chunk = store->GetChunk(entity);
            return em.GetBuffer<T>(chunk->metaChunkEntity);
        }```
oops forgot to post extension, was just this
whole yarrow
#

Yes, it's in our backlog to implement; it just hasn't bubbled up to the front of the queue yet.

pseudo cobalt
#

My company is waiting on this feature to adopt dots. Is there any way to know when it might be considered for inclusion? Many thanks.

pseudo cobalt
#

We are hoping to include DynamicBuffer types in an EntityArchetype definition, which we’ll then use to create entities. That’s why tertle’s great extension method won’t work for us.

daring moat
#

does ComponentType.ChunkComponent<T> not work in an EntityArchetype?

pseudo cobalt
#

It does, but I don’t believe it supports DynamicBuffers. Only IComponentData.

daring moat
#

T has no restriction. doesn't complain here. give a try

pseudo cobalt
#

Thanks, but will it actually add the buffer type as a chunk component when you use the archetype to create a new entity/chunk? Or is the compiler just not complaining for you?

daring moat
#

going through an entity archetype should be the same as tertle used here with state.EntityManager.AddComponent(entity, ComponentType.ChunkComponent<TestChunkBuffer>());

pseudo cobalt
#

No, I mean, when we try to use EntityManager.CreateEntity(EntityArchetype);, it will just ignore the DynamicBuffer type we tried to add to the archetype as a chunk component. The resulting entity’s chunk won’t have that DB as a chunk component.

#

Are you seeing something different?

thorn zinc
#

does that actually work with normal chunk components?

pseudo cobalt
#

I’m afk at the moment, but past tests have worked with normal chunk components.

#

You can include a chunk component in the definition for an archetype, and then use that archetype to spawn entities. The resulting chunks will have that chunk component.

thorn zinc
#

(I'm also surprised that chunk components are the thing stopping you using entities as it's such a niche and rarely used feature)

pseudo cobalt
#

There’s a specific thing we’d like to do, that we haven’t found another good DOTS way to do. But that’s a topic for a different thread sometime.

daring moat
#

sorry, i can't test at the moment :/

thorn zinc
#
    public struct TestChunk : IComponentData
    {
        public int Value;
    }

    public struct TestBufferChunk : IBufferElementData
    {
        public int Value;
    }```
```cs
var archetype = state.EntityManager.CreateArchetype(ComponentType.ChunkComponent<TestChunk>(), ComponentType.ChunkComponent<TestBufferChunk>(), ComponentType.ReadWrite<Active>());
state.EntityManager.CreateEntity(archetype);```
#

works fine it seems? (i haven't tested further though)

pseudo cobalt
#

No worries! Thanks for commenting. I’m excited to try it again after your post.

thorn zinc
pseudo cobalt
#

Super glad to be wrong! Both of you - thank you! I’ll dig into this tonight

daring moat
#

nice! 👍

pseudo cobalt
#

I wonder when this started working. Tertle, your test is the same as what we tried a few months ago. Didn’t work.

#

Also, my phone wants to autocorrect your name to “fertile”.

thorn zinc
#

my alter ego

pseudo cobalt
#

Only posts innuendos, instead of advice.

daring moat
#

lol, turtle would be so much closer 🤣

pseudo cobalt
#

tertle, in your example, is TestBufferChunk actually showing up as a chunk component, or is it actually being added as a regular component on the entity?

daring moat
#

chunk components are their own entity.

pseudo cobalt
#

Chunk components are stored on a behind the scenes chunk, which holds chunk components for several other chunks.

#

But it looks like TestBufferChunk might be being added as a normal buffer (not a chunk buffer) in tertle’s test.

daring moat
#

several? that's not possible

pseudo cobalt
#

It is - that’s how it works. Each chunk holds info about a separate backing entity, which is what ‘owns’ all of that chunk’s chunk components. Those backing entities are normal entities, which live in other, normal chunks.

#

Put another way - there are hidden chunks hanging out behind the scenes, which only contain a bunch of these backing entities - and the chunk component data for several chunks.

thorn zinc
#

the UI doesn't have support for the info box for buffers (probably because it's not supported)

pseudo cobalt
#

Makes sense. I’ll dig in as soon as I can. Thanks again.

daring moat
pseudo cobalt
#

How would you go about accessing a chunk DynamicBuffer from inside of a job? I’m not sure I see a good way to.

#

The only supported way I’m aware of at access chunk components is ArchetypeChunk.GetChunkComponentData<T>(). And that returns T, not a DyanmicBuffer<T>.

#

That method also takes a ArchetypeChunkComponentType<T>, where T is constrained to be an IComponentData.

#

Damn! So close. Looks like this may not be possible yet. Not in a non-hacky way, at least.

#

If any of you know something about this that I’m missing, please comment about it.

thorn zinc
#

You just need to write an extension method

pseudo cobalt
#

What would it extend? ArchetypeChunk?

thorn zinc
#

yes

#

give me a minute i just got out of bed and i'm making a coffee but i might have already written it

pseudo cobalt
#

You are awesome, ty

thorn zinc
#

well i didnt

#

so i wrote one real quick

#
        public static DynamicBuffer<T> GetChunkBufferData<T>(this ArchetypeChunk chunk, ref BufferTypeHandle<T> typeHandle)
            where T : unmanaged, IBufferElementData
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            AtomicSafetyHandle.CheckReadAndThrow(typeHandle.m_Safety0);
#endif
            chunk.m_EntityComponentStore->AssertEntityHasComponent(chunk.m_Chunk->metaChunkEntity, typeHandle.m_TypeIndex);

            BufferHeader* header;
            if (typeHandle.IsReadOnly)
            {
                header = (BufferHeader*)chunk.m_EntityComponentStore->GetComponentDataWithTypeRO(chunk.m_Chunk->metaChunkEntity, typeHandle.m_TypeIndex);
            }
            else
            {
                header = (BufferHeader*)chunk.m_EntityComponentStore->GetComponentDataWithTypeRW(
                    chunk.m_Chunk->metaChunkEntity, typeHandle.m_TypeIndex, chunk.m_EntityComponentStore->GlobalSystemVersion);
            }

            int internalCapacity = TypeManager.GetTypeInfo(typeHandle.m_TypeIndex).BufferCapacity;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            var useMemoryInit = chunk.m_EntityComponentStore->useMemoryInitPattern != 0;
            var memoryInitPattern = chunk.m_EntityComponentStore->memoryInitPattern;
            return new DynamicBuffer<T>(header, typeHandle.m_Safety0, typeHandle.m_Safety1, typeHandle.IsReadOnly, useMemoryInit, memoryInitPattern, internalCapacity);
#else
            return new DynamicBuffer<T>(header, internalCapacity);
#endif
        }```
#

completely untested, use at your own peril

#

but it should make sense

pseudo cobalt
#

Ty! Dang

#

I was under the impression that ArchetypeChunk.m_EntityComponentStore (and other m_ members) were internal. I really need to catch up with the newer versions

thorn zinc
#

oh they totally are

#

you'lk need to give yourself internal access to entities via asmref for any of this

pseudo cobalt
#

Ah, dern. I’ve been hoping to avoid that on this project.

#

It just doesn’t feel too safe to publish a game that relies on internal access via asmref. Feels like the ground could shift out from under us right before we ship, or after we’ve shipped. Can’t promise customers we can definitely support the game.

pseudo cobalt
#

I don’t know. Maybe I’m overthinking it. Are people actually shipping games this way?

thorn zinc
#

i have a huge library of extensions to entities package, a lot requiring internal access

#

i've managed to maintain it for 3-4 years even between 2 major updates (0.17->0.5 and 0.51->1.0)

#

and it's been used in a couple of published games

#

you do know if for some reason entities 2.0 comes out in 5 years and breaks your extensions, you don't have to update straight away on a published game ^^

#

a lot of published games are still using 0.51

#

and the beauty of having source code is you can add support anyway even if things change