We now store all the relevant state of the image inside the VulkanImage
struct, so we can delay barriers for as long as possible.
Whenever we want to use an image, we call the new
gsk_vulkan_image_transition() and it will add a barrier to the desired
state if one is necessary.
This is a massive refactoring because it collects all the renderops
of all renderpasses into one long array in the Render object.
Lots of code in there is still flaky and needs cleanup. That will
follow in further commits.
Other than that it does work fine though.
All the ops that just execute a shader do pretty much the same stuff, so
put it all in a single function that they all call.
It's basically faking a base class for them.