2
\$\begingroup\$

Like many others I figured I would try and make the most of the monster processing power of the GPU but I'm having trouble getting the basics in place.

CPU code:

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour
{
   public ComputeShader Generator;
   public MeshTopology Topology;

   void OnEnable()
   {
      var computedMeshPoints = ComputeMesh();
      CreateMeshFrom(computedMeshPoints);
   }

   private Vector3[] ComputeMesh()
   {
      var size = (32*32) * 4; // 4 points added for each x,z pos
      var buffer = new ComputeBuffer(size, 12, ComputeBufferType.Append);
      Generator.SetBuffer(0, "vertexBuffer", buffer);
      Generator.Dispatch(0, 1, 1, 1);
      var results = new Vector3[size];
      buffer.GetData(results);
      buffer.Dispose();
      return results;
   }

   private void CreateMeshFrom(Vector3[] generatedPoints)
   {
      var filter = GetComponent<MeshFilter>();
      var renderer = GetComponent<MeshRenderer>();

      if (generatedPoints.Length > 0)
      {
         var mesh = new Mesh { vertices = generatedPoints };
         var colors = new Color[generatedPoints.Length];
         var indices = new int[generatedPoints.Length];

         //TODO: build this different based on topology of the mesh being generated
         for (int i = 0; i < indices.Length; i++)
         {
            indices[i] = i;
            colors[i] = Color.blue;
         }

         mesh.SetIndices(indices, Topology, 0);
         mesh.colors = colors;

         mesh.RecalculateNormals();
         mesh.Optimize();
         mesh.RecalculateBounds();
         filter.sharedMesh = mesh;
      }
      else
      {
         filter.sharedMesh = null;
      }
   }
}

GPU code:

#pragma kernel Generate

AppendStructuredBuffer<float3> vertexBuffer : register(u0);

void genVertsAt(uint2 xzPos)
{
   //TODO: put some height generation code here.
   //      could even run marching cubes / dual contouring code.

   float3 corner1 = float3( xzPos[0], 0, xzPos[1] );
   float3 corner2 = float3( xzPos[0] + 1, 0, xzPos[1] );
   float3 corner3 = float3( xzPos[0], 0, xzPos[1] + 1);
   float3 corner4 = float3( xzPos[0] + 1, 0, xzPos[1] + 1 );

   vertexBuffer.Append(corner1);
   vertexBuffer.Append(corner2);
   vertexBuffer.Append(corner3);
   vertexBuffer.Append(corner4);
}

[numthreads(32, 1, 32)]
void Generate (uint3 threadId : SV_GroupThreadID, uint3 groupId : SV_GroupID)
{
   uint2 currentXZ = unint2( groupId.x * 32 + threadId.x, groupId.z * 32 + threadId.z);
   genVertsAt(currentXZ);
}

Can anyone explain why when I call "buffer.GetData(results);" on the CPU after the compute dispatch call my buffer is full of Vector3(0,0,0), I'm not expecting any y values yet but I would expect a bunch of thread indexes in the x,z values for the Vector3 array.

I'm not getting any errors in any of this code which suggests it's correct syntax-wise but maybe the issue is a logical bug.

Also: Yes, I know I'm generating 4,000 Vector3's and then basically round tripping them. However, the purpose of this code is purely to learn how round tripping works between CPU and GPU in Unity.

\$\endgroup\$
0
1
\$\begingroup\$

Have you tried checking the counter in the append buffer, to see if ANYTHING is being appended?

ComputeBuffer argBuffer = new ComputeBuffer(4, sizeof(int), ComputeBufferType.DrawIndirect);
int[] args = new int[]{ 0, 1, 0, 0 };
argBuffer.SetData(args);

ComputeBuffer.CopyCount(buffer, argBuffer, 0);
argBuffer.GetData(args);

Then argBuffer[0] should be the total number of items appended to your first buffer. This blog is the only resource I've yet found:

http://scrawkblog.com/2014/08/14/directcompute-tutorial-for-unity-append-buffers/

A question, in the line:

AppendStructuredBuffer<float3> vertexBuffer : register(u0);

What does the register(u0) mean? I've been having weird results using append buffers, but instead of everything being empty, I just get strange output every once in a while. I think it's an initialization/memory allocation problem, but I can't sniff it out.

\$\endgroup\$
2
  • \$\begingroup\$ Turns out theres a bug in unity with copycount ... been there since v4.5 of unity fogbugz.unity3d.com/default.asp?626315_56383at5hm4mdohj ... typical bloody unity. \$\endgroup\$ – War Feb 2 '16 at 20:02
  • \$\begingroup\$ I have been able to confirm that data is being appended though, after many versions of both the cpu and gpu code I got something going but this copycount thing means its basically unusable as I am working on a set of 64 million (max buffer size) but I need to pull the result (much less) to generate meshes from and the unity API just cries when faced with such senarios \$\endgroup\$ – War Feb 2 '16 at 20:04
0
\$\begingroup\$

The compute shader never gets executed as you're nullifying the dispatch.

Try Generator.Dispatch(0, 1, 1, 1);

\$\endgroup\$
2
  • \$\begingroup\$ :O ... um ... my bad that's a typo! \$\endgroup\$ – War Feb 10 '14 at 22:25
  • \$\begingroup\$ its not a fix though :( \$\endgroup\$ – War Feb 10 '14 at 22:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.