Top > Vulkan

Vulkan Edit

Vulkan に関する個人的なメモを書くページです。自分用なので言葉足らずなことがあります。

20-07-12 他ライブラリとの比較 Edit

まとめてます。

https://github.com/hoboaki/engineplan/blob/main/master/Scratch/memo_low_gfx_api.md

18-10-08 複数の Uniform を DescriptorSet に設定する方法 Edit

こちらのサイトをベースに。(紹介されているのは Uniform を1つだけバインドする例)
https://sites.google.com/site/monshonosuana/vulkan/vulkan_004

試してないけどおそらくこれ。

  • DescriptorSetLayoutBinding を必要な Uniform の数分定義してあげる。2つ必要なら Uniform 用に2つ定義してあげる。
  • DescriptorSetLayoutBinding に指定する binding の値は重複しないはずである。2つなら 0 と 1 になるはず。
  • なので WriteDescriptorSet の dstBinding で書き換えたい Uniform の binding の番号を指定してあげればよい。
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// 雑なサンプルコード
std::array<vk::WriteDescriptorSet, 2> descSetInfos;
// Uniform 0 番のバッファを指定
descSetInfos[0].dstSet = g_VkDescSets[0];
descSetInfos[0].descriptorCount = 1;
descSetInfos[0].descriptorType = vk::DescriptorType::eUniformBuffer;
descSetInfos[0].dstBinding = 0;
descSetInfos[0].pBufferInfo = &g_VkUniformInfo0;
// Uniform 1 番のバッファを指定
descSetInfos[1].dstSet = g_VkDescSets[0];
descSetInfos[1].descriptorCount = 1;
descSetInfos[1].descriptorType = vk::DescriptorType::eUniformBuffer;
descSetInfos[1].dstBinding = 1;
descSetInfos[1].pBufferInfo = &g_VkUniformInfo1;
// 更新を実行
g_VkDevice.updateDescriptorSets(...);

あれ、vertexシェーダとfragmentシェーダでUniformバインディング番号って共有だったっけ?共有ならこの説でOK。共有じゃなかったら破綻しているので間違い・・・。

17-02-19 シェーダーのステージ間最適化する方法を探し中 Edit

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 
 
 
 
-
|
!
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
!
 
 
 
 
 
 
 
 
-
|
|
!
 
// vert
#version 330
#extension GL_ARB_separate_shader_objects : enable
 
out gl_PerVertex {
    vec4 gl_Position;
};
layout(location = 0) out vec3 fragColor;
 
vec2 positions[3] = vec2[](
    vec2(0.0, -0.5),
    vec2(0.5, 0.5),
    vec2(-0.5, 0.5)
);
vec3 colors[3] = vec3[](
    vec3(1.0, 0.0, 0.0),
    vec3(0.0, 1.0, 0.0),
    vec3(0.0, 0.0, 1.0)
);
 
void main() {
    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
    fragColor = colors[gl_VertexIndex];
}
 
// frag
#version 330
#extension GL_ARB_separate_shader_objects : enable
 
layout(location = 0) out vec4 outColor;
layout(location = 0) in vec3 fragColor;
 
void main() {
    outColor = vec4(1.0, 0.0, 0.0, 1.0);
    //outColor = vec4(fragColor, 1.0);
}

こんなシェーダーがあったときに、vertステージでのfragColorの代入は不要になります。
ステージ毎にコンパイルすると残ってしまうのですが、ステージ統合して最適化するタイプのコンパイラだとこのような計算も消えます。
VulkanSDKに付属する glslangValidator.exe ではどうも残ってしまうようで、どうにかして消す方法ないかなぁと探しています。あると思うんだけどなぁ。

17-02-19 インスタンシング描画 Edit

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 周りの単位を考えてみる Edit

DescriptorPool は DesciptorSet が持つエントリー数分の descriptorCount を指定して作る。
DescriptorSetLayout は DescriptorSet がどういう構成なのかを定義するオブジェクト。定義だけなので Pool は参照しない。
DescriptorSet は DescritorSetLayout の定義を使い DescriptorPool のリソースを使ってインスタンス化したもの。なので両者とも参照する。

それを踏まえまして。
例えば1つのモデルを1フレーム中にシャドウマップ用、本番描画用の2回書くととして、それぞれのオブジェクトが何個いるのか考えてみます。

モデルリソース、モデルインスタンス、描画パスの3つの単位があったとして。
リソース単位で済むのは DescriptorSetLayout。複数のモデルインスタンスを作っても1つで良さそう。
インスタンス単位で必須なのは DescriptorSet なのかな。
いやー、描画パス単位で変えるのが例えばカメラ(Uniform)情報なんだとすると、それぞれ 別のUniform 情報を設定するために DescriptorSet を持ちそうですね。
だとすると、DescriptorSet はインスタンスあたり描画パス数分保持するモノになります。。

DescriptorSet はどのタイミングで書き換えて良いのか。
公式の 13.2.5項 に書いてありました。

The descriptor set contents bound by a call to vkCmdBindDescriptorSets may be consumed during host execution of the command, or during shader execution of the resulting draws, or any time in between. Thus, the contents must not be altered (overwritten by an update command, or freed) between when the command is recorded and when the command completes executing on the queue. The contents of pDynamicOffsets are consumed immediately during execution of vkCmdBindDescriptorSets. Once all pending uses have completed, it is legal to update and reuse a descriptor set.

コマンドが走っている間は書き換えちゃダメだよーとのことです。ということで描画パス数分必要ですね。
ダブルバッファリングするなら2フレーム分で2倍になります。

