输入-汇编程序阶段入门

初始化输入-汇编程序 (IA) 阶段需要执行几个步骤。 例如,需要使用管道所需的顶点数据创建缓冲区资源,告诉 IA 阶段缓冲区的位置及其包含的数据类型,并指定要从数据中组装的基元的类型。

本主题介绍了设置 IA 阶段所涉及的基本步骤,如下表所示。

步骤 说明
创建输入缓冲区 使用输入顶点数据创建和初始化输入缓冲区。
创建输入布局对象 定义如何使用输入布局对象将顶点缓冲区数据流式传输到 IA 阶段。
将对象绑定到输入-汇编程序阶段 将创建的对象(输入缓冲区和输入布局对象)绑定到 IA 阶段。
指定基元类型 确定顶点将如何组合到基元中。
调用绘制方法 通过管道发送绑定到 IA 阶段的数据。

 

了解这些步骤后,请继续使用系统生成的值

创建输入缓冲区

有两种类型的输入缓冲区:顶点缓冲区和索引缓冲区。 顶点缓冲区向 IA 阶段提供顶点数据。 索引缓冲区是可选的,它们从顶点缓冲区向顶点提供索引。 你可以创建一个或多个顶点缓冲区,还可以选择创建索引缓冲区。

创建缓冲区资源后,需要创建一个输入布局对象来描述 IA 阶段的数据布局,然后需要将缓冲区资源绑定到 IA 阶段。 如果着色器不使用缓冲区,则不需要创建和绑定缓冲区。 有关绘制单个三角形的简单顶点和像素着色器的示例,请参阅《使用无缓冲区的输入装配器阶段》。

有关创建顶点缓冲区的帮助,请参阅《如何创建顶点缓冲区》。 有关创建索引缓冲区的帮助,请参阅《如何创建索引缓冲区》。

创建输入-布局对象

输入-布局对象封装了输入汇编程序 (IA) 阶段的输入状态。 这包括绑定到 IA 阶段的输入数据的说明。 数据流式传输到内存中的 IA 阶段,从一个或多个顶点缓冲区传输。 说明会标识从一个或多个顶点缓冲区绑定的输入数据,并使运行时能够针对着色器输入参数类型检查输入数据类型。 此类型检查不仅会验证类型是否兼容,还会验证着色器所需的每个元素在缓冲区资源中是否都可用。

输入-布局对象是从输入元素说明数组和指向已编译着色器的指针创建的(请参阅 ID3D11Device::CreateInputLayout)。 该数组包含一个或多个输入元素;每个输入元素描述一个顶点缓冲区中的一个顶点数据元素。 整个输入元素说明集描述了将绑定到 IA 阶段的所有顶点缓冲区中的所有顶点数据元素。

以下布局说明描述了包含 4 个顶点数据元素的顶点缓冲区。

