Direct3D 11でのバッファリソースタイプについて

[ここ](https://msdn.microsoft.com/en-us/library/windows/desktop/ff476335(v=vs.85).aspx)についての日本語訳。

日本語訳が終わった際、[公式の日本語訳](https://msdn.microsoft.com/ja-jp/library/ee417836(v=vs.85).aspx)があることに気づきましたが、直訳だなーと思ったので供養も兼ねてここに残しておきます。

ちょいちょい個人的な意見も挟んでいます。

# New Resource Types
Direct3D 11では、以下のいくつかの新しいリソースタイプが追加されました。

- Read/Write Buffers and Textures
- Structured Buffer
- Byte Adress Buffer
- Unordered Access Buffer or Texture
  - Append and Consume Buffer

## Read/Write Buffers and Textures
シェーダーモデル4では読み取り専用であったバッファを、シェーダーモデル5では読み/書きが可能となるよう実装されました。
- [RWBuffer](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471472(v=vs.85).aspx)
- [RWTexture1D](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471499(v=vs.85).aspx), [RWTexture1DArray](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471500(v=vs.85).aspx)
- [RWTexture2D](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471505(v=vs.85).aspx), [RWTexture2DArray](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471506(v=vs.85).aspx)
- [RWTexture3D](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471511(v=vs.85).aspx)
これらのリソースには、メモリに直接アクセスする方法がないので、インデックスを使用してアクセスする必要があります。
これらの変数値は式の左辺と右辺に用いることが可能です。右辺値として用いる場合は、型は単一の要素（float、int、またはuint）である必要があります。

## Structured Buffer
Structured Bufferはすべての要素が同じサイズを持つバッファです。要素を定義するには、1つ以上のメンバ変数を持った構造体を使用してください。
以下は3つのメンバ変数を持った構造体です。

```c:hlsl
struct MyStruct
{
  float4 Color;
  float4 Normal;
  bool isAwesome;
}
```

この構造体を以下のように用いてStructured Bufferを宣言します。

```c:hlsl
StructuredBuffer<MyStruct> mySB;
```

インデックスを付加することによって、以下のように1つの要素にアクセスできます。

```c:hlsl
float4 myColor = mySB[27].Color;
```

StructuredBufferにアクセスするには以下のオブジェクト型を使用してください。
- [StructuredBuffer](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471514(v=vs.85).aspx) - 読み取り専用
- [RWStructuredBuffer](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471494(v=vs.85).aspx) - 読み/書き可能
RWStructuredBufferでは**int型とuint型**のみスレッド間で同時書き込みをブロック(Interlocked)できる[Atomic関数群](https://msdn.microsoft.com/en-us/library/windows/desktop/ff476334(v=vs.85).aspx)が使用できます。

※**ここが結構大事で、CUDAではfloatでのアトミック演算がサポートされていますので、プラットフォーム選びには注意してください。**
一応、Compute Shaderでfloat値のアトミック加算をやってみる記事も見つかりました。
[HLSLで浮動小数点数のアトミック演算](https://shobomaru.wordpress.com/2014/10/02/float-atomic-operation-with-hlsl/)

## Byte Adress Buffer
Byte Adress Buffer はバイトオフセットを用いて要素にアクセスできるバッファです。
通常、バッファの要素は、各要素のストライド(S)と要素番号(N)を用いてS*Nで与えられるようにインデックスされます。
ByteAdressBufferは、Raw Bufferとも呼ばれ、バッファの始点からのバイトオフセット値を用いて要素にアクセスを行います。
アドレスはDWORD(32ビット符号なし)単位でアライメントされるよう、バイトオフセット値は必ず4の倍数である必要があります。
それ以外の値が与えられた場合の動作は保証されていません。

シェーダーモデル5では、読み取り専用、読み/書き可能の2つのバッファを導入されました。Byte Adress Bufferの要素は、32bit符号なし整数で表現されています。
バッファ内の要素の値が符号なし整数でない場合は、```asfloat```関数を用いて値を読む必要があります。

## Unordered Access Buffer or Textures
Unordered Access Bufferでは、複数スレッドから一時的にunorderedなアクセスを行うことが可能です。つまり、アトミック関数を通して、メモリの競合を起こすことなく同時に異なるバッファ要素にアクセスし、読み書きが可能であることを意味しています。
ID3D11Device :: CreateBufferやID3D11Device :: CreateTexture2Dなどの関数を呼び出し、列挙値D3D11_BIND_FLAGからD3D11_BIND_UNORDERED_ACCESSフラグを渡して、Unordered Access BufferまたはTextureを作成します。
**(UnityではComputeBufferの宣言時にフラグを渡すことで作成できます。)**

Unordered Access Bufferリソースは、ピクセルシェーダとコンピュートシェーダでのみバインド可能です。同時実行中のピクセルシェーダとコンピュートシェーダでは同じUnordered Access Bufferがバインドされます。

### Append and Consume Buffer
Append/Consume Bufferは、バッファの末尾に値を追加/除去が可能な、スタックに似た動作をする特別なUnordered Accessリソースです。
Append/Consumeバッファは、Structured Bufferである必要があります:
- [Append Structured Buffer](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471448(v=vs.85).aspx)
- [Consume Structured Buffer](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471459(v=vs.85).aspx)

バッファへのアクセスは、指定のメソッドを通じてのみ行うことが可能です。インデックスは使用できません。

## Related Topics
[Compute Shader Overview](https://msdn.microsoft.com/ja-jp/library/ee417833(v=vs.85).aspx)