Description
I found that checking the extent of the surface does not match the actual width and height of the underlying CAMetalLayer. I am testing on 12.9inch iPad Pro which has a 2732x2048 resolution display. The CAMetalLayer will report the drawableSize as 2732x2048 but I get a surface extent from Vulkan of 2731x2048.
I believe the culprit is this function in CAMetalLayer+MoltenVK.m
-(CGSize) naturalDrawableSizeMVK {
CGSize drawSize = self.bounds.size;
CGFloat scaleFactor = self.contentsScale;
drawSize.width = trunc(drawSize.width * scaleFactor);
drawSize.height = trunc(drawSize.height * scaleFactor);
return drawSize;
}
The bounds of the layer are 1590x1192 with a contentsScale of 1.7181208053691275.
I tried replacing trunc() with round() which worked great on my 12.9inch iPad but broke the 11inch iPad version.
I can't think of a great way to solve this as per Apple's docs bounds * contentsScale
is the expected way to get the extent of the surface. If you set drawableSize = bounds * contentsScale
then Apple will do some rounding behind the scenes to the correct value, it's not clear what rounding they are doing except that drawableSize will be the correct value (2732x2048).
By default, a layer creates textures sized to match its content—that is, this property’s value is the layer’s bounds size multiplied by its contentsScale factor.
For now, I am just creating swapchains of 2731x2048 so that the image extent and the surface extent match and then letting the system scale appropriately. It would be great to have a proper solution for this, thanks!