Skip to content

Commit 06324ca

Browse files
committed
implemented faceforward in hlsl.Intrinsics.h and its spir-v target built-in, added codegen and sema tests
1 parent 69aee46 commit 06324ca

File tree

10 files changed

+370
-4
lines changed

10 files changed

+370
-4
lines changed

clang/include/clang/Basic/BuiltinsSPIRV.td

+6
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,9 @@ def SPIRVSmoothStep : Builtin {
3131
let Attributes = [NoThrow, Const, CustomTypeChecking];
3232
let Prototype = "void(...)";
3333
}
34+
35+
def SPIRVFaceForward : Builtin {
36+
let Spellings = ["__builtin_spirv_faceforward"];
37+
let Attributes = [NoThrow, Const, CustomTypeChecking];
38+
let Prototype = "void(...)";
39+
}

clang/lib/CodeGen/TargetBuiltins/SPIR.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
7171
ArrayRef<Value *>{Min, Max, X}, /*FMFSource=*/nullptr,
7272
"spv.smoothstep");
7373
}
74+
case SPIRV::BI__builtin_spirv_faceforward: {
75+
Value *N = EmitScalarExpr(E->getArg(0));
76+
Value *I = EmitScalarExpr(E->getArg(1));
77+
Value *Ng = EmitScalarExpr(E->getArg(2));
78+
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
79+
E->getArg(1)->getType()->hasFloatingRepresentation() &&
80+
E->getArg(2)->getType()->hasFloatingRepresentation() &&
81+
"FaceForward operands must have a float representation");
82+
return Builder.CreateIntrinsic(
83+
/*ReturnType=*/N->getType(), Intrinsic::spv_smoothstep,
84+
ArrayRef<Value *>{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
85+
}
7486
}
7587
return nullptr;
7688
}

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

+18
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,24 @@ template <typename T> constexpr vector<T, 4> lit_impl(T NDotL, T NDotH, T M) {
126126
return Result;
127127
}
128128

129+
template <typename T> constexpr T faceforward_impl(T N, T I, T Ng) {
130+
#if (__has_builtin(__builtin_spirv_faceforward))
131+
return __builtin_spirv_faceforward(N, I, Ng);
132+
#else
133+
return select(I * Ng < 0, N, -N);
134+
#endif
135+
}
136+
137+
template <typename T, int L>
138+
constexpr vector<T, L> faceforward_vec_impl(vector<T, L> N, vector<T, L> I,
139+
vector<T, L> Ng) {
140+
#if (__has_builtin(__builtin_spirv_faceforward))
141+
return __builtin_spirv_faceforward(N, I, Ng);
142+
#else
143+
return select(dot(I, Ng) < 0, N, -N);
144+
#endif
145+
}
146+
129147
} // namespace __detail
130148
} // namespace hlsl
131149

clang/lib/Headers/hlsl/hlsl_intrinsics.h

+47
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,53 @@ const inline double4 dst(double4 Src0, double4 Src1) {
214214
return __detail::dst_impl(Src0, Src1);
215215
}
216216

