Vulkan Video を Rust で叩く際は ash のバージョンに注意


## 何に注意するか
`ash` を用いる, 以前から用いているコードベースで新しく Vulkan Video を叩く場合,
依存する `ash` のバージョンが古いままでないか確認すること.

2024-04 に crates.io にリリースされた `0.38.0+1.3.281` 以降を用いること.
```diff_toml:Cargo.toml
- ash = "0.37.0"
+ ash = "0.38.0"
```

:::note warn
これはかなりの breaking change になるので注意.
:::

### しないとどうなるか

例えば [`vkGetPhysicalDeviceVideoCapabilitiesKHR`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetPhysicalDeviceVideoCapabilitiesKHR.html) の呼び出しが,
バッファオーバーランからの**スタック/ヒープ破壊**に繋がり,
原因の調査が難航する可能性がある.

### crates.io のリリースの更新(2024-04)よりも前は
crates.io における `ash` のリリースはかなり長い間更新されておらず,
2024-03 以前では, GitHub にある新しめのブランチ/コミットを指定して用いる必要があった:
```toml:Cargo.toml
ash = { git = "https://github.com/ash-rs/ash/", rev = "f2979c8" }
```

## 直接の原因

`ash` の `0.37.3+1.3.251` では, Rust バインディング生成に用いられた Vulkan Video の仕様がかなり古いこと.


## 詳細

2024-03 時点まで, [crates.io でリリースされていた ash 0.37.3+1.3.251](https://crates.io/crates/ash/0.37.3+1.3.251) では,
Rust コードの生成に用いられた Vulkan Video の仕様が古く,
最新の NVIDIA ベータドライバでの実装が期待する最新の仕様のものと異なるメモリレイアウトが用いられてしまい,
**スタック/ヒープ破壊**に繋がる場合があった.

これは Vulkan Video の H.264 や H.265 などエンコード関連の仕様がまだ provisional[^vk_video_encode_provisional]であり,
依然 Khronos Group により変更がなされていることに起因していた.

これは例えば `vkGetPhysicalDeviceVideoCapabilitiesKHR` の出力先となる, `VkVideoEncodeCapabilitiesKHR` で顕在化していて, ドライバによる書込みがオーバーランしスタック/ヒープ破壊に繋がっていた.

現時点で最新の仕様[^vk_struct_upstream_spec]では:
```diff_c
// Provided by VK_KHR_video_encode_queue
typedef struct VkVideoEncodeCapabilitiesKHR {
    VkStructureType                         sType;
    void*                                   pNext;
    VkVideoEncodeCapabilityFlagsKHR         flags;
    VkVideoEncodeRateControlModeFlagsKHR    rateControlModes;
    uint32_t                                maxRateControlLayers;
+   uint64_t                                maxBitrate;
    uint32_t                                maxQualityLevels;
    VkExtent2D                              encodeInputPictureGranularity;
    VkVideoEncodeFeedbackFlagsKHR           supportedEncodeFeedbackFlags;
} VkVideoEncodeCapabilitiesKHR;
```

[^vk_struct_upstream_spec]: [VkVideoEncodeCapabilitiesKHR(3)](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkVideoEncodeCapabilitiesKHR.html)

一方これは `0.37.3+1.3.251` までの `ash`[^vk_struct_ash_old] では:
```diff_rust
#[repr(C)]
pub struct VideoEncodeCapabilitiesKHR {
    pub s_type: StructureType,
    pub p_next: *mut c_void,
    pub flags: VideoEncodeCapabilityFlagsKHR,
    pub rate_control_modes: VideoEncodeRateControlModeFlagsKHR,
    pub max_rate_control_layers: u32,
-   // 🤯
    pub max_quality_levels: u32,
    pub input_image_data_fill_alignment: Extent2D,
    pub supported_encode_feedback_flags: VideoEncodeFeedbackFlagsKHR,
}
```

[^vk_struct_ash_old]: [VideoEncodeCapabilitiesKHR in ash::vk - Rust](https://docs.rs/ash/0.37.3+1.3.251/ash/vk/struct.VideoEncodeCapabilitiesKHR.html)

最新の仕様では `uint64_t maxBitrate` があるが,
Rust コードにはそれがなく, 構造体の大きさが異なることがわかる.

この `ash::vk::VideoEncodeCapabilitiesKHR` のポインタを愚直に `vkGetPhysicalDeviceVideoCapabilitiesKHR` に出力先として渡すことで,
NVIDIA のベータドライバによる書込みが, バッファオーバーランに繋がっていた.

[^vk_video_encode_provisional]: [Khronos Finalizes Vulkan Video Extensions for Accelerated H.264 and H.265 Encode - Khronos Blog - The Khronos Group Inc](https://www.khronos.org/blog/khronos-finalizes-vulkan-video-extensions-for-accelerated-h.264-and-h.265-encode)

## 参考資料

https://blogs.igalia.com/vjaquez/vulkan-video-status/