如何使用着色器常量缓冲区?

时间:2013-04-09 09:42:20

标签: directx shader hlsl

我很难理解DirectX中的常量缓冲区。我见过两种语法

float4 myVar;

在着色器文件的顶级声明

cbuffer myBuffer
{
    float4 myVar;
}

详见http://msdn.microsoft.com/en-gb/library/windows/desktop/bb509581(v=vs.85).aspx

我知道需要将常量缓冲区分配给插槽(从零开始索引),并且可以在代码中设置。

我看过的两个框架(SlimDX与SharpDX)似乎使用不同的约定来设置它们 - SlimDX按字符串名称(通过着色器反射?)和SharpDX按插槽编号 - 虽然不清楚插槽号在哪里从?

获得

任何人都可以了解两种语法之间的区别,如果它们实际上是不同的,如何将槽号分配给.fx文件中的声明以及如何在着色器之间共享槽号?

任何帮助表示赞赏

3 个答案:

答案 0 :(得分:10)

使用原始Direct3D10 / Direct3D11 API(通过Direct3D10.Device.XXX.SetConstantBuffers和Direct3D11.DeviceContext.XXX.SetConstantBuffers)时,SharpDX和SlimDX都使用相同的约定。

如MSDN文档中的链接“默认常量缓冲区”中所述,解释了未在常量缓冲区内定义的变量将在名为“$ Global”的默认全局常量缓冲区中结束。

另一方面,传统效果框架(与RAW Direct3D10 + API交互)通过其名称提供对单个变量的访问。在内部,他们使用ShaderReflection查询Constant Buffers的内容,并自动处理这些常量缓冲区的分配/更新/上传。最后,这是将上传到GPU的常量缓冲区,而不是单个变量(不存在于常量缓冲区之外)。传统效果框架通过使用ShaderReflection查询绑定槽来动态处理绑定常量缓冲区的槽。

插槽编号由编译器在编译时分配。如果未明确指定寄存器(请参阅MSDN文档中的cbuffer寄存器),编译器将影响第一个使用的cbuffer的可用插槽。除非您明确设置寄存器,否则无法保证编译器会影响着色器之间相同常量缓冲区的相同插槽。

答案 1 :(得分:1)

第一种语法:

float4 myVar;

是Microsoft的效果语法,其中第二个是直接的hlsl。效果语法通过自动为您分配常量缓冲区来简化一些事情,但这是以灵活性为代价的。

使用SharpDX,您可以为插槽1分配一个常量缓冲区,如下所示:

cbuffer myBuffer: register(b1)
{
    float4 myVar;
}

答案 2 :(得分:0)

您引用的文档适用于纯D3D着色器模型API。您需要查阅每个中间件(SlimDX或SharpDX)以了解其语法与底层映射之间的对应关系。

我认为任何第三方发行版都可以完全自由地定义自己的语法(并且它可以以任何过于复杂的方式实现),但这是你必须接受的。您需要查阅每个第三方供应商的相应文档以了解映射,因为详细信息也可能因版本而异。如果源代码可用,您可以检查它以自己理解映射。考虑到某些框架的“黑盒”性质,您可能只需要接受框架的文档 - 在这种情况下,引用规范/基础库文档将是错误或抽象泄漏。

最后一个问题是:你为什么关心实施/制图?这些库的重点是以方便的方式抽象出细节。就个人而言,我可以看出为什么这可能令人沮丧(特别是如果你出于某种原因使用规范文档而不是平台),但是你支付的相关成本是选择这样一个平台代替使用核心的结果/权衡图书馆直接。