バッファー リソースの作成 (Direct3D 10)
バッファーを作成するには、バッファーが格納するデータの定義、初期化データの指定、および適切な利用フラグとバインド フラグの設定が必要です。テクスチャーの作成については、「テクスチャー リソースの作成 (Direct3D 10)」を参照してください。
- 頂点バッファーを作成する
- インデックス バッファーを作成する
- 定数バッファーの作成
頂点バッファーを作成する
頂点バッファーの作成手順は次のようになります。
- バッファー記述の作成
- バッファーの初期化データの作成
- バッファーの作成
バッファー記述の作成
頂点バッファーを使用する際、バッファー記述 (「D3D10_BUFFER_DESC」を参照) がバッファー内のデータを構成する方法、パイプラインからバッファーにアクセする方法、およびバッファーの使用方法を定義するために使われます。
位置とカラー値を含む頂点を使って、1 つの三角形のバッファー記述を作成する例を次に示します。
struct SimpleVertex { D3DXVECTOR3 Position; D3DXVECTOR3 Color; }; D3D10_BUFFER_DESC bufferDesc; bufferDesc.Usage = D3D10_USAGE_DEFAULT; bufferDesc.ByteWidth = sizeof( SimpleVertex ) * 3; bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0;
この例では、利用フラグ、CPU アクセス フラグ、およびその他のフラグのほぼすべてを既定値を使ってバッファー記述を初期化しています。その他の設定は、頂点バッファーとなるリソースのみを識別するバインド フラグと、バッファーのサイズに使用されます。
利用フラグと CPU アクセス フラグは、パフォーマンスにとって重要です。この 2 つのフラグの併用によって、リソースがアクセスされる頻度、リソースをロードできるメモリーの種類、およびどのプロセッサがリソースにアクセスするかを決定します。既定の利用方法では、このリソースが頻繁に更新されることはありません。CPU アクセスの 0 は、CPU がリソースの読み込みや書き込みをする必要がないことを意味します。これは同時に、リソースに CPU のアクセスが必要ないため、ランタイムが GPU の最もパフォーマンスの高いメモリーにリソースをロードできることを意味しています。
当然ながら、パフォーマンスと両方のプロセッサによる常時アクセスは取捨選択する必要があります。たとえば、CPU アクセスのない既定の使用方法では、リソースを GPU のみが独占的に使用できます。これは、CPU から直接アクセスできないメモリーにリソースをロード可能なことを意味します。リソースは ID3D10Device::UpdateSubresource でのみ変更が可能です。
バッファーの初期化データの作成
バッファーは単なる要素の集合であり、1D 配列としてレイアウトされます。その結果、システム メモリーのピッチとシステム メモリー スライスのピッチは両方とも同じ (頂点の宣言データのサイズ) になります。アプリケーションは、サブリソース記述を使ってバッファーを作成する際に、実際のリソース データへのポインターおよびデータのサイズとレイアウトに関する情報を含む初期化データを提供することができます。
固定の使用方法 (「D3D10_USAGE_IMMUTABLE」を参照) で作成したバッファーは、作成時に初期化する必要があります。その他の利用フラグを使用するバッファーは ID3D10Device::CopyResource、ID3D10Device::CopySubresourceRegion、および ID3D10Device::UpdateSubresource を使って初期化した後、または ID3D10Buffer::マップ メソッドを使って基になるメモリーにアクセスすることによって更新が可能になります。
バッファーの作成
頂点バッファーを作成するには、バッファー記述と初期化データ (オプション) を使って ID3D10Device::CreateBuffer を呼び出します。次のコードは、アプリケーションによって宣言された頂点データの配列から頂点バッファーを作成する方法を示しています。
struct SimpleVertexCombined { D3DXVECTOR3 Pos; D3DXVECTOR3 Col; }; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer[2] = { NULL, NULL }; ID3D10Buffer* g_pIndexBuffer = NULL; SimpleVertexCombined verticesCombo[] = { D3DXVECTOR3( 0.0f, 0.5f, 0.5f ), D3DXVECTOR3( 0.0f, 0.0f, 0.5f ), D3DXVECTOR3( 0.5f, -0.5f, 0.5f ), D3DXVECTOR3( 0.5f, 0.0f, 0.0f ), D3DXVECTOR3( -0.5f, -0.5f, 0.5f ), D3DXVECTOR3( 0.0f, 0.5f, 0.0f ), }; D3D10_BUFFER_DESC bufferDesc; bufferDesc.Usage = D3D10_USAGE_DEFAULT; bufferDesc.ByteWidth = sizeof( SimpleVertexCombined ) * 3; bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = verticesCombo; InitData.SysMemPitch = 0; InitData.SysMemSlicePitch = 0; hr = g_pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &g_pVertexBuffer[0] );
インデックス バッファーを作成する
インデックス バッファーの作成は、2 つの違いを除いて頂点バッファーの作成と非常に似ています。インデックス バッファーは 16 ビットまたは 32 ビットのデータのみを含みます (頂点バッファーは多様なフォーマットを利用可能)。また、インデックス バッファーにはインデクス バッファー バインド フラグを必要とします。
次の例はインデックス データの配列からインデックス バッファーを作成する方法を示しています。
ID3D10Buffer *g_pIndexBuffer = NULL; // Create indices unsigned int indices[] = { 0, 1, 2 }; D3D10_BUFFER_DESC bufferDesc; bufferDesc.Usage = D3D10_USAGE_DEFAULT; bufferDesc.ByteWidth = sizeof( unsigned int ) * 3; bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = indices; InitData.SysMemPitch = 0; InitData.SysMemSlicePitch = 0; hr = g_pd3dDevice->CreateBuffer( &bufferDesc, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );
定数バッファーの作成
Direct3D 10 には、定数バッファーが新たに導入されています。定数バッファー、またはシェーダー定数バッファーはシェーダー定数を含むバッファーです。以下は HLSLWithoutFX10 サンプルの一部で、定数バッファー作成の例です。
ID3D10Buffer* g_pConstantBuffer10 = NULL; struct VS_CONSTANT_BUFFER { D3DXMATRIX mWorldViewProj; //mWorldViewProj will probably be global to all shaders in a project. //It's a good idea not to move it around between shaders. D3DXVECTOR4 vSomeVectorThatMayBeNeededByASpecificShader; float fSomeFloatThatMayBeNeededByASpecificShader; float fTime; //fTime may also be global to all shaders in a project. float fSomeFloatThatMayBeNeededByASpecificShader2; float fSomeFloatThatMayBeNeededByASpecificShader3; }; D3D10_BUFFER_DESC cbDesc; cbDesc.ByteWidth = sizeof( VS_CONSTANT_BUFFER ); cbDesc.Usage = D3D10_USAGE_DYNAMIC; cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; cbDesc.MiscFlags = 0; hr = g_pd3dDevice->CreateBuffer( &cbDesc, NULL, &g_pConstantBuffer10 ); if( FAILED( hr ) ) return hr; g_pd3dDevice->VSSetConstantBuffers( 0, 1, g_pConstantBuffer10 );
ID3D10Effect インターフェイス インターフェイスを使用すると、定数バッファーの作成、バインド、およびコミットの各プロセスは ID3D10Effect インターフェイス インスタンスで扱われます。この場合、いずれかの GetVariable メソッド (ID3D10Effect::GetVariableByName など) でエフェクトから変数を取得し、いずれかの SetVariable メソッド (ID3D10EffectMatrixVariable::SetMatrix など) で変数を更新するだけで済みます。ID3D10Effect インターフェイス を使用して定数バッファーを管理する例については、「チュートリアル 7: テクスチャー マッピングと定数バッファー」を参照してください。