是否存在DirectX指南,用于在绘制调用之间绑定和解除绑定资源?

 黄于諭春琪 发布于 2023-02-13 17:32

所有DirectX书籍和教程都强烈建议将绘制调用之间的资源分配减少到最低限度 - 但我找不到任何可以深入了解细节的指南.回顾网上发现的大量示例代码,我得出结论,程序员对此主题有完全不同的编码原则.有些甚至设置和取消设置

VS/PS 
VS/PS ResourceViews
RasterizerStage 
DepthStencilState
PrimitiveTopology
... 

每次绘制调用之前和之后(虽然设置保持不变),而其他人则没有.

我猜这有点过头了......

从我自己的实验,我发现,我不得不在每次绘制调用绑定的唯一资源是ShaderResourceViews(以VSPS在我的情况).此要求可能是由于使用计算着色器引起的,因为我绑定/取消绑定UAVs到绑定到VS/ PS稍后的缓冲区.

在我发现这种重新绑定是必要的之前,我已经失去了许多小时的工作.而且我想许多程序员也不确定,并且更愿意解开并重新绑定"有点太多"而不是陷入类似的陷阱.

问题1:关于这个问题至少有一些经验法则吗?

问题2:我的ShaderResourceViews绑定是否可能VS/PS被驱动程序/ DirectX核心解除绑定,因为我UAVs 在CS调度调用之前绑定了相同的缓冲区(我没有解除绑定SRVs自己)?

问题3:VS/PS在使用计算着色器之前,我甚至没有设置为null.没有问题的工作但我总是不确定我是否正在使用这种"懒惰"的方法挖掘我的下一个陷阱.

1 个回答
  • 您希望减少开销,同时避免无效的管道状态.这就是为什么有些人解开所有东西(尽量防止),这取决于用例,当然你可以平衡这一点.

    为了平衡这一点,您可以根据资源类型预先为插槽分配特定资源,因为您有不同数量的插槽,可以应用不同的规则

    1 /取样器和国家

    您有16个插槽,通常在90%的时间内使用4-5个采样器(线性/点/各向异性/阴影).

    因此,在应用程序启动时,创建这些状态并将它们绑定到您需要的每个着色器阶段(尽量不要从零槽开始,因为它们很容易被错误地覆盖).使用映射SamplerState - > slot创建着色器头文件,并在着色器中使用它,以便自动反映任何插槽更新.

    尽可能多地重用它,并且仅绑定自定义采样器.

    对于标准状态(Blend/Depth/Rasterizer),在应用程序启动时构建一小组常见状态并根据需要绑定是常见做法.

    以低成本最小化渲染状态绑定的简单方法,您可以构建堆栈,因此您设置默认状态,并且如果着色器需要更具体的状态,它可以将新状态推送到堆栈,一旦完成,最后弹出陈述并再次将其应用于管道.

    2 /恒定缓冲区

    你有14个插槽,这是非常多的,非常罕见(至少在我的用例中)使用它们,特别是现在你也可以使用缓冲区/结构化缓冲区.

    一个简单的常见情况是为摄像机设置一个保留的插槽(包含您需要的所有数据,视图/投影/视图投影,以及它们可能也需要它们的反转.

    将它绑定到(如果需要的话)着色器阶段插槽,你只需要每帧更新你的cbuffer,它随时可以在任何地方使用.

    3 /着色器阶段

    你几乎不需要取消绑定Compute Shader,因为它与管道完全分开.

    另一方面,对于管道阶段而言,一个相当好的做法是设置你需要的所有东西,而不是解绑定,而不是解绑定.

    如果您不按照此示例并渲染阴影贴图(仅限深度缓冲区),则可能仍会绑定像素着色器.

    如果您忘记取消先前使用的几何着色器,则最终可能会出现无效的布局组合,并且您的对象将无法渲染(错误仅在运行时调试模式下显示).

    因此,设置完整的着色器阶段会增加很少的开销,但安全性的折衷远非可以忽略不计.

    在您的使用案例中(仅使用VS/PS和CS构建),您可以放心地忽略它.

    4 /无人机-RenderTargets-DepthStencil

    对于写入资源,在完成工作单元时总是不设置.在同一例程中,您可以在内部进行优化,但在渲染/计算着色器函数结束时,将输出设置回null,因为管道将不允许任何内容在输出时作为ShaderResource反弹.

    在功能结束时不要取消写入资源是灾难的秘诀.

    5/ShaderResourceView

    这是非常情境化的,但想法是尽量减少同时也避免运行时警告(这可能是无害的,但随后隐藏重要的消息).

    最后一件事是在帧的开头重置为空所有着色器资源输入,以避免在VS中绑定的缓冲区被设置为CS中的UAV,例如,这会花费您每帧6个管道调用,但它通常是值得的它.

    如果你有足够的备用寄存器和一些常量资源,你当然也可以在一些保留的插槽中设置它们并一劳永逸地绑定它们.

    6/IA相关资源

    对于这个,您需要设置正确的数据来绘制几何体,因此每次绑定它时,设置InputLayout/Topology都是非常合理的.您当然可以组织绘制调用以最小化切换.

    我认为拓扑对于正确设置至关重要,因为无效拓扑(例如,使用带有包括细分的管道的三角形列表)将不会得到任何内容并给你一个运行时警告,但在AMD卡上它会很常见崩溃你的驱动程序,所以最好避免它,因为它变得很难调试.

    通常从不真正取消绑定顶点/索引缓冲区(因为只是覆盖它们而输入布局告诉我们如何获取).如果在计算/流出中生成这些缓冲区的情况下,此规则只有例外,以避免上述运行时警告.

    2023-02-13 17:34 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有