Direct3D12 Descriptor

Descriptor

Descriptor は D3D12 でリソースをシェーダーにバインドする(シェーダーからアクセスするためにリソースを設定する)単位。必ずしも一対一になる訳では無いが、CBV や SRV などの1リソースが 1Descriptor になる。

Descriptor Heap の作成

まずは、Descriptor のメモリー領域となる Descriptor Heap を作成する。専用の構造体に、これから作成する Descriptor Heap の個数とどのようなタイプ(CBV, SRV, UAV や Sampler) として使うのかを指定して、Device::CreateDescriptorHeap() に渡してヒープを作成する。

RTV や CBV など、Type によって Heap は分けて作成する。

Descriptor Handle の作成

作った Descriptor Heap から Descriptor Handle を得る。これは Heap::GetCPUDescriptorHandleForHeapStart() を呼び出して取得する。一つの Descriptor Handle から複数の Descriptor を作成できるが、その際は、 Device::GetDescriptorHandleIncrementSize() を使って、次の Descriptor Handle へのポインタ位置を計算して取得する。

D3D11 の時は View を作成するときは専用の ShaderResourceView などを渡していたが、D3D12 では Descriptor Handle を渡す。CreateConstantBufferView() や CreateRenderTargetView() の引数には、この Descriptor Handle を設定する。

RenderTargetView

  • CommandList->OMSetRenderTargets()
  • CommandList->ClearRenderTargetView()

などを呼び出すときは、View を作成した Descriptor Heap を渡す。

SetDescriptorHeaps

サンプルの中で、CommandList->SetDescriptorHeaps() を呼び出している箇所があった。しかし CBV Heap を設定していたが、RTV heap は設定していなかった。SetDescriptorHeaps() は いつ何を設定する必要があるんだ…?

組織崩壊

前に勤めていたベンチャー企業での話だが、たまに組織の中で、従業員からの思い付きでとんでもない要望が上がってくる。

その一つに、modo を社内標準の 3DCG ツールにしようと話があった。物事を分かっているマネージャーがいたら「何を言ってるの?」という話になるが、そう判断と発言出来る人がいない。

Winodws での Anaconda と PyCharm

Windows で Anaconda を使った Tensorflow
https://blog.acheul.net/?p=1124

でもまとめていたが、2019年5月24日に再セットアップしたので手順を更新。

インストール

Anaconda 公式サイトから Windows 版の 64bit インストーラをダウンロード。Anaconda 2019.03 という名前だった。Python 3.7 Version。大量のパッケージがインストールされるので時間とディスク容量が必要。

PyCharm 2019.1.2 をダウンロード。Community Edition with Anaconda plugin Setup というアナコンダと連携しやすくなったバージョンが存在している。Anaconda Support というプラグインが自動でインストールされている。

Tensorflow1.5.0 インストール

「Tensorflow 開発入門 Keras による深層学習モデル構築手法」では Anaconda3 5.0.1 / Python 3.5.4 or 3.5.5 / Tensorflow 1.5.0 が使われている。
https://repo.continuum.io/archive/

最新の Anaconda だと conda install tensorflow==1.5.0 ができない。その場合 pip install tensorflow==1.5.0 なら通った。

セットアップ

Anacodna Navigator を起動。Environments タブから Create を選択し、Name:tf36, Python 3.6 で作成。再生ボタンで Open Terminal を選択し、下記のコマンドを打ち込み必要パッケージをインストール。

conda install tensorflow
conda install keras
conda install matplotlib

Anaconda の仮想環境は、デフォルトだと
C:¥Users¥username¥AppData¥Local¥Continuum¥Anaconda3¥envs¥ に作られる。フォルダサイズが大きいので注意

# Tensorflow GPU 版とバージョン指定
conda install tensorflow-gpu
conda install tensorflow-gpu==1.5.0

Jupyter Notebook

