2
\$\begingroup\$

When I was learning OpenGL (some old version), the way to update variables in shader was to find their index or whatever by name (string) and then use that index to actually update them. And I've seen it's also possible to update variables by name using ID3D10Effect interface (I don't know if there's any ID3D11Effect). But since I'm not using effect files, I'm wondering if it's still possible. Or should I just stick to manually indexing constant buffers/variables (register(b0)) in shader and then using these indices (slots) in C++ code?

\$\endgroup\$
2
\$\begingroup\$

Yes, you can look up resources and variables from a compiled shader using the ID3D11ShaderReflection interface. This can be used to find the bind points for constant buffers, textures, etc. which you can pass to calls like PSSetConstantBuffers, PSSetShaderResources and so forth. You can also look up the offsets of individual variables in a constant buffer.

FYI, there is also an Effects11 library that provides effect files for D3D11. It is no longer part of the DirectX SDK, though; it's been open-sourced as a standalone library, and Microsoft warns that the HLSL compiler support that it depends on is deprecated and could be removed in a future version of the compiler.

\$\endgroup\$
  • \$\begingroup\$ Do you know what is ID3D11ShaderReflection's performance in comparison to using slots? \$\endgroup\$ – NPS Aug 12 '13 at 23:12
  • 1
    \$\begingroup\$ @NPS I haven't measured it, but of course there is some CPU overhead to look up things by name. Ideally you'd look them up by name once during initialization, and store the slot index to use during rendering. \$\endgroup\$ – Nathan Reed Aug 12 '13 at 23:18
2
\$\begingroup\$

As pointed out here, if you have the DirectX SDK you have the Effects11 framework source code available. Personally I would recommend not relying on it and implementing your own assignment system. I find using cbuffer registers cleaner.

What I did is to have each material implementation (provided you have some sort of Material class) define and assemble all variables, cbuffers, etc. that it needs. For example I create cbuffer proxy objects by adding all the data they might need (matrices, vectors, and so on).

This ConstantBuffer class (C# code) defines what kind of cbuffer it represents, depending on the update frequency (i.e.: PerScene, PerFrame, PerInstance...), to what kind of shader it is associated and the slot:

public CBType Type { get; private set; }
public ShaderType ShaderType { get; private set; }
public int Slot { get; set; }

So before rendering, I have access to all this information. Thus cbuffers, textures, samplers (which have a similar organization), etc. can all be set automatically. If you want to go even further, you can also serialize shader parameters via XML so that when loading a material, it also fetches the necessary data to fill your cbuffers from your engine without hardcoding it.

\$\endgroup\$

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.