Add support for isinf/isnan intrinsics to SPIR-V.

Change-Id: I674d758c11071582e9fbedcda5596c540bfb5f71
Bug: skia:11054
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/342558
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 29b2097..c4f088d 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -233,6 +233,8 @@
   "$_tests/sksl/intrinsics/GreaterThanEqual.sksl",
   "$_tests/sksl/intrinsics/Inverse.sksl",
   "$_tests/sksl/intrinsics/Inversesqrt.sksl",
+  "$_tests/sksl/intrinsics/IsInf.sksl",
+  "$_tests/sksl/intrinsics/IsNan.sksl",
   "$_tests/sksl/intrinsics/Ldexp.sksl",
   "$_tests/sksl/intrinsics/Length.sksl",
   "$_tests/sksl/intrinsics/LessThan.sksl",
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index 79ad269..1866546 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -66,6 +66,8 @@
     fIntrinsicMap[String("sqrt")]          = ALL_GLSL(Sqrt);
     fIntrinsicMap[String("inverse")]       = ALL_GLSL(MatrixInverse);
     fIntrinsicMap[String("transpose")]     = ALL_SPIRV(Transpose);
+    fIntrinsicMap[String("isinf")]         = ALL_SPIRV(IsInf);
+    fIntrinsicMap[String("isnan")]         = ALL_SPIRV(IsNan);
     fIntrinsicMap[String("inversesqrt")]   = ALL_GLSL(InverseSqrt);
     fIntrinsicMap[String("determinant")]   = ALL_GLSL(Determinant);
     fIntrinsicMap[String("matrixInverse")] = ALL_GLSL(MatrixInverse);
diff --git a/tests/sksl/intrinsics/IsInf.sksl b/tests/sksl/intrinsics/IsInf.sksl
new file mode 100644
index 0000000..0326831
--- /dev/null
+++ b/tests/sksl/intrinsics/IsInf.sksl
@@ -0,0 +1 @@
+in half a; void main() { sk_FragColor.x = isinf(a) ? 1 : 0; }
diff --git a/tests/sksl/intrinsics/IsNan.sksl b/tests/sksl/intrinsics/IsNan.sksl
new file mode 100644
index 0000000..e9627a9
--- /dev/null
+++ b/tests/sksl/intrinsics/IsNan.sksl
@@ -0,0 +1 @@
+in half a; void main() { sk_FragColor.x = isnan(a) ? 1 : 0; }
diff --git a/tests/sksl/intrinsics/golden/IsInf.asm.frag b/tests/sksl/intrinsics/golden/IsInf.asm.frag
new file mode 100644
index 0000000..e87fa42
--- /dev/null
+++ b/tests/sksl/intrinsics/golden/IsInf.asm.frag
@@ -0,0 +1,41 @@
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise %a
+OpExecutionMode %main OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %a "a"
+OpName %main "main"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise RelaxedPrecision
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpDecorate %a RelaxedPrecision
+OpDecorate %17 RelaxedPrecision
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%sk_FragColor = OpVariable %_ptr_Output_v4float Output
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%_ptr_Input_float = OpTypePointer Input %float
+%a = OpVariable %_ptr_Input_float Input
+%void = OpTypeVoid
+%13 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%int_0 = OpConstant %int 0
+%_ptr_Output_float = OpTypePointer Output %float
+%main = OpFunction %void None %13
+%14 = OpLabel
+%17 = OpLoad %float %a
+%16 = OpIsInf %bool %17
+%18 = OpSelect %int %16 %int_1 %int_0
+%15 = OpConvertSToF %float %18
+%22 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
+OpStore %22 %15
+OpReturn
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/golden/IsInf.glsl b/tests/sksl/intrinsics/golden/IsInf.glsl
new file mode 100644
index 0000000..ea52a66
--- /dev/null
+++ b/tests/sksl/intrinsics/golden/IsInf.glsl
@@ -0,0 +1,6 @@
+
+out vec4 sk_FragColor;
+in float a;
+void main() {
+    sk_FragColor.x = float(isinf(a) ? 1 : 0);
+}
diff --git a/tests/sksl/intrinsics/golden/IsInf.metal b/tests/sksl/intrinsics/golden/IsInf.metal
new file mode 100644
index 0000000..35b0354
--- /dev/null
+++ b/tests/sksl/intrinsics/golden/IsInf.metal
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Inputs {
+    float a;
+};
+struct Outputs {
+    float4 sk_FragColor [[color(0)]];
+};
+
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+    Outputs _outputStruct;
+    thread Outputs* _out = &_outputStruct;
+    _out->sk_FragColor.x = float(isinf(_in.a) ? 1 : 0);
+    return *_out;
+}
diff --git a/tests/sksl/intrinsics/golden/IsNan.asm.frag b/tests/sksl/intrinsics/golden/IsNan.asm.frag
new file mode 100644
index 0000000..d6f0815
--- /dev/null
+++ b/tests/sksl/intrinsics/golden/IsNan.asm.frag
@@ -0,0 +1,41 @@
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise %a
+OpExecutionMode %main OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %a "a"
+OpName %main "main"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise RelaxedPrecision
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpDecorate %a RelaxedPrecision
+OpDecorate %17 RelaxedPrecision
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%sk_FragColor = OpVariable %_ptr_Output_v4float Output
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%_ptr_Input_float = OpTypePointer Input %float
+%a = OpVariable %_ptr_Input_float Input
+%void = OpTypeVoid
+%13 = OpTypeFunction %void
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%int_0 = OpConstant %int 0
+%_ptr_Output_float = OpTypePointer Output %float
+%main = OpFunction %void None %13
+%14 = OpLabel
+%17 = OpLoad %float %a
+%16 = OpIsNan %bool %17
+%18 = OpSelect %int %16 %int_1 %int_0
+%15 = OpConvertSToF %float %18
+%22 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
+OpStore %22 %15
+OpReturn
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/golden/IsNan.glsl b/tests/sksl/intrinsics/golden/IsNan.glsl
new file mode 100644
index 0000000..fb705ae
--- /dev/null
+++ b/tests/sksl/intrinsics/golden/IsNan.glsl
@@ -0,0 +1,6 @@
+
+out vec4 sk_FragColor;
+in float a;
+void main() {
+    sk_FragColor.x = float(isnan(a) ? 1 : 0);
+}
diff --git a/tests/sksl/intrinsics/golden/IsNan.metal b/tests/sksl/intrinsics/golden/IsNan.metal
new file mode 100644
index 0000000..fee1a13
--- /dev/null
+++ b/tests/sksl/intrinsics/golden/IsNan.metal
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Inputs {
+    float a;
+};
+struct Outputs {
+    float4 sk_FragColor [[color(0)]];
+};
+
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+    Outputs _outputStruct;
+    thread Outputs* _out = &_outputStruct;
+    _out->sk_FragColor.x = float(isnan(_in.a) ? 1 : 0);
+    return *_out;
+}