Search Unity

Most Efficient and Concise Way of Resizing Buffer Element Data

Discussion in 'Entity Component System' started by Matt_De_Boss_Developer, May 21, 2019.

  1. Matt_De_Boss_Developer

    Matt_De_Boss_Developer

    Joined:
    Oct 17, 2014
    Posts:
    46
    So at the current moment I have been looking into ECS to try to convert my Voxel Engine to fully utilize it. At the current moment, I am just playing around with creating entities and plopping on components. However, I found that adding on large Buffers onto an entity is extremely tedious as I have to resize since my sizes are too large for using the InternalCapacity tag. So, what is the most clear and concise way of resizing my Buffer Element Data after they have been added onto an Entity? Code that I have now is below:

    Code (CSharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using System;
    6.  
    7. public class Bootstrap : MonoBehaviour
    8. {
    9.     private void Start()
    10.     {
    11.  
    12.         var entityManager = World.Active.EntityManager;
    13.  
    14.         var chunkEntity = entityManager.CreateEntity(typeof(VoxelData),
    15.                                                      typeof(UnfilteredVerticesArray),
    16.                                                      typeof(CornersArray),
    17.                                                      typeof(GridArray),
    18.                                                      typeof(VertSliceArray),
    19.                                                      typeof(EdgeTable),
    20.                                                      typeof(TriangleTable));
    21.  
    22.         DynamicBuffer<VoxelData> voxelBuffer = entityManager.GetBuffer<VoxelData>(chunkEntity);
    23.         voxelBuffer.ResizeUninitialized(17 * 17 * 17);
    24.  
    25.         DynamicBuffer<UnfilteredVerticesArray> UnfilteredVerticesBuffer = entityManager.GetBuffer<UnfilteredVerticesArray>(chunkEntity);
    26.         UnfilteredVerticesBuffer.ResizeUninitialized(16 * 16 * 16 * 15);
    27.  
    28.         DynamicBuffer<CornersArray> CornersBuffer = entityManager.GetBuffer<CornersArray>(chunkEntity);
    29.         CornersBuffer.ResizeUninitialized(16 * 16 * 16 * 8);
    30.  
    31.         DynamicBuffer<GridArray> GridBuffer = entityManager.GetBuffer<GridArray>(chunkEntity);
    32.         GridBuffer.ResizeUninitialized(16 * 16 * 16 * 8);
    33.  
    34.         DynamicBuffer<VertSliceArray> VertSliceBuffer = entityManager.GetBuffer<VertSliceArray>(chunkEntity);
    35.         VertSliceBuffer.ResizeUninitialized(16 * 16 * 16 * 12);
    36.  
    37.         DynamicBuffer<EdgeTable> EdgeTableBuffer = entityManager.GetBuffer<EdgeTable>(chunkEntity);
    38.         EdgeTableBuffer.ResizeUninitialized(256);
    39.  
    40.         DynamicBuffer<TriangleTable> TriangleTableBuffer = entityManager.GetBuffer<TriangleTable>(chunkEntity);
    41.         TriangleTableBuffer.ResizeUninitialized(4096);
    42.  
    43.     }
    44.  
    45.  
     
  2. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Yeah, looks fine to me.
    .Capacity
    will have a setter in the future too (source).

    Code (CSharp):
    1. /// <summary>
    2. /// Increases the buffer capacity and length.
    3. /// </summary>
    4. /// <param name="length">The new length of the buffer.</param>
    5. public void ResizeUninitialized(int length)
    6. {
    7.     Reserve(length);
    8.     m_Buffer->Length = length;
    9. }
    10.  
    11. /// <summary>
    12. /// Increases the buffer capacity without increasing its length.
    13. /// </summary>
    14. /// <param name="length">The new buffer capacity.</param>
    15. public void Reserve(int length)
    16. {
    17.     CheckWriteAccessAndInvalidateArrayAliases();
    18.     BufferHeader.EnsureCapacity(m_Buffer, length, UnsafeUtility.SizeOf<T>(), UnsafeUtility.AlignOf<T>(), BufferHeader.TrashMode.RetainOldData);
    19. }
     
  3. Matt_De_Boss_Developer

    Matt_De_Boss_Developer

    Joined:
    Oct 17, 2014
    Posts:
    46
    I mean, the code works. However, I am going to be spawning tons of Entities with all of these buffers, and resizing like that just seems a little tedious and maybe even performance killing?
     
  4. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Oh, I'm also working on a pseudo-voxel project, but haven't ran into any perf issue with DynamicBuffer yet. For my purposes, I mostly work with NativeArrays in Jobs, then MemCpy them over to DynamicBuffers.

    I may be completely mis-understanding your problem. But resizing should be a one-time thing for you right? Since chunks are fixed. Is allocating memory giving you performance problems?
     
    Last edited: May 21, 2019
  5. Matt_De_Boss_Developer

    Matt_De_Boss_Developer

    Joined:
    Oct 17, 2014
    Posts:
    46
    Not at the current moment, but constantly creating entities and then resizing was something I was not very keen on. I too plan on using NativeArrays to voxelize and create the vertices required, and I already have highly efficient code that can generate 500 chunks per second that are 16x16x16 in size.
     
  6. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    For large fixed-size buffers, maybe
    [InitialHeapCapacity]
    will be a good addition to the API.

    I do wish we have a more streamlined way for feature/API proposals. Because really the only other alternative is to ping @Joachim_Ante