Search Unity

Question how to send mesh's vertex& index buffer into compute shader?

Discussion in 'Shaders' started by KiraSnow, Sep 30, 2022.

  1. KiraSnow

    KiraSnow

    Joined:
    Feb 22, 2021
    Posts:
    21
    i did tried GetIndexBuffer and GetVertexBuffer for it, but the result looks not right.

    Code (CSharp):
    1. mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
    2. var vertexBuffer = mesh.GetVertexBuffer(0);
    3. var indexBuffer = mesh.GetIndexBuffer();
    4.  
    5. computeShader.SetBuffer(kernel, "indexBuffer",indexBuffer);
    6. computeShader.SetBuffer(kernel, "vertexBuffer",vertexBuffer);
    if i use the StructuredBuffer<uint> to handle indexBuffer, then the sum of the list in buffer will be 0, while if i use the ByteAddressBuffer like the doc shows, the value of index will be extra huge.

    how can i use those? or any other way to pass mesh into compute shader?
     
  2. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Hmmm... that's close to what I'm doing and not having any problems. Are you sure everything is being bound correctly?

    You should not need to fetch them every frame. Instead just fetch them once and check if they're valid or not, eg...

    Code (CSharp):
    1.         public GraphicsBuffer unskinnedVertices
    2.         {
    3.             get
    4.             {
    5.                 checkValid();
    6.                 if(_isSkinned)
    7.                     throw new Exception("unskinnedVertices is only valid for unskinned meshes");
    8.                 if(_unskinnedVertices == null || !_unskinnedVertices.IsValid())
    9.                 {
    10.                     // unity seems to invalide this at random times
    11.                     _unskinnedVertices?.Dispose(); // non-null but invalid case
    12.                     _mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
    13.                     _unskinnedVertices = _mesh.GetVertexBuffer(0);
    14.                 }
    15.                 return _unskinnedVertices;
    16.             }
    17.         }
    18.  
    19.         public GraphicsBuffer indices
    20.         {
    21.             get
    22.             {
    23.                 checkValid();
    24.                 if(_indices == null || !_indices.IsValid())
    25.                 {
    26.                     _indices?.Dispose(); // non-null but invalid case
    27.                     _mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
    28.                     _indices = _mesh.GetIndexBuffer();
    29.                 }
    30.                 return _indices;
    31.             }
    32.         }
    Also try setting them via the command buffer instead of the compute shader instance immediately before dispatching, eg...

    Code (CSharp):
    1.  
    2.         private void dispatchKernel(int kernel, GraphicsBuffer vertices, int threadGroupsX, int threadGroupsY, bool setI2W)
    3.         {
    4.             if(kernel != _lastKernel)
    5.             {
    6.                 _lastKernel = kernel;
    7.                 _cmd.SetComputeBufferParam(_csComputeShadow, kernel, ID_VERTICES_OUT, _verticesOut);
    8.                 _cmd.SetComputeBufferParam(_csComputeShadow, kernel, ID_INDIRECT_ARGS, _indirectArgs);
    9.                 if(setI2W) _cmd.SetComputeBufferParam(_csComputeShadow, kernel, ID_INSTANCE_TO_WORLD, _instanceToWorld);
    10.             }
    11.             _cmd.SetComputeBufferParam(_csComputeShadow, kernel, ID_VERTICES_IN, vertices);
    12.             _cmd.DispatchCompute(_csComputeShadow, kernel, threadGroupsX, threadGroupsY, 1);
    13.         }
    14.  
     
  3. KiraSnow

    KiraSnow

    Joined:
    Feb 22, 2021
    Posts:
    21
    thanks for reply 0-0,
    actually i have forgotten that i asked this question before, and i met it again (found this post from google XD) ,
    the way i avoid this problem is to set new buffers from cpu side, but this way is quite costly:
    Code (CSharp):
    1.         _vertexBuffer.SetData(targetMeshFilter.mesh.vertices);
    2.         _indexBuffer.SetData(targetMeshFilter.mesh.triangles);
    3.         MeshSliceCS.SetBuffer(_kernelMain, "_Vertex", _vertexBuffer);
    4.         MeshSliceCS.SetBuffer(_kernelMain, "_Triangles", _indexBuffer);
     
    Last edited: Jan 31, 2023