在HLSL中使用一个包含所有相关数据或几个较小缓冲区的大缓冲区更好

A. *_*ats 4 directx shader hlsl directx-11

如果在使用HLSL或其他高级着色器语言将数据发送到GPU时,如果有一个单独的缓冲区,我对代码设计和性能方面感兴趣.

这是特定着色器需要具有大量可变数据的地方,这些数据在运行时期间会发生变化,因此需要通过缓冲区传递信息.

我举一个非常基本的例子:

cbuffer SomeLargeBuffer : register(cb0)
{
    float3 data;
    float someData;
    float4 largeArray[2500];
    float moreData;
    ...
    ...
    ... 
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

或者拥有

cbuffer SamllerBuffer: register(cb0)
{
    float3 data;
    float someRelatedData;

}

cbuffer SecondSmallerBuffer : register(cb1)
{

    float4 largeArray[2500];
    float moreData;

}

cbuffer ThirdBuffer: register(cb2)
{
    ...
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

Mue*_*ito 5

在效率方面,HLSL中着色器常量文档提供了以下建议:

有效使用常量缓冲区的最佳方法是根据更新频率将着色器变量组织到常量缓冲区中.这允许应用程序最小化更新着色器常量所需的带宽.例如,着色器可能会声明两个常量缓冲区,并根据其更新频率组织每个缓冲区中的数据:需要基于每个对象更新的数据(如世界矩阵)被分组到一个常量缓冲区中,该缓冲区可能是为每个对象更新.这与表征场景的数据是分开的,因此可能更不频繁地更新(当场景改变时).

因此,如果您以不同的速率更新数据,最好将在同一频率下更新的所有数据分组到相同的常量缓冲区中.通常,数据要么更新a)每一帧,b)零星地或c)从不(一次启动时).减少总常量缓冲区的数量也有助于提高性能,因为它将减少绑定调用的数量和所需的资源跟踪.

在代码设计方面,很难说,尽管通常它很适合更新频率模式.

  • 最初的Direct3D 10常量缓冲区设计是每次更改整个CB时都会更新整个CB,因此最好按更新频率组织它们,以避免一遍又一遍地上传相同的数据.使用支持可选功能的Windows 8或更高版本的DirectX 11.1,您可以更有效地为效果系统执行部分常量缓冲区更新,以便更好地使用更大的"全局样式"CB. (2认同)