D3D11_INPUT_ELEMENT_DESC layout[] =
{
    { L"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, 
          D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { L"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, 
          D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { L"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, 
          D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

输入元素说明描述了顶点缓冲区中单个顶点包含的每个元素,包括大小、类型、位置和用途。 每一行使用语义、语义索引和数据格式标识数据类型。 语义是一个文本字符串,用于标识数据的使用方式。 在此示例中,第一行标识 3 分量位置数据(例如 xyz);第二行标识 2 分量纹理数据(例如 UV);第三行标识正常数据。

在此输入元素说明示例中,所有三行的语义索引(即第二个参数)均设置为零。 语义索引有助于区分使用相同语义的两行。 由于此示例中没有类似的语义,因此语义索引可以设置为其默认值零。

第三个参数是“格式”。 格式(请参阅 DXGI_FORMAT)指定每个元素的组件数,以及用于定义每个元素的数据大小的数据类型。 可以在创建资源时完全输入格式,也可以使用标识元素中的组件数的 DXGI_FORMAT 创建资源,但未定义数据类型。

输入槽

数据通过称为输入槽的输入进入 IA 阶段,如下图所示。 IA 阶段具有 n 个输入槽,旨在容纳最多 n 个提供输入数据的顶点缓冲区。 必须将每个顶点缓冲区分配给不同的槽。创建输入布局对象时,此信息将存储在输入布局声明中。 你还可以指定每个缓冲区的起始位置和要读取的缓冲区中第一个元素的偏移量。

illustration of the input slots for the ia stage

接下来的两个参数是“输入槽”和“输入偏移量”。 使用多个缓冲区时,可以将它们绑定到一个或多个输入槽。 输入偏移量是缓冲区开始位置和数据开头之间的字节数。

重用输入布局对象

每个输入布局对象都基于着色器签名创建。这允许 API 根据着色器输入签名验证输入布局对象元素,以确保类型和语义完全匹配。 可以为许多着色器创建单个输入布局对象,只要所有着色器输入签名完全匹配。

将对象绑定到输入-汇编程序阶段

创建顶点缓冲区资源和输入布局对象后,可以通过调用 ID3D11DeviceContext::IASetVertexBuffersID3D11DeviceContext::IASetInputLayout,将它们绑定到 IA 阶段。 以下示例演示单个顶点缓冲区和输入布局对象到 IA 阶段的绑定:

UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pd3dDevice->IASetVertexBuffers( 
    0,                // the first input slot for binding
    1,                // the number of buffers in the array
    &g_pVertexBuffer, // the array of vertex buffers
    &stride,          // array of stride values, one for each buffer
    &offset );        // array of offset values, one for each buffer

// Set the input layout
g_pd3dDevice->IASetInputLayout( g_pVertexLayout );

绑定输入布局对象只需要指向对象的指针。

在前面的示例中,绑定了单个顶点缓冲区,但是,你可以通过对 ID3D11DeviceContext::IASetVertexBuffers 的单个调用绑定多个顶点缓冲区,并且以下代码显示绑定三个顶点缓冲区的此类调用:

UINT strides[3];
strides[0] = sizeof(SimpleVertex1);
strides[1] = sizeof(SimpleVertex2);
strides[2] = sizeof(SimpleVertex3);
UINT offsets[3] = { 0, 0, 0 };
g_pd3dDevice->IASetVertexBuffers( 
    0,                 //first input slot for binding
    3,                 //number of buffers in the array
    &g_pVertexBuffers, //array of three vertex buffers
    &strides,          //array of stride values, one for each buffer
    &offsets );        //array of offset values, one for each buffer

索引缓冲区通过调用 ID3D11DeviceContext::IASetIndexBuffer 绑定到 IA 阶段。

指定基元类型

绑定输入缓冲区后,必须告知 IA 阶段如何将顶点组装到基元中。 为此,可通过调用 ID3D11DeviceContext::IASetPrimitiveTopology 指定基元类型。以下代码会调用此函数将数据定义为不相邻的三角形列表:

g_pd3dDevice->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

基元类型的其余部分列在 D3D_PRIMITIVE_TOPOLOGY 中。

调用绘制方法

将输入资源绑定到管道后,应用程序会调用绘图方法来呈现基元。 下表显示了几个绘制方法:一些使用索引缓冲区,一些使用实例数据,还有一些使用流输出阶段中的数据作为输入-汇编程序阶段的输入。

绘制方法 说明
ID3D11DeviceContext::Draw 绘制非索引的非实例化基元。
ID3D11DeviceContext::DrawInstanced 绘制非索引的实例化基元。
ID3D11DeviceContext::DrawIndexed 绘制索引的非实例化基元。
ID3D11DeviceContext::DrawIndexedInstanced 绘制索引的实例化基元。
ID3D11DeviceContext::DrawAuto 根据来自流输出阶段的输入数据绘制非索引的非实例化基元。

 

每个绘制方法都呈现单个拓扑类型。 在呈现期间,不完整的基元(没有足够顶点、缺少索引、部分基元等的基元)将无提示地被消除。

输入装配器阶段