古典的な Vulkan イメージアップロードは3ステップの儀式:
ステージングバッファ → vkCmdCopyBufferToImage → レイアウト
遷移——すべてキュー上のコマンドバッファ内。
VK_EXT_host_image_copy(Vulkan 1.4 でコア化)はホスト側の
ドアを加える:vkCopyMemoryToImageEXT が CPU メモリから
ピクセルをイメージに直接書き込む——ステージングなし、
コマンドバッファなし、キュー投入なし。
古典経路 vs ホスト経路
paths.txt
classic: cpu buf → staging VkBuffer → cmd copy → image (キュー投入!)
host: cpu buf ──────────────────► image (即座)upload.cpp
// 1. イメージは作成時に HOST_TRANSFER フラグが必要:
vk::ImageCreateInfo ici{};
ici.format = vk::Format::eR8G8B8A8Unorm;
ici.extent = {w, h, 1};
ici.usage = vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eHostTransferEXT;
ici.initialLayout = vk::ImageLayout::eUndefined;
// … vkCreateImage、メモリをバインド、それから:
// 2. ホスト経由で一度遷移——vkTransitionImageLayoutEXT:
vk::HostImageLayoutTransitionInfoEXT tr{};
tr.image = img;
tr.oldLayout = vk::ImageLayout::eUndefined;
tr.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
tr.subresourceRange = {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1};
dev.transitionImageLayoutEXT(1, &tr);
// 3. ピクセルをコピー——同期、ホスト可視側:
vk::MemoryToImageCopyEXT cpy{};
cpy.pHostPointer = pixels.data();
cpy.memoryRowLength = w * 4; // 行あたりバイト数、0 = 密
cpy.imageSubresource = {vk::ImageAspectFlagBits::eColor, 0, 0, 1};
cpy.imageExtent = {w, h, 1};
dev.copyMemoryToImageEXT(vk::CopyMemoryToImageInfoEXT{
vk::CopyMemoryToImageFlagBitsEXT::eNoInternalFormatConversion,
img, vk::ImageLayout::eShaderReadOnlyOptimal, 1, &cpy});vkCopyImageToMemoryEXT は鏡像——リードバックバッファ +
フェンスの踊りなしでイメージを CPU に読み戻す。
なぜ使うか
- 小さくまれなアップロード(フォント、LUT、アイコン): コマンドプールなし、フェンスなし、ステージング簿記なし ——1回の呼び出しで完了。
- タイル/最適レイアウト書き込み:ドライバが内部でスウィズル、 あなたは線形行を渡すだけ。
- 初期化時リソース:キューが存在する前にアップロード; エンジン起動を劇的に単純化。
合わない場面
- フレームごとのストリーミング——コピーは同期寄りの
ホスト作業で、しばしば非同期 DMA ステージングコピーより遅い;
毎フレームデータ(ビデオフレーム、動的アトラス)では古典
ステージング経路か
HOST_COHERENTデバイスローカルバッファが 速いまま。 - すべてのフォーマット/レイアウトが対象ではない——
vkGetPhysicalDeviceFormatProperties2→VkFormatProperties3::hostImageCopyとvkGetPhysicalDeviceImageFormatProperties2のhostImageCopySupportを確認。
probe.cpp
vk::FormatProperties3 fp3{};
dev.getPhysicalDeviceFormatProperties2(
vk::PhysicalDeviceFormatInfo2{vk::Format::eR8G8B8A8Unorm})
.get<vk::FormatProperties2, vk::FormatProperties3>();
// fp3.optimalTilingFeatures & eHostImageCopy?
実践的なルール
- 常に
eHostTransferusage を設定 + 書き込み間でイメージを ホスト転送互換レイアウトに保つ(eGeneralはどこでも動く)。 - 正しいレイアウト追跡の必要性を取り除かない——遷移を ホスト呼び出しに移すだけ。
- 利便性 + 配管削減と考え、perf 向上ではない。
この記事が役に立った場合は、TechOverflow での新しい記事の調査と公開を支援するため、「Buy Me a Coffee」でのご支援、または PayPal 経由でのご寄付をご検討ください