创建缓冲区资源 (Direct3D 10)

创建缓冲区需要定义缓冲区将存储的数据、提供初始化数据以及设置适当的用法和绑定标志。 若要创建纹理,请参阅“创建纹理资源”(Direct3D 10)。

创建顶点缓冲区

创建 顶点缓冲区 的步骤如下所示。

创建缓冲区说明

创建顶点缓冲区时,缓冲区说明(请参阅 D3D10_BUFFER_DESC)用于定义如何在缓冲区内组织数据、管道如何访问缓冲区以及如何使用缓冲区。

以下示例演示如何为包含位置和颜色值的顶点的单个三角形创建缓冲区说明。

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 访问标志对于性能非常重要。 这两个标志共同决定了资源访问的频率、可以加载到的资源类型以及访问资源所需的处理器。 此资源的默认使用情况不会非常频繁地更新。 将 CPU 访问设置为 0 意味着 CPU 不需要读取或写入资源。 结合使用,这意味着运行时可以将资源加载到 GPU 的性能最高的内存中,因为资源不需要 CPU 访问。

如预期所示,任何一个处理器在最佳性能和任何时间辅助功能之间都有利弊。 例如,没有 CPU 访问权限的默认用法意味着资源可以独占提供给 GPU。 这可能包括将资源加载到 CPU 无法直接访问的内存中。 只能使用 UpdateSubresource 修改资源。

为缓冲区创建初始化数据

缓冲区只是元素的集合,并作为 1D 数组布局。 因此,系统内存间距和系统内存切片间距相同:顶点数据声明的大小。 使用 子资源说明创建缓冲区时,应用程序可以提供初始化数据,该说明包含指向实际资源数据的指针,并包含有关该数据的大小和布局的信息。

使用不可变用法创建的任何缓冲区(请参阅 D3D10_USAGE_IMMUTABLE)必须在创建时初始化。 使用任何其他使用标志的缓冲区可以在使用 CopyResource、CopySubresourceRegion UpdateSubresource 初始化后更新,或者通过使用 Map 方法访问其基础内存。

创建缓冲区

使用缓冲区说明和初始化数据(可选)调用 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] );

创建索引缓冲区

创建索引缓冲区与创建顶点缓冲区非常相似;有两个差异。 索引缓冲区仅包含 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 接口实例处理。 在这种情况下,只需使用 GetVariableByName GetVariable 方法之一从效果中获取变量,并使用 SetMatrixSetVariable 方法之一更新变量。 有关使用 ID3D10Effect 接口 管理常量缓冲区的示例,请参阅 教程 7:纹理映射和常量缓冲区

资源 (Direct3D 10)