none
Why is this function call ambiguous when compiling my D3D shader? RRS feed

  • Question

  • Hi,

    The shader below (compiled with fxc /Pps_4_0 <filename>) illustrates my question.  The call to MulAcrossAddDown from main() is ambiguous.  The MulAcrossAddDown function is overloaded against two different structures each with different contents, so I didn't expect this to be ambiguous.  Adding an extra (unused) member to either structure is sufficient to disambiguate the call.

    Why is the MulAcrossAddDown call ambiguous?


    Example shader code:

    // A structure containing 3 float4s.
    struct MyStruct1
    {
    	float4 m_vec1;
    	float4 m_vec2;
    	float4 m_vec3;
    //	uint m_int1;				// Adding this disambiguates the call.
    };
    
    // A structure containing 4 float3s.
    struct MyStruct2
    {
    	float3 m_vec1;
    	float3 m_vec2;
    	float3 m_vec3;
    	float3 m_vec4;
    };
    
    // Overloaded method for each of the structures.
    static float MulAcrossAddDown(MyStruct1 s)
    {
    	float prod1 = s.m_vec1.x * s.m_vec1.y * s.m_vec1.z * s.m_vec1.w;
    	float prod2 = s.m_vec2.x * s.m_vec2.y * s.m_vec2.z * s.m_vec2.w;
    	float prod3 = s.m_vec3.x * s.m_vec3.y * s.m_vec3.z * s.m_vec3.w;
    
    	return prod1 + prod2 + prod3;
    }
    
    static float MulAcrossAddDown(MyStruct2 s)
    {
    	float prod1 = s.m_vec1.x * s.m_vec1.y * s.m_vec1.z;
    	float prod2 = s.m_vec2.x * s.m_vec2.y * s.m_vec2.z;
    	float prod3 = s.m_vec3.x * s.m_vec3.y * s.m_vec3.z;
    	float prod4 = s.m_vec4.x * s.m_vec4.y * s.m_vec4.z;
    
    	return prod1 + prod2 + prod3 + prod4;
    }
    
    // A vertex/pixel shader that attempts to invoke the overloaded function on one of the structures.
    MyStruct1 param_struct;
    
    struct MyVertex
    {
    	float4	Position			: SV_POSITION;
    };
    
    float4 main(MyVertex IN) : SV_TARGET
    {
    	float v = MulAcrossAddDown(param_struct);						// This call is ambiguous.
    	return float4(v,v,v,v);
    }
    

    Output from compiling the shader:

    fxc.exe /Tps_4_0 D3DAmbiguousShader.hlsl
    Microsoft (R) Direct3D Shader Compiler 9.29.952.3111
    Copyright (C) Microsoft Corporation 2002-2009. All rights reserved.
    
    C:\Temp\D3DAmbiguousShader.hlsl(49,12): error X3067: 'MulAcrossAddDown': ambiguous function call
    
    compilation failed; no code produced

    Shader compiler version info:

    Microsoft (R) Direct3D Shader Compiler 9.29.952.3111
    Copyright (C) Microsoft Corporation 2002-2009. All rights reserved.

    Information on function overloading states:

    A function can be overloaded as long as it is given a unique combination of name, return value, parameter types, or parameter order.

    The parameter types are unique (MyStruct1 vs MyStruct2), and if the types are ignored and the contents used instead then the contents are unique also (3xfloat4 vs 4xfloat3). It almost appears that the compiler is treating each as 12 floats, ignoring the structures entirely.

    Thanks in advance

    Rob

    Tuesday, September 15, 2015 4:31 PM

Answers

All replies

  • HLSL considers both MyStruct1 and MyStruct2 to be equivalent for function overloading because they both consist of 12 floats. Adding anything else to either structure makes them 'distinct'.
    Wednesday, September 23, 2015 1:25 AM
  • Hi Chuck,

    Thanks for the reply.  It's as I had feared then.  :-(

    Is this documented anywhere?  It's not obvious that it'll break them down to the very lowest component types when considering overloading. I might have expected it to break the structure down to float3s and float4s (being the data types used) but not to floats.

    If it's not already, would you consider documenting this limitation to prevent others falling into the same trap?  Perhaps at https://msdn.microsoft.com/en-us/library/windows/desktop/bb509668%28v=vs.85%29.aspx or at https://msdn.microsoft.com/en-us/library/windows/desktop/bb509607%28v=vs.85%29.aspx ?

    Thanks

    Rob

    Wednesday, September 23, 2015 1:43 PM