Skip to content

Commit 5af43f8

Browse files
[HLSL] Implement the fwidth intrinsic
Closes #99120
1 parent a3ab110 commit 5af43f8

File tree

12 files changed

+329
-8
lines changed

12 files changed

+329
-8
lines changed

clang/include/clang/Basic/BuiltinsSPIRVVK.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ include "clang/Basic/BuiltinsSPIRVBase.td"
1212
def reflect : SPIRVBuiltin<"void(...)", [NoThrow, Const]>;
1313
def faceforward : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
1414
def refract : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;
15+
def fwidth : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>;

clang/lib/CodeGen/TargetBuiltins/SPIR.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
151151
Intrinsic::spv_global_offset,
152152
ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))}, nullptr,
153153
"spv.global.offset");
154+
case SPIRV::BI__builtin_spirv_fwidth:
155+
return Builder.CreateIntrinsic(
156+
/*ReturnType=*/getTypes().ConvertType(E->getType()),
157+
Intrinsic::spv_fwidth, ArrayRef<Value *>{EmitScalarExpr(E->getArg(0))},
158+
nullptr, "spv.fwidth");
154159
}
155160
return nullptr;
156161
}

clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ constexpr K firstbithigh_impl(T X) {
160160
return FBH;
161161
}
162162

163+
template <typename T> constexpr T fwidth_impl(T input) {
164+
#if (__has_builtin(__builtin_spirv_fwidth))
165+
return __builtin_spirv_fwidth(input);
166+
#else
167+
T derivCoarseX = ddx_coarse(input);
168+
derivCoarseX = abs(derivCoarseX);
169+
T derivCoarseY = ddy_coarse(input);
170+
derivCoarseY = abs(derivCoarseY);
171+
return derivCoarseX + derivCoarseY;
172+
#endif
173+
}
174+
163175
} // namespace __detail
164176
} // namespace hlsl
165177

clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,5 +666,45 @@ smoothstep(__detail::HLSL_FIXED_VECTOR<float, N> Min,
666666
return __detail::smoothstep_vec_impl(Min, Max, X);
667667
}
668668

669+
//===----------------------------------------------------------------------===//
670+
// fwidth builtin
671+
//===----------------------------------------------------------------------===//
672+
673+
/// \fn T fwidth(T x)
674+
/// \brief Computes the sum of the absolute values of the partial derivatives
675+
/// with regard to the x and y screen space coordinates.
676+
/// \param x [in] The floating-point scalar or vector to process.
677+
///
678+
/// The return value is a floating-point scalar or vector where each element
679+
/// holds the computation of the matching element in the input.
680+
681+
template <typename T>
682+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
683+
const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value &&
684+
__detail::is_same<half, T>::value,
685+
T> fwidth(T input) {
686+
return __detail::fwidth_impl(input);
687+
}
688+
689+
template <typename T>
690+
const inline __detail::enable_if_t<
691+
__detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T>
692+
fwidth(T input) {
693+
return __detail::fwidth_impl(input);
694+
}
695+
696+
template <int N>
697+
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
698+
const inline __detail::HLSL_FIXED_VECTOR<half, N> fwidth(
699+
__detail::HLSL_FIXED_VECTOR<half, N> input) {
700+
return __detail::fwidth_impl(input);
701+
}
702+
703+
template <int N>
704+
const inline __detail::HLSL_FIXED_VECTOR<float, N>
705+
fwidth(__detail::HLSL_FIXED_VECTOR<float, N> input) {
706+
return __detail::fwidth_impl(input);
707+
}
708+
669709
} // namespace hlsl
670710
#endif //_HLSL_HLSL_INTRINSICS_H_

