Update web ui fragment shader tests (#181877)

Adds a bunch of tests for uniform setting functionality for custom
fragment shaders on the web.

Deletes redundant tests.

Fixes a discovered issue in the uniform offset calculation. We were
previously using the `location`, which is the integer offset of the
uniform, not the offset in floats.
diff --git a/engine/src/flutter/impeller/compiler/README.md b/engine/src/flutter/impeller/compiler/README.md
index cf44365..746f036 100644
--- a/engine/src/flutter/impeller/compiler/README.md
+++ b/engine/src/flutter/impeller/compiler/README.md
@@ -5,3 +5,10 @@
 shaders and generates libraries suitable for consumption by an Impeller backend.
 Along with said libraries, the reflector generates code and meta-data to
 construct rendering and compute pipelines at runtime.
+
+# Invocation
+
+To invoke `impellerc` by itself, [compile the engine](https://github.com/flutter/flutter/blob/master/docs/engine/contributing/Compiling-the-engine.md) and run the binary via 
+```
+`find engine/src/out/host_debug_unopt_arm64 -name impellerc` --input=path/to/shader.frag --input-type=frag --entry-point=main`
+```
diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/painting.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/painting.dart
index f0a5726..7b28bb5 100644
--- a/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/painting.dart
+++ b/engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/painting.dart
@@ -423,7 +423,7 @@
 
     IndexError.check(index, info.floatCount, message: 'Index `$index` out of bounds for `$name`.');
 
-    return CkUniformFloatSlot._(this, index, name, info.location + index);
+    return CkUniformFloatSlot._(this, index, name, info.floatOffset + index);
   }
 
   @override
@@ -461,7 +461,7 @@
     final elements = List<T>.generate(numElements, (i) {
       final slots = List<CkUniformFloatSlot>.generate(
         info.floatCount,
-        (j) => CkUniformFloatSlot._(this, j, name, info.location + i * elementSize + j),
+        (j) => CkUniformFloatSlot._(this, j, name, info.floatOffset + i * elementSize + j),
       );
       return elementFactory(slots);
     });
@@ -554,7 +554,7 @@
 
     return List<CkUniformFloatSlot>.generate(
       size,
-      (i) => CkUniformFloatSlot._(this, i, name, info.location + i),
+      (i) => CkUniformFloatSlot._(this, i, name, info.floatOffset + i),
     );
   }
 }
diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/shader_data.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/shader_data.dart
index 371bb6b..9b645f6 100644
--- a/engine/src/flutter/lib/web_ui/lib/src/engine/shader_data.dart
+++ b/engine/src/flutter/lib/web_ui/lib/src/engine/shader_data.dart
@@ -34,6 +34,7 @@
 
     var textureCount = 0;
     var floatCount = 0;
+    var floatOffset = 0;
     for (var i = 0; i < rawUniforms.length; i += 1) {
       final Object? rawUniformData = rawUniforms[i];
       if (rawUniformData is! Map<String, Object?>) {
@@ -78,7 +79,9 @@
         location: location,
         type: type,
         floatCount: uniformFloatCount,
+        floatOffset: floatOffset,
       );
+      floatOffset += uniformFloatCount;
     }
     return ShaderData(
       source: source,
@@ -100,18 +103,21 @@
     required this.location,
     required this.type,
     required this.floatCount,
+    required this.floatOffset,
   });
 
   final String name;
   final UniformType type;
   final int location;
   final int floatCount;
+  final int floatOffset;
 
   static const UniformData empty = UniformData(
     name: '',
     location: -1,
     type: UniformType.Float,
     floatCount: -1,
+    floatOffset: -1,
   );
 }
 
diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart
index 81e5cd54..5c39427 100644
--- a/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart
+++ b/engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/shaders.dart
@@ -376,7 +376,7 @@
 
     IndexError.check(index, info.floatCount, message: 'Index `$index` out of bounds for `$name`.');
 
-    return SkwasmUniformFloatSlot._(this, index, name, info.location + index);
+    return SkwasmUniformFloatSlot._(this, index, name, info.floatOffset + index);
   }
 
   @override
@@ -441,7 +441,7 @@
 
     return List<SkwasmUniformFloatSlot>.generate(
       size,
-      (i) => SkwasmUniformFloatSlot._(this, i, name, info.location + i),
+      (i) => SkwasmUniformFloatSlot._(this, i, name, info.floatOffset + i),
     );
   }
 
@@ -462,7 +462,7 @@
     final elements = List<T>.generate(numElements, (i) {
       final slots = List<SkwasmUniformFloatSlot>.generate(
         info.floatCount,
-        (j) => SkwasmUniformFloatSlot._(this, j, name, info.location + i * elementSize + j),
+        (j) => SkwasmUniformFloatSlot._(this, j, name, info.floatOffset + i * elementSize + j),
       );
       return elementFactory(slots);
     });
diff --git a/engine/src/flutter/lib/web_ui/test/ui/fragment_shader_test.dart b/engine/src/flutter/lib/web_ui/test/ui/fragment_shader_test.dart
index 0947730..852ef7c 100644
--- a/engine/src/flutter/lib/web_ui/test/ui/fragment_shader_test.dart
+++ b/engine/src/flutter/lib/web_ui/test/ui/fragment_shader_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:convert';
+import 'dart:math';
 import 'dart:typed_data';
 
 import 'package:test/bootstrap/browser.dart';
@@ -325,12 +326,112 @@
 }
 ''';
 
+// Simple shader with a float uniform
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/float_uniform.frag
+// For changes, update that file and regenerate using impellerc.
+const String kFloatSkSl = r'''
+{
+  "format_version": 2,
+  "sksl": {
+    "entrypoint": "float_uniform_fragment_main",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform float color_r;\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = vec4(color_r, 0.0, 0.0, 1.0);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "stage": 1,
+    "uniforms": [
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "color_r",
+        "rows": 1,
+        "type": 10
+      }
+    ]
+  }
+}
+''';
+
+// Simple shader with a vec2 uniform
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/vec2_uniform.frag
+// For changes, update that file and regenerate using impellerc.
+const String kVec2SkSl = r'''
+{
+  "format_version": 2,
+  "sksl": {
+    "entrypoint": "vec2_uniform_fragment_main",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec2 color_rg;\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = vec4(color_rg, 0.0, 1.0);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "stage": 1,
+    "uniforms": [
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "color_rg",
+        "rows": 2,
+        "type": 10
+      }
+    ]
+  }
+}
+''';
+
+// Simple shader with a vec3 uniform
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/vec3_uniform.frag
+// For changes, update that file and regenerate using impellerc.
+const String kVec3SkSl = r'''
+{
+  "format_version": 2,
+  "sksl": {
+    "entrypoint": "vec3_uniform_fragment_main",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec3 color_rgb;\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = vec4(color_rgb, 1.0);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "stage": 1,
+    "uniforms": [
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "color_rgb",
+        "rows": 3,
+        "type": 10
+      }
+    ]
+  }
+}
+''';
+
+// Simple shader with a vec4 uniform
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/vec4_uniform.frag
+// For changes, update that file and regenerate using impellerc.
+const String kVec4SkSl = r'''
+{
+  "format_version": 2,
+  "sksl": {
+    "entrypoint": "vec4_uniform_fragment_main",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec4 color_rgba;\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = color_rgba;\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "stage": 1,
+    "uniforms": [
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "color_rgba",
+        "rows": 4,
+        "type": 10
+      }
+    ]
+  }
+}
+''';
+
 // Simple shader with a float[] uniform
-// Generated from engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/float_array_uniform.frag
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/float_array_uniform.frag
 // For changes, update that file and regenerate using impellerc.
 const String kFloatArraySkSl = r'''
 {
-  "format_version": 1,
+  "format_version": 2,
   "sksl": {
     "entrypoint": "float_array_uniform_fragment_main",
     "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform float color_array[4];\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = vec4(color_array[0], color_array[1], color_array[2], color_array[3]);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
@@ -351,11 +452,11 @@
 ''';
 
 // Simple shader with a vec2[] uniform
-// Generated from engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/vec2_array_uniform.frag
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/vec2_array_uniform.frag
 // For changes, update that file and regenerate using impellerc.
 const String kVec2ArraySkSl = r'''
 {
-  "format_version": 1,
+  "format_version": 2,
   "sksl": {
     "entrypoint": "vec2_array_uniform_fragment_main",
     "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec2 color_array[2];\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = vec4(color_array[0].x, color_array[0].y, color_array[1].x, color_array[1].y);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
@@ -376,21 +477,30 @@
 ''';
 
 // Simple shader with a vec3[] uniform
-// Generated from engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/vec3_array_uniform.frag
+// Generated from engine/src/flutter/lib/ui/fixtures/shaders/uniforms/vec3_array_uniform.frag
 // For changes, update that file and regenerate using impellerc.
 const String kVec3ArraySkSl = r'''
 {
-  "format_version": 1,
+  "format_version": 2,
   "sksl": {
     "entrypoint": "vec3_array_uniform_fragment_main",
-    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec3 color_array[2];\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = vec4(mix(color_array[0], color_array[1], vec3(0.5)), 1.0);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec2 u_size;\nuniform vec3 color_array[2];\n\nvec4 fragColor;\n\nvec2 FLT_flutter_local_FlutterFragCoord()\n{\n    return flutter_FragCoord.xy;\n}\n\nvoid FLT_main()\n{\n    vec2 uv = FLT_flutter_local_FlutterFragCoord() / u_size;\n    if (uv.x < 0.5)\n    {\n        fragColor = vec4(color_array[0], 1.0);\n    }\n    else\n    {\n        fragColor = vec4(color_array[1], 1.0);\n    }\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
     "stage": 1,
     "uniforms": [
       {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "u_size",
+        "rows": 2,
+        "type": 10
+      },
+      {
         "array_elements": 2,
         "bit_width": 32,
         "columns": 1,
-        "location": 0,
+        "location": 1,
         "name": "color_array",
         "rows": 3,
         "type": 10
@@ -405,17 +515,26 @@
 // For changes, update that file and regenerate using impellerc.
 const String kVec4ArraySkSl = r'''
 {
-  "format_version": 1,
+  "format_version": 2,
   "sksl": {
     "entrypoint": "vec4_array_uniform_fragment_main",
-    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec4 color_array[2];\n\nvec4 fragColor;\n\nvoid FLT_main()\n{\n    fragColor = mix(color_array[0], color_array[1], vec4(0.5));\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec2 u_size;\nuniform vec4 color_array[2];\n\nvec4 fragColor;\n\nvec2 FLT_flutter_local_FlutterFragCoord()\n{\n    return flutter_FragCoord.xy;\n}\n\nvoid FLT_main()\n{\n    vec2 uv = FLT_flutter_local_FlutterFragCoord() / u_size;\n    if (uv.x < 0.5)\n    {\n        fragColor = color_array[0];\n    }\n    else\n    {\n        fragColor = color_array[1];\n    }\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
     "stage": 1,
     "uniforms": [
       {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "u_size",
+        "rows": 2,
+        "type": 10
+      },
+      {
         "array_elements": 2,
         "bit_width": 32,
         "columns": 1,
-        "location": 0,
+        "location": 1,
         "name": "color_array",
         "rows": 4,
         "type": 10
@@ -425,25 +544,115 @@
 }
 ''';
 
+const String kAllUniformsSkSl = r'''
+{
+  "format_version": 2,
+  "sksl": {
+    "entrypoint": "all_uniforms_fragment_main",
+    "shader": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform float uFloat;\nuniform vec2 uVec2;\nuniform vec3 uVec3;\nuniform vec4 uVec4;\nuniform float uFloatArray[10];\nuniform vec2 uVec2Array[10];\nuniform vec3 uVec3Array[10];\nuniform vec4 uVec4Array[10];\n\nvec4 fragColor;\n\nfloat N_COLOR_VALUES;\n\nvec2 FLT_flutter_local_FlutterFragCoord()\n{\n    return flutter_FragCoord.xy;\n}\n\nvoid FLT_main()\n{\n    N_COLOR_VALUES = 44.0;\n    float u = FLT_flutter_local_FlutterFragCoord().x / N_COLOR_VALUES;\n    float increment = 1.0 / N_COLOR_VALUES;\n    float offset = increment;\n    if (u < offset)\n    {\n        fragColor = vec4(uFloat, 0.0, 0.0, 1.0);\n        return;\n    }\n    offset += increment;\n    if (u < offset)\n    {\n        fragColor = vec4(uVec2, 0.0, 1.0);\n        return;\n    }\n    offset += increment;\n    if (u < offset)\n    {\n        fragColor = vec4(uVec3, 1.0);\n        return;\n    }\n    offset += increment;\n    if (u < offset)\n    {\n        fragColor = uVec4;\n        return;\n    }\n    offset += increment;\n    for (int i = 0; i < 10; i++)\n    {\n        if (u < offset)\n        {\n            fragColor = vec4(uFloatArray[i], 0.0, 0.0, 1.0);\n            return;\n        }\n        offset += increment;\n    }\n    for (int i_1 = 0; i_1 < 10; i_1++)\n    {\n        if (u < offset)\n        {\n            fragColor = vec4(uVec2Array[i_1], 0.0, 1.0);\n            return;\n        }\n        offset += increment;\n    }\n    for (int i_2 = 0; i_2 < 10; i_2++)\n    {\n        if (u < offset)\n        {\n            fragColor = vec4(uVec3Array[i_2], 1.0);\n            return;\n        }\n        offset += increment;\n    }\n    for (int i_3 = 0; i_3 < 10; i_3++)\n    {\n        if (u < offset)\n        {\n            fragColor = uVec4Array[i_3];\n            return;\n        }\n        offset += increment;\n    }\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return fragColor;\n}\n",
+    "stage": 1,
+    "uniforms": [
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 0,
+        "name": "uFloat",
+        "rows": 1,
+        "type": 10
+      },
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 1,
+        "name": "uVec2",
+        "rows": 2,
+        "type": 10
+      },
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 2,
+        "name": "uVec3",
+        "rows": 3,
+        "type": 10
+      },
+      {
+        "array_elements": 0,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 3,
+        "name": "uVec4",
+        "rows": 4,
+        "type": 10
+      },
+      {
+        "array_elements": 10,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 4,
+        "name": "uFloatArray",
+        "rows": 1,
+        "type": 10
+      },
+      {
+        "array_elements": 10,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 14,
+        "name": "uVec2Array",
+        "rows": 2,
+        "type": 10
+      },
+      {
+        "array_elements": 10,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 24,
+        "name": "uVec3Array",
+        "rows": 3,
+        "type": 10
+      },
+      {
+        "array_elements": 10,
+        "bit_width": 32,
+        "columns": 1,
+        "location": 34,
+        "name": "uVec4Array",
+        "rows": 4,
+        "type": 10
+      }
+    ]
+  }
+}
+''';
+
 Future<void> testMain() async {
   setUpUnitTests(withImplicitView: true, setUpTestViewDimensions: false);
 
   const region = ui.Rect.fromLTWH(0, 0, 300, 300);
 
   late FakeAssetScope assetScope;
-  setUp(() {
+  setUpAll(() {
     assetScope = fakeAssetManager.pushAssetScope();
     assetScope.setAsset('voronoi_shader', ByteData.sublistView(utf8.encode(kVoronoiShaderSksl)));
     assetScope.setAsset('texture_shader', ByteData.sublistView(utf8.encode(kTextureShaderSksl)));
     assetScope.setAsset('many_arrays', ByteData.sublistView(utf8.encode(kManyArraysSksl)));
     assetScope.setAsset('ink_sparkle', ByteData.sublistView(utf8.encode(kInkSparkleSksl)));
-    assetScope.setAsset('float_array', ByteData.sublistView(utf8.encode(kFloatArraySkSl)));
-    assetScope.setAsset('vec2_array', ByteData.sublistView(utf8.encode(kVec2ArraySkSl)));
-    assetScope.setAsset('vec3_array', ByteData.sublistView(utf8.encode(kVec3ArraySkSl)));
-    assetScope.setAsset('vec4_array', ByteData.sublistView(utf8.encode(kVec4ArraySkSl)));
+    assetScope.setAsset('float_uniform', ByteData.sublistView(utf8.encode(kFloatSkSl)));
+    assetScope.setAsset('vec2_uniform', ByteData.sublistView(utf8.encode(kVec2SkSl)));
+    assetScope.setAsset('vec3_uniform', ByteData.sublistView(utf8.encode(kVec3SkSl)));
+    assetScope.setAsset('vec4_uniform', ByteData.sublistView(utf8.encode(kVec4SkSl)));
+    assetScope.setAsset('float_array_uniform', ByteData.sublistView(utf8.encode(kFloatArraySkSl)));
+    assetScope.setAsset('vec2_array_uniform', ByteData.sublistView(utf8.encode(kVec2ArraySkSl)));
+    assetScope.setAsset('vec3_array_uniform', ByteData.sublistView(utf8.encode(kVec3ArraySkSl)));
+    assetScope.setAsset('vec4_array_uniform', ByteData.sublistView(utf8.encode(kVec4ArraySkSl)));
+    assetScope.setAsset('all_uniforms', ByteData.sublistView(utf8.encode(kAllUniformsSkSl)));
   });
 
-  tearDown(() {
+  tearDownAll(() {
     fakeAssetManager.popAssetScope(assetScope);
   });
 
@@ -527,160 +736,470 @@
     await expectLater(ui.FragmentProgram.fromAsset('voronoi shader'), completes);
   }, skip: isWimp); // https://github.com/flutter/flutter/issues/175431
 
-  test('getUniformFloat works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('ink_sparkle');
-    final ui.FragmentShader shader = program.fragmentShader();
-    final ui.UniformFloatSlot slot = shader.getUniformFloat('u_rotation1', 1);
-    expect(slot.shaderIndex, equals(15));
-  });
-
-  test('getUniformVec2 works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('many_arrays');
-    final ui.FragmentShader shader = program.fragmentShader();
-    shader.getUniformVec2('uSize').set(6.0, 7.0);
-  });
-  test('getUniformVec3 works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('many_arrays');
-    final ui.FragmentShader shader = program.fragmentShader();
-    shader.getUniformVec3('uLoneVector').set(11.0, 22.0, 19.96);
-  });
-
-  test('getUniformVec4 works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('ink_sparkle');
-    final ui.FragmentShader shader = program.fragmentShader();
-    shader.getUniformVec4('u_color').set(0.8, 0.1, 0.3, 1.0);
-  });
-
-  test('getUniformFloatArray works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('float_array');
-    final ui.FragmentShader shader = program.fragmentShader();
-    final ui.UniformArray<ui.UniformFloatSlot> colorArray = shader.getUniformFloatArray(
-      'color_array',
-    );
-    colorArray[0].set(0.6);
-    colorArray[1].set(0.7);
-    colorArray[2].set(0.8);
-    colorArray[3].set(0.9);
-
-    final recorder = ui.PictureRecorder();
-    final canvas = ui.Canvas(recorder, region);
-    canvas.drawRect(
-      ui.Rect.fromLTRB(0, 0, region.width, region.height),
-      ui.Paint()..shader = shader,
-    );
-
-    await drawPictureUsingCurrentRenderer(recorder.endRecording());
-
-    await matchGoldenFile('uniform_float_array.png', region: region);
-  }, skip: isWimp);
-
-  test('getUniformVec2Array works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('vec2_array');
-    final ui.FragmentShader shader = program.fragmentShader();
-    final ui.UniformArray<ui.UniformVec2Slot> colorArray = shader.getUniformVec2Array(
-      'color_array',
-    );
-    colorArray[0].set(0.6, 0.7);
-    colorArray[1].set(0.8, 0.9);
-
-    final recorder = ui.PictureRecorder();
-    final canvas = ui.Canvas(recorder, region);
-    canvas.drawRect(
-      ui.Rect.fromLTRB(0, 0, region.width, region.height),
-      ui.Paint()..shader = shader,
-    );
-
-    await drawPictureUsingCurrentRenderer(recorder.endRecording());
-
-    await matchGoldenFile('uniform_vec2_array.png', region: region);
-  }, skip: isWimp);
-
-  test('getUniformVec3Array works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('vec3_array');
-    final ui.FragmentShader shader = program.fragmentShader();
-    final ui.UniformArray<ui.UniformVec3Slot> colorArray = shader.getUniformVec3Array(
-      'color_array',
-    );
-    colorArray[0].set(0.6, 0.7, 0.8);
-    colorArray[1].set(0.9, 1.0, 0.0);
-
-    final recorder = ui.PictureRecorder();
-    final canvas = ui.Canvas(recorder, region);
-    canvas.drawRect(
-      ui.Rect.fromLTRB(0, 0, region.width, region.height),
-      ui.Paint()..shader = shader,
-    );
-
-    await drawPictureUsingCurrentRenderer(recorder.endRecording());
-
-    await matchGoldenFile('uniform_vec3_array.png', region: region);
-  }, skip: isWimp);
-
-  test('getUniformVec4Array works with correct datatype', () async {
-    final ui.FragmentProgram program = await renderer.createFragmentProgram('vec4_array');
-    final ui.FragmentShader shader = program.fragmentShader();
-    final ui.UniformArray<ui.UniformVec4Slot> colorArray = shader.getUniformVec4Array(
-      'color_array',
-    );
-    colorArray[0].set(0.6, 0.7, 0.8, 0.9);
-    colorArray[1].set(0.9, 0.8, 0.7, 0.6);
-
-    final recorder = ui.PictureRecorder();
-    final canvas = ui.Canvas(recorder, region);
-    canvas.drawRect(
-      ui.Rect.fromLTRB(0, 0, region.width, region.height),
-      ui.Paint()..shader = shader,
-    );
-
-    await drawPictureUsingCurrentRenderer(recorder.endRecording());
-
-    await matchGoldenFile('uniform_vec4_array.png', region: region);
-  }, skip: isWimp);
-
-  group('Uniform by-name accessors throw errors with incorrect datatypes.', () {
-    late ui.FragmentProgram program;
-    late ui.FragmentShader shader;
-    setUp(() async {
-      program = await renderer.createFragmentProgram('many_arrays');
-      shader = program.fragmentShader();
+  group('fragmentShader uniforms', () {
+    late Map<Type, ui.FragmentShader> shaderMap;
+    setUpAll(() async {
+      shaderMap = {
+        ui.UniformFloatSlot: (await renderer.createFragmentProgram(
+          'float_uniform',
+        )).fragmentShader(),
+        ui.UniformVec2Slot: (await renderer.createFragmentProgram('vec2_uniform')).fragmentShader(),
+        ui.UniformVec3Slot: (await renderer.createFragmentProgram('vec3_uniform')).fragmentShader(),
+        ui.UniformVec4Slot: (await renderer.createFragmentProgram('vec4_uniform')).fragmentShader(),
+        ui.UniformArray<ui.UniformFloatSlot>: (await renderer.createFragmentProgram(
+          'float_array_uniform',
+        )).fragmentShader(),
+        ui.UniformArray<ui.UniformVec2Slot>: (await renderer.createFragmentProgram(
+          'vec2_array_uniform',
+        )).fragmentShader(),
+        ui.UniformArray<ui.UniformVec3Slot>: (await renderer.createFragmentProgram(
+          'vec3_array_uniform',
+        )).fragmentShader(),
+        ui.UniformArray<ui.UniformVec4Slot>: (await renderer.createFragmentProgram(
+          'vec4_array_uniform',
+        )).fragmentShader(),
+      };
     });
-    test('getUniformVec2', () {
-      expect(
-        () => shader.getUniformVec2('uLoneMatrix'),
-        throwsA(
-          isA<ArgumentError>().having(
-            (e) => e.message,
-            'message',
-            'Uniform `uLoneMatrix` has size 16, not size 2.',
-          ),
-        ),
-      );
+
+    group('float', () {
+      group('float', () {
+        test('set using setUniformFloat', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformFloatSlot]!;
+          const color = ui.Color.fromARGB(255, 255, 0, 0);
+          shader.setFloat(0, color.r);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('set using getUniformFloat', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformFloatSlot]!;
+          const color = ui.Color.fromARGB(255, 50, 0, 0);
+          shader.getUniformFloat('color_r').set(color.r);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('getUniformFloat offset overflow', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformFloatSlot]!;
+          expect(
+            () => shader.getUniformFloat('color_r', 2),
+            throwsA(
+              isA<IndexError>().having(
+                (e) => e.message,
+                'message',
+                contains('Index `2` out of bounds for `color_r`.'),
+              ),
+            ),
+          );
+        });
+
+        test('getUniformFloat offset underflow', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformFloatSlot]!;
+          expect(
+            () => shader.getUniformFloat('color_r', -1),
+            throwsA(
+              isA<IndexError>().having(
+                (e) => e.message,
+                'message',
+                contains('Index `-1` out of bounds for `color_r`.'),
+              ),
+            ),
+          );
+        });
+      });
+      group('vec2', () {
+        test('set using setFloat', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec2Slot]!;
+          const color = ui.Color.fromARGB(255, 255, 255, 0);
+          shader.setFloat(0, color.r);
+          shader.setFloat(1, color.g);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('set using getUniformVec2', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec2Slot]!;
+          const color = ui.Color.fromARGB(255, 50, 50, 0);
+          shader.getUniformVec2('color_rg').set(color.r, color.g);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('wrong datatype', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec3Slot]!;
+          expect(
+            () => shader.getUniformVec2('color_rgb'),
+            throwsA(
+              isA<ArgumentError>().having(
+                (e) => e.message,
+                'message',
+                contains('`color_rgb` has size 3, not size 2.'),
+              ),
+            ),
+          );
+        });
+      });
+      group('vec3', () {
+        test('set using setFloat', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec3Slot]!;
+          const color = ui.Color.fromARGB(255, 67, 42, 12);
+          shader.setFloat(0, color.r);
+          shader.setFloat(1, color.g);
+          shader.setFloat(2, color.b);
+          // Note: The original test also called getUniformVec3 after setFloat.
+          // Assuming this was intentional to test idempotency or a specific interaction.
+          shader.getUniformVec3('color_rgb').set(color.r, color.g, color.b);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('set using getUniformVec3', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec3Slot]!;
+          const color = ui.Color.fromARGB(255, 42, 67, 12);
+          shader.getUniformVec3('color_rgb').set(color.r, color.g, color.b);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('wrong datatype', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec2Slot]!;
+          expect(
+            () => shader.getUniformVec3('color_rg'),
+            throwsA(
+              isA<ArgumentError>().having(
+                (e) => e.message,
+                'message',
+                contains('`color_rg` has size 2, not size 3.'),
+              ),
+            ),
+          );
+        });
+      });
+
+      group('vec4', () {
+        test('set using setFloat', () async {
+          const color = ui.Color.fromARGB(255, 67, 42, 12);
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec4Slot]!;
+          shader.setFloat(0, color.r);
+          shader.setFloat(1, color.g);
+          shader.setFloat(2, color.b);
+          shader.setFloat(3, color.a);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('set using getUniformVec4', () async {
+          const color = ui.Color.fromARGB(255, 12, 37, 27);
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec4Slot]!;
+          shader.getUniformVec4('color_rgba').set(color.r, color.g, color.b, color.a);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('wrong datatype', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec3Slot]!;
+          expect(
+            () => shader.getUniformVec4('color_rgb'),
+            throwsA(
+              isA<ArgumentError>().having(
+                (e) => e.message,
+                'message',
+                contains('`color_rgb` has size 3, not size 4.'),
+              ),
+            ),
+          );
+        });
+      });
+
+      group('float array', () {
+        test('set using setFloat', () async {
+          const color = ui.Color.fromARGB(255, 11, 22, 96);
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformFloatSlot>]!;
+          shader.setFloat(0, color.r);
+          shader.setFloat(1, color.g);
+          shader.setFloat(2, color.b);
+          shader.setFloat(3, color.a);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('set using getUniformFloatArray', () async {
+          const color = ui.Color.fromARGB(255, 96, 11, 22);
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformFloatSlot>]!;
+          final ui.UniformArray<ui.UniformFloatSlot> colorRgba = shader.getUniformFloatArray(
+            'color_array',
+          );
+          colorRgba[0].set(color.r);
+          colorRgba[1].set(color.g);
+          colorRgba[2].set(color.b);
+          colorRgba[3].set(color.a);
+          await _expectShaderRendersColor(shader, color);
+        });
+      });
+
+      group('vec2 array', () {
+        test('set using setFloat', () async {
+          const color = ui.Color.fromARGB(255, 67, 42, 12);
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformVec2Slot>]!;
+          shader.setFloat(0, color.r);
+          shader.setFloat(1, color.g);
+          shader.setFloat(2, color.b);
+          shader.setFloat(3, color.a);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('set using getUniformVec2Array', () async {
+          const color = ui.Color.fromARGB(255, 1, 73, 26);
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformVec2Slot>]!;
+          final ui.UniformArray<ui.UniformVec2Slot> colorRgba = shader.getUniformVec2Array(
+            'color_array',
+          );
+          colorRgba[0].set(color.r, color.g);
+          colorRgba[1].set(color.b, color.a);
+          await _expectShaderRendersColor(shader, color);
+        });
+
+        test('wrong datatype', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec3Slot]!;
+          expect(
+            () => shader.getUniformVec2Array('color_rgb'),
+            throwsA(
+              isA<ArgumentError>().having(
+                (e) => e.message,
+                'message',
+                contains('Uniform size (3) for "color_rgb" is not a multiple of 2.'),
+              ),
+            ),
+          );
+        });
+      });
+
+      group('vec3 array', () {
+        test('set using setFloat', () async {
+          const cpuColors = [
+            ui.Color.fromARGB(255, 67, 42, 12),
+            ui.Color.fromARGB(255, 11, 22, 96),
+          ];
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformVec3Slot>]!;
+          shader.setFloat(0, 2);
+          shader.setFloat(1, 2);
+          shader.setFloat(2, cpuColors[0].r);
+          shader.setFloat(3, cpuColors[0].g);
+          shader.setFloat(4, cpuColors[0].b);
+          shader.setFloat(5, cpuColors[1].r);
+          shader.setFloat(6, cpuColors[1].g);
+          shader.setFloat(7, cpuColors[1].b);
+          await _expectShaderRendersBarcode(shader, cpuColors);
+        });
+
+        test('set using getUniformVec3Array', () async {
+          const cpuColors = [
+            ui.Color.fromARGB(255, 11, 22, 96),
+            ui.Color.fromARGB(255, 67, 42, 12),
+          ];
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformVec3Slot>]!;
+          shader.getUniformVec2('u_size').set(2, 2);
+          final ui.UniformArray<ui.UniformVec3Slot> gpuColors = shader.getUniformVec3Array(
+            'color_array',
+          );
+          gpuColors[0].set(cpuColors[0].r, cpuColors[0].g, cpuColors[0].b);
+          gpuColors[1].set(cpuColors[1].r, cpuColors[1].g, cpuColors[1].b);
+          await _expectShaderRendersBarcode(shader, cpuColors);
+        });
+
+        test('wrong datatype', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec4Slot]!;
+          expect(
+            () => shader.getUniformVec3Array('color_rgba'),
+            throwsA(
+              isA<ArgumentError>().having(
+                (e) => e.message,
+                'message',
+                contains('Uniform size (4) for "color_rgba" is not a multiple of 3.'),
+              ),
+            ),
+          );
+        });
+      });
+
+      group('vec4 array', () {
+        test('set using setFloat', () async {
+          const cpuColors = [
+            ui.Color.fromARGB(255, 67, 42, 12),
+            ui.Color.fromARGB(255, 11, 22, 96),
+          ];
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformVec4Slot>]!;
+          // 'u_size'
+          shader.setFloat(0, 2);
+          shader.setFloat(1, 2);
+          shader.setFloat(2, cpuColors[0].r);
+          shader.setFloat(3, cpuColors[0].g);
+          shader.setFloat(4, cpuColors[0].b);
+          shader.setFloat(5, cpuColors[0].a);
+          shader.setFloat(6, cpuColors[1].r);
+          shader.setFloat(7, cpuColors[1].g);
+          shader.setFloat(8, cpuColors[1].b);
+          shader.setFloat(9, cpuColors[1].a);
+          await _expectShaderRendersBarcode(shader, cpuColors);
+        });
+
+        test('set using getUniformVec4Array', () async {
+          const cpuColors = [
+            ui.Color.fromARGB(255, 11, 22, 96),
+            ui.Color.fromARGB(255, 67, 42, 12),
+          ];
+          final ui.FragmentShader shader = shaderMap[ui.UniformArray<ui.UniformVec4Slot>]!;
+          shader.getUniformVec2('u_size').set(2, 2);
+          final ui.UniformArray<ui.UniformVec4Slot> colors = shader.getUniformVec4Array(
+            'color_array',
+          );
+          colors[0].set(cpuColors[0].r, cpuColors[0].g, cpuColors[0].b, cpuColors[0].a);
+          colors[1].set(cpuColors[1].r, cpuColors[1].g, cpuColors[1].b, cpuColors[1].a);
+          await _expectShaderRendersBarcode(shader, cpuColors);
+        });
+
+        test('wrong datatype', () async {
+          final ui.FragmentShader shader = shaderMap[ui.UniformVec3Slot]!;
+          expect(
+            () => shader.getUniformVec4Array('color_rgb'),
+            throwsA(
+              isA<ArgumentError>().having(
+                (e) => e.message,
+                'message',
+                contains('Uniform size (3) for "color_rgb" is not a multiple of 4.'),
+              ),
+            ),
+          );
+        });
+      });
+
+      group('all uniforms', () {
+        late ui.FragmentProgram program;
+        late List<ui.Color> cpuColors;
+        final random = Random(1337);
+        setUpAll(() async {
+          program = await ui.FragmentProgram.fromAsset('all_uniforms');
+        });
+
+        setUp(() async {
+          cpuColors = List<ui.Color>.empty(growable: true);
+          // uFloat
+          cpuColors.add(ui.Color.fromARGB(255, random.nextInt(255), 0, 0));
+          // uVec2
+          cpuColors.add(ui.Color.fromARGB(255, random.nextInt(255), random.nextInt(255), 0));
+          // uVec3
+          cpuColors.add(
+            ui.Color.fromARGB(255, random.nextInt(255), random.nextInt(255), random.nextInt(255)),
+          );
+          // uVec4
+          cpuColors.add(
+            ui.Color.fromARGB(255, random.nextInt(255), random.nextInt(255), random.nextInt(255)),
+          );
+          for (var i = 0; i < 10; ++i) {
+            cpuColors.add(ui.Color.fromARGB(255, random.nextInt(255), 0, 0));
+          }
+
+          for (var i = 0; i < 10; ++i) {
+            cpuColors.add(ui.Color.fromARGB(255, random.nextInt(255), random.nextInt(255), 0));
+          }
+
+          for (var i = 0; i < 10; ++i) {
+            cpuColors.add(
+              ui.Color.fromARGB(255, random.nextInt(255), random.nextInt(255), random.nextInt(255)),
+            );
+          }
+          for (var i = 0; i < 10; ++i) {
+            cpuColors.add(
+              ui.Color.fromARGB(255, random.nextInt(255), random.nextInt(255), random.nextInt(255)),
+            );
+          }
+        });
+
+        test('set using setFloat', () async {
+          final ui.FragmentShader shader = program.fragmentShader();
+          // uFloat
+          shader.setFloat(0, cpuColors[0].r);
+          //uVec2
+          shader.setFloat(1, cpuColors[1].r);
+          shader.setFloat(2, cpuColors[1].g);
+          //uVec3
+          shader.setFloat(3, cpuColors[2].r);
+          shader.setFloat(4, cpuColors[2].g);
+          shader.setFloat(5, cpuColors[2].b);
+          //uVec4
+          shader.setFloat(6, cpuColors[3].r);
+          shader.setFloat(7, cpuColors[3].g);
+          shader.setFloat(8, cpuColors[3].b);
+          shader.setFloat(9, cpuColors[3].a);
+
+          var shaderOffset = 10;
+          var colorOffset = 4;
+
+          for (var i = 0; i < 10; ++i) {
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset++].r);
+          }
+          for (var i = 0; i < 10; ++i) {
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset].r);
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset++].g);
+          }
+          for (var i = 0; i < 10; ++i) {
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset].r);
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset].g);
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset++].b);
+          }
+          for (var i = 0; i < 10; ++i) {
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset].r);
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset].g);
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset].b);
+            shader.setFloat(shaderOffset++, cpuColors[colorOffset++].a);
+          }
+          await _expectShaderRendersBarcode(shader, cpuColors);
+        });
+
+        test('set using getUniform*', () async {
+          final ui.FragmentShader shader = program.fragmentShader();
+          shader.getUniformFloat('uFloat').set(cpuColors[0].r);
+          shader.getUniformVec2('uVec2').set(cpuColors[1].r, cpuColors[1].g);
+          shader.getUniformVec3('uVec3').set(cpuColors[2].r, cpuColors[2].g, cpuColors[2].b);
+          shader
+              .getUniformVec4('uVec4')
+              .set(cpuColors[3].r, cpuColors[3].g, cpuColors[3].b, cpuColors[3].a);
+
+          final ui.UniformArray<ui.UniformFloatSlot> floatArray = shader.getUniformFloatArray(
+            'uFloatArray',
+          );
+          final ui.UniformArray<ui.UniformVec2Slot> vec2Array = shader.getUniformVec2Array(
+            'uVec2Array',
+          );
+          final ui.UniformArray<ui.UniformVec3Slot> vec3Array = shader.getUniformVec3Array(
+            'uVec3Array',
+          );
+          final ui.UniformArray<ui.UniformVec4Slot> vec4Array = shader.getUniformVec4Array(
+            'uVec4Array',
+          );
+
+          var colorOffset = 4;
+
+          for (var i = 0; i < 10; ++i) {
+            floatArray[i].set(cpuColors[colorOffset++].r);
+          }
+          for (var i = 0; i < 10; ++i) {
+            vec2Array[i].set(cpuColors[colorOffset].r, cpuColors[colorOffset].g);
+            ++colorOffset;
+          }
+          for (var i = 0; i < 10; ++i) {
+            vec3Array[i].set(
+              cpuColors[colorOffset].r,
+              cpuColors[colorOffset].g,
+              cpuColors[colorOffset].b,
+            );
+            ++colorOffset;
+          }
+          for (var i = 0; i < 10; ++i) {
+            vec4Array[i].set(
+              cpuColors[colorOffset].r,
+              cpuColors[colorOffset].g,
+              cpuColors[colorOffset].b,
+              cpuColors[colorOffset].a,
+            );
+            ++colorOffset;
+          }
+          await _expectShaderRendersBarcode(shader, cpuColors);
+        });
+      });
     });
-    test('getUniformVec3', () {
-      expect(
-        () => shader.getUniformVec3('uSize'),
-        throwsA(
-          isA<ArgumentError>().having(
-            (e) => e.message,
-            'message',
-            'Uniform `uSize` has size 2, not size 3.',
-          ),
-        ),
-      );
-    });
-    test('getUniformVec4', () {
-      expect(
-        () => shader.getUniformVec4('uLoneMatrix'),
-        throwsA(
-          isA<ArgumentError>().having(
-            (e) => e.message,
-            'message',
-            'Uniform `uLoneMatrix` has size 16, not size 4.',
-          ),
-        ),
-      );
-    });
-  });
+  }, skip: isWimp);
 }
 
 // Image of an oval painted with a linear gradient.
@@ -708,3 +1227,64 @@
     picture.dispose();
   }
 }
+
+ui.Image _imageFromShader({required ui.Shader shader, required int imageDimension}) {
+  final recorder = ui.PictureRecorder();
+  final canvas = ui.Canvas(recorder);
+  final paint = ui.Paint()..shader = shader;
+  canvas.drawPaint(paint);
+  final ui.Picture picture = recorder.endRecording();
+  return picture.toImageSync(imageDimension, imageDimension);
+}
+
+Future<ByteData?> _imageByteDataFromShader({
+  required ui.Shader shader,
+  int imageDimension = 100,
+}) async {
+  final ui.Image image = _imageFromShader(shader: shader, imageDimension: imageDimension);
+  return image.toByteData();
+}
+
+Future<void> _expectShaderRendersColor(ui.Shader shader, ui.Color color) async {
+  final ByteData renderedBytes = (await _imageByteDataFromShader(shader: shader))!;
+
+  expect(renderedBytes.lengthInBytes % 4, 0);
+  for (var byteOffset = 0; byteOffset < renderedBytes.lengthInBytes; byteOffset += 4) {
+    final pixelColor = ui.Color.fromARGB(
+      renderedBytes.getUint8(byteOffset + 3),
+      renderedBytes.getUint8(byteOffset),
+      renderedBytes.getUint8(byteOffset + 1),
+      renderedBytes.getUint8(byteOffset + 2),
+    );
+
+    expect(pixelColor, color);
+  }
+}
+
+Future<void> _expectShaderRendersBarcode(ui.Shader shader, List<ui.Color> barcodeColors) async {
+  final ByteData renderedBytes = (await _imageByteDataFromShader(
+    shader: shader,
+    imageDimension: barcodeColors.length,
+  ))!;
+
+  expect(renderedBytes.lengthInBytes % 4, 0);
+  final List<ui.Color> renderedColors = List.generate(barcodeColors.length, (int xCoord) {
+    return ui.Color.fromARGB(
+      renderedBytes.getUint8(xCoord * 4 + 3),
+      renderedBytes.getUint8(xCoord * 4),
+      renderedBytes.getUint8(xCoord * 4 + 1),
+      renderedBytes.getUint8(xCoord * 4 + 2),
+    );
+  });
+
+  for (var i = 0; i < barcodeColors.length; ++i) {
+    final ui.Color renderedColor = renderedColors[i];
+    final ui.Color expectedColor = barcodeColors[i];
+    final reasonString =
+        'Comparison failed on color $i. \nExpected: $expectedColor.\nActual: $renderedColor.';
+    expect(renderedColor.r.clamp(-1, 1), closeTo(expectedColor.r, 0.06), reason: reasonString);
+    expect(renderedColor.g.clamp(-1, 1), closeTo(expectedColor.g, 0.06), reason: reasonString);
+    expect(renderedColor.b.clamp(-1, 1), closeTo(expectedColor.b, 0.06), reason: reasonString);
+    expect(renderedColor.a.clamp(-1, 1), closeTo(expectedColor.a, 0.06), reason: reasonString);
+  }
+}