Are there DirectX guidelines for binding and unbinding resources between draw calls?

蓝咒 提交于 2019-12-03 16:19:23

You want to have as less overhead, but also while avoiding invalid pipeline state. That's why some people unbind everything (try to prevent as much), it depends on uses cases, and of course you can balance this a bit.

To balance this you can pre allocate a specific resource to a slot, depending on resource type, since you have a different number of slots, different rules can apply

1/Samplers and States

You have 16 slots, and generally 4-5 samplers you use 90% of the time (linear/point/anisotropic/shadow).

So on application startup create those states and bind them to each shader stage you need (try not to start at zero slot, since they would easily be overriden by mistake). Create a shader header file with mapping SamplerState -> slot, and use it in your shaders, so any slot update is reflected automatically.

Reuse this as much as possible, and only bind custom samplers.

For standard states (Blend/Depth/Rasterizer), building a small collection of common states on application startup and bind as needed is common practice.

An easy way to minimize Render State binding at low cost, you can build a stack, so you set a default state, and if a shader needs a more specific state, it can push new state to the stack, once it's done, pop last state and apply it again to the pipeline.

2/Constant Buffers

You have 14 slots, which is quite a lot, it's pretty rare (at least in my use cases) to use all of them, specially now you can also use buffers/structuredbuffers as well.

One simple common case is setting a reserved slots for camera (with all data that you need, view/projection/viewprojection, plus their inverses since you might need that too.

Bind it to (all if needed) shader stage slots, and only thing you have to do is update your cbuffer every frame, it's ready to use anywhere.

3/Shader stages

You pretty much never need to unbind Compute Shader, since it's fully separated from the pipeline.

On the other side, for pipeline stage, instead of unbinding, a reasonably good practice is to set all the ones you need and set to null the ones you don't.

If you don't follow this as example and render a shadow map (depth buffer only), a pixel shader might still be bound.

If you forget to unset a Geometry Shader that you previously used, you might end up with invalid layout combination and your object will not render (error will only show up in runtime debug mode).

So setting the full shader stage adds little overhead, but the safety trade off is very far from negligible.

In your use case (using only VS/PS and CS to build), you can safely ignore that.

4/Uavs-RenderTargets-DepthStencil

For write resources, always unset when you done with unit of work. Within the same routine you can optimize inside, but at the end of your render/compute shader function, set your output back to null, since pipeline will not allow anything to be rebound as ShaderResource while it's on output.

Not unsetting a write resource at the end of your function is recipe for disaster.

5/ShaderResourceView

This is very situational, but idea is to minimize while also avoiding runtime warnings (which can be harmless, but then hide important messages).

One eventual thing is to reset to null all shader resource inputs at the beginning of the frame, to avoid a buffer still bound in VS to be set as UAV in CS for example, this costs you 6 pipeline calls per frame, but it's generally worth it.

If you have enough spare registers and some constant resources you can also of course set those in some reserved slots and bind those once and for all.

6/IA related resources

For this one, you need to set the right data to draw your geometry, so everytime you bind it it's pretty reasonable to set InputLayout/Topology . You can of course organize your draw calls to minimize switches.

I find Topology to be rather critical to be set properly, since invalid topology (for example, using Triangle List with a pipeline including tesselation), will draw nothing and give you a runtime warning, but it's very common that on AMD card it will just crash your driver, so better to avoid that as it becomes rather hard to debug.

Generally never really unbinding vertex/index buffers (since just overwriting them and Input layout tells how to fetch anyway). Only exception to this rule if in the case those buffers are generated in compute/stream out, to avoid the above mentioned runtime warning.

Answer 1 : less is better.

Answer 2 : it is the opposite, you have to unbind a view before you bind the resource with a different kind of view. You should enable the debug layer to catch errors like this.

Answer 3 : that's fine.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!