locked
ID3D11ShaderReflection::GetNumInterfaceSlots() ALWAYS returns 0 / Dynamic Linking

    Question

  • My environment is:

          - Windows 8 x64 (RTM)

          - Visual Studio 2012

          - FXC (9.30.9200.16384 -- the one that ships in the box with VS2012 AFAIK)

    So basically, I've added a Compute Shader source (HLSL) to my project, and FXC compiles it successfully into a CSO.  I load this up (ReadFile() to a  BYTE buffer) and successfully create a shader via ID3D11Device::CreateComputeShader(), passing it a new ID3D11ClassLinkage object as per your examples.  So far so good, no errors or D3D warnings (not during compilation, or during running).

    However, no matter what I write in the ComputeShader code, using interfaces and classes in every different way I could think of (and actually copying most of the code from your own examples) I cannot get the GetNumInterfaceSlots() call to return anything other than 0 (no matter how many interfaces, classes, global objects or cbuffers containing those things I declare).  At the moment it's just a minimalistic Win32/C++ application compiled for x64 debug.

    So, my questions are:
          1) Is it just not possible to use HLSL Dynamic Linking for COMPUTE shaders?

          2) ...or does anyone have a *really really* simplistic example that definitely works? (the DX11 samples are a bit huge for the small problem I'm trying to fix)

    Sorry if this is obvious, I'm new to this.

    P.S. I'm wondering if there's some difference between D3DCompile...() APIs and using FXC as the samples using D3DCompile...() APIs seem to work with pretty much identical shader code (I've not included any code as quite frankly, anything I write using Interfaces/Classes in HLSL does not return GetNumInterfaceSlots() <> 0 ).

    Wednesday, October 17, 2012 12:40 AM

Answers

  • There are some conditions that must be meet before an interface is visible 'externally' to the shader:

      • At least two classes that derive from a single interface, or at least one derived class that uses external resources (member variables or resources declared in the class definition).
        • Otherwise, only one class can possibly satisfy the needs of the interface pointer: No external variability exists
      • Declaration of a variable in global space with that interface as its type
        • Otherwise, there is no way to actually set an interface to a specific class from outside: No external variability exists
      • This interface variable is used (by method call) in code being compiled
        • Otherwise, nothing uses the variability: No external variability exists
    • The numerical outputs of this method call contribute to the output of the shader program (are not dead-coded)
      • Otherwise any variability turns out to not affect the program: No external variability exists

    It is likely you aren't meeting one or more of these conditions, and so the HLSL compiler is optimizing out the use of Dynamic Shader Linkage.

    Here's a simple example that should have a public interface slot:

    interface IFace
    {
    	float DoIt(float a);
    };
    
    class CFoo : IFace
    {
    	float DoIt(float a)
    	{
    		return a / 16.0;
    	}
    };
    
    class CBar : IFace
    {
    	float DoIt(float a)
    	{
    		return a * 2;
    	}
    };
    
    IFace MyIFacePtr;
    
    RWBuffer<float> Buf;
    
    [numthreads(16,1,1)]
    void main(uint3 gtid : SV_GroupThreadID)
    {
    	Buf[gtid.x] = MyIFacePtr.DoIt(Buf[gtid.x]);
    }




    Wednesday, October 24, 2012 9:21 PM

All replies

  • Forgot to mention-- Compiling as CS_5_0 and running against DirectX v11.0.
    Wednesday, October 17, 2012 8:15 AM
  • There are some conditions that must be meet before an interface is visible 'externally' to the shader:

      • At least two classes that derive from a single interface, or at least one derived class that uses external resources (member variables or resources declared in the class definition).
        • Otherwise, only one class can possibly satisfy the needs of the interface pointer: No external variability exists
      • Declaration of a variable in global space with that interface as its type
        • Otherwise, there is no way to actually set an interface to a specific class from outside: No external variability exists
      • This interface variable is used (by method call) in code being compiled
        • Otherwise, nothing uses the variability: No external variability exists
    • The numerical outputs of this method call contribute to the output of the shader program (are not dead-coded)
      • Otherwise any variability turns out to not affect the program: No external variability exists

    It is likely you aren't meeting one or more of these conditions, and so the HLSL compiler is optimizing out the use of Dynamic Shader Linkage.

    Here's a simple example that should have a public interface slot:

    interface IFace
    {
    	float DoIt(float a);
    };
    
    class CFoo : IFace
    {
    	float DoIt(float a)
    	{
    		return a / 16.0;
    	}
    };
    
    class CBar : IFace
    {
    	float DoIt(float a)
    	{
    		return a * 2;
    	}
    };
    
    IFace MyIFacePtr;
    
    RWBuffer<float> Buf;
    
    [numthreads(16,1,1)]
    void main(uint3 gtid : SV_GroupThreadID)
    {
    	Buf[gtid.x] = MyIFacePtr.DoIt(Buf[gtid.x]);
    }




    Wednesday, October 24, 2012 9:21 PM
  • Great, that's helpful-- thank you very much! :)
    • Edited by K Reece Saturday, November 10, 2012 12:09 AM
    Saturday, November 10, 2012 12:09 AM