[D3D12] Driver level check to avoid duplicate function call?

Started by
4 comments, last by Dingleberry 8 years, 3 months ago

According to MS doc, most ID3DCommandList functions calls are cheap (like RSSetViewports, RSSetScissorRects....) but some of them which involve pipeline state changes are comparably expensive (like SetPipelineState, SetDescriptorHeap...).

So my question here is that: Does the driver do some basic check to prevent duplicate commands? For example, in one cmdlist we've called SetPipelineState(PSO1) and then later we call SetPipelineState(PSO2), and PSO1 and PSO2 have exact same bindings. Does driver intelligent enough to avoid the second SetPipelineState call during cmdlist execution? ( same as other cmd functions?) Or we as developer have to do this kind of check ourself?(like using hash value to identify duplicated func call with same params and avoid it?) or the perf delta is negligible?

Thanks

Advertisement
As far as I know there's no API-level guarantee that the implementation will filter out redundant calls for you. It's possible that the drivers will do it, but there's no way of knowing without asking them or profiling. Filtering yourself should be pretty easy and cheap, you can just cache the pointer to the PSO that's currently set for that command list and compare with it before setting a new one.

Does the driver do some basic check to prevent duplicate commands?

No. That was D3D11's motto. D3D12 is exactly the opposite. You get what you ask.

However, because PSOs are a huge block of state to fit all hardware efficiently, but not all hardware requires all that data as a fixed block; a particular driver may go through the PSO, check if anything's different, and skip if nothing changed.
But this isn't a guarantee and you shouldn't rely on this. It's vendor, model and driver specific.

Or we as developer have to do this kind of check ourself?(like using hash value to identify duplicated func call with same params and avoid it?) or the perf delta is negligible?

Yep.


pso = getPsoFromCache( draw_parameters );
if( pso != lastPso )
{
    SetPipelineState( pso );
    lastPso = pso;
}

See Valve's slides on fast multithreaded PSO caching (slides 13-23 PPT version may be animated).

In principle, the driver does as little as it possibly can in D3D12. Your commands go to GPU, end of story. I suspect that the story in reality is currently pretty close to that, because everything is still very new. You can never really rely on driver optimizations in the first place, unless you happen to be somebody NV/AMD are working directly with.

A year or two from now though, the drivers will be massively optimized for this stuff and will be playing all kinds of clever tricks. That's just how it goes. But even so, you can't rely on it.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

I thought the whole purpose of the DX12 is to offload that responsibility to the application since the application developer knows more about the intended use case. As such, that would be putting the responsibility back onto the driver. Thats not to say as others have mentioned that the driver doesn't do it, but why count on/hope on it when as the developer you made that choice to begin. This is more akin to redundant state check in previous API, we all know that was something the application should be managing.

I'm pretty sure there was no guarantee in DX11 because having tested on different vendors' cards, some would and some wouldn't and there would be a night and day perf difference sometimes.

I'd really prefer if none of the vendors tried to outsmart the apps we write so that you don't get into the situation where everything seems to be really performant until you switch cards and it's a disaster.

This topic is closed to new replies.

Advertisement