Anaconda Navigator の Home に戻り Jupyter Notebook を Install。ホームの左上に Application on “VM Name” のプルダウンがあるので、そこで作った環境を選択して Launch で起動。

Jupyter Notebook を起動して、新しいノートブックを作り、Tensorflow のチュートリアルから MNIST のコードを貼り付けて実行できたら成功。

Jupyter Notebook はデフォルトだと
C:¥Users¥username¥ 以下に ipynb ファイルが作られる。

PyCharm

Create New Project から Existing interpreter を選択。Conda Environment タブの Interpreter に、先ほど Anaconda Navigator で作った tf36 が選べるので選択。そのまま新規プロジェクトと Python ファイルを作って、MINIST が実行できたら成功。

PyCharm はデフォルトだと、
C:¥Users¥username¥PycharmProjects¥ にプロジェクトが作られる。

「モデル化」という言葉

最近「モデル」という言葉の定義そのものが、自分の中で認識が怪しい。

「モデル化」という言葉の使い方に、若干の難を感じている。色んな使われ方があると思うが「抽象化」と考えるのが一番しっくりくる。

数学で言えば、現実世界の具体的な事象を、数式という抽象的な言葉で表現する事をモデル化という。

機械学習で使われるモデル化というのも、AI を使って解きたい現象を、抽象的なロジックにする(アルゴリズムに落とす)ことをモデル化と呼んでいる。

ただ、人によっては、ニューラルネットワークを使って数字の分類を行いたい場合に、ネットワークの構造までを含めて(問題を解く、動作するプログラムまでの事を)モデル化すると呼ぶ場合もあれば、「ニューラルネットワークというモデルを使って、AI をモデル化する」などと言う事もある。

個人的にはニューラルネットワークやサポートベクターマシンのようなものは「AI アルゴリズム」と呼び、CNN や RNN のようなものは「AI アーキテクチャ」と呼び、それらを使って問題を解くために構築した実装を「AI モデル」、その一連の工程を「モデル化する」と認識すれば、理解しやすかった。

DirectX Raytracing 学習リソース

DirectX Raytracing – The life of a ray tracing kernel.
https://cedil.cesa.or.jp/cedil_sessions/view/1825

microsoft/DirectX-Graphics-Samples
https://github.com/microsoft/DirectX-Graphics-Samples

NVIDIAGameWorks/DxrTutorials
https://github.com/NVIDIAGameWorks/DxrTutorials

確率密度関数からモンテカルロ積分まで
https://qiita.com/Ushio/items/0040b3c74a480c46c80c

Introduction to DirectX RayTracing
http://intro-to-dxr.cwyman.org/

Ray Tracing Resources Page
http://www.realtimerendering.com/raytracing.html

Vulkan Descriptor

難しい。分からない。

Descriptor

Vulkan でのリソース単位。リソースバインドの単位。
Sampler, Texture, Uniform Buffer のようなものが1つの Descriptor として定義されている。

DescriptorPool

Descriptor を作る前に、最初に DescriptorPool を作成しておかないといけない。DescriptorPool を作成するためには、引数としてこれから作成する Descriptor の個数や種類をあらかじめ指定する必要がある。でないと Pool サイズが決まらないため。DescriptorSet は DescriptorPool から作成される。DescriptorPool には作成できる DescriptorSet の最大個数なども指定する。これも、確保する Pool サイズを決めるためだと思われる。Thread ごとに Pool を持つと効率的に Descriptor の割り当てが可能になる。

DescriptorSet

Descriptor をグループ化したもの。Descriptor は個々にバインドされずに、DescriptorSet に統合されて照される。DescriptorSet を作るためには、先に何の Descriptor が何個あるかを定義した DescriptorSetLayout を作る必要がある。DescriptorSetLayout のインストタンスとして DescriptorSet が作られるイメージ。DescriptorSet を作るときは、あらかじめ確保した DescriptorPool を使って作られるため、関数が vkCreate ではなく、vkAllocate という名前。描画時に vkCmdBindDescriptorSets() に対して使用する VkDescriptorSet を設定する。

