Add support for pack/unpackUnorm2x16 to public SkSL.

This includes compile-time optimization and tests.

The unit test is disabled in a followup CL
(http://review.skia.org/447057) because it exposes a Radeon 5300M bug
in OpenGL.

Change-Id: I8b2f0411358aeb68c4edfeb0bd7a2814c4be1f40
Bug: skia:12202
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/447056
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 1421880..d7b2e0f 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -261,6 +261,7 @@
   "/sksl/intrinsics/NotEqual.sksl",
   "/sksl/intrinsics/OuterProduct.sksl",
   "/sksl/intrinsics/Pack.sksl",
+  "/sksl/intrinsics/PackUnorm2x16.sksl",
   "/sksl/intrinsics/Pow.sksl",
   "/sksl/intrinsics/Radians.sksl",
   "/sksl/intrinsics/Reflect.sksl",
diff --git a/resources/sksl/intrinsics/PackUnorm2x16.sksl b/resources/sksl/intrinsics/PackUnorm2x16.sksl
new file mode 100644
index 0000000..fc7c83b
--- /dev/null
+++ b/resources/sksl/intrinsics/PackUnorm2x16.sksl
@@ -0,0 +1,18 @@
+uniform half4 colorGreen, colorRed;
+uniform float4 testInputs;  // equals (-1.25, 0, 0.75, 2.25)
+
+half4 main(float2 coords) {
+    const float4 constVal = float4(-1.25, 0, 0.75, 2.25);
+    const float4 expected = clamp(constVal, 0, 1);
+    const uint constXY = packUnorm2x16(constVal.xy);
+    const uint constZW = packUnorm2x16(constVal.zw);
+    uint xy = packUnorm2x16(testInputs.xy);
+    uint zw = packUnorm2x16(testInputs.zw);
+    const float2 tolerance = float2(0.015625);
+
+    return (all(lessThan(abs(unpackUnorm2x16(xy)      - float2(expected.xy)), tolerance)) &&
+            all(lessThan(abs(unpackUnorm2x16(zw)      - float2(expected.zw)), tolerance)) &&
+            all(lessThan(abs(unpackUnorm2x16(constXY) - float2(expected.xy)), tolerance)) &&
+            all(lessThan(abs(unpackUnorm2x16(constZW) - float2(expected.zw)), tolerance)))
+              ? colorGreen : colorRed;
+}
diff --git a/src/sksl/generated/sksl_public.dehydrated.sksl b/src/sksl/generated/sksl_public.dehydrated.sksl
index 057103c..d2bd929 100644
--- a/src/sksl/generated/sksl_public.dehydrated.sksl
+++ b/src/sksl/generated/sksl_public.dehydrated.sksl
@@ -1,4 +1,4 @@
-static uint8_t SKSL_INCLUDE_sksl_public[] = {128,3,
+static uint8_t SKSL_INCLUDE_sksl_public[] = {165,3,
 7,100,101,103,114,101,101,115,
 8,36,103,101,110,84,121,112,101,
 7,114,97,100,105,97,110,115,
@@ -63,6 +63,12 @@
 5,105,115,105,110,102,
 1,105,
 4,109,111,100,102,
+1,118,
+6,102,108,111,97,116,50,
+13,112,97,99,107,85,110,111,114,109,50,120,49,54,
+4,117,105,110,116,
+1,112,
+15,117,110,112,97,99,107,85,110,111,114,109,50,120,49,54,
 6,108,101,110,103,116,104,
 2,112,48,
 2,112,49,
@@ -112,7 +118,6 @@
 4,98,111,111,108,
 3,97,108,108,
 3,110,111,116,
-1,112,
 4,100,70,100,120,
 4,100,70,100,121,
 5,99,111,108,111,114,
@@ -122,7 +127,6 @@
 1,115,
 6,115,104,97,100,101,114,
 6,99,111,111,114,100,115,
-6,102,108,111,97,116,50,
 6,115,97,109,112,108,101,
 1,102,
 11,99,111,108,111,114,70,105,108,116,101,114,
@@ -131,7 +135,7 @@
 3,115,114,99,
 3,100,115,116,
 5,36,101,118,97,108,
-48,59,2,
+48,63,2,
 52,1,0,
 17,2,0,
 49,2,0,10,0,3,
@@ -1237,820 +1241,834 @@
 46,5,0,
 46,90,1,
 52,91,1,
-17,55,0,
-46,2,0,3,
-29,92,1,
-17,159,1,1,91,1,
-46,145,0,
-52,93,1,
-17,55,0,
-46,5,0,3,
-51,94,1,2,
+17,159,1,
+49,92,1,161,1,3,
+29,93,1,
+37,
+16,0,16,0,0,168,1,1,91,1,
+49,94,1,182,1,
+52,95,1,
+17,187,1,
+46,94,1,3,
+29,96,1,
+37,
+16,0,16,0,0,189,1,1,95,1,
 46,92,1,
-29,95,1,
-17,159,1,1,93,1,
-46,153,0,
-46,95,1,
-52,96,1,
-17,166,1,
-46,2,0,3,
 52,97,1,
-17,169,1,
+17,55,0,
 46,2,0,3,
 29,98,1,
-17,172,1,2,96,1,97,1,
+17,205,1,1,97,1,
 46,145,0,
 52,99,1,
-17,166,1,
+17,55,0,
 46,5,0,3,
-52,100,1,
-17,169,1,
-46,5,0,3,
-51,101,1,2,
+51,100,1,2,
 46,98,1,
-29,102,1,
-17,172,1,2,99,1,100,1,
+29,101,1,
+17,205,1,1,99,1,
 46,153,0,
-46,102,1,
+46,101,1,
+52,102,1,
+17,212,1,
+46,2,0,3,
 52,103,1,
-17,55,0,
+17,215,1,
 46,2,0,3,
-52,104,1,
-17,67,0,
-46,2,0,3,
-29,105,1,
-17,181,1,2,103,1,104,1,
+29,104,1,
+17,218,1,2,102,1,103,1,
 46,145,0,
+52,105,1,
+17,212,1,
+46,5,0,3,
 52,106,1,
-17,55,0,
+17,215,1,
 46,5,0,3,
-52,107,1,
-17,67,0,
-46,5,0,3,
-51,108,1,2,
-46,105,1,
-29,109,1,
-17,181,1,2,106,1,107,1,
+51,107,1,2,
+46,104,1,
+29,108,1,
+17,218,1,2,105,1,106,1,
 46,153,0,
-46,109,1,
+46,108,1,
+52,109,1,
+17,55,0,
+46,2,0,3,
 52,110,1,
-17,55,0,
-49,111,1,185,1,3,
-52,112,1,
 17,67,0,
-46,111,1,3,
-29,113,1,
-17,192,1,2,110,1,112,1,
-46,111,1,
-52,114,1,
-17,55,0,
-49,115,1,198,1,3,
-52,116,1,
-17,67,0,
-46,115,1,3,
-51,117,1,2,
-46,113,1,
-29,118,1,
-17,192,1,2,114,1,116,1,
-46,115,1,
-46,118,1,
-52,119,1,
-17,55,0,
 46,2,0,3,
-29,120,1,
-17,204,1,1,119,1,
-46,2,0,
-52,121,1,
-17,55,0,
-46,5,0,3,
-51,122,1,2,
-46,120,1,
-29,123,1,
-17,204,1,1,121,1,
-46,5,0,
-46,123,1,
-52,124,1,
-17,214,1,
-46,2,0,3,
-52,125,1,
-17,216,1,
-46,2,0,3,
-52,126,1,
-17,218,1,
-46,2,0,3,
-29,127,1,
-17,223,1,3,124,1,125,1,126,1,
-46,2,0,
-52,128,1,
-17,214,1,
-46,5,0,3,
-52,129,1,
-17,216,1,
-46,5,0,3,
-52,130,1,
-17,218,1,
-46,5,0,3,
-51,131,1,2,
-46,127,1,
-29,132,1,
-17,223,1,3,128,1,129,1,130,1,
-46,5,0,
-46,132,1,
-52,133,1,
-17,216,1,
-46,2,0,3,
-52,134,1,
-17,214,1,
-46,2,0,3,
-29,135,1,
-17,235,1,2,133,1,134,1,
-46,2,0,
-52,136,1,
-17,216,1,
-46,5,0,3,
-52,137,1,
-17,214,1,
-46,5,0,3,
-51,138,1,2,
-46,135,1,
-29,139,1,
-17,235,1,2,136,1,137,1,
-46,5,0,
-46,139,1,
-52,140,1,
-17,216,1,
-46,2,0,3,
-52,141,1,
-17,214,1,
-46,2,0,3,
-52,142,1,
-17,243,1,
-46,145,0,3,
-29,143,1,
-17,247,1,3,140,1,141,1,142,1,
-46,2,0,
-52,144,1,
-17,216,1,
-46,5,0,3,
-52,145,1,
-17,214,1,
-46,5,0,3,
-52,146,1,
-17,243,1,
-46,153,0,3,
-51,147,1,2,
-46,143,1,
-29,148,1,
-17,247,1,3,144,1,145,1,146,1,
-46,5,0,
-46,148,1,
-52,149,1,
-17,55,0,
-49,150,1,255,1,3,
-52,151,1,
-17,67,0,
-46,150,1,3,
-29,152,1,
-17,10,2,2,149,1,151,1,
-46,150,1,
-52,153,1,
-17,55,0,
-49,154,1,25,2,3,
-52,155,1,
-17,67,0,
-46,154,1,3,
-51,156,1,2,
-46,152,1,
-29,157,1,
-17,10,2,2,153,1,155,1,
-46,154,1,
-46,157,1,
-52,158,1,
-17,37,2,
-46,150,1,3,
-29,159,1,
-37,
-16,0,16,0,0,39,2,1,158,1,
+29,111,1,
+17,227,1,2,109,1,110,1,
 46,145,0,
-52,160,1,
-17,37,2,
-46,154,1,3,
-51,161,1,2,
-46,159,1,
-29,162,1,
-37,
-16,0,16,0,0,39,2,1,160,1,
+52,112,1,
+17,55,0,
+46,5,0,3,
+52,113,1,
+17,67,0,
+46,5,0,3,
+51,114,1,2,
+46,111,1,
+29,115,1,
+17,227,1,2,112,1,113,1,
 46,153,0,
-46,162,1,
-52,163,1,
-17,37,2,
-46,150,1,3,
-29,164,1,
-37,
-16,0,16,0,0,51,2,1,163,1,
-46,150,1,
-52,165,1,
-17,37,2,
-46,154,1,3,
-51,166,1,2,
-46,164,1,
-29,167,1,
-37,
-16,0,16,0,0,51,2,1,165,1,
+46,115,1,
+52,116,1,
+17,55,0,
+49,117,1,231,1,3,
+52,118,1,
+17,67,0,
+46,117,1,3,
+29,119,1,
+17,238,1,2,116,1,118,1,
+46,117,1,
+52,120,1,
+17,55,0,
+49,121,1,244,1,3,
+52,122,1,
+17,67,0,
+46,121,1,3,
+51,123,1,2,
+46,119,1,
+29,124,1,
+17,238,1,2,120,1,122,1,
+46,121,1,
+46,124,1,
+52,125,1,
+17,55,0,
+46,2,0,3,
+29,126,1,
+17,250,1,1,125,1,
+46,2,0,
+52,127,1,
+17,55,0,
+46,5,0,3,
+51,128,1,2,
+46,126,1,
+29,129,1,
+17,250,1,1,127,1,
+46,5,0,
+46,129,1,
+52,130,1,
+17,4,2,
+46,2,0,3,
+52,131,1,
+17,6,2,
+46,2,0,3,
+52,132,1,
+17,8,2,
+46,2,0,3,
+29,133,1,
+17,13,2,3,130,1,131,1,132,1,
+46,2,0,
+52,134,1,
+17,4,2,
+46,5,0,3,
+52,135,1,
+17,6,2,
+46,5,0,3,
+52,136,1,
+17,8,2,
+46,5,0,3,
+51,137,1,2,
+46,133,1,
+29,138,1,
+17,13,2,3,134,1,135,1,136,1,
+46,5,0,
+46,138,1,
+52,139,1,
+17,6,2,
+46,2,0,3,
+52,140,1,
+17,4,2,
+46,2,0,3,
+29,141,1,
+17,25,2,2,139,1,140,1,
+46,2,0,
+52,142,1,
+17,6,2,
+46,5,0,3,
+52,143,1,
+17,4,2,
+46,5,0,3,
+51,144,1,2,
+46,141,1,
+29,145,1,
+17,25,2,2,142,1,143,1,
+46,5,0,
+46,145,1,
+52,146,1,
+17,6,2,
+46,2,0,3,
+52,147,1,
+17,4,2,
+46,2,0,3,
+52,148,1,
+17,33,2,
+46,145,0,3,
+29,149,1,
+17,37,2,3,146,1,147,1,148,1,
+46,2,0,
+52,150,1,
+17,6,2,
+46,5,0,3,
+52,151,1,
+17,4,2,
+46,5,0,3,
+52,152,1,
+17,33,2,
+46,153,0,3,
+51,153,1,2,
+46,149,1,
+29,154,1,
+17,37,2,3,150,1,151,1,152,1,
+46,5,0,
 46,154,1,
-46,167,1,
-52,168,1,
-17,37,2,
-49,169,1,61,2,3,
-51,170,1,3,
-46,164,1,
-46,167,1,
-29,171,1,
+52,155,1,
+17,55,0,
+49,156,1,45,2,3,
+52,157,1,
+17,67,0,
+46,156,1,3,
+29,158,1,
+17,56,2,2,155,1,157,1,
+46,156,1,
+52,159,1,
+17,55,0,
+49,160,1,71,2,3,
+52,161,1,
+17,67,0,
+46,160,1,3,
+51,162,1,2,
+46,158,1,
+29,163,1,
+17,56,2,2,159,1,161,1,
+46,160,1,
+46,163,1,
+52,164,1,
+17,83,2,
+46,156,1,3,
+29,165,1,
 37,
-16,0,16,0,0,51,2,1,168,1,
-49,172,1,70,2,
-46,171,1,
-52,173,1,
-17,37,2,
-49,174,1,79,2,3,
-51,175,1,4,
-46,164,1,
-46,167,1,
-46,171,1,
-29,176,1,
+16,0,16,0,0,85,2,1,164,1,
+46,145,0,
+52,166,1,
+17,83,2,
+46,160,1,3,
+51,167,1,2,
+46,165,1,
+29,168,1,
 37,
-16,0,16,0,0,51,2,1,173,1,
-49,177,1,87,2,
-46,176,1,
-52,178,1,
-17,37,2,
-49,179,1,95,2,3,
-51,180,1,5,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-29,181,1,
+16,0,16,0,0,85,2,1,166,1,
+46,153,0,
+46,168,1,
+52,169,1,
+17,83,2,
+46,156,1,3,
+29,170,1,
 37,
-16,0,16,0,0,51,2,1,178,1,
-49,182,1,104,2,
-46,181,1,
-52,183,1,
-17,37,2,
-49,184,1,113,2,3,
-51,185,1,6,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-29,186,1,
+16,0,16,0,0,97,2,1,169,1,
+46,156,1,
+52,171,1,
+17,83,2,
+46,160,1,3,
+51,172,1,2,
+46,170,1,
+29,173,1,
 37,
-16,0,16,0,0,51,2,1,183,1,
-49,187,1,121,2,
-46,186,1,
-52,188,1,
-17,37,2,
-46,172,1,3,
-51,189,1,7,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-29,190,1,
+16,0,16,0,0,97,2,1,171,1,
+46,160,1,
+46,173,1,
+52,174,1,
+17,83,2,
+49,175,1,107,2,3,
+51,176,1,3,
+46,170,1,
+46,173,1,
+29,177,1,
 37,
-16,0,16,0,0,51,2,1,188,1,
-46,169,1,
-46,190,1,
-52,191,1,
-17,37,2,
-46,177,1,3,
-51,192,1,8,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-29,193,1,
+16,0,16,0,0,97,2,1,174,1,
+49,178,1,116,2,
+46,177,1,
+52,179,1,
+17,83,2,
+49,180,1,125,2,3,
+51,181,1,4,
+46,170,1,
+46,173,1,
+46,177,1,
+29,182,1,
 37,
-16,0,16,0,0,51,2,1,191,1,
-46,174,1,
-46,193,1,
+16,0,16,0,0,97,2,1,179,1,
+49,183,1,133,2,
+46,182,1,
+52,184,1,
+17,83,2,
+49,185,1,141,2,3,
+51,186,1,5,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+29,187,1,
+37,
+16,0,16,0,0,97,2,1,184,1,
+49,188,1,150,2,
+46,187,1,
+52,189,1,
+17,83,2,
+49,190,1,159,2,3,
+51,191,1,6,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+29,192,1,
+37,
+16,0,16,0,0,97,2,1,189,1,
+49,193,1,167,2,
+46,192,1,
 52,194,1,
-17,37,2,
-49,195,1,129,2,3,
-51,196,1,9,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-46,193,1,
-29,197,1,
+17,83,2,
+46,178,1,3,
+51,195,1,7,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+29,196,1,
 37,
-16,0,16,0,0,51,2,1,194,1,
-49,198,1,138,2,
-46,197,1,
-52,199,1,
-17,37,2,
-49,200,1,147,2,3,
-51,201,1,10,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-46,193,1,
-46,197,1,
-29,202,1,
+16,0,16,0,0,97,2,1,194,1,
+46,175,1,
+46,196,1,
+52,197,1,
+17,83,2,
+46,183,1,3,
+51,198,1,8,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+29,199,1,
 37,
-16,0,16,0,0,51,2,1,199,1,
-49,203,1,155,2,
-46,202,1,
-52,204,1,
-17,37,2,
-46,182,1,3,
-51,205,1,11,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-46,193,1,
-46,197,1,
-46,202,1,
-29,206,1,
+16,0,16,0,0,97,2,1,197,1,
+46,180,1,
+46,199,1,
+52,200,1,
+17,83,2,
+49,201,1,175,2,3,
+51,202,1,9,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+46,199,1,
+29,203,1,
 37,
-16,0,16,0,0,51,2,1,204,1,
-46,179,1,
-46,206,1,
-52,207,1,
-17,37,2,
-46,187,1,3,
-51,208,1,12,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-46,193,1,
-46,197,1,
-46,202,1,
-46,206,1,
-29,209,1,
+16,0,16,0,0,97,2,1,200,1,
+49,204,1,184,2,
+46,203,1,
+52,205,1,
+17,83,2,
+49,206,1,193,2,3,
+51,207,1,10,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+46,199,1,
+46,203,1,
+29,208,1,
 37,
-16,0,16,0,0,51,2,1,207,1,
-46,184,1,
-46,209,1,
+16,0,16,0,0,97,2,1,205,1,
+49,209,1,201,2,
+46,208,1,
 52,210,1,
-17,37,2,
-46,198,1,3,
-51,211,1,13,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-46,193,1,
-46,197,1,
-46,202,1,
-46,206,1,
-46,209,1,
+17,83,2,
+46,188,1,3,
+51,211,1,11,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+46,199,1,
+46,203,1,
+46,208,1,
 29,212,1,
 37,
-16,0,16,0,0,51,2,1,210,1,
-46,195,1,
+16,0,16,0,0,97,2,1,210,1,
+46,185,1,
 46,212,1,
 52,213,1,
-17,37,2,
-46,203,1,3,
-51,214,1,14,
-46,164,1,
-46,167,1,
-46,171,1,
-46,176,1,
-46,181,1,
-46,186,1,
-46,190,1,
-46,193,1,
-46,197,1,
-46,202,1,
-46,206,1,
-46,209,1,
+17,83,2,
+46,193,1,3,
+51,214,1,12,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+46,199,1,
+46,203,1,
+46,208,1,
 46,212,1,
 29,215,1,
 37,
-16,0,16,0,0,51,2,1,213,1,
-46,200,1,
+16,0,16,0,0,97,2,1,213,1,
+46,190,1,
 46,215,1,
 52,216,1,
-17,37,2,
-46,150,1,3,
-29,217,1,
-17,163,2,1,216,1,
-46,150,1,
-52,218,1,
-17,37,2,
-46,154,1,3,
-51,219,1,2,
-46,217,1,
-29,220,1,
-17,163,2,1,218,1,
-46,154,1,
-46,220,1,
-52,221,1,
+17,83,2,
+46,204,1,3,
+51,217,1,13,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+46,199,1,
+46,203,1,
+46,208,1,
+46,212,1,
+46,215,1,
+29,218,1,
+37,
+16,0,16,0,0,97,2,1,216,1,
+46,201,1,
+46,218,1,
+52,219,1,
+17,83,2,
+46,209,1,3,
+51,220,1,14,
+46,170,1,
+46,173,1,
+46,177,1,
+46,182,1,
+46,187,1,
+46,192,1,
+46,196,1,
+46,199,1,
+46,203,1,
+46,208,1,
+46,212,1,
+46,215,1,
+46,218,1,
+29,221,1,
+37,
+16,0,16,0,0,97,2,1,219,1,
+46,206,1,
+46,221,1,
+52,222,1,
+17,83,2,
+46,156,1,3,
+29,223,1,
+17,209,2,1,222,1,
+46,156,1,
+52,224,1,
+17,83,2,
+46,160,1,3,
+51,225,1,2,
+46,223,1,
+29,226,1,
+17,209,2,1,224,1,
+46,160,1,
+46,226,1,
+52,227,1,
 17,55,0,
-49,222,1,171,2,3,
-52,223,1,
+49,228,1,217,2,3,
+52,229,1,
 17,67,0,
-46,222,1,3,
-29,224,1,
-17,176,2,2,221,1,223,1,
-49,225,1,185,2,
-52,226,1,
-17,55,0,
-49,227,1,191,2,3,
-52,228,1,
-17,67,0,
-46,227,1,3,
-51,229,1,2,
-46,224,1,
+46,228,1,3,
 29,230,1,
-17,176,2,2,226,1,228,1,
-46,225,1,
-46,230,1,
-52,231,1,
+17,222,2,2,227,1,229,1,
+49,231,1,231,2,
+52,232,1,
 17,55,0,
-49,232,1,197,2,3,
-52,233,1,
+49,233,1,237,2,3,
+52,234,1,
 17,67,0,
-46,232,1,3,
-51,234,1,3,
-46,224,1,
+46,233,1,3,
+51,235,1,2,
 46,230,1,
-29,235,1,
-17,176,2,2,231,1,233,1,
-46,225,1,
-46,235,1,
-52,236,1,
-17,55,0,
-46,222,1,3,
+29,236,1,
+17,222,2,2,232,1,234,1,
+46,231,1,
+46,236,1,
 52,237,1,
-17,67,0,
-46,222,1,3,
-29,238,1,
-17,203,2,2,236,1,237,1,
-46,225,1,
+17,55,0,
+49,238,1,243,2,3,
 52,239,1,
-17,55,0,
-46,227,1,3,
-52,240,1,
 17,67,0,
-46,227,1,3,
-51,241,1,2,
-46,238,1,
-29,242,1,
-17,203,2,2,239,1,240,1,
-46,225,1,
-46,242,1,
+46,238,1,3,
+51,240,1,3,
+46,230,1,
+46,236,1,
+29,241,1,
+17,222,2,2,237,1,239,1,
+46,231,1,
+46,241,1,
+52,242,1,
+17,55,0,
+46,228,1,3,
 52,243,1,
-17,55,0,
-46,232,1,3,
-52,244,1,
 17,67,0,
-46,232,1,3,
-51,245,1,3,
-46,238,1,
-46,242,1,
-29,246,1,
-17,203,2,2,243,1,244,1,
-46,225,1,
-46,246,1,
-52,247,1,
+46,228,1,3,
+29,244,1,
+17,249,2,2,242,1,243,1,
+46,231,1,
+52,245,1,
 17,55,0,
-46,222,1,3,
-52,248,1,
+46,233,1,3,
+52,246,1,
 17,67,0,
-46,222,1,3,
-29,249,1,
-17,217,2,2,247,1,248,1,
-46,225,1,
+46,233,1,3,
+51,247,1,2,
+46,244,1,
+29,248,1,
+17,249,2,2,245,1,246,1,
+46,231,1,
+46,248,1,
+52,249,1,
+17,55,0,
+46,238,1,3,
 52,250,1,
-17,55,0,
-46,227,1,3,
-52,251,1,
 17,67,0,
-46,227,1,3,
-51,252,1,2,
-46,249,1,
-29,253,1,
-17,217,2,2,250,1,251,1,
-46,225,1,
-46,253,1,
+46,238,1,3,
+51,251,1,3,
+46,244,1,
+46,248,1,
+29,252,1,
+17,249,2,2,249,1,250,1,
+46,231,1,
+46,252,1,
+52,253,1,
+17,55,0,
+46,228,1,3,
 52,254,1,
-17,55,0,
-46,232,1,3,
-52,255,1,
 17,67,0,
-46,232,1,3,
-51,0,2,3,
-46,249,1,
-46,253,1,
-29,1,2,
-17,217,2,2,254,1,255,1,
-46,225,1,
-46,1,2,
-52,2,2,
+46,228,1,3,
+29,255,1,
+17,7,3,2,253,1,254,1,
+46,231,1,
+52,0,2,
 17,55,0,
-46,222,1,3,
-52,3,2,
+46,233,1,3,
+52,1,2,
 17,67,0,
-46,222,1,3,
-29,4,2,
-17,229,2,2,2,2,3,2,
-46,225,1,
+46,233,1,3,
+51,2,2,2,
+46,255,1,
+29,3,2,
+17,7,3,2,0,2,1,2,
+46,231,1,
+46,3,2,
+52,4,2,
+17,55,0,
+46,238,1,3,
 52,5,2,
-17,55,0,
-46,227,1,3,
-52,6,2,
 17,67,0,
-46,227,1,3,
-51,7,2,2,
-46,4,2,
-29,8,2,
-17,229,2,2,5,2,6,2,
-46,225,1,
-46,8,2,
+46,238,1,3,
+51,6,2,3,
+46,255,1,
+46,3,2,
+29,7,2,
+17,7,3,2,4,2,5,2,
+46,231,1,
+46,7,2,
+52,8,2,
+17,55,0,
+46,228,1,3,
 52,9,2,
-17,55,0,
-46,232,1,3,
-52,10,2,
 17,67,0,
-46,232,1,3,
-51,11,2,3,
-46,4,2,
-46,8,2,
-29,12,2,
-17,229,2,2,9,2,10,2,
-46,225,1,
-46,12,2,
-52,13,2,
+46,228,1,3,
+29,10,2,
+17,19,3,2,8,2,9,2,
+46,231,1,
+52,11,2,
 17,55,0,
-46,222,1,3,
-52,14,2,
+46,233,1,3,
+52,12,2,
 17,67,0,
-46,222,1,3,
-29,15,2,
-17,246,2,2,13,2,14,2,
-46,225,1,
+46,233,1,3,
+51,13,2,2,
+46,10,2,
+29,14,2,
+17,19,3,2,11,2,12,2,
+46,231,1,
+46,14,2,
+52,15,2,
+17,55,0,
+46,238,1,3,
 52,16,2,
-17,55,0,
-46,227,1,3,
-52,17,2,
 17,67,0,
-46,227,1,3,
-51,18,2,2,
-46,15,2,
-29,19,2,
-17,246,2,2,16,2,17,2,
-46,225,1,
-46,19,2,
+46,238,1,3,
+51,17,2,3,
+46,10,2,
+46,14,2,
+29,18,2,
+17,19,3,2,15,2,16,2,
+46,231,1,
+46,18,2,
+52,19,2,
+17,55,0,
+46,228,1,3,
 52,20,2,
-17,55,0,
-46,232,1,3,
-52,21,2,
 17,67,0,
-46,232,1,3,
-51,22,2,3,
-46,15,2,
-46,19,2,
-29,23,2,
-17,246,2,2,20,2,21,2,
-46,225,1,
-46,23,2,
-52,24,2,
+46,228,1,3,
+29,21,2,
+17,36,3,2,19,2,20,2,
+46,231,1,
+52,22,2,
 17,55,0,
-46,225,1,3,
-52,25,2,
+46,233,1,3,
+52,23,2,
 17,67,0,
-46,225,1,3,
-51,26,2,4,
-46,15,2,
-46,19,2,
-46,23,2,
-29,27,2,
-17,246,2,2,24,2,25,2,
-46,225,1,
-46,27,2,
-52,28,2,
+46,233,1,3,
+51,24,2,2,
+46,21,2,
+29,25,2,
+17,36,3,2,22,2,23,2,
+46,231,1,
+46,25,2,
+52,26,2,
 17,55,0,
-46,222,1,3,
-52,29,2,
+46,238,1,3,
+52,27,2,
 17,67,0,
-46,222,1,3,
-29,30,2,
-17,252,2,2,28,2,29,2,
-46,225,1,
+46,238,1,3,
+51,28,2,3,
+46,21,2,
+46,25,2,
+29,29,2,
+17,36,3,2,26,2,27,2,
+46,231,1,
+46,29,2,
+52,30,2,
+17,55,0,
+46,231,1,3,
 52,31,2,
-17,55,0,
-46,227,1,3,
-52,32,2,
 17,67,0,
-46,227,1,3,
-51,33,2,2,
-46,30,2,
-29,34,2,
-17,252,2,2,31,2,32,2,
-46,225,1,
-46,34,2,
+46,231,1,3,
+51,32,2,4,
+46,21,2,
+46,25,2,
+46,29,2,
+29,33,2,
+17,36,3,2,30,2,31,2,
+46,231,1,
+46,33,2,
+52,34,2,
+17,55,0,
+46,228,1,3,
 52,35,2,
-17,55,0,
-46,232,1,3,
-52,36,2,
 17,67,0,
-46,232,1,3,
-51,37,2,3,
-46,30,2,
-46,34,2,
-29,38,2,
-17,252,2,2,35,2,36,2,
-46,225,1,
-46,38,2,
-52,39,2,
+46,228,1,3,
+29,36,2,
+17,42,3,2,34,2,35,2,
+46,231,1,
+52,37,2,
 17,55,0,
-46,225,1,3,
-52,40,2,
+46,233,1,3,
+52,38,2,
 17,67,0,
-46,225,1,3,
-51,41,2,4,
-46,30,2,
-46,34,2,
-46,38,2,
-29,42,2,
-17,252,2,2,39,2,40,2,
-46,225,1,
-46,42,2,
-52,43,2,
+46,233,1,3,
+51,39,2,2,
+46,36,2,
+29,40,2,
+17,42,3,2,37,2,38,2,
+46,231,1,
+46,40,2,
+52,41,2,
 17,55,0,
-46,225,1,3,
+46,238,1,3,
+52,42,2,
+17,67,0,
+46,238,1,3,
+51,43,2,3,
+46,36,2,
+46,40,2,
 29,44,2,
-17,5,3,1,43,2,
-49,45,2,9,3,
+17,42,3,2,41,2,42,2,
+46,231,1,
+46,44,2,
+52,45,2,
+17,55,0,
+46,231,1,3,
 52,46,2,
+17,67,0,
+46,231,1,3,
+51,47,2,4,
+46,36,2,
+46,40,2,
+46,44,2,
+29,48,2,
+17,42,3,2,45,2,46,2,
+46,231,1,
+46,48,2,
+52,49,2,
 17,55,0,
-46,225,1,3,
-29,47,2,
-17,14,3,1,46,2,
-46,45,2,
-52,48,2,
-17,55,0,
-46,225,1,3,
-29,49,2,
-17,18,3,1,48,2,
-46,225,1,
-52,50,2,
-17,22,3,
-46,2,0,3,
-29,51,2,
-37,
-16,0,16,0,0,24,3,1,50,2,
-46,2,0,
+46,231,1,3,
+29,50,2,
+17,51,3,1,49,2,
+49,51,2,55,3,
 52,52,2,
-17,22,3,
-46,2,0,3,
+17,55,0,
+46,231,1,3,
 29,53,2,
-37,
-16,0,16,0,0,29,3,1,52,2,
-46,2,0,
-52,54,2,
-17,22,3,
-46,5,0,3,
-51,55,2,2,
+17,60,3,1,52,2,
 46,51,2,
-29,56,2,
+52,54,2,
+17,55,0,
+46,231,1,3,
+29,55,2,
+17,64,3,1,54,2,
+46,231,1,
+52,56,2,
+17,187,1,
+46,2,0,3,
+29,57,2,
 37,
-16,0,16,0,0,24,3,1,54,2,
-46,5,0,
-46,56,2,
-52,57,2,
-17,22,3,
-46,5,0,3,
-51,58,2,2,
-46,53,2,
+16,0,16,0,0,68,3,1,56,2,
+46,2,0,
+52,58,2,
+17,187,1,
+46,2,0,3,
 29,59,2,
 37,
-16,0,16,0,0,29,3,1,57,2,
-46,5,0,
-46,59,2,
+16,0,16,0,0,73,3,1,58,2,
+46,2,0,
 52,60,2,
-17,34,3,
-49,61,2,40,3,3,
+17,187,1,
+46,5,0,3,
+51,61,2,2,
+46,57,2,
 29,62,2,
-17,46,3,1,60,2,
-46,61,2,
-52,63,2,
-17,34,3,
-49,64,2,55,3,3,
-51,65,2,2,
+37,
+16,0,16,0,0,68,3,1,60,2,
+46,5,0,
 46,62,2,
-29,66,2,
-17,46,3,1,63,2,
-46,64,2,
-46,66,2,
-52,67,2,
-17,62,3,
-49,68,2,64,3,3,
+52,63,2,
+17,187,1,
+46,5,0,3,
+51,64,2,2,
+46,59,2,
+29,65,2,
+37,
+16,0,16,0,0,73,3,1,63,2,
+46,5,0,
+46,65,2,
+52,66,2,
+17,78,3,
+49,67,2,84,3,3,
+29,68,2,
+17,90,3,1,66,2,
+46,67,2,
 52,69,2,
-17,71,3,
-49,70,2,78,3,3,
-29,71,2,
-17,85,3,2,67,2,69,2,
-46,61,2,
-52,72,2,
-17,92,3,
-49,73,2,94,3,3,
-52,74,2,
-17,34,3,
-46,61,2,3,
-51,75,2,2,
-46,71,2,
+17,78,3,
+49,70,2,99,3,3,
+51,71,2,2,
+46,68,2,
+29,72,2,
+17,90,3,1,69,2,
+46,70,2,
+46,72,2,
+52,73,2,
+17,106,3,
+49,74,2,108,3,3,
+52,75,2,
+17,115,3,
+46,92,1,3,
 29,76,2,
-17,85,3,2,72,2,74,2,
-46,61,2,
-46,76,2,
+17,122,3,2,73,2,75,2,
+46,67,2,
 52,77,2,
-17,106,3,
-49,78,2,108,3,3,
+17,129,3,
+49,78,2,131,3,3,
 52,79,2,
-17,116,3,
-46,61,2,3,
-52,80,2,
-17,120,3,
-46,61,2,3,
-51,81,2,3,
-46,71,2,
+17,78,3,
+46,67,2,3,
+51,80,2,2,
 46,76,2,
-29,82,2,
-17,85,3,3,77,2,79,2,80,2,
-46,61,2,
-46,82,2,
-52,83,2,
-17,71,3,
-46,70,2,3,
+29,81,2,
+17,122,3,2,77,2,79,2,
+46,67,2,
+46,81,2,
+52,82,2,
+17,143,3,
+49,83,2,145,3,3,
 52,84,2,
-17,62,3,
-46,68,2,3,
-29,85,2,
-17,124,3,2,83,2,84,2,
-46,61,2,
-52,86,2,
-17,34,3,
-46,61,2,3,
-52,87,2,
-17,92,3,
-46,73,2,3,
-51,88,2,2,
-46,85,2,
-29,89,2,
-17,124,3,2,86,2,87,2,
-46,61,2,
-46,89,2,
-52,90,2,
-17,116,3,
-46,61,2,3,
-52,91,2,
-17,120,3,
-46,61,2,3,
-52,92,2,
+17,153,3,
+46,67,2,3,
+52,85,2,
+17,157,3,
+46,67,2,3,
+51,86,2,3,
+46,76,2,
+46,81,2,
+29,87,2,
+17,122,3,3,82,2,84,2,85,2,
+46,67,2,
+46,87,2,
+52,88,2,
+17,115,3,
+46,92,1,3,
+52,89,2,
 17,106,3,
+46,74,2,3,
+29,90,2,
+17,161,3,2,88,2,89,2,
+46,67,2,
+52,91,2,
+17,78,3,
+46,67,2,3,
+52,92,2,
+17,129,3,
 46,78,2,3,
-51,93,2,3,
-46,85,2,
-46,89,2,
+51,93,2,2,
+46,90,2,
 29,94,2,
-17,124,3,3,90,2,91,2,92,2,
-46,61,2,
-46,94,2,70,0,
-57,2,
+17,161,3,2,91,2,92,2,
+46,67,2,
+46,94,2,
+52,95,2,
+17,153,3,
+46,67,2,3,
+52,96,2,
+17,157,3,
+46,67,2,3,
+52,97,2,
+17,143,3,
+46,83,2,3,
+51,98,2,3,
+46,90,2,
+46,94,2,
+29,99,2,
+17,161,3,3,95,2,96,2,97,2,
+46,67,2,
+46,99,2,72,0,
+61,2,
 118,0,
 33,0,
 71,0,
-17,2,
-15,2,
+21,2,
+19,2,
 28,0,
 66,0,
 46,0,
@@ -2059,49 +2077,50 @@
 53,1,
 18,0,
 56,0,
-106,1,
-25,2,
-28,2,
+110,1,
+29,2,
+32,2,
 8,0,
-148,1,
-92,1,
-99,1,
-253,1,
+152,1,
+96,1,
+103,1,
+1,2,
 88,0,
 98,0,
-120,1,
+124,1,
 7,1,
 9,1,
 128,0,
 138,0,
-227,1,
-238,1,
+231,1,
+242,1,
 11,1,
-194,1,
+198,1,
 113,0,
 73,1,
 68,1,
-85,1,
-205,1,
-216,1,
+89,1,
+209,1,
+220,1,
 93,0,
 103,0,
-143,1,
+147,1,
 43,1,
 35,1,
 63,1,
 153,0,
 80,1,
-111,1,
-19,2,
-12,2,
+115,1,
+23,2,
+16,2,
+83,1,
 83,0,
 3,0,
-127,1,
-136,1,
+131,1,
+140,1,
 22,1,
 27,1,
-45,2,
+49,2,
 207,0,
 123,0,
 13,0,
@@ -2111,44 +2130,45 @@
 241,0,
 23,0,
 61,0,
-189,1,
+193,1,
 17,1,
 13,1,
-33,2,
+85,1,
+37,2,
 20,
-28,62,2,
+28,68,2,
 2,
 48,0,0,0,0,1,
 40,
 8,
-46,61,2,2,
+46,67,2,2,
 1,
 45,
-55,60,2,0,3,0,1,2,50,
+55,66,2,0,3,0,1,2,50,
 27,
 46,153,0,185,0,2,
 45,
-55,60,2,0,1,3,
+55,66,2,0,1,3,
 25,
 46,153,0,23,183,209,56,
 45,
-55,60,2,0,1,3,1,
-28,66,2,
+55,66,2,0,1,3,1,
+28,72,2,
 2,
 48,0,0,0,0,1,
 40,
 8,
-46,64,2,2,
+46,70,2,2,
 1,
 45,
-55,63,2,0,3,0,1,2,50,
+55,69,2,0,3,0,1,2,50,
 27,
 46,145,0,177,0,2,
 45,
-55,63,2,0,1,3,
+55,69,2,0,1,3,
 25,
 46,145,0,23,183,209,56,
 45,
-55,63,2,0,1,3,1,
+55,69,2,0,1,3,1,
 21,};
 static constexpr size_t SKSL_INCLUDE_sksl_public_LENGTH = sizeof(SKSL_INCLUDE_sksl_public);
diff --git a/src/sksl/ir/SkSLFunctionCall.cpp b/src/sksl/ir/SkSLFunctionCall.cpp
index 9ec5baf..afe8f2c 100644
--- a/src/sksl/ir/SkSLFunctionCall.cpp
+++ b/src/sksl/ir/SkSLFunctionCall.cpp
@@ -612,8 +612,20 @@
         case k_uintBitsToFloat_IntrinsicKind:
             return evaluate_intrinsic<SKSL_INT>(context, arguments, returnType,
                                                 Intrinsics::evaluate_uintBitsToFloat);
-        // TODO(skia:12202): 8.4 : Floating-Point Pack and Unpack Functions
-
+        // 8.4 : Floating-Point Pack and Unpack Functions
+        case k_packUnorm2x16_IntrinsicKind: {
+            auto Pack = [&](int n) -> unsigned int {
+                double x = arguments[0]->getConstantSubexpression(n)->as<FloatLiteral>().value();
+                return (int)std::round(Intrinsics::evaluate_clamp(x, 0.0, 1.0) * 65535.0);
+            };
+            return UInt(((Pack(0) << 0)  & 0x0000FFFF) |
+                        ((Pack(1) << 16) & 0xFFFF0000)).release();
+        }
+        case k_unpackUnorm2x16_IntrinsicKind: {
+            SKSL_INT x = arguments[0]->getConstantSubexpression(0)->as<IntLiteral>().value();
+            return Float2(double((x >> 0)  & 0x0000FFFF) / 65535.0,
+                          double((x >> 16) & 0x0000FFFF) / 65535.0).release();
+        }
         // 8.5 : Geometric Functions
         case k_length_IntrinsicKind:
             return coalesce_vector<float>(arguments, /*startingState=*/0, returnType,
diff --git a/src/sksl/sksl_public.sksl b/src/sksl/sksl_public.sksl
index 652aea1..fcd24aa 100644
--- a/src/sksl/sksl_public.sksl
+++ b/src/sksl/sksl_public.sksl
@@ -126,7 +126,9 @@
 $es3 $genType  modf($genType  x, out $genType  i);
 $es3 $genHType modf($genHType x, out $genHType i);
 
-// TODO(skia:12202): 8.4 : Floating-Point Pack and Unpack Functions (GLSL ES 3.0)
+// 8.4 : Floating-Point Pack and Unpack Functions (GLSL ES 3.0)
+$es3 uint packUnorm2x16(float2 v);
+$es3 float2 unpackUnorm2x16(uint p);
 
 // 8.5 : Geometric Functions
 float length($genType  x);
diff --git a/tests/SkSLTest.cpp b/tests/SkSLTest.cpp
index 6ec73d1..9ce5b49 100644
--- a/tests/SkSLTest.cpp
+++ b/tests/SkSLTest.cpp
@@ -222,6 +222,7 @@
 // skbug.com/11919: Fails on Adreno + Vulkan
 SKSL_TEST_CPU(SkSLIntrinsicMixFloat,           "intrinsics/MixFloat.sksl")
 SKSL_TEST_ES3(SkSLIntrinsicModf,               "intrinsics/Modf.sksl")
+SKSL_TEST_ES3(SkSLIntrinsicPackUnorm2x16,      "intrinsics/PackUnorm2x16.sksl")
 SKSL_TEST_ES3(SkSLIntrinsicRound,              "intrinsics/Round.sksl")
 SKSL_TEST_ES3(SkSLIntrinsicRoundEven,          "intrinsics/RoundEven.sksl")
 SKSL_TEST(SkSLIntrinsicSignFloat,              "intrinsics/SignFloat.sksl")
diff --git a/tests/sksl/intrinsics/PackUnorm2x16.asm.frag b/tests/sksl/intrinsics/PackUnorm2x16.asm.frag
new file mode 100644
index 0000000..7997853
--- /dev/null
+++ b/tests/sksl/intrinsics/PackUnorm2x16.asm.frag
@@ -0,0 +1,124 @@
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "colorGreen"
+OpMemberName %_UniformBuffer 1 "colorRed"
+OpMemberName %_UniformBuffer 2 "testInputs"
+OpName %_entrypoint_v "_entrypoint_v"
+OpName %main "main"
+OpName %xy "xy"
+OpName %zw "zw"
+OpName %tolerance "tolerance"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 2 Offset 32
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %72 RelaxedPrecision
+OpDecorate %75 RelaxedPrecision
+OpDecorate %76 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
+%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
+%void = OpTypeVoid
+%15 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%19 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%23 = OpTypeFunction %v4float %_ptr_Function_v2float
+%uint = OpTypeInt 32 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%int = OpTypeInt 32 1
+%int_2 = OpConstant %int 2
+%float_0_015625 = OpConstant %float 0.015625
+%43 = OpConstantComposite %v2float %float_0_015625 %float_0_015625
+%false = OpConstantFalse %bool
+%v2bool = OpTypeVector %bool 2
+%float_0_75 = OpConstant %float 0.75
+%float_1 = OpConstant %float 1
+%61 = OpConstantComposite %v2float %float_0_75 %float_1
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%_entrypoint_v = OpFunction %void None %15
+%16 = OpLabel
+%20 = OpVariable %_ptr_Function_v2float Function
+OpStore %20 %19
+%22 = OpFunctionCall %v4float %main %20
+OpStore %sk_FragColor %22
+OpReturn
+OpFunctionEnd
+%main = OpFunction %v4float None %23
+%24 = OpFunctionParameter %_ptr_Function_v2float
+%25 = OpLabel
+%xy = OpVariable %_ptr_Function_uint Function
+%zw = OpVariable %_ptr_Function_uint Function
+%tolerance = OpVariable %_ptr_Function_v2float Function
+%65 = OpVariable %_ptr_Function_v4float Function
+%30 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%34 = OpLoad %v4float %30
+%35 = OpVectorShuffle %v2float %34 %34 0 1
+%29 = OpExtInst %uint %1 PackUnorm2x16 %35
+OpStore %xy %29
+%38 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%39 = OpLoad %v4float %38
+%40 = OpVectorShuffle %v2float %39 %39 2 3
+%37 = OpExtInst %uint %1 PackUnorm2x16 %40
+OpStore %zw %37
+OpStore %tolerance %43
+%49 = OpLoad %uint %xy
+%48 = OpExtInst %v2float %1 UnpackUnorm2x16 %49
+%47 = OpExtInst %v2float %1 FAbs %48
+%50 = OpLoad %v2float %tolerance
+%46 = OpFOrdLessThan %v2bool %47 %50
+%45 = OpAll %bool %46
+OpSelectionMerge %53 None
+OpBranchConditional %45 %52 %53
+%52 = OpLabel
+%58 = OpLoad %uint %zw
+%57 = OpExtInst %v2float %1 UnpackUnorm2x16 %58
+%62 = OpFSub %v2float %57 %61
+%56 = OpExtInst %v2float %1 FAbs %62
+%63 = OpLoad %v2float %tolerance
+%55 = OpFOrdLessThan %v2bool %56 %63
+%54 = OpAll %bool %55
+OpBranch %53
+%53 = OpLabel
+%64 = OpPhi %bool %false %25 %54 %52
+OpSelectionMerge %69 None
+OpBranchConditional %64 %67 %68
+%67 = OpLabel
+%70 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%72 = OpLoad %v4float %70
+OpStore %65 %72
+OpBranch %69
+%68 = OpLabel
+%73 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%75 = OpLoad %v4float %73
+OpStore %65 %75
+OpBranch %69
+%69 = OpLabel
+%76 = OpLoad %v4float %65
+OpReturnValue %76
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/PackUnorm2x16.glsl b/tests/sksl/intrinsics/PackUnorm2x16.glsl
new file mode 100644
index 0000000..0333147
--- /dev/null
+++ b/tests/sksl/intrinsics/PackUnorm2x16.glsl
@@ -0,0 +1,11 @@
+
+out vec4 sk_FragColor;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+uniform vec4 testInputs;
+vec4 main() {
+    uint xy = packUnorm2x16(testInputs.xy);
+    uint zw = packUnorm2x16(testInputs.zw);
+    const vec2 tolerance = vec2(0.015625);
+    return all(lessThan(abs(unpackUnorm2x16(xy)), tolerance)) && all(lessThan(abs(unpackUnorm2x16(zw) - vec2(0.75, 1.0)), tolerance)) ? colorGreen : colorRed;
+}
diff --git a/tests/sksl/intrinsics/PackUnorm2x16.metal b/tests/sksl/intrinsics/PackUnorm2x16.metal
new file mode 100644
index 0000000..897858e
--- /dev/null
+++ b/tests/sksl/intrinsics/PackUnorm2x16.metal
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Uniforms {
+    float4 colorGreen;
+    float4 colorRed;
+    float4 testInputs;
+};
+struct Inputs {
+};
+struct Outputs {
+    float4 sk_FragColor [[color(0)]];
+};
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+    Outputs _out;
+    (void)_out;
+    uint xy = pack_float_to_unorm2x16(_uniforms.testInputs.xy);
+    uint zw = pack_float_to_unorm2x16(_uniforms.testInputs.zw);
+    const float2 tolerance = float2(0.015625);
+    _out.sk_FragColor = all((abs(unpack_unorm2x16_to_float(xy)) < tolerance)) && all((abs(unpack_unorm2x16_to_float(zw) - float2(0.75, 1.0)) < tolerance)) ? _uniforms.colorGreen : _uniforms.colorRed;
+    return _out;
+}