在处理图形时,我经常倾向于做很多过早的优化。我一直尝试遵循一些原则:
- 使D3D组件的数量最少。(渲染状态,缓冲区,着色器等)
- 仅在绝对必要时绑定组件。(尚未绑定,等等。)
- 尽可能专门化组件。(仅设置必要的BindFlags等)
这导致我构建非常复杂的包装器来管理创建的组件和当前管道状态。这不仅消耗了我宝贵的开发时间,还增加了另一层复杂性。
最糟糕的是:我什至不知道这一切是否值得麻烦。
我的一些优化考虑因素可能已经在较低级别上实现,而我只是在复制它们,从而浪费了CPU时间。由于对性能的影响可以忽略不计,因此其他考虑可能完全没有必要。
所以我的问题是:
- 以上哪些准则有效,我应在多大程度上遵循这些准则?
- GPU如何处理状态变化?
- 如果我更改了一个从未使用过的状态会怎样?(处于活动状态时,不会进行抽奖。)
- 绑定各种不同组件的实际性能损失是什么?
- 还应考虑哪些其他性能方面的考虑?
请不要只是告诉我,在达到实际极限之前,我不应该关心性能。从实践的角度来看,这显然是正确的,但我主要对该理论感兴趣。我不知何故需要抵制建立最佳图形框架的冲动,而且我认为我通常无法通过“过早的优化讲座”来做到这一点。
管理组件
我目前正在使用SlimDX作为托管包装用C#编写DirectX 11应用程序。这是一个非常低级的包装器,而我当前的抽象是基于它的。
使用Direct3D抽象时,有一些明显的优势。设置环境,加载着色器,设置常量和绘制网格更加简单,并且使用的代码更少。而且,由于它管理着大多数组件的创建和处理,因此它们可以在任何地方自动重用,而且我几乎完全避免了内存泄漏。
- 您通常如何管理所有图形组件和资源?
- 您能否推荐任何与下面的示例类似的托管包装器?
这是我当前实现的一个示例。我对界面非常满意。它具有足够的灵活性来满足我的需求,并且易于使用和理解:
// Init D3D environment
var window = new RenderForm();
var d3d = new Direct3D(window, GraphicsSettings.Default);
var graphics = new GraphicsManager(d3d.Device);
// Load assets
var mesh = GeometryPackage.FromFile(d3d, "teapot.gp");
var texture = Texture.FromFile(d3d, "bricks.dds");
// Render states
graphics.SetViewports(new Viewport(0, 0, 800, 600);
graphics.SetRasterizer(wireFrame: false, culling: CullMode.Back);
graphics.SetDepthState(depthEnabled: true, depthWriteEnabled: true);
graphics.SetBlendState(BlendMethod.Transparency);
// Input layout
graphics.SetLayout("effect.fx", "VS", "vs_4_0",
new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0)
);
// Vertex shader
graphics.SetShader(Shader.Vertex, "effect.fx", "VS", "vs_4_0");
graphics.SetConstants(Shader.Vertex, 0, 4, stream => stream.Write(wvpMatrix));
// Pixel shader
graphics.SetShader(Shader.Pixel, "effect.fx", "PS", "ps_4_0");
graphics.SetTexture(Shader.Pixel, 0, texture);
graphics.SetSampler(Shader.Pixel, 0, Sampler.AnisotropicWrap);
graphics.SetConstants(Shader.Pixel, 0, 1, stream => stream.Write(new Color4(1, 0, 1, 0);
d3d.Run(() =>
{
// Draw and present
d3d.BackBuffer.Clear(new Color4(1, 0, 0.5f, 1));
graphics.SetOutput(d3d.BackBuffer);
graphics.Draw(mesh);
d3d.Present();
}
8
对于此类问题,我不会讲“过早的优化”,而只会讲“概要文件更改,以便您自己查看”。
—
Tetrad
@Tetrad我几乎as愧地承认这是一些相当不错的建议。我绝对应该做更多分析。
—
Lucius
剖析数字是肯定是“图片或未发生”的gamedev版本=)
—
Patrick Hughes 2013年