Kernel shader with [[stage_in]] attribute

Hi again @caroline
I need to send the vertices of an imported geometry to GPU, update the position with a noise algorithm, send back to CPU, update the normals, and send it again to GPU to draw it.

My approach:

init(metalView:)

  let computeFunction = Renderer.library.makeFunction(name: "computeFunction")!
        let descriptor = MTLComputePipelineDescriptor()
        descriptor.computeFunction = computeFunction
        
        let ioDescriptor = MTLStageInputOutputDescriptor()
        var offset = 0
        let att = MTLAttributeDescriptor()
        att.bufferIndex = 0
        att.offset = 0
        att.format = MTLAttributeFormat.float3
        ioDescriptor.attributes[0] = att

        offset += MemoryLayout<float3>.stride
        
        att.offset = offset
        ioDescriptor.attributes[1] = att
        
        offset += MemoryLayout<float3>.stride

        let layout = MTLBufferLayoutDescriptor()
        layout.stride = offset
        layout.stepFunction =  .threadPositionInGridX
        layout.stepRate = 1
        ioDescriptor.layouts[0] = layout
        descriptor.stageInputDescriptor = ioDescriptor
        
        do {
            computePipelineState = try Renderer.device.makeComputePipelineState(descriptor: descriptor, options: [], reflection: nil)
        }catch let error{
            fatalError(error.localizedDescription)
        }

draw()

        computeEncoder.setComputePipelineState(computePipelineState)
        let width = computePipelineState.threadExecutionWidth
        let threadsPerGroup = MTLSizeMake(width,1,1)
        let bufferSize = model.meshes[0].mtkMesh.vertexBuffers[0].length
        let threadsPerGrid = MTLSizeMake(bufferSize,1,1)
        computeEncoder.setBuffer(model.meshes[0].mtkMesh.vertexBuffers[0].buffer, offset: 0, index: 0)
        computeEncoder.dispatchThreads(threadsPerGrid, threadsPerThreadgroup: threadsPerGroup)
        computeEncoder.endEncoding()

Metal shader:

**struct** VertexIn {

**float4** position [[ attribute(0) ]];

**float3** normal [[ attribute(1)] ];

};

**kernel** **void** computeFunction ( VertexIn in [[stage_in]]){

in.position=noise();

}

I’m going in a good way?
Not draws updated positions with noise
Can you give some advice, please :wink:

Thks in advance!!

@ferranc - I’d need to see the complete code. I can’t see anything immediately wrong with the snippets, but I’d need to be able to run them to see results and work it out from there.

Btw, you appear to be the only person on Google ever to have used MTLStageInputOutputDescriptor, so I applaud you :clap:!

@ferranc - you can’t write to a [[stage_in]] buffer.

So you’ll have to do something like:

struct VertexIn {
  float4 position;
  float3 normal;
};

kernel void computeFunction(device VertexIn *vertices [[buffer(0)]],
                             uint tid [[thread_position_in_grid]]) {
  VertexIn vert = vertices[tid];
  vertices[tid].position = float4(vert.position.x/2,vert.position.y/2,vert.position.z/2,1) ;
}

And you’d have to make sure that your vertex descriptor reading in the vertices matches your struct here, as you’re not relying on stage_in

Ok. Thank you very much!!!