我最近一直在寻找使用 Direct3D 9 进行渲染的应用程序中的 PIX for Windows。我注意到的是,给定帧对渲染目标或包装它们的纹理的第一次操作似乎需要很长时间。系统运行的是 Windows 7,并且没有出现图形内存不足。因此不应该发生颠簸。我发现有趣的是,在 16 位浮点表面上的操作所花费的时间大约是在 8 位整数表面上的两倍。
有人对这种现象有任何解释吗?
-蒂莫
在 D3D9 中,驱动程序体系结构使得在使用资源时必须对其进行验证。这增加了许多 API 调用的开销,也是您应该优化以使用更少的 API 调用做更多事情的部分原因。
此外,在较旧的 Windows 平台(例如 Windows XP)上,D3D 驱动程序完全处于内核模式,因此 API 调用将调用用户模式到内核模式的上下文切换(在 Windows Vista、7 或 8 中不是这种情况,它有一个像 OpenGL 一样的用户模式前端)。
在 D3D10 中,资源仅在创建时进行验证。可能是因为 D3D10 在 WDDM 之上分层,这使得从完整内核模式切换到部分用户模式 D3D 运行时。在 WDDM 中,如果 D3D 运行时崩溃,它不会导致内核恐慌 (BSOD),因此验证并不那么重要。当您在用户模式下运行时,您不必对这些事情如此偏执。
现在,至于 8 位整数和 16 位 fp 之间的性能,这其实是意料之中的。不是因为一个是整数,另一个是 FP(GPU 非常适合 FP),而是因为一个是另一个的大小的两倍。GPU 具有大量内存带宽,但您仍然可以通过使用尽可能小的数据类型来提高性能。
如果第一个操作需要很长时间,但后续操作没有,这听起来像是 JIT(即时)编译问题。您没有提到您使用的是什么语言/框架,但如果它是在运行时编译的任何内容(.NET、Java 等),您将在第一次运行一些您不会在后续操作的代码时遇到延迟迭代。
至于 16 位的时间是 8 位的两倍,很难说出引擎盖下到底发生了什么。相信 16 位浮点运算的时间可能是 8 位定宽整数的两倍,这并不是完全荒谬的。