【发布时间】:2016-04-25 19:44:06
【问题描述】:
我有一个 HLSL 着色器,它定义了一些资源,比如一个常量缓冲区:
cbuffer MyCB : register(b0);
如果我编译我的着色器,我将能够通过反射 API 查询寄存器。但是是否可以更改已编译着色器 blob 中的寄存器(例如,更改为 b3),就像在已编译的 OpenGL 程序中为资源分配绑定点一样?
【问题讨论】:
标签: c++ direct3d direct3d11 direct3d12
我有一个 HLSL 着色器,它定义了一些资源,比如一个常量缓冲区:
cbuffer MyCB : register(b0);
如果我编译我的着色器,我将能够通过反射 API 查询寄存器。但是是否可以更改已编译着色器 blob 中的寄存器(例如,更改为 b3),就像在已编译的 OpenGL 程序中为资源分配绑定点一样?
【问题讨论】:
标签: c++ direct3d direct3d11 direct3d12
没有 API 可以在运行时更改已编译着色器中的着色器绑定。
如果您跳过了很多困难,您也许可以在 Shader Model 5.0 中使用 dynamic shader linking 来实现这一点,尽管这将是很多工作而且并不值得,当有一个非常简单的替代方案时 - 只需创建一个具有所需绑定的新编译着色器。
【讨论】:
您可以在direct3d12 中通过在D3D12_DESCRIPTOR_RANGE 结构中指定除零以外的BaseShaderRegister 或使用不同的RegisterSpace 值来完成此操作。如果代码更改不可行,您可以通过设置根参数的ShaderVisibility 属性隐式隔离每组寄存器。例如,这将隔离 VS b0 与 PS b0。更多详情,您可以查看该主题的developer video。
唯一遇到麻烦的情况是,如果您实际上已将两个资源显式绑定到同一个插槽和寄存器空间(通过使用着色器模型 5.1 语法显式指定它)。在这种情况下,您应该了解,在 D3D12 中,寄存器是跨阶段共享的,您需要确保没有冲突。
在 D3D11 中,不会发生此问题,因为每个阶段都有自己的寄存器空间(VS b0 与 PS b0 不同)并且您不能即使你想分享。尽管如此,如果您出于某种原因有一个硬编码的组件来将数据附加到 VS b0 但您的顶点着色器已经编译为在 b1 上期待它,那么您无能为力。
【讨论】:
cbuffer CBinVS : register(b0,space0); 和cbuffer CBinPS : register(b0,space1);,那将解决我的问题。我所拥有的是带有我可能发生冲突的寄存器绑定的源代码。我想知道我是否可以通过编程方式纠正此类冲突而不更改源代码。
SHADER_VISIBILITY 属性来隔离着色器阶段,这些阶段独立于寄存器空间。我会更新我的答案。