Skip to content

[HLSL] Overloads for lerp with a scalar weight #137877

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_compat_overloads.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ constexpr bool4 isinf(double4 V) { return isinf((float4)V); }
// lerp builtins overloads
//===----------------------------------------------------------------------===//

template <typename T, uint N>
constexpr __detail::enable_if_t<(N > 1 && N <= 4), vector<T, N>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think compat overload is the right place for this. Seems like we might want to keep this around past 202x.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think it feels a bit odd, but I was following the examples from clamp and min/max. I think if we're going to move them, we should do all of these together.

lerp(vector<T, N> x, vector<T, N> y, T s) {
return lerp(x, y, (vector<T, N>)s);
}

_DXC_COMPAT_TERNARY_DOUBLE_OVERLOADS(lerp)
_DXC_COMPAT_TERNARY_INTEGER_OVERLOADS(lerp)

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2587,7 +2587,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_lerp: {
if (SemaRef.checkArgCount(TheCall, 3))
return true;
if (CheckVectorElementCallArgs(&SemaRef, TheCall))
if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0) ||
CheckAllArgsHaveSameType(&SemaRef, TheCall))
return true;
if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))
return true;
Expand Down
23 changes: 21 additions & 2 deletions clang/test/CodeGenHLSL/builtins/lerp-overloads.hlsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK -DFNATTRS="noundef nofpclass(nan inf)" -DTARGET=dx
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-compute %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK -DFNATTRS="spir_func noundef nofpclass(nan inf)" -DTARGET=spv
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NATIVE_HALF -DFNATTRS="noundef nofpclass(nan inf)" -DTARGET=dx
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF -DFNATTRS="noundef nofpclass(nan inf)" -DTARGET=dx
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-compute %s -fnative-half-type -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NATIVE_HALF -DFNATTRS="spir_func noundef nofpclass(nan inf)" -DTARGET=spv
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-compute %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF -DFNATTRS="spir_func noundef nofpclass(nan inf)" -DTARGET=spv

// CHECK: define [[FNATTRS]] float @_Z16test_lerp_doubled(
// CHECK: [[CONV0:%.*]] = fptrunc {{.*}} double %{{.*}} to float
Expand Down Expand Up @@ -160,3 +162,20 @@ float3 test_lerp_uint64_t3(uint64_t3 p0) { return lerp(p0, p0, p0); }
// CHECK: [[LERP:%.*]] = call {{.*}} <4 x float> @llvm.[[TARGET]].lerp.v4f32(<4 x float> [[CONV0]], <4 x float> [[CONV1]], <4 x float> [[CONV2]])
// CHECK: ret <4 x float> [[LERP]]
float4 test_lerp_uint64_t4(uint64_t4 p0) { return lerp(p0, p0, p0); }

// NATIVE_HALF: define [[FNATTRS]] <3 x [[TY:half]]> @_Z21test_lerp_half_scalarDv3_DhS_Dh{{.*}}(
// NO_HALF: define [[FNATTRS]] <3 x [[TY:float]]> @_Z21test_lerp_half_scalarDv3_DhS_Dh(
// CHECK: [[SPLATINSERT:%.*]] = insertelement <3 x [[TY]]> poison, [[TY]] %{{.*}}, i64 0
// CHECK: [[SPLAT:%.*]] = shufflevector <3 x [[TY]]> [[SPLATINSERT]], <3 x [[TY]]> poison, <3 x i32> zeroinitializer
// CHECK: [[LERP:%.*]] = call {{.*}} <3 x [[TY]]> @llvm.[[TARGET]].lerp.{{.*}}(<3 x [[TY]]> {{.*}}, <3 x [[TY]]> {{.*}}, <3 x [[TY]]> [[SPLAT]])
// CHECK: ret <3 x [[TY]]> [[LERP]]
half3 test_lerp_half_scalar(half3 x, half3 y, half s) { return lerp(x, y, s); }

// CHECK: define [[FNATTRS]] <3 x float> @_Z22test_lerp_float_scalarDv3_fS_f(
// CHECK: [[SPLATINSERT:%.*]] = insertelement <3 x float> poison, float %{{.*}}, i64 0
// CHECK: [[SPLAT:%.*]] = shufflevector <3 x float> [[SPLATINSERT]], <3 x float> poison, <3 x i32> zeroinitializer
// CHECK: [[LERP:%.*]] = call {{.*}} <3 x float> @llvm.[[TARGET]].lerp.v3f32(<3 x float> {{.*}}, <3 x float> {{.*}}, <3 x float> [[SPLAT]])
// CHECK: ret <3 x float> [[LERP]]
float3 test_lerp_float_scalar(float3 x, float3 y, float s) {
return lerp(x, y, s);
}
22 changes: 11 additions & 11 deletions clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -62,42 +62,42 @@ float2 test_lerp_element_type_mismatch(half2 p0, float2 p1) {

float2 test_builtin_lerp_float2_splat(float p0, float2 p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float2 test_builtin_lerp_float2_splat2(double p0, double2 p1) {
return __builtin_hlsl_lerp(p1, p0, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float2 test_builtin_lerp_float2_splat3(double p0, double2 p1) {
return __builtin_hlsl_lerp(p1, p1, p0);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float3 test_builtin_lerp_float3_splat(float p0, float3 p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float4 test_builtin_lerp_float4_splat(float p0, float4 p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float2 test_lerp_float2_int_splat(float2 p0, int p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float3 test_lerp_float3_int_splat(float3 p0, int p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float2 test_builtin_lerp_int_vect_to_float_vec_promotion(int2 p0, float p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float test_builtin_lerp_bool_type_promotion(bool p0) {
Expand All @@ -107,17 +107,17 @@ float test_builtin_lerp_bool_type_promotion(bool p0) {

float builtin_bool_to_float_type_promotion(float p0, bool p1) {
return __builtin_hlsl_lerp(p0, p0, p1);
// expected-error@-1 {{3rd argument must be a scalar or vector of floating-point types (was 'bool')}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float builtin_bool_to_float_type_promotion2(bool p0, float p1) {
return __builtin_hlsl_lerp(p1, p0, p1);
// expected-error@-1 {{2nd argument must be a scalar or vector of floating-point types (was 'bool')}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float builtin_lerp_int_to_float_promotion(float p0, int p1) {
return __builtin_hlsl_lerp(p0, p0, p1);
// expected-error@-1 {{3rd argument must be a scalar or vector of floating-point types (was 'int')}}
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float4 test_lerp_int4(int4 p0, int4 p1, int4 p2) {
Expand Down
Loading