Implement compile-time optimization for refract().
$genType refract($genType I, $genType N, float eta);
$genHType refract($genHType I, $genHType N, half eta);
The half form of refract was originally taking a `float eta` in our
headers, which seems wrong (and causes the DSL to break unless you add
casts). I've corrected the headers to use `half eta`.
Change-Id: I74b9ac330e0f7e99622d19cf7365aaa4cc910e57
Bug: skia:12034
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/412664
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/resources/sksl/intrinsics/Refract.sksl b/resources/sksl/intrinsics/Refract.sksl
index ba04c4d..3d29308 100644
--- a/resources/sksl/intrinsics/Refract.sksl
+++ b/resources/sksl/intrinsics/Refract.sksl
@@ -3,4 +3,8 @@
void main() {
sk_FragColor.x = refract(a, b, c);
sk_FragColor = refract(d, e, c);
+
+ sk_FragColor.xy = refract(half2(1,0), half2(0,1), 0.5);
+ sk_FragColor.xyz = refract(half3(1,0,0), half3(0,0,1), 0.5);
+ sk_FragColor.xyzw = refract(half4(1,0,0,0), half4(0,0,0,1), 0.5);
}
diff --git a/src/sksl/generated/sksl_gpu.dehydrated.sksl b/src/sksl/generated/sksl_gpu.dehydrated.sksl
index 27a15ee..1d4afc7 100644
--- a/src/sksl/generated/sksl_gpu.dehydrated.sksl
+++ b/src/sksl/generated/sksl_gpu.dehydrated.sksl
@@ -1685,7 +1685,7 @@
47,49,0,3,
53,203,1,
16,186,2,
-47,168,0,3,
+47,176,0,3,
52,204,1,2,
47,200,1,
30,205,1,
diff --git a/src/sksl/generated/sksl_public.dehydrated.sksl b/src/sksl/generated/sksl_public.dehydrated.sksl
index 8abfa6d..1083779 100644
--- a/src/sksl/generated/sksl_public.dehydrated.sksl
+++ b/src/sksl/generated/sksl_public.dehydrated.sksl
@@ -962,7 +962,7 @@
47,5,0,3,
53,36,1,
16,67,1,
-47,115,0,3,
+47,123,0,3,
52,37,1,2,
47,33,1,
30,38,1,
diff --git a/src/sksl/ir/SkSLFunctionCall.cpp b/src/sksl/ir/SkSLFunctionCall.cpp
index b02e11b..5cc4030 100644
--- a/src/sksl/ir/SkSLFunctionCall.cpp
+++ b/src/sksl/ir/SkSLFunctionCall.cpp
@@ -499,6 +499,21 @@
auto N = [&] { return DSLExpression{arguments[1]->clone()}; };
return (I() - 2.0 * Dot(N(), I()) * N()).release();
}
+ case k_refract_IntrinsicKind: {
+ auto I = [&] { return DSLExpression{arguments[0]->clone()}; };
+ auto N = [&] { return DSLExpression{arguments[1]->clone()}; };
+ auto Eta = [&] { return DSLExpression{arguments[2]->clone()}; };
+
+ std::unique_ptr<Expression> k =
+ (1 - Pow(Eta(), 2) * (1 - Pow(Dot(N(), I()), 2))).release();
+ if (!k->is<FloatLiteral>()) {
+ return nullptr;
+ }
+ float kValue = k->as<FloatLiteral>().value();
+ return ((kValue < 0) ?
+ (0 * I()) :
+ (Eta() * I() - (Eta() * Dot(N(), I()) + sqrt(kValue)) * N())).release();
+ }
default:
return nullptr;
}
diff --git a/src/sksl/sksl_gpu.sksl b/src/sksl/sksl_gpu.sksl
index d159746..07aed7a 100644
--- a/src/sksl/sksl_gpu.sksl
+++ b/src/sksl/sksl_gpu.sksl
@@ -141,7 +141,7 @@
$genType reflect($genType I, $genType N);
$genHType reflect($genHType I, $genHType N);
$genType refract($genType I, $genType N, float eta);
-$genHType refract($genHType I, $genHType N, float eta);
+$genHType refract($genHType I, $genHType N, half eta);
$mat matrixCompMult($mat x, $mat y);
$hmat matrixCompMult($hmat x, $hmat y);
float2x2 outerProduct(float2 c, float2 r);
diff --git a/src/sksl/sksl_public.sksl b/src/sksl/sksl_public.sksl
index 5a14767..bd6a514 100644
--- a/src/sksl/sksl_public.sksl
+++ b/src/sksl/sksl_public.sksl
@@ -100,7 +100,7 @@
$genType reflect($genType I, $genType N);
$genHType reflect($genHType I, $genHType N);
$genType refract($genType I, $genType N, float eta);
-$genHType refract($genHType I, $genHType N, float eta);
+$genHType refract($genHType I, $genHType N, half eta);
// 8.5 : Matrix Functions
$squareMat matrixCompMult($squareMat x, $squareMat y);
diff --git a/tests/sksl/intrinsics/Refract.asm.frag b/tests/sksl/intrinsics/Refract.asm.frag
index a3da953..75e8b6c 100644
--- a/tests/sksl/intrinsics/Refract.asm.frag
+++ b/tests/sksl/intrinsics/Refract.asm.frag
@@ -37,6 +37,13 @@
OpDecorate %34 RelaxedPrecision
OpDecorate %37 RelaxedPrecision
OpDecorate %39 RelaxedPrecision
+OpDecorate %43 RelaxedPrecision
+OpDecorate %44 RelaxedPrecision
+OpDecorate %45 RelaxedPrecision
+OpDecorate %48 RelaxedPrecision
+OpDecorate %49 RelaxedPrecision
+OpDecorate %50 RelaxedPrecision
+OpDecorate %51 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -58,6 +65,14 @@
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int_3 = OpConstant %int 3
%int_4 = OpConstant %int 4
+%v2float = OpTypeVector %float 2
+%float_0_5 = OpConstant %float 0.5
+%float_n0_866025388 = OpConstant %float -0.866025388
+%43 = OpConstantComposite %v2float %float_0_5 %float_n0_866025388
+%v3float = OpTypeVector %float 3
+%float_0 = OpConstant %float 0
+%48 = OpConstantComposite %v3float %float_0_5 %float_0 %float_n0_866025388
+%51 = OpConstantComposite %v4float %float_0_5 %float_0 %float_0 %float_n0_866025388
%main = OpFunction %void None %14
%15 = OpLabel
%17 = OpAccessChain %_ptr_Uniform_float %10 %int_0
@@ -77,5 +92,12 @@
%39 = OpLoad %float %38
%30 = OpExtInst %v4float %1 Refract %34 %37 %39
OpStore %sk_FragColor %30
+%44 = OpLoad %v4float %sk_FragColor
+%45 = OpVectorShuffle %v4float %44 %43 4 5 2 3
+OpStore %sk_FragColor %45
+%49 = OpLoad %v4float %sk_FragColor
+%50 = OpVectorShuffle %v4float %49 %48 4 5 6 3
+OpStore %sk_FragColor %50
+OpStore %sk_FragColor %51
OpReturn
OpFunctionEnd
diff --git a/tests/sksl/intrinsics/Refract.glsl b/tests/sksl/intrinsics/Refract.glsl
index bab3625..cb844e2 100644
--- a/tests/sksl/intrinsics/Refract.glsl
+++ b/tests/sksl/intrinsics/Refract.glsl
@@ -8,4 +8,7 @@
void main() {
sk_FragColor.x = refract(a, b, c);
sk_FragColor = refract(d, e, c);
+ sk_FragColor.xy = vec2(0.5, -0.86602538824081421);
+ sk_FragColor.xyz = vec3(0.5, 0.0, -0.86602538824081421);
+ sk_FragColor = vec4(0.5, 0.0, 0.0, -0.86602538824081421);
}
diff --git a/tests/sksl/intrinsics/Refract.metal b/tests/sksl/intrinsics/Refract.metal
index 67bbdba..e6fbfc8 100644
--- a/tests/sksl/intrinsics/Refract.metal
+++ b/tests/sksl/intrinsics/Refract.metal
@@ -18,5 +18,8 @@
(void)_out;
_out.sk_FragColor.x = (refract(float2(_uniforms.a, 0), float2(_uniforms.b, 0), _uniforms.c).x);
_out.sk_FragColor = refract(_uniforms.d, _uniforms.e, _uniforms.c);
+ _out.sk_FragColor.xy = float2(0.5, -0.86602538824081421);
+ _out.sk_FragColor.xyz = float3(0.5, 0.0, -0.86602538824081421);
+ _out.sk_FragColor = float4(0.5, 0.0, 0.0, -0.86602538824081421);
return _out;
}