vulkan: Enable midpoint sampling for interleaved 8-bit YCbCr
Vulkan has two sampling modes for down-sampled chroma:
VK_CHROMA_LOCATION_COSITED_EVEN
specifies that downsampled chroma samples are aligned with luma samples with even coordinates.
VK_CHROMA_LOCATION_MIDPOINT
specifies that downsampled chroma samples are located half way between each even luma sample and the nearest higher odd luma sample.
For multi-plane formats, we have one nir_op_tex
for luminance and one or two nir_op_tex
for chroma. (Luminance is always in its own plane.) MIDPOINT
sampling is the trivial case here because, with normalized coordinates, the coordinate at the center of the one chroma pixel will naturally lie at the center of the cluster of 2 or 4 Luminance pixels. We handle COSITED_EVEN
by adding a half pixel to the chroma coordinate, thus making it so that when you sample at the center of the upper-left luminance pixel, you get the center of the chroma pixel.
For single-plane interleaved 8-bit YCbCr, i.e. VK_FORMAT_G8B8G8R8_422_UNORM
and VK_FORMAT_B8G8R8G8_422_UNORM
, we only have a single nir_op_tex
and it's up to the hardware to decide how to sample from chroma vs. luminance. Both Intel and NVIDIA hardware default to COSITED_EVEN
and, indeed, that is the only one which is required by the Vulkan spec. Without a sampler or image descriptor bit to tweak the sampling position, this is all we can get on that hardware in a single nir_op_tex
.
However, it is possible to get MIDPOINT
sampling if we do two texture ops, one for luminance and one for chroma, which both target plane 0. We just have to subtract a quarter pixel from the X coordinate when we sample for chroma. This is a slightly annoying modification to the lowering pass but should be possible. It would allow enabling MIDPOINT
sampling in both NVK and ANV.