clang/lib/Sema/SemaSPIRV.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,24 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI,
360360
case SPIRV::BI__builtin_spirv_generic_cast_to_ptr_explicit: {
361361
return checkGenericCastToPtr(SemaRef, TheCall);
362362
}
363+
case SPIRV::BI__builtin_spirv_fwidth: {
364+
if (SemaRef.checkArgCount(TheCall, 1))
365+
return true;
366+
367+
// Check if first argument has floating representation
368+
ExprResult A = TheCall->getArg(0);
369+
QualType ArgTyA = A.get()->getType();
370+
if (!ArgTyA->hasFloatingRepresentation()) {
371+
SemaRef.Diag(A.get()->getBeginLoc(), diag::err_builtin_invalid_arg_type)
372+
<< /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 0
373+
<< /* fp */ 1 << ArgTyA;
374+
return true;
375+
}
376+
377+
QualType RetTy = ArgTyA;
378+
TheCall->setType(RetTy);
379+
break;
380+
}
363381
}
364382
return false;
365383
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
2+
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
3+
// RUN: FileCheck %s --check-prefixes=CHECK
4+
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
5+
// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
6+
// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
7+
8+
// CHECK-LABEL: define {{.*}} half @_ZN4hlsl8__detail11fwidth_implIDhEET_S2_
9+
// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
10+
// CHECK: %{{.*}} = call {{.*}} half @llvm.fabs.f16(half %{{.*}})
11+
// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
12+
// CHECK: %{{.*}} = call {{.*}} half @llvm.fabs.f16(half %{{.*}})
13+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
14+
// CHECK: ret half %{{.*}}
15+
// CHECK-LABEL-SPIRV: half @_Z15test_f16_fwidthDh
16+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} half @llvm.spv.fwidth.f16(half %{{.*}})
17+
// CHECK-SPIRV: ret half %spv.fwidth
18+
half test_f16_fwidth(half val) {
19+
return fwidth(val);
20+
}
21+
22+
// CHECK-LABEL: define {{.*}} <2 x half> @_ZN4hlsl8__detail11fwidth_implIDv2_DhEET_S3_
23+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
24+
// CHECK: %{{.*}} = call {{.*}} <2 x half> @llvm.fabs.v2f16(<2 x half> %{{.*}})
25+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
26+
// CHECK: %{{.*}} = call {{.*}} <2 x half> @llvm.fabs.v2f16(<2 x half> %{{.*}})
27+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
28+
// CHECK: ret <2 x half> %{{.*}}
29+
// CHECK-LABEL-SPIRV: <2 x half> @_Z16test_f16_fwidth2Dv2_Dh
30+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <2 x half> @llvm.spv.fwidth.v2f16(<2 x half> %{{.*}})
31+
// CHECK-SPIRV: ret <2 x half> %spv.fwidth
32+
half2 test_f16_fwidth2(half2 val) {
33+
return fwidth(val);
34+
}
35+
36+
// CHECK-LABEL: define {{.*}} <3 x half> @_ZN4hlsl8__detail11fwidth_implIDv3_DhEET_S3_
37+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
38+
// CHECK: %{{.*}} = call {{.*}} <3 x half> @llvm.fabs.v3f16(<3 x half> %{{.*}})
39+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
40+
// CHECK: %{{.*}} = call {{.*}} <3 x half> @llvm.fabs.v3f16(<3 x half> %{{.*}})
41+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
42+
// CHECK: ret <3 x half> %{{.*}}
43+
// CHECK-LABEL-SPIRV: <3 x half> @_Z16test_f16_fwidth3Dv3_Dh
44+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <3 x half> @llvm.spv.fwidth.v3f16(<3 x half> %{{.*}})
45+
// CHECK-SPIRV: ret <3 x half> %spv.fwidth
46+
half3 test_f16_fwidth3(half3 val) {
47+
return fwidth(val);
48+
}
49+
50+
// CHECK-LABEL: define {{.*}} <4 x half> @_ZN4hlsl8__detail11fwidth_implIDv4_DhEET_S3_
51+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
52+
// CHECK: %{{.*}} = call {{.*}} <4 x half> @llvm.fabs.v4f16(<4 x half> %{{.*}})
53+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
54+
// CHECK: %{{.*}} = call {{.*}} <4 x half> @llvm.fabs.v4f16(<4 x half> %{{.*}})
55+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
56+
// CHECK: ret <4 x half> %{{.*}}
57+
// CHECK-LABEL-SPIRV: <4 x half> @_Z16test_f16_fwidth4Dv4_Dh
58+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <4 x half> @llvm.spv.fwidth.v4f16(<4 x half> %{{.*}})
59+
// CHECK-SPIRV: ret <4 x half> %spv.fwidth
60+
half4 test_f16_fwidth4(half4 val) {
61+
return fwidth(val);
62+
}
63+
64+
// CHECK-LABEL: define {{.*}} float @_ZN4hlsl8__detail11fwidth_implIfEET_S2_
65+
// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
66+
// CHECK: %{{.*}} = call {{.*}} float @llvm.fabs.f32(float %{{.*}})
67+
// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
68+
// CHECK: %{{.*}} = call {{.*}} float @llvm.fabs.f32(float %{{.*}})
69+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
70+
// CHECK: ret float %{{.*}}
71+
// CHECK-LABEL-SPIRV: float @_Z15test_f32_fwidthf
72+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} float @llvm.spv.fwidth.f32(float %{{.*}})
73+
// CHECK-SPIRV: ret float %spv.fwidth
74+
float test_f32_fwidth(float val) {
75+
return fwidth(val);
76+
}
77+
78+
// CHECK-LABEL: define {{.*}} <2 x float> @_ZN4hlsl8__detail11fwidth_implIDv2_fEET_S3_
79+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
80+
// CHECK: %{{.*}} = call {{.*}} <2 x float> @llvm.fabs.v2f32(<2 x float> %{{.*}})
81+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
82+
// CHECK: %{{.*}} = call {{.*}} <2 x float> @llvm.fabs.v2f32(<2 x float> %{{.*}})
83+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
84+
// CHECK: ret <2 x float> %{{.*}}
85+
// CHECK-LABEL-SPIRV: <2 x float> @_Z16test_f32_fwidth2Dv2_f
86+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <2 x float> @llvm.spv.fwidth.v2f32(<2 x float> %{{.*}})
87+
// CHECK-SPIRV: ret <2 x float> %spv.fwidth
88+
float2 test_f32_fwidth2(float2 val) {
89+
return fwidth(val);
90+
}
91+
92+
// CHECK-LABEL: define {{.*}} <3 x float> @_ZN4hlsl8__detail11fwidth_implIDv3_fEET_S3_
93+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
94+
// CHECK: %{{.*}} = call {{.*}} <3 x float> @llvm.fabs.v3f32(<3 x float> %{{.*}})
95+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
96+
// CHECK: %{{.*}} = call {{.*}} <3 x float> @llvm.fabs.v3f32(<3 x float> %{{.*}})
97+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
98+
// CHECK: ret <3 x float> %{{.*}}
99+
// CHECK-LABEL-SPIRV: <3 x float> @_Z16test_f32_fwidth3Dv3_f
100+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <3 x float> @llvm.spv.fwidth.v3f32(<3 x float> %{{.*}})
101+
// CHECK-SPIRV: ret <3 x float> %spv.fwidth
102+
float3 test_f32_fwidth3(float3 val) {
103+
return fwidth(val);
104+
}
105+
106+
// CHECK-LABEL: define {{.*}} <4 x float> @_ZN4hlsl8__detail11fwidth_implIDv4_fEET_S3_
107+
// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
108+
// CHECK: %{{.*}} = call {{.*}} <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
109+
// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
110+
// CHECK: %{{.*}} = call {{.*}} <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
111+
// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
112+
// CHECK: ret <4 x float> %{{.*}}
113+
// CHECK-LABEL-SPIRV: <4 x float> @_Z16test_f32_fwidth4Dv4_f
114+
// CHECK-SPIRV: %spv.fwidth = call {{.*}} <4 x float> @llvm.spv.fwidth.v4f32(<4 x float> %{{.*}})
115+
// CHECK-SPIRV: ret <4 x float> %spv.fwidth
116+
float4 test_f32_fwidth4(float4 val) {
117+
return fwidth(val);
118+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -emit-llvm -o - | FileCheck %s
2+
3+
typedef _Float16 half;
4+
typedef half half2 __attribute__((ext_vector_type(2)));
5+
typedef half half3 __attribute__((ext_vector_type(3)));
6+
typedef half half4 __attribute__((ext_vector_type(4)));
7+
typedef float float2 __attribute__((ext_vector_type(2)));
8+
typedef float float3 __attribute__((ext_vector_type(3)));
9+
typedef float float4 __attribute__((ext_vector_type(4)));
10+
11+
// CHECK: [[fwidth0:%.*]] = tail call half @llvm.spv.fwidth.f16(half {{%.*}})
12+
// CHECK: ret half [[fwidth0]]
13+
half test_fwidth_half(half X) { return __builtin_spirv_fwidth(X); }
14+
15+
// CHECK: [[fwidth0:%.*]] = tail call <2 x half> @llvm.spv.fwidth.v2f16(<2 x half> {{%.*}})
16+
// CHECK: ret <2 x half> [[fwidth0]]
17+
half2 test_fwidth_half2(half2 X) { return __builtin_spirv_fwidth(X); }
18+
19+
// CHECK: [[fwidth0:%.*]] = tail call <3 x half> @llvm.spv.fwidth.v3f16(<3 x half> {{%.*}})
20+
// CHECK: ret <3 x half> [[fwidth0]]
21+
half3 test_fwidth_half3(half3 X) { return __builtin_spirv_fwidth(X); }
22+
23+
// CHECK: [[fwidth0:%.*]] = tail call <4 x half> @llvm.spv.fwidth.v4f16(<4 x half> {{%.*}})
24+
// CHECK: ret <4 x half> [[fwidth0]]
25+
half4 test_fwidth_half4(half4 X) { return __builtin_spirv_fwidth(X); }
26+
27+
// CHECK: [[fwidth0:%.*]] = tail call float @llvm.spv.fwidth.f32(float {{%.*}})
28+
// CHECK: ret float [[fwidth0]]
29+
float test_fwidth_float(float X) { return __builtin_spirv_fwidth(X); }
30+
31+
// CHECK: [[fwidth1:%.*]] = tail call <2 x float> @llvm.spv.fwidth.v2f32(<2 x float> {{%.*}})
32+
// CHECK: ret <2 x float> [[fwidth1]]
33+
float2 test_fwidth_float2(float2 X) { return __builtin_spirv_fwidth(X); }
34+
35+
// CHECK: [[fwidth2:%.*]] = tail call <3 x float> @llvm.spv.fwidth.v3f32(<3 x float> {{%.*}})
36+
// CHECK: ret <3 x float> [[fwidth2]]
37+
float3 test_fwidth_float3(float3 X) { return __builtin_spirv_fwidth(X); }
38+
39+
// CHECK: [[fwidth3:%.*]] = tail call <4 x float> @llvm.spv.fwidth.v4f32(<4 x float> {{%.*}})
40+
// CHECK: ret <4 x float> [[fwidth3]]
41+
float4 test_fwidth_float4(float4 X) { return __builtin_spirv_fwidth(X); }
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify
2+
3+
typedef float float2 __attribute__((ext_vector_type(2)));
4+
5+
void test_too_few_arg()
6+
{
7+
return __builtin_spirv_fwidth();
8+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
9+
}
10+
11+
float test_too_many_arg(float p0) {
12+
return __builtin_spirv_fwidth(p0, p0);
13+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
14+
}
15+
16+
float test_int_scalar_inputs(int p0) {
17+
return __builtin_spirv_fwidth(p0);
18+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}}
19+
}
20+
21+
float test_mismatched_return(float2 p0) {
22+
return __builtin_spirv_fwidth(p0);
23+
// expected-error@-1 {{returning 'float2' (vector of 2 'float' values) from a function with incompatible result type 'float'}}
24+
}

