Practical Rendering and Computation with Direct3D 11
+ -

2.2.1缓冲区资源-间接参数缓冲区Indirect Argument Buffers

2024-06-17 4 0

最后一个缓冲区配置是间接参数缓冲区。正如我们将在本书的许多案例中看到的那样,Direct3D11已经采取了许多步骤,使GPU更加有用,并且能够独立操作。间接参数缓冲区就是其中一个步骤。它用于从资源中为渲染和计算管道调用方法提供参数,而不是由主机程序直接传递这些参数。允许这种类型的流水线控制背后的概念是允许GPU在一个执行过程中生成所需的几何体或输入数据资源,然后在接下来的过程中处理或渲染该数据,而CPU不知道正在处理多少基元。尽管CPU必须仍然启动管道执行并传递间接参数缓冲区引用,但这种情况将CPU的角色简化为GPU传递之间的简单代理。

使用间接参数缓冲区

间接参数缓冲区可以用于几种不同的管道执行方法。我们还没有详细介绍管道执行,但我们仍然可以在不了解每个参数的含义的情况下讨论这些缓冲区是如何操作的。下面列出了可用的间接参数管道执行方法。

DrawInstancedIndirect( ID3D11 Buffer *pBufferForArgs,UINT AlignedByteOffsetForArgs)

Drawlndexedlnstancedlndirect( ID3D11 Buffer *pBufferForArgs,UINT AlignedByteOffsetForArgs)

Dispatchlndirect( ID3D11 Buffer *pBufferForArgs, UINT AlignedByteOffsetForArgs)

这些方法中的每一个都在其中一个标准方法的末尾附加间接项,并简单地将方法的参数替换为对缓冲区资源的引用和缓冲区中的偏移量,缓冲区用于标识参数在其中的位置。例如,标准DrawInstance()方法采用四个uint参数:VertexCountPerlnstance、InstanceCount、StartVertexLocation和StartInstanceLocation。这些参数在API调用中直接传递,以指示运行时和驱动程序要绘制什么以及需要什么选项。DrawInstancedIndirect()方法将这些值传递给ffer资源中的运行时和驱动程序,而不是直接传递。要做到这一点,应用程序必须确保缓冲区中与缓冲区引用一起传递的偏移量参数所指示的位置存储有四个连续的uint值。在这些方法中包含一个偏移量参数,可以将单个缓冲区用于许多不同的管道调用,并可以将参数同时存储在不同的位置。图2.20显示了该方案的运作方式。同样重要的是要注意,进入缓冲区的偏移量必须是4字节对齐的,以允许各个值跨越标准的32位变量大小。

有很多方法可以更新间接参数缓冲区中的数据。可以使用任何流水线输出方法或CPU操作技术。只要缓冲区中的数据可用,就可以用来执行管道。例如,一种可能性是使用计算着色器中的AppendStructuredBufferresource类型来填充一些GPU生成的内容。缓冲区中的项数可以使用ID3DllDeviceContext::CopyStructureCount()方法复制到间接参数缓冲区,并且最终可以使用提供了单个实例的ID3DllDevices Context::DrawInstancedIndirect()方法绘制几何体。这将允许GPU在AppendStructuredBuffer中生成的内容直接渲染,而CPU永远不知道缓冲区中有多少项.
105742591420

创建用间接参数缓冲区

创建间接参数缓冲区与我们以前看到的其他创建方法非常相似。它还遵循我们所看到的相同的usagecontrol语义。通常,如果我们希望能够在GPU上生成数据,然后使用缓冲区作为管道的输入,我们必须选择默认使用标志来提供对GPU的读写访问。此外,为了向运行时指示此缓冲区将用于间接参数,必须指定3DS11_RES0URCE_MISC_DRAWINDIRECT_ARGS杂项标志。ByteWidth参数应该是4字节的倍数,因为draw和dispatch方法的输入参数都是32位变量。

ID3DllBuffer* CreateIndirectArgsBuffer( UINT size, D3D11_SUBRES0URCE_DATA* pData )
{
    D3D11_BUFFER_DESC desc;
    desc.ByteWidth = size;
    desc.MiscFlagS = D3Dll_RES0URCE_MISC_DRAWINDIRECT_ARGS;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.StructureByteStride = 0;
    desc.BindFlags = 0;
    desc.CPUAccessFlags = 0;
    // Create the buffer with the specified configuration
    ID3DllBuffer* pBuffer = 0;
    HRESULT hr = g_pDevice->CreateBuffer( &desc, pData, &pBuffer );
    if ( FAILED( hr ) )
    {
    // Handle the error here...
    return( 0 );
    }
    return( pBuffer );
}

资源视图要求

间接参数缓冲区用于两个不同的阶段。首先,它由GPU或CPU加载数据,这些数据最终将表示管道调用的参数。其次,它被CPU作为输入传递给draw/dispatch调用。第一种情况可能需要资源视图,而第二种情况则不需要。

当GPU要填充缓冲区时,可以使用流输出功能对其进行更新,将其写入渲染目标,或使用无序访问视图对其进行修改。如果缓冲区将由CPU更新,则可以使用修改其内容的标准方法之一,如ID3D11DeviceContext::UpdateSubresource()方法,或使用ID3D11Device Context::CopyStructureCount()方法更新以从缓冲区读取隐藏的计数器值。一般来说,在第2章和第3章的各自领域中讨论了这些向小丑写作的技巧,这里不再赘述。但是,如果可以将数据放入缓冲区,则可以随后使用它来执行管道

HLSL indirect argument buffer objects.

间接参数缓冲区用作管道执行方法的输入,因此不会直接在HLSL中使用。如上所述,有多种方法可以将参数数据放入缓冲区,其中一些方法需要资源视图,并且必须直接从HLSL写入,而另一些方法则不需要。所使用的特定技术将决定是否可以通过HLSL资源对象将数据写入缓冲区

0 篇笔记 写笔记

作者信息
站长漫谈
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!