SkSL: Add test for scalar versions of geometric intrinsics

Fix code generation for Metal and Vulkan with geometric
intrinsics that have scalar versions in GLSL/SkSL, but no
native support in MSL/SPIR-V.

Change-Id: Id4538a00172e0d233ad9d5ed8d33db6436b83208
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/338276
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index 50548c4..af2b4bc 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -32,8 +32,12 @@
 void MetalCodeGenerator::setupIntrinsics() {
 #define METAL(x) std::make_pair(kMetal_IntrinsicKind, k ## x ## _MetalIntrinsic)
 #define SPECIAL(x) std::make_pair(kSpecial_IntrinsicKind, k ## x ## _SpecialIntrinsic)
-    fIntrinsicMap[String("sample")]             = SPECIAL(Texture);
+    fIntrinsicMap[String("distance")]           = SPECIAL(Distance);
+    fIntrinsicMap[String("dot")]                = SPECIAL(Dot);
+    fIntrinsicMap[String("length")]             = SPECIAL(Length);
     fIntrinsicMap[String("mod")]                = SPECIAL(Mod);
+    fIntrinsicMap[String("normalize")]          = SPECIAL(Normalize);
+    fIntrinsicMap[String("sample")]             = SPECIAL(Texture);
     fIntrinsicMap[String("equal")]              = METAL(Equal);
     fIntrinsicMap[String("notEqual")]           = METAL(NotEqual);
     fIntrinsicMap[String("lessThan")]           = METAL(LessThan);
@@ -405,6 +409,51 @@
             this->write(", " + tmpX + " - " + tmpY + " * floor(" + tmpX + " / " + tmpY + "))");
             break;
         }
+        // GLSL declares scalar versions of most geometric intrinsics, but these don't exist in MSL
+        case kDistance_SpecialIntrinsic: {
+            if (arguments[0]->type().columns() == 1) {
+                this->write("abs(");
+                this->writeExpression(*arguments[0], kAdditive_Precedence);
+                this->write(" - ");
+                this->writeExpression(*arguments[1], kAdditive_Precedence);
+                this->write(")");
+            } else {
+                this->write("distance(");
+                this->writeExpression(*arguments[0], kSequence_Precedence);
+                this->write(", ");
+                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->write(")");
+            }
+            break;
+        }
+        case kDot_SpecialIntrinsic: {
+            if (arguments[0]->type().columns() == 1) {
+                this->write("(");
+                this->writeExpression(*arguments[0], kMultiplicative_Precedence);
+                this->write(" * ");
+                this->writeExpression(*arguments[1], kMultiplicative_Precedence);
+                this->write(")");
+            } else {
+                this->write("dot(");
+                this->writeExpression(*arguments[0], kSequence_Precedence);
+                this->write(", ");
+                this->writeExpression(*arguments[1], kSequence_Precedence);
+                this->write(")");
+            }
+            break;
+        }
+        case kLength_SpecialIntrinsic: {
+            this->write(arguments[0]->type().columns() == 1 ? "abs(" : "length(");
+            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->write(")");
+            break;
+        }
+        case kNormalize_SpecialIntrinsic: {
+            this->write(arguments[0]->type().columns() == 1 ? "sign(" : "normalize(");
+            this->writeExpression(*arguments[0], kSequence_Precedence);
+            this->write(")");
+            break;
+        }
         default:
             ABORT("unsupported special intrinsic kind");
     }