5

我正在努力理解 DirectX 中的常量缓冲区。我见过两种语法

float4 myVar;

在着色器文件的顶层声明,并且

cbuffer myBuffer
{
    float4 myVar;
}

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

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

我看过的两个框架(SlimDX vs SharpDX)似乎使用不同的约定来设置它们 - SlimDX 通过字符串名称(通过着色器反射?)和 SharpDX 通过插槽号 - 尽管不清楚插槽号是从哪里获得的?

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

任何帮助表示赞赏

4

3 回答 3

11

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

如 MSDN 文档的链接中所述,“默认常量缓冲区”部分,说明未在常量缓冲区内定义的变量将最终出现在名为“$Global”的默认全局常量缓冲区中。

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

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

于 2013-04-09T12:43:04.123 回答
1

第一种语法:

float4 myVar;

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

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

cbuffer myBuffer: register(b1)
{
    float4 myVar;
}
于 2013-04-17T14:25:06.090 回答
0

您引用的文档适用于纯 D3D 着色器模型 api。您需要咨询每个单独的中间件(SlimDX 或 SharpDX)以了解它们的语法和底层映射之间的对应关系。

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

最后一个问题是:你为什么关心实现/映射?这些库的全部意义在于以一种方便的方式抽象出细节。就个人而言,我可以理解为什么这可能令人沮丧(特别是如果您出于任何原因求助于规范文档而不是平台的文档),但是您支付的相关成本是选择这样一个平台而不是使用核心的结果/权衡图书馆直接。

于 2013-04-09T09:53:25.647 回答