Instead of always using getField and set, I believe some non-opaque struct types could benefit from using explicitly bidirectional pattern synonyms. For instance:
{-# COMPLETE VkSurfaceFormatKHR #-}
pattern VkSurfaceFormatKHR :: VkFormat -> VkColorSpaceKHR -> VkSurfaceFormatKHR
pattern VkSurfaceFormatKHR fmt spc
<- ( getField @"format" &&& getField @"colorSpace"-> (fmt, spc) )
where VkSurfaceFormatKHR fmt spc
= createVk ( set @"format" fmt &* set @"colorSpace" spc )