そして DescriptorPool は管理しやすい方法で良さそうです。
モデル単位で持たせたければそれで作ればいいですし、シーン全体で1つというのもありですね。アプリの方針次第。

17-02-12 あらゆるところで RenderPass Edit

Pipeline 作るときになぜ RenderPass を指定せんといかんの。
vkCmdBeginRenderPass してから vkCmdBindPipeline をするので、指定いらないと思うのだけども。
RenderPass を Pipeline で指定することになると相互参照になってすごく変な感じがする。
そういえば Framebuffer も RenderPass 知ってるけどそれも変な感じがする。
なんでみんな RenderPass を知りたがるのか。
相互参照になっているから RenderPass を作り直すと Pipeline も Framebuffer も作り直さないといけない(と自分は認識した)。
RenderPass のサブパスを増やしたり減らしたりは動的に切り替えたくなるけども、
それをしたかったら毎回 RenderPass とそれを見ているものを作り直せということなのでしょうか。
なにかメリットがあってこういう形をとってるはずなんですけど、そのメリットが見えてこないのでモヤモヤ。

17-02-12 細々と気になるところ Edit

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 Edit

使い分けがイメージできないモヤっとを取り除いてみよう。

BufferとBufferViewの関係はぱっと想像できるんです。
大きなバッファ作って部分ごとに使い分けたいとか。

ImageとImageView。こちらがモヤっとしています。
同じメモリ領域を別の使い方をしたいときにViewを量産するんでしょうか?
例えば、MSAA用に大きいメモリ領域をImageに割り当てるが、状況によって小さな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 の違い Edit

分かりやすく解説されてました。ありがたい。
https://www.reddit.com/r/vulkan/comments/47tc3s/differences_between_vkfence_vkevent_and/

17-02-12 クイックリファレンス Edit

クイックなんだけど、ページ数すごいですね。ココに出てくるものがざっくり理解できたら大枠は理解できたと考えてよさそうです。
https://www.khronos.org/files/vulkan10-reference-guide.pdf

17-02-08 だいたいハテナがとれたので Edit

CrossFrameworkにモジュールを作ってみよう。
その前に名前空間整理をやってしまおう。

17-02-07 SPIR-V から名前などの一覧はとれるのか Edit

デモのシェーダーを少し書き換えて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 Edit

頭がこんがらがってきた。けどめげない。
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 Edit

レンダーパスと同じくなんじゃこりゃと思ったパイプライン。
コードを見る限り、マテリアルに関するRenderStateを集めたモノと考えてよさそう。
Blend、DepthStencilTest、Vertex&Fragmentシェーダの設定などなど。
頻繁に変える項目は DynamicState で指定できるようにすることも可能らしく、1項目の設定値が異なるマテリアルがあっても Pipeline をもう1つ作る必要はないみたい。

また、 uniform やリードするテクスチャは vkCmdBindDescriptorSets で Descriptor という概念で反映するらしく、Pipelineとは別らしい。
これはまた別で調べましょう。

17-02-05 テクスチャフォーマットで調べたこと Edit

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への転送 Edit

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 Edit

解説ページを見ながらお勉強。ありがとうございます。
http://qiita.com/Pctg-x8/items/2b3d5c8a861f42aa533f

Subpass、Attachment、Dependencyの言葉が何を指すのかが分かり一気に理解が進みました。
GPUを少しでも暇させないための仕組みなんですね。すっきり!

17-02-05 VulkanInfo を見てぱっと分からなかったもの Edit

FORMAT_R8_USCALED にある USCALED や SCALED ってどういうタイプなのか。
linearTiling、optimalTiling、bufferFeaturesとは。(想像通りかもしれないけど念のため)
VK_FORMAT_FEATURE_ 各種定数の意味は。
フォーマットのE,S,X,は何なのか。(Sはステンシル・・・?)

レンダーパス調べた後ぐらいに調べよう。

17-02-04 GTX680 で Vulkan Edit

GTX680が届いたので早速MacProさんに装着。Metalも動き、MoltenVkのサンプルも動きました。
BootcampのWin10でもVulkanInfoサンプルが動きました。
filevulkaninfo-gtx680.txt
昨日のメモリの話関連になりますが、↑を見るとビデオカードのメモリと通常メモリでヒープが分かれているのが分かりますね。

17-02-03 メモリあれこれ Edit

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 コードの解説 Edit

http://qiita.com/Pctg-x8/items/6fd3ef76b58d98f26634

丁寧に書かれていて入門編としてとてもありがたかった。
レンダーパスとパイプライン、ぼんやりとしかまだ分かってないです。

17-02-01 オーバービューを読む Edit

https://vulkan-tutorial.com/Overview

わかりやすーい!だいたいイメージできた。
Render pass と Graphics pipeline は初めて見る概念な気がする。
そしてまだよく理解できてないので後で改めて読み直してみよー。

17-02-01 実行環境どうしようかな Edit

Macで確認するならMetalをラップした MoltenVK を使用する必要あり。
MacBook 環境ではサンプルが動いた。
タワー型 MacPro は基本Metalをノンサポートのため動かない。
近日グラボを変えるのでそれで動くことを期待。(動いて欲しいなぁ)
試用は Windows 上のほうが安定してそうなので対応グラボをさした Bootcamp を使おう。


Attach file: filevulkaninfo-gtx680.txt 759 download [Information]

Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup Referer   Help   RSS of recent changes
Last-modified: (769d)