llvm/include/llvm/IR/IntrinsicsSPIRV.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
136136
def int_spv_discard : DefaultAttrsIntrinsic<[], [], []>;
137137
def int_spv_ddx_coarse : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
138138
def int_spv_ddy_coarse : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
139+
def int_spv_fwidth : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
139140
def int_spv_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
140141
def int_spv_sclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
141142
def int_spv_nclamp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
328328
MachineInstr &I) const;
329329
bool selectFrexp(Register ResVReg, const SPIRVType *ResType,
330330
MachineInstr &I) const;
331-
bool selectDpdCoarse(Register ResVReg, const SPIRVType *ResType,
332-
MachineInstr &I, const unsigned DPdOpCode) const;
331+
bool selectDerivativeInst(Register ResVReg, const SPIRVType *ResType,
332+
MachineInstr &I, const unsigned DPdOpCode) const;
333333
// Utilities
334334
std::pair<Register, bool>
335335
buildI32Constant(uint32_t Val, MachineInstr &I,
@@ -3143,10 +3143,9 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
31433143
return Result;
31443144
}
31453145

3146-
bool SPIRVInstructionSelector::selectDpdCoarse(Register ResVReg,
3147-
const SPIRVType *ResType,
3148-
MachineInstr &I,
3149-
const unsigned DPdOpCode) const {
3146+
bool SPIRVInstructionSelector::selectDerivativeInst(
3147+
Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
3148+
const unsigned DPdOpCode) const {
31503149
// TODO: This should check specifically for Fragment Execution Model, but STI
31513150
// doesn't provide that information yet. See #167562
31523151
errorIfInstrOutsideShader(I);
@@ -3584,10 +3583,13 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
35843583
return selectExtInst(ResVReg, ResType, I, GL::UnpackHalf2x16);
35853584
}
35863585
case Intrinsic::spv_ddx_coarse: {
3587-
return selectDpdCoarse(ResVReg, ResType, I, SPIRV::OpDPdxCoarse);
3586+
return selectDerivativeInst(ResVReg, ResType, I, SPIRV::OpDPdxCoarse);
35883587
}
35893588
case Intrinsic::spv_ddy_coarse: {
3590-
return selectDpdCoarse(ResVReg, ResType, I, SPIRV::OpDPdyCoarse);
3589+
return selectDerivativeInst(ResVReg, ResType, I, SPIRV::OpDPdyCoarse);
3590+
}
3591+
case Intrinsic::spv_fwidth: {
3592+
return selectDerivativeInst(ResVReg, ResType, I, SPIRV::OpFwidth);
35913593
}
35923594
default: {
35933595
std::string DiagMsg;

0 commit comments

Comments
 (0)