3
\$\begingroup\$

Let's say I render 2 objects that are using the same shader (and the same ID3D11VertexShader object). When I call VSSetShader() to set the shader for the 1st object DirectX has to change previous shader to the new one which takes some CPU/GPU time. But when I then render the 2nd object and call VSSetShader() again with the same argument(s) does it set the shader again (and take as much CPU/GPU time as before) or is DirectX "smart" enough to figure out it's the same shader and it doesn't have to change anything?

Actually, I'd like to ask a broader question - does the same hold true for other analogous state changing function calls? Like setting buffers, sampler states, blending states etc... Pretty much whenever it's a matter of "applying"/"setting as current" objects and states when I actually try to set the same as before.

\$\endgroup\$
  • \$\begingroup\$ This is very dependent on what the underlying driver does, which means it will likely vary by GPU vendor, architecture, driver version etc...probably your best bet is to write some tests and measure the timing. \$\endgroup\$ – Nathan Reed May 9 '14 at 2:43
  • \$\begingroup\$ I could do that but that would only give me the answer for my GPU, wouldn't it? If I released a game it would behave differently on other people's GPU's, right? \$\endgroup\$ – NPS May 9 '14 at 8:42
  • \$\begingroup\$ I'm not sure if the GPU would be "smart" enough. Maybe it's better (more secure) to assume that it won't be "smart" (even if your great GPU will, somebody's else won't) and group the objects "by the shader", so you can work like this (each frame): set shader1, render all the objects that use it, change shader1 to shader2, render... etc.? \$\endgroup\$ – PolGraphic May 9 '14 at 10:32
2
\$\begingroup\$

Looking at the doc on MSDN, it says nothing about having that functionality. It just sets "a vertex shader to the device." So while it might be included as part of the driver-implementation for a specific gpu, there is no requirement that a vender includes that functionality.

It would be best to avoid relying on your driver to check. If you need to, do the check yourself. Should be simple enough. Perhaps:

const ID3D11VertexShader* g_SetShader;

void SetShader(ID3D11VertexShader* shader, ...)
{
    if (shader == g_SetShader)
    {
        return; // the shader is already set
    }

    //...

    g_SetShader = shader;
    return;
}

And as a result of you being able to implement a check yourself, the programmers for the driver could well have just not included that check (making their implementation a little bit faster than it would be otherwise.)

Even better would be to have a system setup to avoid the need for the check all-together. eg.

for each shader
{
    bind shader
    for each object using shader
    {
        render object
    }
}
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Obviously, that's what I'm gonna do if there's no other way. I just wanted to know if I could possibly rely on DirectX to do that for me. \$\endgroup\$ – NPS May 9 '14 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.