217+
//===----------------------------------------------------------------------===//
218+
// faceforward builtin
219+
//===----------------------------------------------------------------------===//
220+
221+
/// \fn T faceforward(T N, T I, T Ng)
222+
/// \brief Flips the surface-normal (if needed) to face in a direction opposite
223+
/// to \a I. Returns the result in \a N.
224+
/// \param N The resulting floating-point surface-normal vector.
225+
/// \param I A floating-point, incident vector that points from the view
226+
/// position to the shading position.
227+
/// \param Ng A floating-point surface-normal vector.
228+
///
229+
/// Return a floating-point, surface normal vector that is facing the view
230+
/// direction.
231+
232+
template <typename T>
233+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
234+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
235+
__detail::is_same<half, T>::value,
236+
T> faceforward(T N, T I, T Ng) {
237+
return __detail::faceforward_impl(N, I, Ng);
238+
}
239+
240+
template <typename T>
241+
const inline __detail::enable_if_t<
242+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
243+
faceforward(T N, T I, T Ng) {
244+
return __detail::faceforward_impl(N, I, Ng);
245+
}
246+
247+
template <int L>
248+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
249+
const inline __detail::HLSL_FIXED_VECTOR<half, L> faceforward(
250+
__detail::HLSL_FIXED_VECTOR<half, L> N,
251+
__detail::HLSL_FIXED_VECTOR<half, L> I,
252+
__detail::HLSL_FIXED_VECTOR<half, L> Ng) {
253+
return __detail::faceforward_vec_impl(N, I, Ng);
254+
}
255+
256+
template <int L>
257+
const inline __detail::HLSL_FIXED_VECTOR<float, L>
258+
faceforward(__detail::HLSL_FIXED_VECTOR<float, L> N,
259+
__detail::HLSL_FIXED_VECTOR<float, L> I,
260+
__detail::HLSL_FIXED_VECTOR<float, L> Ng) {
261+
return __detail::faceforward_vec_impl(N, I, Ng);
262+
}
263+
217264
//===----------------------------------------------------------------------===//
218265
// fmod builtins
219266
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaSPIRV.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,42 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID,
137137
TheCall->setType(RetTy);
138138
break;
139139
}
140+
case SPIRV::BI__builtin_spirv_faceforward: {
141+
if (SemaRef.checkArgCount(TheCall, 3))
142+
return true;
143+
144+
// check if all arguments have floating representation
145+
for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
146+
ExprResult Arg = TheCall->getArg(i);
147+
QualType ArgTy = Arg.get()->getType();
148+
if (!ArgTy->hasFloatingRepresentation()) {
149+
SemaRef.Diag(Arg.get()->getBeginLoc(),
150+
diag::err_builtin_invalid_arg_type)
151+
<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */ 1
152+
<< ArgTy;
153+
return true;
154+
}
155+
}
156+
157+
// check if all arguments are of the same type
158+
ExprResult A = TheCall->getArg(0);
159+
ExprResult B = TheCall->getArg(1);
160+
ExprResult C = TheCall->getArg(2);
161+
if (!(SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
162+
B.get()->getType()) &&
163+
SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
164+
C.get()->getType()))) {
165+
SemaRef.Diag(TheCall->getBeginLoc(),
166+
diag::err_vec_builtin_incompatible_vector)
167+
<< TheCall->getDirectCallee() << /*useAllTerminology*/ true
168+
<< SourceRange(A.get()->getBeginLoc(), C.get()->getEndLoc());
169+
return true;
170+
}
171+
172+
QualType RetTy = A.get()->getType();
173+
TheCall->setType(RetTy);
174+
break;
175+
}
140176
}
141177
return false;
142178
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3+
// RUN: -emit-llvm -o - | FileCheck %s
4+
// RUN: %clang_cc1 -finclude-default-header -triple \
5+
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
6+
// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=SPVCHECK
7+
8+
// CHECK-LABEL: test_faceforward_half
9+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}}
10+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %mul.i, 0xH0000
11+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn half %{{.*}}
12+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, half %{{.*}}, half %fneg.i
13+
// CHECK: ret half %hlsl.select.i
14+
// SPVCHECK-LABEL: test_faceforward_half
15+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef half @llvm.spv.smoothstep.f16(half %{{.*}}, half %{{.*}}, half %{{.*}})
16+
// SPVCHECK: ret half %spv.faceforward.i
17+
half test_faceforward_half(half N, half I, half Ng) { return faceforward(N, I, Ng); }
18+
19+
// CHECK-LABEL: test_faceforward_half2
20+
// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
21+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %hlsl.dot.i, 0xH0000
22+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}
23+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <2 x half> %{{.*}}, <2 x half> %fneg.i
24+
// CHECK: ret <2 x half> %hlsl.select.i
25+
// SPVCHECK-LABEL: test_faceforward_half2
26+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <2 x half> @llvm.spv.smoothstep.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, <2 x half> %{{.*}})
27+
// SPVCHECK: ret <2 x half> %spv.faceforward.i
28+
half2 test_faceforward_half2(half2 N, half2 I, half2 Ng) { return faceforward(N, I, Ng); }
29+
30+
// CHECK-LABEL: test_faceforward_half3
31+
// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}})
32+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %hlsl.dot.i, 0xH0000
33+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}
34+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <3 x half> %{{.*}}, <3 x half> %fneg.i
35+
// CHECK: ret <3 x half> %hlsl.select.i
36+
// SPVCHECK-LABEL: test_faceforward_half3
37+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <3 x half> @llvm.spv.smoothstep.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}, <3 x half> %{{.*}})
38+
// SPVCHECK: ret <3 x half> %spv.faceforward.i
39+
half3 test_faceforward_half3(half3 N, half3 I, half3 Ng) { return faceforward(N, I, Ng); }
40+
41+
// CHECK-LABEL: test_faceforward_half4
42+
// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}})
43+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %hlsl.dot.i, 0xH0000
44+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}
45+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <4 x half> %{{.*}}, <4 x half> %fneg.i
46+
// CHECK: ret <4 x half> %hlsl.select.i
47+
// SPVCHECK-LABEL: test_faceforward_half4
48+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <4 x half> @llvm.spv.smoothstep.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}, <4 x half> %{{.*}})
49+
// SPVCHECK: ret <4 x half> %spv.faceforward.i
50+
half4 test_faceforward_half4(half4 N, half4 I, half4 Ng) { return faceforward(N, I, Ng); }
51+
52+
// CHECK-LABEL: test_faceforward_float
53+
// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn float %{{.*}}, %{{.*}}
54+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %mul.i, 0.000000e+00
55+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn float %{{.*}}
56+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, float %{{.*}}, float %fneg.i
57+
// CHECK: ret float %hlsl.select.i
58+
// SPVCHECK-LABEL: test_faceforward_float
59+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef float @llvm.spv.smoothstep.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
60+
// SPVCHECK: ret float %spv.faceforward.i
61+
float test_faceforward_float(float N, float I, float Ng) { return faceforward(N, I, Ng); }
62+
63+
// CHECK-LABEL: test_faceforward_float2
64+
// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}})
65+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %hlsl.dot.i, 0.000000e+00
66+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}
67+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <2 x float> %{{.*}}, <2 x float> %fneg.i
68+
// CHECK: ret <2 x float> %hlsl.select.i
69+
// SPVCHECK-LABEL: test_faceforward_float2
70+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.smoothstep.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
71+
// SPVCHECK: ret <2 x float> %spv.faceforward.i
72+
float2 test_faceforward_float2(float2 N, float2 I, float2 Ng) { return faceforward(N, I, Ng); }
73+
74+
// CHECK-LABEL: test_faceforward_float3
75+
// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}})
76+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %hlsl.dot.i, 0.000000e+00
77+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}
78+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <3 x float> %{{.*}}, <3 x float> %fneg.i
79+
// CHECK: ret <3 x float> %hlsl.select.i
80+
// SPVCHECK-LABEL: test_faceforward_float3
81+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.smoothstep.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
82+
// SPVCHECK: ret <3 x float> %spv.faceforward.i
83+
float3 test_faceforward_float3(float3 N, float3 I, float3 Ng) { return faceforward(N, I, Ng); }
84+
85+
// CHECK-LABEL: test_faceforward_float4
86+
// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
87+
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %hlsl.dot.i, 0.000000e+00
88+
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}
89+
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <4 x float> %{{.*}}, <4 x float> %fneg.i
90+
// CHECK: ret <4 x float> %hlsl.select.i
91+
// SPVCHECK-LABEL: test_faceforward_float4
92+
// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.smoothstep.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
93+
// SPVCHECK: ret <4 x float> %spv.faceforward.i
94+
float4 test_faceforward_float4(float4 N, float4 I, float4 Ng) { return faceforward(N, I, Ng); }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
3+
// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -emit-llvm -o - | FileCheck %s
4+
5+
typedef float float2 __attribute__((ext_vector_type(2)));
6+
typedef float float3 __attribute__((ext_vector_type(3)));
7+
typedef float float4 __attribute__((ext_vector_type(4)));
8+
9+
// CHECK-LABEL: define spir_func float @test_faceforward_float(
10+
// CHECK-SAME: float noundef [[N:%.*]], float noundef [[I:%.*]], float noundef [[NG:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
11+
// CHECK-NEXT: [[ENTRY:.*:]]
12+
// CHECK-NEXT: [[SPV_FACEFORWARD:%.*]] = tail call float @llvm.spv.smoothstep.f32(float [[N]], float [[I]], float [[NG]])
13+
// CHECK-NEXT: ret float [[SPV_FACEFORWARD]]
14+
float test_faceforward_float(float N, float I, float Ng) { return __builtin_spirv_faceforward(N, I, Ng); }
15+
16+
// CHECK-LABEL: define spir_func <2 x float> @test_faceforward_float2(
17+
// CHECK-SAME: <2 x float> noundef [[N:%.*]], <2 x float> noundef [[I:%.*]], <2 x float> noundef [[NG:%.*]]) local_unnamed_addr #[[ATTR0]] {
18+
// CHECK-NEXT: [[ENTRY:.*:]]
19+
// CHECK-NEXT: [[SPV_FACEFORWARD:%.*]] = tail call <2 x float> @llvm.spv.smoothstep.v2f32(<2 x float> [[N]], <2 x float> [[I]], <2 x float> [[NG]])
20+
// CHECK-NEXT: ret <2 x float> [[SPV_FACEFORWARD]]
21+
float2 test_faceforward_float2(float2 N, float2 I, float2 Ng) { return __builtin_spirv_faceforward(N, I, Ng); }
22+
23+
// CHECK-LABEL: define spir_func <3 x float> @test_faceforward_float3(
24+
// CHECK-SAME: <3 x float> noundef [[N:%.*]], <3 x float> noundef [[I:%.*]], <3 x float> noundef [[NG:%.*]]) local_unnamed_addr #[[ATTR0]] {
25+
// CHECK-NEXT: [[ENTRY:.*:]]
26+
// CHECK-NEXT: [[SPV_FACEFORWARD:%.*]] = tail call <3 x float> @llvm.spv.smoothstep.v3f32(<3 x float> [[N]], <3 x float> [[I]], <3 x float> [[NG]])
27+
// CHECK-NEXT: ret <3 x float> [[SPV_FACEFORWARD]]
28+
float3 test_faceforward_float3(float3 N, float3 I, float3 Ng) { return __builtin_spirv_faceforward(N, I, Ng); }
29+
30+
// CHECK-LABEL: define spir_func <4 x float> @test_faceforward_float4(
31+
// CHECK-SAME: <4 x float> noundef [[N:%.*]], <4 x float> noundef [[I:%.*]], <4 x float> noundef [[NG:%.*]]) local_unnamed_addr #[[ATTR0]] {
32+
// CHECK-NEXT: [[ENTRY:.*:]]
33+
// CHECK-NEXT: [[SPV_FACEFORWARD:%.*]] = tail call <4 x float> @llvm.spv.smoothstep.v4f32(<4 x float> [[N]], <4 x float> [[I]], <4 x float> [[NG]])
34+
// CHECK-NEXT: ret <4 x float> [[SPV_FACEFORWARD]]
35+
float4 test_faceforward_float4(float4 N, float4 I, float4 Ng) { return __builtin_spirv_faceforward(N, I, Ng); }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify
2+
3+
float test_double_inputs(double p0, double p1, double p2) {
4+
return faceforward(p0, p1, p2);
5+
// expected-error@-1 {{no matching function for call to 'faceforward'}}
6+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
7+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
8+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
9+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
10+
}
11+
12+
float test_int_inputs(int p0, int p1, int p2) {
13+
return faceforward(p0, p1, p2);
14+
// expected-error@-1 {{no matching function for call to 'faceforward'}}
15+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
16+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
17+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
18+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
19+
}
20+
21+
float1 test_vec1_inputs(float1 p0, float1 p1, float1 p2) {
22+
return faceforward(p0, p1, p2);
23+
// expected-error@-1 {{no matching function for call to 'faceforward'}}
24+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}}
25+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}}
26+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
27+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
28+
}
29+
30+
typedef float float5 __attribute__((ext_vector_type(5)));
31+
32+
float5 test_vec5_inputs(float5 p0, float5 p1, float5 p2) {
33+
return faceforward(p0, p1, p2);
34+
// expected-error@-1 {{no matching function for call to 'faceforward'}}
35+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 5>>'}}
36+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 5>>'}}
37+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}}
38+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}}
39+
}

0 commit comments

Comments
 (0)