Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

how to cache mesh.GetNativeVertexBufferPtr()

Discussion in 'Graphics Experimental Previews' started by o1o1o1o1o2, Oct 17, 2019.

  1. o1o1o1o1o2

    o1o1o1o1o2

    Joined:
    May 22, 2014
    Posts:
    34
    Help me I'm stuck, what does GetNativeVertexBufferPtr() do?

    Im trying to write native plugin to push vertices and indices directly to their buffer. Now i'm just a bit change unity example and can write to vertex buffer, but every time i do it i need to call mesh.GetNativeVertexBufferPtr(0) before SetMeshBuffersFromUnity. It is problem cause most of time cpu spend on this work is mesh.GetNativeVertexBufferPtr(0), it is very expensive.

    My setup:

    1.at start I do layout and mesh.SetVertexBufferParams(20000, layout); because in my approach vertexCount changing so I allocate 20000 for vertecies, cause after allocation we cant change buffer size without loosing a pointer. I mark mesh as dynamic and cache vertBuffIntPtr = mesh.GetNativeVertexBufferPtr(0);

    Code (CSharp):
    1. private void Start()
    2.     {
    3. #if UNITY_WEBGL && !UNITY_EDITOR
    4.         RegisterPlugin();
    5. #endif
    6.         var filter = GetComponent<MeshFilter>();
    7.         filter.mesh = new Mesh();
    8.         mesh = filter.mesh;
    9.         mesh.MarkDynamic();
    10.         layout = new[]
    11.         {
    12.             new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
    13.             new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32,2),
    14.         };
    15.         mesh.SetVertexBufferParams(20000, layout);
    16.  
    17.         vertBuffIntPtr = mesh.GetNativeVertexBufferPtr(0);
    18.         CreateTextureAndPassToPlugin(atlas.GetSprite("iso-64x64-outside_0").texture);
    19.     }
    2. When i need to change vertices i do

    Code (CSharp):
    1.  
    2.  
    3. if (tilemapBuffersPtrs.vertexCount > 0)
    4. {
    5. // if (gameObject.name == "Tilemap [0,0]") Debug.Log(vertBuffIntPtr.ToString());
    6.    if (mesh.GetNativeVertexBufferPtr(0)!= vertBuffIntPtr) Debug.  Log("1");
    7.    SetMeshBuffersFromUnity(vertBuffIntPtr, tilemapBuffersPtrs.vertexCount, tilemapBuffersPtrs.vertexBuff, tilemapBuffersPtrs.uvsBuff);
    8.    CallPluginAtEndOfFrames(ID);
    9. }
    10.  
    11.  
    so I cant understand why I need to do mesh.GetNativeVertexBufferPtr(0); because if I do not, I get crush, but when I check vertBuffIntPtr it doesn't change, so why unity crushes?, please help..... I set only vertices and uvs by plugin, indices is set by
    Code (CSharp):
    1.  
    2.             mesh.indexFormat = IndexFormat.UInt16;
    3.             mesh.SetIndexBufferParams(triangles.Length,IndexFormat.UInt16);
    4.             mesh.SetIndexBufferData(triangles,0,0,triangles.Length,flags);
    5.             mesh.subMeshCount = 1;
    6.             mesh.SetSubMesh(0,new SubMeshDescriptor(0, triangles.Length));
    And here is my plugin code parts

    Code (CSharp):
    1. extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetMeshBuffersFromUnity(void* vertexBufferHandle, int vertexCount, float* sourceVertices, /*float* sourceNormals,*/ float* sourceUV)
    2. {
    3. if (vertexCount <= 0 || !vertexBufferHandle || !sourceVertices || !sourceUV)
    4.     {
    5.         g_VertexBufferHandle = NULL;
    6.         g_sourceVertices = NULL;
    7.         g_sourceUV = NULL;
    8.         g_VertexBufferVertexCount = 0;
    9.         return;
    10.         }
    11.  
    12.  
    13.     g_VertexBufferHandle = vertexBufferHandle;
    14.     g_VertexBufferVertexCount = vertexCount;
    15.  
    16.     g_sourceVertices = sourceVertices;
    17.     g_sourceUV = sourceUV;
    18.  
    19.  
    20. }
    Code (CSharp):
    1. static void ModifyVertexBuffer()
    2. {
    3.     void* bufferHandle = g_VertexBufferHandle;
    4.     int vertexCount = g_VertexBufferVertexCount;
    5.  
    6.     if (!bufferHandle) return;
    7.  
    8.     size_t bufferSize;
    9.     void* bufferDataPtr = s_CurrentAPI->BeginModifyVertexBuffer(bufferHandle, &bufferSize);
    10.     if (!bufferDataPtr)
    11.         return;
    12.  
    13.     int vertexStride = 20;// int(bufferSize / 20000);/////////////////////////////////////
    14.  
    15.     char* bufferPtr = (char*)bufferDataPtr;
    16.     float* sourceVertices = (float*)g_sourceVertices;
    17.     float* sourceUV = (float*)g_sourceUV;
    18.  
    19.     for (int i = 0; i < vertexCount; ++i)
    20.     {
    21.         MeshVertex& dst = *(MeshVertex*)bufferPtr;
    22.         dst.pos[0] = sourceVertices[0];
    23.         dst.pos[1] = sourceVertices[1];
    24.         dst.pos[2] = sourceVertices[2];
    25.         dst.uv[0] = sourceUV[0];
    26.         dst.uv[1] = sourceUV[1];
    27.         bufferPtr += vertexStride;
    28.         sourceVertices += 3;
    29.         sourceUV += 2;
    30.  
    31.     }
    32.     memset(bufferPtr, 0, bufferSize - vertexCount * vertexStride);
    33.  
    34.     s_CurrentAPI->EndModifyVertexBuffer(bufferHandle);
    35. }
    36.  
    and implementations of BeginModifyVertexBuffer and EndModifyVertexBuffer are the same, as in unity sample

    Also Ive noticed that internal Mesh.CreateMesh is called every time when mesh.GetNativeVertexBufferPtr(0) is called, may be reason is that Mesh.CreateMesh.png


    Here is video showing problem, first with calling mesh.GetNativeVertexBufferPtr(0) and then without calling, where you can see mesh glitching and unity crush at the end(it is not seen on video cause only unity window was written but believe me it crushed).


     
    Last edited: Oct 19, 2019