Skip to content

Commit 2b5c513

Browse files
committed
Refract implementation
1 parent 6504c96 commit 2b5c513

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
// RUN: %clang_cc1 -finclude-default-header -triple \
3+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
4+
// RUN: -emit-llvm -O1 -o - | FileCheck %s
5+
// RUN: %clang_cc1 -finclude-default-header -triple \
6+
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
7+
// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK
8+
9+
// CHECK-LABEL: define noundef nofpclass(nan inf) float @_Z18test_refract_floatff(
10+
// CHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
11+
// CHECK-NEXT: [[ENTRY:.*:]]
12+
// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[I]], 2.000000e+00
13+
// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[N]]
14+
// CHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[MUL_I]]
15+
// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[I]], [[MUL2_I]]
16+
// CHECK-NEXT: ret float [[SUB_I]]
17+
//
18+
// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) float @_Z18test_refract_floatff(
19+
// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
20+
// SPVCHECK-NEXT: [[ENTRY:.*:]]
21+
// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[I]], 2.000000e+00
22+
// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[N]]
23+
// SPVCHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[MUL_I]]
24+
// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[I]], [[MUL2_I]]
25+
// SPVCHECK-NEXT: ret float [[SUB_I]]
26+
//
27+
float test_refract_float(float I, float N, float eta) {
28+
return refract(I, N, eta);
29+
}
30+
31+
// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_(
32+
// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
33+
// CHECK-NEXT: [[ENTRY:.*:]]
34+
// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> [[I]], <2 x float> [[N]])
35+
// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00
36+
// CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[DOTSCALAR]], i64 0
37+
// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[TMP0]], <2 x float> poison, <2 x i32> zeroinitializer
38+
// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[TMP1]], [[N]]
39+
// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[I]], [[MUL1_I]]
40+
// CHECK-NEXT: ret <2 x float> [[SUB_I]]
41+
//
42+
// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_(
43+
// SPVCHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
44+
// SPVCHECK-NEXT: [[ENTRY:.*:]]
45+
// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.refract.v2f32(<2 x float> [[I]], <2 x float> [[N]])
46+
// SPVCHECK-NEXT: ret <2 x float> [[SPV_refract_I]]
47+
//
48+
float2 test_refract_float2(float2 I, float2 N, float eta) {
49+
return refract(I, N, eta);
50+
}
51+
52+
// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_(
53+
// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
54+
// CHECK-NEXT: [[ENTRY:.*:]]
55+
// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> [[I]], <3 x float> [[N]])
56+
// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00
57+
// CHECK-NEXT: [[TMP0:%.*]] = insertelement <3 x float> poison, float [[DOTSCALAR]], i64 0
58+
// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <3 x float> [[TMP0]], <3 x float> poison, <3 x i32> zeroinitializer
59+
// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[TMP1]], [[N]]
60+
// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> [[I]], [[MUL1_I]]
61+
// CHECK-NEXT: ret <3 x float> [[SUB_I]]
62+
//
63+
// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_(
64+
// SPVCHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
65+
// SPVCHECK-NEXT: [[ENTRY:.*:]]
66+
// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.refract.v3f32(<3 x float> [[I]], <3 x float> [[N]])
67+
// SPVCHECK-NEXT: ret <3 x float> [[SPV_refract_I]]
68+
//
69+
float3 test_refract_float3(float3 I, float3 N, float eta) {
70+
return refract(I, N, eta);
71+
}
72+
73+
// CHECK-LABEL: define noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_(
74+
// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
75+
// CHECK-NEXT: [[ENTRY:.*:]]
76+
// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> [[I]], <4 x float> [[N]])
77+
// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00
78+
// CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x float> poison, float [[DOTSCALAR]], i64 0
79+
// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[TMP0]], <4 x float> poison, <4 x i32> zeroinitializer
80+
// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[TMP1]], [[N]]
81+
// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> [[I]], [[MUL1_I]]
82+
// CHECK-NEXT: ret <4 x float> [[SUB_I]]
83+
//
84+
// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_(
85+
// SPVCHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
86+
// SPVCHECK-NEXT: [[ENTRY:.*:]]
87+
// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.refract.v4f32(<4 x float> [[I]], <4 x float> [[N]])
88+
// SPVCHECK-NEXT: ret <4 x float> [[SPV_refract_I]]
89+
//
90+
float4 test_refract_float4(float4 I, float4 N, float eta) {
91+
return refract(I, N, eta);
92+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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 <2 x float> @test_refract_float2(
10+
// CHECK-SAME: <2 x float> noundef [[X:%.*]], <2 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
11+
// CHECK-NEXT: [[ENTRY:.*:]]
12+
// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <2 x float> @llvm.spv.refract.v2f32(<2 x float> [[X]], <2 x float> [[Y]])
13+
// CHECK-NEXT: ret <2 x float> [[SPV_REFRACT]]
14+
//
15+
float2 test_refract_float2(float2 X, float2 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); }
16+
17+
// CHECK-LABEL: define spir_func <3 x float> @test_refract_float3(
18+
// CHECK-SAME: <3 x float> noundef [[X:%.*]], <3 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
19+
// CHECK-NEXT: [[ENTRY:.*:]]
20+
// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <3 x float> @llvm.spv.refract.v3f32(<3 x float> [[X]], <3 x float> [[Y]])
21+
// CHECK-NEXT: ret <3 x float> [[SPV_REFRACT]]
22+
//
23+
float3 test_refract_float3(float3 X, float3 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); }
24+
25+
// CHECK-LABEL: define spir_func <4 x float> @test_refract_float4(
26+
// CHECK-SAME: <4 x float> noundef [[X:%.*]], <4 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
27+
// CHECK-NEXT: [[ENTRY:.*:]]
28+
// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <4 x float> @llvm.spv.refract.v4f32(<4 x float> [[X]], <4 x float> [[Y]])
29+
// CHECK-NEXT: ret <4 x float> [[SPV_REFRACT]]
30+
//
31+
float4 test_refract_float4(float4 X, float4 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); }
32+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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_no_second_arg(float3 p0) {
4+
return refract(p0);
5+
// expected-error@-1 {{no matching function for call to 'refract'}}
6+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
7+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
8+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
9+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
10+
}
11+
12+
float test_no_third_arg(float3 p0) {
13+
return refract(p0, p0);
14+
// expected-error@-1 {{no matching function for call to 'refract'}}
15+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
16+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
17+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
18+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
19+
}
20+
21+
float test_too_many_arg(float2 p0) {
22+
return refract(p0, p0, p0, p0);
23+
// expected-error@-1 {{no matching function for call to 'refract'}}
24+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
25+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
26+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
27+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
28+
}
29+
30+
float test_double_inputs(double p0, double p1, double p2) {
31+
return refract(p0, p1, p2);
32+
// expected-error@-1 {{no matching function for call to 'refract'}}
33+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
34+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
35+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
36+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
37+
}
38+
39+
float test_int_inputs(int p0, int p1, int p2) {
40+
return refract(p0, p1, p2);
41+
// expected-error@-1 {{no matching function for call to 'refract'}}
42+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
43+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
44+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
45+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
46+
}
47+
48+
float1 test_vec1_inputs(float1 p0, float1 p1, float1 p2) {
49+
return refract(p0, p1, p2);
50+
// expected-error@-1 {{no matching function for call to 'refract'}}
51+
// 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>>'}}
52+
// 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>>'}}
53+
// 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>'}}
54+
// 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>'}}
55+
}
56+
57+
float3 test_mixed_datatype_inputs(float3 p0, float3 p1, half p2) {
58+
return refract(p0, p1, p2);
59+
}
60+
61+
half3 test_mixed_datatype_inputs(half3 p0, half3 p1, float p2) {
62+
return refract(p0, p1, p2);
63+
}
64+
65+
typedef float float5 __attribute__((ext_vector_type(5)));
66+
67+
float5 test_vec5_inputs(float5 p0, float5 p1, float p2) {
68+
return refract(p0, p1, p2);
69+
// expected-error@-1 {{no matching function for call to 'refract'}}
70+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}}
71+
// expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}}
72+
// 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>'}}
73+
// 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>'}}
74+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; Make sure SPIRV operation function calls for refract are lowered correctly.
5+
6+
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
7+
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
8+
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
9+
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
10+
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
11+
12+
define noundef <4 x half> @refract_half4(<4 x half> noundef %a, <4 x half> noundef %b, half %eta) {
13+
entry:
14+
; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
15+
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
16+
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
17+
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] refract %[[#arg0]] %[[#arg1]]
18+
%spv.refract = call <4 x half> @llvm.spv.refract.f16(<4 x half> %a, <4 x half> %b)
19+
ret <4 x half> %spv.refract
20+
}
21+
22+
define noundef <4 x float> @refract_float4(<4 x float> noundef %a, <4 x float> noundef %b, float %eta) {
23+
entry:
24+
; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]]
25+
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
26+
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
27+
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] refract %[[#arg0]] %[[#arg1]]
28+
%spv.refract = call <4 x float> @llvm.spv.refract.f32(<4 x float> %a, <4 x float> %b)
29+
ret <4 x float> %spv.refract
30+
}
31+
32+
declare <4 x half> @llvm.spv.refract.f16(<4 x half>, <4 x half>, half)
33+
declare <4 x float> @llvm.spv.refract.f32(<4 x float>, <4 x float>, float)

0 commit comments

Comments
 (0)