Just figured out! I have to use multiple command buffers, use one command buffer for each mesh, but carefully set load actions and store actions to protect the middle result, call waitUntilCompleted is important, only call presentDrawable once before the last commit.
Source code:
---------------------------
void draw_all() {
before_draw();
for (int i=0; i<mesh_count; i++) {
draw(i);
}
after_draw();
}
void before_draw() {
// Create a new command buffer for each render pass to the current drawable
commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"MyClearCommand";
// Obtain a renderPassDescriptor generated from the view's drawable textures
renderPassDescriptor = metal_view.currentRenderPassDescriptor;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDescriptor.depthAttachment.loadAction = MTLLoadActionClear;
renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionStore;
renderPassDescriptor.depthAttachment.clearDepth = 1.0;
// Create a render command encoder so we can render into something
renderEncoder =
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyClearEncoder";
[renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise];
[renderEncoder setDepthStencilState:_depthState];
[renderEncoder endEncoding];
[commandBuffer commit];
// block until command buffer complete.
[commandBuffer waitUntilCompleted];
}
void draw(const int mesh_index) {
// Create a new command buffer for each render pass to the current drawable
commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"MyRenderCommand";
// Obtain a renderPassDescriptor generated from the view's drawable textures
renderPassDescriptor = metal_view.currentRenderPassDescriptor;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionLoad;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDescriptor.depthAttachment.loadAction = MTLLoadActionLoad;
renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionStore;
renderPassDescriptor.depthAttachment.clearDepth = 1.0;
// Create a render command encoder so we can render into something
renderEncoder =
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyRenderEncoder";
[renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise];
[renderEncoder setDepthStencilState:_depthState];
// Draw the mesh ...
[renderEncoder endEncoding];
[commandBuffer commit];
// block until command buffer complete.
[commandBuffer waitUntilCompleted];
}
void after_draw() {
// Create a new command buffer for each render pass to the current drawable
commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"MyPresentCommand";
// Obtain a renderPassDescriptor generated from the view's drawable textures
renderPassDescriptor = metal_view.currentRenderPassDescriptor;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionLoad;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDescriptor.depthAttachment.loadAction = MTLLoadActionDontCare;
renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionDontCare;
renderPassDescriptor.depthAttachment.clearDepth = 1.0;
// Create a render command encoder so we can render into something
renderEncoder =
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyPresentEncoder";
[renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise];
[renderEncoder setDepthStencilState:_depthState];
[renderEncoder endEncoding];
// Schedule a present once the framebuffer is complete using the current drawable
[commandBuffer presentDrawable:metal_view.currentDrawable];
[commandBuffer commit];
// block until command buffer complete.
[commandBuffer waitUntilCompleted];
}
};
---------------------------