I have a compute shader that generates voxels and mesh data for voxel terrain chunks.
I have a flattened 3D array holding the voxels and an AppendStructuredBuffer holding structures that define the mesh data for a each face to be displayed.
My problem is : once I’ve run my compute shader to generate the mesh, I’m getting wrong sizes for the append buffer. These values are not completely random. For example, I can get like 157, 348, 409, 245, etc… when I’m expecting 256 (for example). I’m not getting crazy values like 1423751, 752554, 12175, etc… The values seem rather “close” to what is expected, but they are just wrong.
I made a temporary modification to the function that generates the voxels so that I getting a perfectly flat terrain, i.e voxels for which y > 0 are air, and others are not. This should result in CHUNK_SIZE * CHUNK_SIZE faces per chunk, for chunks that contain the ground level. This is how I am sure that I’m getting wrong values, because I should always get the same sizes for the append buffer.
I tried two different ways to count the face mesh data structures I’m appending to the append buffer :
- Using the HLSL function InterlockedAdd() ;
- Using the Unity function ComputeShader.CopyCount().
In both cases I’m getting weird results, which lets me think that I’m doing something wrong somewhere, but can’t see what it is.
So my question : would you have any idea what could be causing these append buffer size issues ?
Below is a piece of my shader :
RWStructuredBuffer<int> faceMeshDataCount;
AppendStructuredBuffer<FaceMeshData> faceMeshDataArray;
// ETC...
[numthreads(2, 2, 2 * 6)]
void GenerateMeshData(uint3 id : SV_DispatchThreadID)
{
const int x = id.x;
const int y = id.y;
const int z = id.z / FACES_PER_CUBE;
const int index = Flatten3DIndex(x, y, z, CHUNK_SIZE);
const int type = GetVoxel(index);
if (type == 0)
{
return;
}
const int face = id.z % FACES_PER_CUBE;
const float cubePosX = x + 0.5;
const float cubePosY = y + 0.5;
const float cubePosZ = z + 0.5;
FaceMeshData faceMeshData;
faceMeshData.type = type;
switch (face)
{
case 0:
if (GetVoxelAdj(1 + x - 1, 1 + y - 0, 1 + z - 0) == 0)
{
faceMeshData.vertex0 = float3(cubePosX - 0.5, cubePosY - 0.5, cubePosZ - 0.5) * INVERSE_CHUNK_SIZE;
faceMeshData.vertex1 = float3(cubePosX - 0.5, cubePosY - 0.5, cubePosZ + 0.5) * INVERSE_CHUNK_SIZE;
faceMeshData.vertex2 = float3(cubePosX - 0.5, cubePosY + 0.5, cubePosZ - 0.5) * INVERSE_CHUNK_SIZE;
faceMeshData.vertex3 = float3(cubePosX - 0.5, cubePosY + 0.5, cubePosZ + 0.5) * INVERSE_CHUNK_SIZE;
faceMeshData.triangleVertexIndex0 = 0;
faceMeshData.triangleVertexIndex1 = 1;
faceMeshData.triangleVertexIndex2 = 2;
faceMeshData.triangleVertexIndex3 = 1;
faceMeshData.triangleVertexIndex4 = 3;
faceMeshData.triangleVertexIndex5 = 2;
faceMeshData.uv0 = float2(0, 0);
faceMeshData.uv1 = float2(0, 0.5);
faceMeshData.uv2 = float2(0.5, 0);
faceMeshData.uv3 = float2(1, 1);
faceMeshDataArray.Append(faceMeshData);
//InterlockedAdd(faceMeshDataCount[0], 1);
}
break;
// ETC...
And here is a piece of the C# code supposed to retrieve the size of the append buffer :
int[] temp = new int[1];
temp[0] = 0;
faceMeshDataCountCBuf.SetData(temp);
faceMeshDataArrayCBuf.SetCounterValue(0);
// Generate the mesh data.
computeShader.Dispatch(generateMeshDataKernel, Constants.ChunkSize / 2, Constants.ChunkSize / 2, Constants.ChunkSize / 2);
ComputeBuffer.CopyCount(faceMeshDataArrayCBuf, faceMeshDataCountCBuf, 0);
faceMeshDataCountCBuf.GetData(temp);
int faceCount = temp[0];
faceMeshDataArrayCBuf.GetData(faceMeshDataArray, 0, 0, faceCount);