|
Clearly it is possible
to jump directly from step one to five, having removed no less than
two resolve operations, whilst maintaining the subsample color information.
So why would the developer fail to
spot this? The answer lies in the fact that modern engines are highly
object oriented, and that several developers are making changes to the
rendering code over time.
Apparently step three was originally a valid
post-processing effect, and when it was changed, it effectively became
just a copy operation which made steps two and three redundant. The
resolve in step four was triggered because M was accidently added as
an input to step five.
As you can see it is very easy to introduce
redundant resolves into the rendering pipeline. It always pays to be
on top of the various passes carried out during a frame, and is generally
good practice to regularly inspect PIX dumps for unexpected behavior.
Harmful Resolves
It is common for deferred rendering
techniques to store information such as depth, position, normal, velocity
and material ID to an intermediate render target. If this is carried
out in MSAA mode, then the data would need to be resolved before being
put to use later in the frame.
The problem here is that the fixed function
resolve operation will simply perform an average of the subsamples.
This is very unlikely to yield the developer's intended result, and
will most probably result in graphical artifacts.
Let us consider the case where material
IDs are to be resolved. I think we would all have to agree that averaging
material IDs is never going to make any sense, and that performing such
an operation would, in a worst case scenario, produce invalid IDs.
So how should we deal with this kind
of data, when a standard fixed function resolve, is clearly not the
way to go?
In DX10 it is possible to write a pixel
shader that can read the subsamples of an input texture. In the case
of a deferred lighting technique, it would then be possible to perform
the lighting calculation on each subsample, and then average the results.
In this way the shader has effectively performed a custom resolve.
DX10.1
capable hardware removes a further limitation by allowing access to
the subsamples of the depth buffer, which can eliminate the need for
a separate depth pass.
Another prominent example of a technique
that suffers from using fixed function resolved data is non-linear tone
mapping. The only correct way to perform tone mapping in a multi-sampling
context is to tone map every subsample using a shader-based custom resolve.
In DX9 it is not possible to do this,
so it may be that the resulting artifacts have to be tolerated, although
it should be said that the implementation of explicit super sampling
could achieve similar results. For performance reasons it may be necessary
to carry out post-processing with data produced by a harmful resolve,
though this should be kept to a minimum.
Conclusion
It is very important to appreciate
that a resolve is not a free operation, in fact it is a decidedly expensive
procedure, and should therefore be kept to a minimum. Keep in mind that
most resolves are either redundant or harmful.
To avoid redundancy,
remember to resolve the main MSAA render target as early as possible,
and then work in non-MSAA mode for post-processing effects. Write shader
based custom resolves, to properly deal with high quality post-processing
and deferred rendering techniques.
Remember that it's easy to overlook
what is really happening amongst the various rendering passes, so regular
analysis is essential to resolving your resolves!
|