DescriptorSetLayout

Descriptor の定義構造と DescriptorPool を関連づけるために必要?vkCreateDescriptorSetLayout() によって 新しい Descriptor Set Layout が作成される。 C 言語の構造体定義のようなもので、Descriptor の種類と数を決定する。この情報は、DescriptorSet を作る時に構造体として渡される。

DescriptorSetLayoutBinding

DescriptorSetLayout を作るための構造体。リソースのバインディング位置 (シェダーから参照する binding 値) や、Type、個数、どのシェーダーステージからアクセス可能かのフラグ指定などの項目を持っている。DescriptorSetLayout と PipelineLayout を作るために両方で使用される。PipelineLayout がなぜ、DescriptorSetLayoutBinding 情報が必要なのかは分からない。

WriteDescriptorSet

1つの DescriptorSet の中に 2つの Descriptor があれば、書き込むために WriteDescriptorSet write[2] で定義する。write の中に Descriptor の Buffer, Type, Count などを指定できる。

AllocateDescriptorSets

DescriptorPool から DescriptorSet の領域を確保する。

UpdateDescriptorSets

DescriptorSet を実際のバッファと関連づける。更新する場合は WriteDescriptorSet を使用する。

Vulkan の Descriptor Type

DirectX12 の Descriptor Type

  • Shader Resource View (SRV)
  • Constant Buffer View (CBV)
  • Unordered Access View (UAV)
  • Sampler

SAMPLER

  • Read Only
  • VK_DESCRIPTOR_TYPE_SAMPLER
  • DirectX で言う SamplerState
  • Sampler オブジェクトに関連づけられており、 サンプリングイメージに対して実行される、サンプリング操作の動作を制御する。

SAMPLED_IMAGE

  • Read Only
  • VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
  • DirectX で言う Texture
  • Image View を介して Image Resouce に関連づけられており、 Smpling Op (Load?) を実行できる。

STORAGE_IMAGE

  • Read Write
  • VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
  • DirectX で言う RWTexture
  • Image View を介して Image Resource に関連づけられており、 Load, Store, Atomic Op を実行できる。

COMBINED_IMAGE_SAMPLER

  • Read Only
  • VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
  • Sampler と Image Resource に関連づけられており、 一つの Discriptor で両方を結合している。

UNIFORM_TEXEL_BUFFER

  • Read Only
  • VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
  • DirectX で言う Buffer
  • Buffer View を介して Buffer Resource に関連づけられており、 フォーマットされた Load を実行できる。

STORAGE_TEXEL_BUFFER

  • Read Write
  • VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
  • DirectX で言う RWBuffer
  • Buffer View を介して Buffer Resource に関連づけられており、 フォーマットされた、Load, Store, Atomic Op を実行できる。

UNIFORM_BUFFER

  • Read Only
  • VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
  • DirectX で言う Constant Buffer
  • Buffer Resource に直接関連づけられており、 Load を実行できる。

STORAGE_BUFFER

  • Read Write
  • DirectX で言う Byte Address Buffer や Structured Buffer や Append/Consume Buffer など
  • VK_DESCRIPTOR_TYPE_STRAGE_BUFFER
  • Buffer Resource に直接関連づけられており、 Load, Store, Atomic Op を実行できる。

UNIFORM_BUFFER_DYNAMIC

  • Read Only
  • VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
  • Uniform Buffer とほぼ同じ。バッファへのオフセットの指定方法が異なるだけ。

STORAGE_BUFFER_DYNAMIC

  • Read Write
  • VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
  • Storage Buffet とほぼ同じ。バッファへのオフセットの指定方法が異なるだけ。

INPUT_ATTACHEMENT

  • VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
  • Image View を介して Image Resource に関連づけられており、 Fragment Buffer Local Load 操作に使用される。

INLINE_UNIFORM_BLOCK

  • VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT
  • Uniform Buffert とほぼ同じ。