Sunday, November 5, 2017

[Vulkan] vkCmdPipelineBarrierで指定するVkPipelineStageFlagBitsとは? [SDC 2017]

Samsung Developer Conference 2017で行われた、VulkanのvkCmdPipelineBarrierの使い方の技術セッションがYouTubeで公開されています。

vkCmdPipelineBarrierに指定するsrcStageMaskとdstStageMaskの指定方法に関して説明されており、Khronosの文書が関数リファレンスのレベルしか言及していない現状で、動作原理を解説する貴重なセッションとなっています。

連続する2つのパスはGPUで並行に実行される可能性がありますが、前のパスの結果に後のパスが依存する場合、vkCmdPipelineBarrierを置くことで後のパスを待たせる必要があります。ただし、GPUコア間の並行性が失われて待機時間が生じます。これがPipeline Bubbleと呼ばれます。

srcStageMaskは前のパスのパイプラインステージ(例:vertex shader等)、dstStageMaskは後のパスのパイプラインステージを表します。前のパスのsrcStageMaskで指定のステージが終わるまで、後のパスのdstStageMaskで指定のステージは始めてはいけないという意味になります。

VK_PIPELINE_STAGE_TOP_OF_PIPE_BITとVK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BITは存在しない一種の仮想のパイプラインステージで、それぞれ全てのパイプラインステージの前と後を意味しています。

保守的には、srcStageMask=VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT、dstStageMask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BITとすることで並列動作を出来なくします。

逆に、srcStageMask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT、dstStageMask=VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BITとすることで、2つのパスは並列に動き出すそうです。

残念ながら、どのように依存関係を解決しながら平行動作させるかには言及されていませんでしたが、2つのパスの依存関係の無い場合には並列動作させることでpipeline bubbleを取り除こうという趣旨と思われます。

また、AMDのサイトでもVulkan barriers explained と題してvkCmdPipelineBarrierを解説しています。

おそらく最も使用頻度が多いのが、前のパスで作った絵を次のパスのfragment shaderで使うというシナリオだと思いますが、srcStageMask=VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT、dstStageMask=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BITとすればよいそうです。これなら前のパスが絵を描き終わる前に次のパスの頂点処理を平行させることが出来そうです。

DX12では、ID3D12GraphicsCommandList::ResourceBarrierでリソースのステートを遷移させるには前後のD3D12_RESOURCE_STATESを指定すればタイミングはドライバが決めてくれました。Vulkanでは前後のVkImageLayoutに加えてVkPipelineStageFlagBitsでタイミングまでプログラマが把握して指定しなければいけません。

No comments:

Post a Comment