Gpu sync refactor

This attempts to pull most of the logic out of the GPU backends and write them as earlier passes instead. This makes it easier to inspect their output and debug in isolation. Along the way I uncovered large numbers of latent bugs. E.g. our synchronization was sometimes missing and sometimes occurred inside if statements, mixed dimensionalities didn't work, some typecasts were bad in OpenCL, etc.

Now that we have enough core developers (esp dsharletg), I'm phrasing this as a pull request for review, where in the past I would have just pushed it.