Hi there,
I am working on a 3d game engine in Swift and Metal. Currently I dynamically generate vertex buffers for terrain "chunks" on the CPU and pass all models to the GPU via argument buffer and make indirect draw calls.
Calculating where vertices should be is costly and I would like to offload the work to a compute shader. Setting up the shader was straightforward and I can see that it (at least as an empty function) is being executed in the CommandBuffer.
However, I come to this problem: since I do not know ahead of time how many vertices a chunk of terrain will have, I cannot create a correctly-sized MTLBuffer to pass into the compute function to be populated for later use in a draw call.
The only solution I could think of is something like the following:
- For each chunk model, allocate a VertexBuffer and IndexBuffer that will accommodate the maximum possible number of vertices for a chunk.
- Pass in the empty too-large buffers to the compute function
- Populate the too-large buffers and set the actual vertex count and index count on the relevant argument buffer.
- On the CPU, before the render encoder executes commands in the indirect command buffer, do the following:
- for each chunk argument buffer, create new buffers that fix the actual vertex count and index count
- blit copy the populated sections of memory from the original too-large buffers to the new correctly-sized buffers
- replace the buffers on each chunk model and update the argument buffers for the draw kernel function
But I am still a Metal novice and would like to know if there is any more straightforward or optimal way to accomplish something like this.