GraphicsVulkanVulkan に関する個人的なメモを書くページです。自分用なので言葉足らずなことがあります。
20-07-12 他ライブラリとの比較まとめてます。 https://github.com/hoboaki/engineplan/blob/main/master/Scratch/memo_low_gfx_api.md 18-10-08 複数の Uniform を DescriptorSet に設定する方法こちらのサイトをベースに。(紹介されているのは Uniform を1つだけバインドする例) https://sites.google.com/site/monshonosuana/vulkan/vulkan_004 試してないけどおそらくこれ。
あれ、vertexシェーダとfragmentシェーダでUniformバインディング番号って共有だったっけ?共有ならこの説でOK。共有じゃなかったら破綻しているので間違い・・・。 17-02-19 シェーダーのステージ間最適化する方法を探し中
こんなシェーダーがあったときに、vertステージでのfragColorの代入は不要になります。 ステージ毎にコンパイルすると残ってしまうのですが、ステージ統合して最適化するタイプのコンパイラだとこのような計算も消えます。 VulkanSDKに付属する glslangValidator.exe ではどうも残ってしまうようで、どうにかして消す方法ないかなぁと探しています。あると思うんだけどなぁ。 17-02-19 インスタンシング描画OpenGL なら gl_InstanceID を使いますが、Vulkan の GLSL は gl_InstanceIndex を使うようです。 gl_InstanceID だと途中からリクエストしても0番から始まる仕様ですが、gl_InstanceIndex だと0個目でもそのインデックス番号が格納されているそうです。 参考: http://stackoverflow.com/questions/35638512/instanced-glsl-shaders-in-vulkan 17-02-12 Descriptor 周りの単位を考えてみるDescriptorPool は DesciptorSet が持つエントリー数分の descriptorCount を指定して作る。 DescriptorSetLayout は DescriptorSet がどういう構成なのかを定義するオブジェクト。定義だけなので Pool は参照しない。 DescriptorSet は DescritorSetLayout の定義を使い DescriptorPool のリソースを使ってインスタンス化したもの。なので両者とも参照する。 それを踏まえまして。 例えば1つのモデルを1フレーム中にシャドウマップ用、本番描画用の2回書くととして、それぞれのオブジェクトが何個いるのか考えてみます。 モデルリソース、モデルインスタンス、描画パスの3つの単位があったとして。 リソース単位で済むのは DescriptorSetLayout。複数のモデルインスタンスを作っても1つで良さそう。 インスタンス単位で必須なのは DescriptorSet なのかな。 いやー、描画パス単位で変えるのが例えばカメラ(Uniform)情報なんだとすると、それぞれ 別のUniform 情報を設定するために DescriptorSet を持ちそうですね。 だとすると、DescriptorSet はインスタンスあたり描画パス数分保持するモノになります。。 DescriptorSet はどのタイミングで書き換えて良いのか。 公式の 13.2.5項 に書いてありました。
コマンドが走っている間は書き換えちゃダメだよーとのことです。ということで描画パス数分必要ですね。 ダブルバッファリングするなら2フレーム分で2倍になります。 そして DescriptorPool は管理しやすい方法で良さそうです。 モデル単位で持たせたければそれで作ればいいですし、シーン全体で1つというのもありですね。アプリの方針次第。 17-02-12 あらゆるところで RenderPassPipeline 作るときになぜ RenderPass を指定せんといかんの。 vkCmdBeginRenderPass してから vkCmdBindPipeline をするので、指定いらないと思うのだけども。 RenderPass を Pipeline で指定することになると相互参照になってすごく変な感じがする。 そういえば Framebuffer も RenderPass 知ってるけどそれも変な感じがする。 なんでみんな RenderPass を知りたがるのか。 相互参照になっているから RenderPass を作り直すと Pipeline も Framebuffer も作り直さないといけない(と自分は認識した)。 RenderPass のサブパスを増やしたり減らしたりは動的に切り替えたくなるけども、 それをしたかったら毎回 RenderPass とそれを見ているものを作り直せということなのでしょうか。 なにかメリットがあってこういう形をとってるはずなんですけど、そのメリットが見えてこないのでモヤモヤ。 17-02-12 細々と気になるところQuery ってなんですの。 https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#queries 最初の1節に全部書いてあった。解決。 Sparse Resources ってなんですの。 https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#sparsememory 連続した1つのメモリブロック片に設置しないといけない、といった制限がないもの?ということなのかな。 pfnInternalAllocation ってなんですの。 https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#memory-host vkInternalAllocationNotification の型をみるに通知だけっぽい。 「This is a purely informational callback.」って書いてあるし。 17-02-12 Buffer BufferView Image ImageView使い分けがイメージできないモヤっとを取り除いてみよう。 BufferとBufferViewの関係はぱっと想像できるんです。 大きなバッファ作って部分ごとに使い分けたいとか。 ImageとImageView。こちらがモヤっとしています。 同じメモリ領域を別の使い方をしたいときにViewを量産するんでしょうか? 違うか、その場合は同じメモリ領域を別のImageにバインドすることになりますね。 あ!例えばキューブマップの1面ずつをオフスクリーンレンダする場合、1面ずつをViewに割り当てて描画先に指定するのかな。 そんで、6面描画しおわったら、CUBEなViewをサンプラーとして使って描画する、とかでしょうか。 CUBEマップを指定する場合のImageとViewの設定がこちらに載っていました。 https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#resources-image-views-compatibility View を作る際に指定する VkImageSubresourceRange に baseArrayLayer がある。 CUBEのときは各面が0〜5 に対応しているんですね。View の役割がイメージできました。 17-02-12 Fence Semaphore Event の違い分かりやすく解説されてました。ありがたい。 https://www.reddit.com/r/vulkan/comments/47tc3s/differences_between_vkfence_vkevent_and/ 17-02-12 クイックリファレンスクイックなんだけど、ページ数すごいですね。ココに出てくるものがざっくり理解できたら大枠は理解できたと考えてよさそうです。 https://www.khronos.org/files/vulkan10-reference-guide.pdf 17-02-08 だいたいハテナがとれたのでCrossFrameworkにモジュールを作ってみよう。 その前に名前空間整理をやってしまおう。 17-02-07 SPIR-V から名前などの一覧はとれるのかデモのシェーダーを少し書き換えてSPVにしてみました。 #spanend #spanadd ; SPIR-V #spanend #spanadd ; Version: 1.0 #spanend #spanadd ; Generator: Khronos Glslang Reference Front End; 1 #spanend #spanadd ; Bound: 20 #spanend #spanadd ; Schema: 0 #spanend OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %main "main" %uFragColor %texcoord OpExecutionMode %main OriginUpperLeft OpSource GLSL 400 OpSourceExtension "GL_ARB_separate_shader_objects" OpSourceExtension "GL_ARB_shading_language_420pack" OpName %main "main" OpName %uFragColor "uFragColor" OpName %tex "tex" OpName %texcoord "texcoord" OpDecorate %uFragColor Location 0 OpDecorate %tex DescriptorSet 0 OpDecorate %tex Binding 0 OpDecorate %texcoord Location 0 %void = OpTypeVoid %3 = OpTypeFunction %void %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 #spanadd %_ptr_Output_v4float = OpTypePointer Output %v4float #spanend %uFragColor = OpVariable %_ptr_Output_v4float Output %10 = OpTypeImage %float 2D 0 0 0 1 Unknown %11 = OpTypeSampledImage %10 #spanadd %_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 #spanend %tex = OpVariable %_ptr_UniformConstant_11 UniformConstant %v2float = OpTypeVector %float 2 #spanadd %_ptr_Input_v2float = OpTypePointer Input %v2float #spanend %texcoord = OpVariable %_ptr_Input_v2float Input %main = OpFunction %void None %3 %5 = OpLabel %14 = OpLoad %11 %tex %18 = OpLoad %v2float %texcoord %19 = OpImageSampleImplicitLod %v4float %14 %18 OpStore %uFragColor %19 OpReturn OpFunctionEnd #spanadd Uniformやサンプラーの名前はSPVから取得できるのかの件ですが、SPVを解析したら出せそうですね。 C++での解析ライブラリは見つけたのですがC#のはあるのかな? そしたらバイナリコンバータで手軽に好きな形で情報をつっこめるんだけどねぇ。 17-02-06 Uniform と DescriptorSet頭がこんがらがってきた。けどめげない。 Uniform まわりをすっきりさせよう。 日本語解説ページにお世話になります。ありがとうございます。 https://sites.google.com/site/monshonosuana/vulkan/vulkan_004 DescriptorSetLayoutBinding::descriptorCount は何に使うのか最初ハテナでしたが、どうやら配列を指定するときに使うようです。 https://vulkan.lunarg.com/doc/view/1.0.33.0/linux/vkspec.chunked/ch13s02.html シェーダのユニフォーム値や頂点属性名はシェーダーバイナリ(SPIR-V)に含まれてるのかどうか気になりました。 次調べます。 17-02-05 Pipelineレンダーパスと同じくなんじゃこりゃと思ったパイプライン。 コードを見る限り、マテリアルに関するRenderStateを集めたモノと考えてよさそう。 Blend、DepthStencilTest、Vertex&Fragmentシェーダの設定などなど。 頻繁に変える項目は DynamicState で指定できるようにすることも可能らしく、1項目の設定値が異なるマテリアルがあっても Pipeline をもう1つ作る必要はないみたい。 また、 uniform やリードするテクスチャは vkCmdBindDescriptorSets で Descriptor という概念で反映するらしく、Pipelineとは別らしい。 これはまた別で調べましょう。 17-02-05 テクスチャフォーマットで調べたこと
公式ドキュメントに書いてありました。 #spanend #spanadd USCALED #spanend #spanadd The components are unsigned integer values that get converted to floating-point in the range [0,2n-1] #spanend #spanadd #spanend #spanadd SSCALED #spanend #spanadd The components are signed integer values that get converted to floating-point in the range [-2n-1,2n-1-1] #spanend #spanadd floatに変換されますというだけなのかな?どういう使い方をするのかは分かりませんでした。
指数部(RGB共通にかかる指数)、未使用、ステンシルを示すものでした。
公式ドキュメントより。 #spanend linearTilingFeatures describes the features supported by VK_IMAGE_TILING_LINEAR. #spanadd #spanend optimalTilingFeatures describes the features supported by VK_IMAGE_TILING_OPTIMAL. #spanadd #spanend bufferFeatures describes the features supported by buffers. #spanadd タイリングはピクセルの並びのことです。 LINEARは1行ごとに(おそらく左端から右端の順で)ピクセルデータが並んでいるようです。 OPTIMALはGPUが処理しやすい並びの順でピクセルデータが並んでいるようです。 LINEARで使える用途、OPTIMALで使える用途、あとバッファ系で使える用途がここで列挙されているようです。 OPTIMALな並びはGPU依存ですけど、よく使うBCシリーズはそのものがOPTIMALな並びなのかどうかが気になりました。 ひとまずそれは置いておいて、先にチュートリアルページを読んでいくことにします。 17-02-05 ROデータのVRAMへの転送RO = リードオンリーのこと。 昨日の VulkanInfo の結果を見たら DeviceLocal なメモリが明確に扱えることが分かりました。 これをいわゆるVRAM(GPUしかアクセスできないメモリで通常のメモリより高速)であると考えますと、 アセットとしてロードしたテクスチャや頂点属性は基本不変であるならばそこに突っ込んだほうが早くなりそうですね。 通常メモリからVRAMへコピーする方法はあるのかと思って検索したらあっさり出てきました。 https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer 不変なものは基本VRAMへ。変更回数が少ないものも基本VRAMに載せたほうがいいのかもしれません。 ハードによっては通常メモリが超遅いものもあるので、もしかすると毎フレーム変わるようなものも毎フレームコピーしたほうが早い、なんてこともあるのかもしれませんね。 スマートデバイス系はVRAMがなく共有メモリで済ませているのがほとんどという印象なので、効果があるのはVRAMのあるハード(PCやコンシューマ機)となりそうです。 参考:Android 機の VulkanInfo http://dench.flatlib.jp/vulkan/vulkaninfo ※いつも参考にさせていただいております&ありがとうございます! 17-02-05 RenderPass解説ページを見ながらお勉強。ありがとうございます。 http://qiita.com/Pctg-x8/items/2b3d5c8a861f42aa533f Subpass、Attachment、Dependencyの言葉が何を指すのかが分かり一気に理解が進みました。 GPUを少しでも暇させないための仕組みなんですね。すっきり! 17-02-05 VulkanInfo を見てぱっと分からなかったものFORMAT_R8_USCALED にある USCALED や SCALED ってどういうタイプなのか。 linearTiling、optimalTiling、bufferFeaturesとは。(想像通りかもしれないけど念のため) VK_FORMAT_FEATURE_ 各種定数の意味は。 フォーマットのE,S,X,は何なのか。(Sはステンシル・・・?) レンダーパス調べた後ぐらいに調べよう。 17-02-04 GTX680 で VulkanGTX680が届いたので早速MacProさんに装着。Metalも動き、MoltenVkのサンプルも動きました。 BootcampのWin10でもVulkanInfoサンプルが動きました。 vulkaninfo-gtx680.txt 昨日のメモリの話関連になりますが、↑を見るとビデオカードのメモリと通常メモリでヒープが分かれているのが分かりますね。 17-02-03 メモリあれこれVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT と VK_MEMORY_PROPERTY_HOST_COHERENT_BIT はどっちのほうがパフォーマンスが良いのか気になったので調べました。 VkPhysicalDeviceMemoryProperties の公式の説明を読むと「パフォーマンスが同等もしくはそれより良いもの順に見つかるように memoryTypes は並んでいます」というようなことが書いてあります。 つまり、 HOST_VISIBLE_BIT だけで良い場合は HOST_COHERENT_BIT がたっていないメモリタイプのヒープからメモリを確保するほうがパフォーマンスが良くなる可能性がある、ということだと理解しました。 続いてHeap。 VkMemoryHeap.size はMoltenVk では 0 が格納されていました。 おそらく Metal からはその情報がとれないのか、もしくは未対応なのかと思われます。 Apple系OS環境も考慮するならばサイズみてほにゃららするという処理は書かず、Allocを試してサイズを測る方が良さそうです。 最後にメモリアロケーションは少ない方がいいのかどうか。 NVIDIAさんの解説の最後の図を見る限り、1つのBufferでまとめられるならまとめたほうが良さそう。 ということはメモリブロックも少ないにこしたことはないということだと理解しました。 CPUからRead or Write するようなタイプのものは全部1つの VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT なメモリタイプ&ヒープから確保したメモリブロックからやりくりするのが一番良さそうです。 もちろんその場合、もちろんヒープ管理をこちらでする必要がでてくるため少し面倒ではありますがパフォーマンスを重要にするならやるっきゃない、ということですかね。 17-02-02 コードの解説http://qiita.com/Pctg-x8/items/6fd3ef76b58d98f26634 丁寧に書かれていて入門編としてとてもありがたかった。 17-02-01 オーバービューを読むhttps://vulkan-tutorial.com/Overview わかりやすーい!だいたいイメージできた。 17-02-01 実行環境どうしようかなMacで確認するならMetalをラップした MoltenVK を使用する必要あり。 |