Practical Rendering and Computation with Direct3D 11
+ -

2.2.1缓冲区资源-字节地址缓冲区

2024-06-17 3 0

字节地址缓冲区旨在允许开发人员在缓冲区资源中实现自定义数据结构。根据定义,内存块的使用可以由与之结合的算法进行解释。例如,如果链表数据结构将用于存储32位颜色值的列表,则每个链接节点将由一个颜色值和一个到下一个元素的链接组成。当添加第一个元素时,颜色值在偏移量0处写入内存位置,并且到下一个元素的链接被初始化为-1,因为下一个元件尚未添加。当另一个元素要添加到列表中时,HLSL程序将开始索引位置0处的内存,并读取两个32位的数据元素——一个用于颜色值,另一个用于到下一个元素的链接。如果链接设置为-1,则程序已找到列表的尾部,并可以在末尾添加另一个元素。

有了这些基本的链表,程序可以像传统的基于CPU的程序一样插入或删除节点。这提供了一种完全通用的方法——创建字节地址缓冲区。创建字节地址缓冲区的过程与我们在前面的缓冲区类型中看到的过程非常相似。它还必须指示它将用于的使用场景,以及它将在什么位置与管道绑定以使用GPU内的资源。然而,GPU的并行性也会给这些资源的使用带来一些复杂性。由于内存访问模式是由HLSL程序定义的,因此有必要确保在多个执行线程之间以一致和安全的方式访问内存。我们将在第5章“计算管道”中讨论这种类型的同步的细节,但开发人员可以使用一系列技术来确保对资源的线程安全访问。
104955423508

创建字节地址缓冲区

创建字节地址缓冲区的过程与我们在前面的缓冲区类型中看到的过程非常相似。它还必须指示它将用于的使用场景,以及它将在哪些位置使用绑定标志绑定到管道。还必须使用D3D11_RES0URCE_MISC_buffer_ALLOW_RAW_VIEWS杂项标志创建字节地址缓冲区。

lD3DHBuffer* CreateRawBuffer( UINT size,bool GPUWritable,D3D11_SUBRES0URCE_DATA* pData )
{
    D3D11_BUFFER_DESC desc;
    desc.ByteWidth = size;
    desc.MiscFlagS = D3D11_RES0URCE_MISC_BUFFER_ALL0W_RAW_VIEWS;
    desc.StructureByteStride = 0;
    // Select the appropriate usage and CPU access flags based on the passed
    // in flags
    desc.BindFlags = D3D11_BIND_SHADER_RES0URCE | D3D11_BIND_UN0RDERED_ACCESS;
    desc.Usage = D3D11_USAGE_DEFAULT;
    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 );
}

资源视图要求

字节地址缓冲区可以以两种不同的方式使用。它可以通过着色器资源视图附加到管道,以只读方式访问缓冲区,也可以通过无序访问视图附加到管线,以提供对缓冲区的读写访问。虽然着色器资源视图提供只读访问,但它可用于所有可编程着色器阶段。无序访问视图仅在计算和像素着色器阶段可用。在这两种情况下,资源视图的格式都必须是DXGI_FORMAT_R32_TYPELESS。使用无序访问视图时,还必须使用D3D11_BUFFER_UAV_FLAG_RAW创建该视图,以指示它将提供对数据的访问作为字节地址缓冲。

HLSL byte address buffer objects

一旦创建了缓冲区,并且适当的资源视图可用于将资源绑定到管道,HLSL程序就必须声明适当的资源对象以与缓冲区交互。可以声明两个不同的对象,每个对象都对应于HLSL代码对资源的访问类型。如果缓冲区绑定到具有shadersource视图的管道,则相应的HLSL对象将声明为ByteAddressBuffer。如果它绑定到具有无序访问视图的管道,则相应的HLSL对象将被声明为RWByteAddressBuffer。清单2.17中提供了这些字节地址缓冲区类型声明的示例。

ByteAddressBuffer rawBufferl
RWByteAddressBuffer rawBuffer2j

通常,这些对象的方法需要一个地址来指定缓冲区中执行给定操作的位置。这些地址必须是4位对齐的,并且始终使用uint数据类型。如果需要其他数据类型,则可以使用其中一种转换内在方法重新解释返回的数据。这两个对象都支持可用于从缓冲区资源中检索数据的各种Load方法,并且一次最多可以读取四个32位内存位置。然而,读/写字节地址缓冲区也提供了大量用于操作缓冲区内容的方法。除了用于从多个线程同时更新资源的大量原子指令之外,还有与Load方法类似的简单Store。

0 篇笔记 写笔记

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

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

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