Thanks Alecazam. One important thing I didn't mention is that our game uses "untracked" ressources.
In this same thread mentioned earlier, the Apple engineer mentions :
You must use a fence to sychronize untracked resource across command buffers from the same queue. So if command buffer 1 writes to an untracked texture and later excute command buffer 2 which reads from it, you need a fence
That is a little confusing. Apple's documentation states that the scope of a fence is limited to a single command buffer:
An MTLFence synchronizes access to one or more resources across different passes within a command buffer. Use fences to specify any inter-pass resource dependencies within the same command buffer.
I made a request to Apple to add a note in the documentation about that. Adding a fence fixed all the flickering on our side.