objective-cgpuassertmetalmetal-performance-shaders

Metal assertion `A command encoder is already encoding to this command buffer`


I am using Metal in my project and I have encapsulated some of the kernels as functions kind of the same way as MetalPerformanceShaders suggests.

So each my Metal kernel has Objective-C class with the method:

- (void)encodeToCommandBuffer:(id<MTLCommandBuffer>)cmdBuffer
                 inputTexture:(id<MTLTexture>)inputTexture
                outputTexture:(id<MTLTexture>)outputTexture
                    inputSize:(TextureSize)inputSize
                   outputSize:(TextureSize)outputSize
{
    id<MTLComputeCommandEncoder> enc = [cmdBuffer computeCommandEncoder];
    
    [enc setComputePipelineState:_state];
    
    //set arguments to the state
    
    [enc dispatchThreadgroups:_threadgroupsPerGrid threadsPerThreadgroup:_threadsPerThreadgroup];
    [enc endEncoding];
}

The problem is that my code crashes with the assertion:

failed assertion A command encoder is already encoding to this command buffer

Issue is random, happens at different functions. The error description is self explanatory, but what I am curious is - crashes happen in my encodeToCommandBuffer methods. In the pipeline I also use Image Processing functions from MetalPerformanceShaders and these are also get called with encodeToCommandBuffer method and these do not crash.

So it is clear that my understanding how encodeToCommandBuffer method should be written is wrong. How do I need to modify the code? Do I need to check for cmdBuffer state somehow? That it is ready to produce new Encoder. And what if it's not? Do I need to have some sort of while loop that will wait until buffer is ready?


Solution

  • Ok, sorted out. My pipeline is processing multiple instances in parallel, and I made a mistake in the code - pipeline tried to process all instances through the same command buffer, when it was not intended.