Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

What is a native slice?

Discussion in 'Entity Component System' started by imaginaryhuman, Dec 4, 2019.

  1. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    I understand what a native array is and how to use it. But what is a native slice? Is it just some 'window' into another native array? Sort of a virtual array that shares the same memory?

    And where does 'stride set' come into the native slice? Isn't a stride usually a space between two rows allowing you to map onto a 1d array that represents 2d data like a rectangle within an image? How to use? I can find no explanation.

    https://docs.unity3d.com/ScriptReference/Unity.Collections.NativeSlice_1.html

    I
    t seems when the native slice is created here:
    public NativeSlice<T0>(NativeArray<T> array, int start, int length);
    all you give is an offset and length (presumably a virtual window into the native array). But there is no mention of STRIDE here.

    Do you construct a 1-row native slice first, then use SliceWithStide() to specify a stride to use for multiple rows?

    (Just general overview here, i'm trying to copy a rectangular area of a larger native array which represents '2d image data' into a smaller native array, somehow, with maximum performance. Is a slice the way to do it, or is there a better way, WITHOUT unsafe code/utility?)
     
    Last edited: Dec 4, 2019
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,315
    Correct.

    I think you're misreading the very poorly worded documentation here. I believe "Returns stride set for Slice" should be read as "Returns [the] stride [that has been] set for [this] Slice".

    The "stride" of an array just refers to the size in bytes of each element in that array, which could be different than the size of the object being held by the array. This has nothing to do with 2d arrays. That documentation is pretty bad though. I'm not sure what SliceWithStride is meant to do just reading the documentation.

    You're probably not going to be able to do this using just a native slice since each row of the target rectangle is not guaranteed to be contiguous in memory. You could make a separate slice for each affected row, though. I don't know of the performance implications of that.
     
    Bunny83 and MineLucky like this.
  3. ExNinja

    ExNinja

    Joined:
    Dec 4, 2013
    Posts:
    29
    I'm also pretty new to this (and I see that this was thread last posted to in 2019), but the link below shows some code that appears to use SliceWithStride<byte>() to make a slice of just the Red, Green, or Blue pixel data from an image.


    Here's the relevant code:
    Code (CSharp):
    1.         m_Data = new Color32[m_WebcamTextureSize.x * m_WebcamTextureSize.y];
    2.         m_NativeColors = new NativeArray<Color32>(m_Data, Allocator.Persistent);
    3.  
    4.         var slice = new NativeSlice<Color32>(m_NativeColors);
    5.         m_NativeRed = slice.SliceWithStride<byte>(0);
    6.         m_NativeGreen = slice.SliceWithStride<byte>(1);
    7.         m_NativeBlue = slice.SliceWithStride<byte>(2);
    That seems like something very useful for an NativeArray of any combination of values.
     
  4. CameronOtten

    CameronOtten

    Joined:
    Apr 1, 2015
    Posts:
    12
    yeah looking at that code it seems its mostly for slicing up arrays of structs into individual arrays of each component
     
  5. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    Keep in mind that this is only done for convenience and no data is moved/copied/packed anywhere. The memory layout of the data is exactly the same as the original array, the slice will just jump a larger distance when indexing it. In the color32 example, acessing item 1 of the "red" slice will return the 4th byte in the underlying color array.
     
  6. Stevens-R-Miller

    Stevens-R-Miller

    Joined:
    Oct 20, 2017
    Posts:
    664
    Gracious, you're right about that documentation. Looking at the reference source and running some tests, the argument to SliceWithStride turns out to be the offset in bytes into the individual NativeArray elements where the particular member of the structure will be found. I mention this because the example happens to look at the individual members of a Color32 structure, which actually are bytes.

    I'm working with some Mesh vertex buffers composed of structures that pack a Vector3 and Color32 into 16 bytes (the Vector3's three floats take up the first 12, and the Color32's four bytes contribute the final 4). Thus, when I want to access the Vector3 entries and the Color32 entries as though they were in their own arrays, I use this code:
    Code (CSharp):
    1.             var verts = new NativeArray<AdvancedVertex>(100000, Allocator.Temp);
    2.  
    3.             var vertsSlice = new NativeSlice<AdvancedVertex>(verts);
    4.             var points = vertsSlice.SliceWithStride<Vector3>(0);
    5.             var colors = vertsSlice.SliceWithStride<Color32>(12);
    6.  
    7.             Color32 triColor = UnityEngine.Color.white;
    8.  
    9.             points[0] = new Vector3(-1, 0, 0);
    10.             points[1] = new Vector3(0, 1, 0);
    11.             points[2] = new Vector3(2, -1, 0);
    12.             colors[0] = triColor;
    13.             colors[1] = triColor;
    14.             colors[2] = triColor;
    At Line 5, I provide an offset of 12 bytes, which is the size of the Vector3 that precedes the Color32 in my AdvancedVertex structure. For this to work, you have to be certain of the layout of the structure. To do that, I defined the structure this way:
    Code (CSharp):
    1.     [StructLayout(LayoutKind.Sequential)]
    2.     struct AdvancedVertex
    3.     {
    4.         public Vector3 pos;
    5.         public Color32 color;
    6.     }
    To avoid hard code, one could replace the
    12
    with
    Marshal.SizeOf(typeof(Vector3))
    , which would also be rather more self-documenting, I think.

    Maybe someone will find this useful, so I thought I'd add it.
     
  7. inSight01

    inSight01

    Joined:
    Apr 18, 2017
    Posts:
    87
    From what I understand, it allows you to take a slice from an array. For example, if you have an array of 10 elements and you only want elements between 2 and 8 then you can specify that in the parameter.

    Personally, I actually found this to be slower than just creating a new array and using a for loop with a starting index and length. However, it is much cleaner and more convenient to work with.
     
  8. Stevens-R-Miller

    Stevens-R-Miller

    Joined:
    Oct 20, 2017
    Posts:
    664
    That's not how it's working for me. I'm finding that it lets you skip elements. So, if your NativeArray contains structs with entries [A, B, C], and you have four of them in your array, the array's contents in memory would be A0, B0, C0, A1, B1, C1, A2, B2, C2, A3, B3, C3. Entry 0 in the NativeArray would be [A0, B0, C0], and entry 1 would be [A1, B1, C1], and so on. Using a slice, you can access the individual elements as though they were in an array. So you can create a slice that selects the B elements and, in that slice, entry 0 would be [B0], entry 1 would be [B1], and so on.

    That's how it works for me, anyway.
     
    Bigotry0 likes this.