Post 55。サブパス入力アタッチメント(「書き込んでいるピクセルを
読む」)はかつて VkRenderPass/VkSubpass オブジェクトを必要と
した。VK_KHR_dynamic_rendering_local_read は同じパターンを
vkCmdBeginRendering にもたらす:1つのイメージがカラー
アタッチメントと入力アタッチメントを同時に兼ね、フラグメントは
subpassLoad() で自分のピクセルを読む。タイルベース GPU では
データはタイルメモリから出ない;どこでもブレンドモード、蓄積
エフェクト、追加パスなしのマルチステージポストエフェクトの背後に
あるパス内フィードバックプリミティブだ。
デモ:draw 1 がグラデーションを書く → by-region バリアが
アタッチメントを eRenderingLocalRead に反転 → draw 2 が自分の
ピクセルを読み反転を書く——同じイメージ、同じレンダーパス。
材料
vk::PhysicalDeviceDynamicRenderingLocalReadFeaturesKHR lr{};
lr.setDynamicRenderingLocalRead(true);
// デバイス作成にチェイン + 有効化
// VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME
// イメージは両方の usage が必要:
ici.setUsage(eColorAttachment | eInputAttachment | eTransferSrc);デスクリプタタイプは eInputAttachment——サンプラは関わらない
(subpassLoad はテクセルを読む、フィルタしない):
layout(input_attachment_index = 0, binding = 0)
uniform subpassInput prev;
void main() {
vec4 p = subpassLoad(prev); // このフラグメント自身のピクセル
outColor = vec4(1.0 - p.rgb, 1.0);
}by-region バリア——重要な1行
書き込み draw と読み取り draw の間、同じ beginRendering 内で:
vk::ImageMemoryBarrier2 mid{};
mid.setOldLayout(vk::ImageLayout::eColorAttachmentOptimal)
.setNewLayout(vk::ImageLayout::eRenderingLocalRead) // ← 魔法
.setSrcStageMask(eColorAttachmentOutput)
.setSrcAccessMask(eColorAttachmentWrite)
.setDstStageMask(eFragmentShader | eColorAttachmentOutput)
.setDstAccessMask(eInputAttachmentRead | eColorAttachmentWrite);
vk::DependencyInfo dep{};
dep.setDependencyFlags(vk::DependencyFlagBits::eByRegion)
.setImageMemoryBarriers(mid);
cmd.pipelineBarrier2(dep);eByRegion がこれをタイル安全にする:順序付けは同じピクセルを
覆うフラグメント間でのみ必要——それはタイル GPU がフラッシュなしで
保証できるものそのもの。
同様に重要:beginRendering に渡す
VkRenderingAttachmentInfo::imageLayout は draw 1 では
eColorAttachmentOptimal;local-read セクションでは
eRenderingLocalRead に更新——そしてデスクリプタも
eRenderingLocalRead を宣言しなければならない(描画時の
レイアウトを記述する)。
vk::DescriptorImageInfo dii{{}, view,
vk::ImageLayout::eRenderingLocalRead}; // eShaderReadOnly ではない!
VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR は特殊:入力
アタッチメント読み取りとカラーアタッチメント書き込みの両方を
許可——それがポイント全体、フラグメントが自分のテクセルを
読み-修正-書きする。
使うべきとき
- ピクセル毎の読み-修正-書きパターン(カスタムブレンディング、 カラーキー合成)——さもなければ2パス + VRAM 経由の完全イメージ 往復が必要。
- タイル GPU 上:レンダーパスオブジェクトなしのサブパス式 アルゴリズム(遅延マージ、半透明)。
- 隣接読み取りには向かない:
subpassLoadはフラグメント 自身のピクセルのみ読む——畳み込み/ブラーには本物のイメージ バリアが必要。
注意点
subpassLoad(prev)——texture()ではない。入力アタッチメントは サンプラを完全にバイパス;フレームバッファへのインデックスは 暗黙。- 複数アタッチメントには
vkCmdSetRenderingAttachmentLocations/InputAttachmentIndicesが必要;単一アタッチメントならデフォルトで十分(このデモ)。 eByRegionは同一キュー・同一レンダーパスを要求——レンダー パスを跨ぐならリージョンバリアではなく完全なパイプライン バリアが必要。- フィーチャを確認:
dynamicRenderingLocalRead——デスクトップでは 普遍的、タイル GPU でのパターン正確性に必要。
完全プログラム
Example: VulkanExamples/p55_localread
—main.cpp:グラデーション → パス内反転 → PPM、check.py が隅が
書き込まれたグラデーションの反転であることを検証(約300行)。