Vulkan 
Vulkan に関する個人的なメモを書くページです。
17-02-08 だいたいハテナがとれたので 
CrossFrameworkにモジュールを作ってみよう。
その前に名前空間整理をやってしまおう。
17-02-07 SPIR-V から名前などの一覧はとれるのか 
デモのシェーダーを少し書き換えてSPVにしてみました。
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 20
; Schema: 0
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
%_ptr_Output_v4float = OpTypePointer Output %v4float
%uFragColor = OpVariable %_ptr_Output_v4float Output
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
%11 = OpTypeSampledImage %10
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
%tex = OpVariable %_ptr_UniformConstant_11 UniformConstant
%v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
%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
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 テクスチャフォーマットで調べたこと 
- USCALED SSCALED
- 公式ドキュメントに書いてありました。
USCALED
The components are unsigned integer values that get converted to floating-point in the range [0,2n-1]
SSCALED
The components are signed integer values that get converted to floating-point in the range [-2n-1,2n-1-1]
floatに変換されますというだけなのかな?どういう使い方をするのかは分かりませんでした。
- E, X, S
- 指数部(RGB共通にかかる指数)、未使用、ステンシルを示すものでした。
- linearTiling、optimalTiling、bufferFeatures
- 公式ドキュメントより。
linearTilingFeatures describes the features supported by VK_IMAGE_TILING_LINEAR.
optimalTilingFeatures describes the features supported by VK_IMAGE_TILING_OPTIMAL.
bufferFeatures describes the features supported by buffers.
タイリングはピクセルの並びのことです。
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 で Vulkan 
GTX680が届いたので早速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
わかりやすーい!だいたいイメージできた。
Render pass と Graphics pipeline は初めて見る概念な気がする。
そしてまだよく理解できてないので後で改めて読み直してみよー。
17-02-01 実行環境どうしようかな 
Macで確認するならMetalをラップした MoltenVK を使用する必要あり。
MacBook 環境ではサンプルが動いた。
タワー型 MacPro は基本Metalをノンサポートのため動かない。
近日グラボを変えるのでそれで動くことを期待。(動いて欲しいなぁ)
試用は Windows 上のほうが安定してそうなので対応グラボをさした Bootcamp を使おう。