directx - 常量缓冲区和只读结构化缓冲区有什么区别?
问题描述
我想知道最好使用哪种资源类型,以便为静态数据保存尽可能多的元素,并且在绘图调用期间不会更改。常量缓冲区和只读结构化缓冲区之间的唯一区别是常量缓冲区数据必须在其ID3D12Resource
对象内部对齐 256 个字节。
lights.hlsl
#define as_many_as_possible 1000
struct light
{
float3 position;
float falloff_start;
float3 direction;
float falloff_end;
float3 color;
float3 strenght;
};
struct light_data
{
light lights [as_many_as_possible];
};
ConstantBuffer<light_data> cb_lights : register(b0);
// Versus
StructuredBuffer<light> sb_lights : register(s0);
如果我的目标是保存尽可能多的灯光数据,那么哪个更好?
解决方案
常量缓冲区和结构化缓冲区之间存在更多差异。
在常量缓冲区中,只能同时看到 64k 的数据,因此您不能在着色器中同时看到 1mb 的数据,而在结构化缓冲区中却可以。
常量缓冲区比结构化缓冲区具有更复杂的对齐规则,您的示例实际上非常适合它:
在结构化缓冲区的情况下,您的轻量结构的大小为:
struct light
{
float3 position; /12
float falloff_start; /4 -> 16
float3 direction; /12 -> 28
float falloff_end; /4 -> 32
float3 color; /12 -> 44
float3 strenght; /12 -> 56
};
因此,您的数据将被解释为 56 字节结构的数组。
但是,常量缓冲区结构对齐需要 16 个字节,因此您的结构将被解释为:
struct light
{
float3 position; /12
float falloff_start; /4 -> 16
float3 direction; /12 -> 28 (not 16 byte boundary crossing)
float falloff_end; /4 -> 32
float3 color; /12 -> 44 (no 16 byte boundary crossing)
float pad; /4 -> 48 (float3 would cross 16 boundary)
float3 strenght; /12 -> 60
float pad2; /4 ->64 (next float3 would cross 16 boundary, which is the next position in the array, there is no end padding for the last element of the array however)
所以你的灯将是 64 字节(需要匹配你的 cpu 结构,否则你的数据将不匹配)。
在某些硬件上,由于这些限制,在常量缓冲区与结构化缓冲区的情况下,读取访问可以得到更好的优化。这取决于许多因素(例如,着色器中的读取频率),因此您需要进行分析以查看用例中的差异。
此外,出于性能原因(在结构化缓冲区的情况下),一些供应商(如 NVidia)建议结构应与 16 字节边界对齐,因此在您的情况下,结构将是:
struct light
{
float3 position; /12
float falloff_start; /4 -> 16
float3 direction; /12 -> 28
float falloff_end; /4 -> 32
float3 color; /12 -> 44
float3 strenght; /12 -> 56
float2 _pad;
};
推荐阅读
- swift - 以编程方式添加具有自动布局的 uibutton
- python-3.x - 反转一系列数字的输出
- javascript - 我似乎无法理解这个
- javascript - 尝试在 AlanJuden.MvcReportViewer 中使用 Find (Hightlight) - asp.net.core
- android - PyQt5 到 android 与 pyqtdeploy
- python - 带小数点的 map 和 flatMap 的行为
- android - 来自非技术业务用户的问题:手机存储与云存储
- r - 合并包含空 NA 值的多个列
- javascript - plotly.js:如果所有值都为 0,为什么要计算面积?
- javascript - FirebaseError:函数 Query.where() 需要有效的第三个参数,但未定义