Tint&Dawn: Enable f16 override

This CL enable using f16 override, and also fix related tests in Dawn
and Tint.

Bug: tint:1473, tint:1502
Change-Id: I8336770e8a73e5023c1aba224b7b5f21692fbaa6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/124544
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/Pipeline.cpp b/src/dawn/native/Pipeline.cpp
index 37d0928..cffeaa3 100644
--- a/src/dawn/native/Pipeline.cpp
+++ b/src/dawn/native/Pipeline.cpp
@@ -25,6 +25,14 @@
 #include "dawn/native/PipelineLayout.h"
 #include "dawn/native/ShaderModule.h"
 
+namespace {
+bool IsDoubleValueRepresentableAsF16(double value) {
+    constexpr double kLowestF16 = -65504.0;
+    constexpr double kMaxF16 = 65504.0;
+    return kLowestF16 <= value && value <= kMaxF16;
+}
+}  // namespace
+
 namespace dawn::native {
 MaybeError ValidateProgrammableStage(DeviceBase* device,
                                      const ShaderModuleBase* module,
@@ -80,6 +88,12 @@
                                 "representable in type (%s)",
                                 constants[i].key, constants[i].value, "f32");
                 break;
+            case EntryPointMetadata::Override::Type::Float16:
+                DAWN_INVALID_IF(!IsDoubleValueRepresentableAsF16(constants[i].value),
+                                "Pipeline overridable constant \"%s\" with value (%f) is not "
+                                "representable in type (%s)",
+                                constants[i].key, constants[i].value, "f16");
+                break;
             case EntryPointMetadata::Override::Type::Int32:
                 DAWN_INVALID_IF(!IsDoubleValueRepresentable<int32_t>(constants[i].value),
                                 "Pipeline overridable constant \"%s\" with value (%f) is not "
diff --git a/src/dawn/native/ShaderModule.cpp b/src/dawn/native/ShaderModule.cpp
index 4143457..ae45a32 100644
--- a/src/dawn/native/ShaderModule.cpp
+++ b/src/dawn/native/ShaderModule.cpp
@@ -288,6 +288,8 @@
             return EntryPointMetadata::Override::Type::Boolean;
         case tint::inspector::Override::Type::kFloat32:
             return EntryPointMetadata::Override::Type::Float32;
+        case tint::inspector::Override::Type::kFloat16:
+            return EntryPointMetadata::Override::Type::Float16;
         case tint::inspector::Override::Type::kInt32:
             return EntryPointMetadata::Override::Type::Int32;
         case tint::inspector::Override::Type::kUint32:
diff --git a/src/dawn/native/ShaderModule.h b/src/dawn/native/ShaderModule.h
index fd604a8..5d33cd2 100644
--- a/src/dawn/native/ShaderModule.h
+++ b/src/dawn/native/ShaderModule.h
@@ -221,7 +221,7 @@
 
         // Match tint::inspector::Override::Type
         // Bool is defined as a macro on linux X11 and cannot compile
-        enum class Type { Boolean, Float32, Uint32, Int32 } type;
+        enum class Type { Boolean, Float32, Uint32, Int32, Float16 } type;
 
         // If the constant doesn't not have an initializer in the shader
         // Then it is required for the pipeline stage to have a constant record to initialize a
diff --git a/src/dawn/tests/unittests/validation/OverridableConstantsValidationTests.cpp b/src/dawn/tests/unittests/validation/OverridableConstantsValidationTests.cpp
index 542bb06..8a518f6 100644
--- a/src/dawn/tests/unittests/validation/OverridableConstantsValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/OverridableConstantsValidationTests.cpp
@@ -21,19 +21,46 @@
 
 class ComputePipelineOverridableConstantsValidationTest : public ValidationTest {
   protected:
+    WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter) override {
+        std::vector<const char*> enabledToggles;
+        std::vector<const char*> disabledToggles;
+
+        disabledToggles.push_back("disallow_unsafe_apis");
+
+        wgpu::DawnTogglesDescriptor deviceTogglesDesc;
+        deviceTogglesDesc.enabledToggles = enabledToggles.data();
+        deviceTogglesDesc.enabledTogglesCount = enabledToggles.size();
+        deviceTogglesDesc.disabledToggles = disabledToggles.data();
+        deviceTogglesDesc.disabledTogglesCount = disabledToggles.size();
+
+        const wgpu::FeatureName requiredFeatures[] = {wgpu::FeatureName::ShaderF16};
+
+        wgpu::DeviceDescriptor deviceDescriptor;
+        deviceDescriptor.nextInChain = &deviceTogglesDesc;
+        deviceDescriptor.requiredFeatures = requiredFeatures;
+        deviceDescriptor.requiredFeaturesCount = 1;
+
+        return dawnAdapter.CreateDevice(&deviceDescriptor);
+    }
+
     void SetUpShadersWithDefaultValueConstants() {
         computeModule = utils::CreateShaderModule(device, R"(
-override c0: bool = true;      // type: bool
-override c1: bool = false;      // default override
-override c2: f32 = 0.0;         // type: float32
-override c3: f32 = 0.0;         // default override
-override c4: f32 = 4.0;         // default
-override c5: i32 = 0;           // type: int32
-override c6: i32 = 0;           // default override
-override c7: i32 = 7;           // default
-override c8: u32 = 0u;          // type: uint32
-override c9: u32 = 0u;          // default override
-@id(1000) override c10: u32 = 10u;  // default
+enable f16;
+
+override c0: bool = true;            // type: bool
+override c1: bool = false;           // default override
+override c2: f32 = 0.0;              // type: float32
+override c3: f32 = 0.0;              // default override
+override c4: f32 = 4.0;              // default
+override c5: i32 = 0;                // type: int32
+override c6: i32 = 0;                // default override
+override c7: i32 = 7;                // default
+override c8: u32 = 0u;               // type: uint32
+override c9: u32 = 0u;               // default override
+override c10: u32 = 10u;             // default
+override c11: f16 = 0.0h;            // type: float16
+override c12: f16 = 0.0h;            // default override
+@id(1000) override c13: f16 = 4.0h;  // default
 
 @compute @workgroup_size(1) fn main() {
     // make sure the overridable constants are not optimized out
@@ -48,22 +75,30 @@
     _ = u32(c8);
     _ = u32(c9);
     _ = u32(c10);
+    _ = u32(c11);
+    _ = u32(c12);
+    _ = u32(c13);
 })");
     }
 
     void SetUpShadersWithUninitializedConstants() {
         computeModule = utils::CreateShaderModule(device, R"(
-override c0: bool;              // type: bool
-override c1: bool = false;      // default override
-override c2: f32;               // type: float32
-override c3: f32 = 0.0;         // default override
-override c4: f32 = 4.0;         // default
-override c5: i32;               // type: int32
-override c6: i32 = 0;           // default override
-override c7: i32 = 7;           // default
-override c8: u32;               // type: uint32
-override c9: u32 = 0u;          // default override
-@id(1000) override c10: u32 = 10u;  // default
+enable f16;
+
+override c0: bool;                   // type: bool
+override c1: bool = false;           // default override
+override c2: f32;                    // type: float32
+override c3: f32 = 0.0;              // default override
+override c4: f32 = 4.0;              // default
+override c5: i32;                    // type: int32
+override c6: i32 = 0;                // default override
+override c7: i32 = 7;                // default
+override c8: u32;                    // type: uint32
+override c9: u32 = 0u;               // default override
+override c10: u32 = 10u;             // default
+override c11: f16;                   // type: float16
+override c12: f16 = 0.0h;            // default override
+@id(1000) override c13: f16 = 4.0h;  // default
 
 @compute @workgroup_size(1) fn main() {
     // make sure the overridable constants are not optimized out
@@ -78,6 +113,9 @@
     _ = u32(c8);
     _ = u32(c9);
     _ = u32(c10);
+    _ = u32(c11);
+    _ = u32(c12);
+    _ = u32(c13);
 })");
     }
 
@@ -95,6 +133,11 @@
 };
 
 // Basic constants lookup tests
+TEST_F(ComputePipelineOverridableConstantsValidationTest, CreateShaderWithOverride) {
+    SetUpShadersWithUninitializedConstants();
+}
+
+// Basic constants lookup tests
 TEST_F(ComputePipelineOverridableConstantsValidationTest, ConstantsIdentifierLookUp) {
     SetUpShadersWithDefaultValueConstants();
     {
@@ -122,7 +165,7 @@
     }
     {
         // Error: c10 already has a constant numeric id specified
-        std::vector<wgpu::ConstantEntry> constants{{nullptr, "c10", 0}};
+        std::vector<wgpu::ConstantEntry> constants{{nullptr, "c13", 0}};
         ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
     }
     {
@@ -152,24 +195,23 @@
             {nullptr, "c2", 1},
             // c5 is missing
             {nullptr, "c8", 1},
+            {nullptr, "c11", 1},
         };
         ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
     }
     {
         // Valid: all constants initialized
         std::vector<wgpu::ConstantEntry> constants{
-            {nullptr, "c0", false},
-            {nullptr, "c2", 1},
-            {nullptr, "c5", 1},
-            {nullptr, "c8", 1},
+            {nullptr, "c0", false}, {nullptr, "c2", 1},  {nullptr, "c5", 1},
+            {nullptr, "c8", 1},     {nullptr, "c11", 1},
         };
         TestCreatePipeline(constants);
     }
     {
         // Error: duplicate initializations
         std::vector<wgpu::ConstantEntry> constants{
-            {nullptr, "c0", false}, {nullptr, "c2", 1}, {nullptr, "c5", 1},
-            {nullptr, "c8", 1},     {nullptr, "c2", 2},
+            {nullptr, "c0", false}, {nullptr, "c2", 1},  {nullptr, "c5", 1},
+            {nullptr, "c8", 1},     {nullptr, "c11", 1}, {nullptr, "c2", 2},
         };
         ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
     }
@@ -214,7 +256,7 @@
     }
     {
         // Error: constant with numeric id cannot be referenced with variable name
-        std::vector<wgpu::ConstantEntry> constants{{nullptr, "c10", 0}};
+        std::vector<wgpu::ConstantEntry> constants{{nullptr, "c13", 0}};
         ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
     }
 }
@@ -268,6 +310,34 @@
         ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
     }
     {
+        // Valid: max f32 representable value
+        std::vector<wgpu::ConstantEntry> constants{
+            {nullptr, "c3", std::numeric_limits<float>::max()}};
+        TestCreatePipeline(constants);
+    }
+    {
+        // Error: one ULP higher than max f32 representable value
+        std::vector<wgpu::ConstantEntry> constants{
+            {nullptr, "c3",
+             std::nextafter<double>(std::numeric_limits<float>::max(),
+                                    std::numeric_limits<double>::max())}};
+        ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
+    }
+    {
+        // Valid: lowest f32 representable value
+        std::vector<wgpu::ConstantEntry> constants{
+            {nullptr, "c3", std::numeric_limits<float>::lowest()}};
+        TestCreatePipeline(constants);
+    }
+    {
+        // Error: one ULP lower than lowest f32 representable value
+        std::vector<wgpu::ConstantEntry> constants{
+            {nullptr, "c3",
+             std::nextafter<double>(std::numeric_limits<float>::lowest(),
+                                    std::numeric_limits<double>::lowest())}};
+        ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
+    }
+    {
         // Error: i32 out of range
         std::vector<wgpu::ConstantEntry> constants{
             {nullptr, "c5", static_cast<double>(std::numeric_limits<int32_t>::max()) + 1.0}};
@@ -291,4 +361,27 @@
             {nullptr, "c0", static_cast<double>(std::numeric_limits<int32_t>::max()) + 1.0}};
         TestCreatePipeline(constants);
     }
+    {
+        // Valid: max f16 representable value
+        std::vector<wgpu::ConstantEntry> constants{{nullptr, "c11", 65504.0}};
+        TestCreatePipeline(constants);
+    }
+    {
+        // Error: one ULP higher than max f16 representable value
+        std::vector<wgpu::ConstantEntry> constants{
+            {nullptr, "c11", std::nextafter<double>(65504.0, std::numeric_limits<double>::max())}};
+        ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
+    }
+    {
+        // Valid: lowest f16 representable value
+        std::vector<wgpu::ConstantEntry> constants{{nullptr, "c11", -65504.0}};
+        TestCreatePipeline(constants);
+    }
+    {
+        // Error: one ULP lower than lowest f16 representable value
+        std::vector<wgpu::ConstantEntry> constants{
+            {nullptr, "c11",
+             std::nextafter<double>(-65504.0, std::numeric_limits<double>::lowest())}};
+        ASSERT_DEVICE_ERROR(TestCreatePipeline(constants));
+    }
 }
diff --git a/src/tint/cmd/helper.cc b/src/tint/cmd/helper.cc
index 49b970a..6ff1e7a 100644
--- a/src/tint/cmd/helper.cc
+++ b/src/tint/cmd/helper.cc
@@ -505,6 +505,8 @@
             return "bool";
         case tint::inspector::Override::Type::kFloat32:
             return "f32";
+        case tint::inspector::Override::Type::kFloat16:
+            return "f16";
         case tint::inspector::Override::Type::kUint32:
             return "u32";
         case tint::inspector::Override::Type::kInt32:
diff --git a/src/tint/inspector/entry_point.h b/src/tint/inspector/entry_point.h
index fd17ba0..8fd003c 100644
--- a/src/tint/inspector/entry_point.h
+++ b/src/tint/inspector/entry_point.h
@@ -92,6 +92,7 @@
         kFloat32,
         kUint32,
         kInt32,
+        kFloat16,
     };
 
     /// Type of the scalar
diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc
index 93e5c58..0b8b22c 100644
--- a/src/tint/inspector/inspector.cc
+++ b/src/tint/inspector/inspector.cc
@@ -204,7 +204,11 @@
             if (type->is_bool_scalar_or_vector()) {
                 override.type = Override::Type::kBool;
             } else if (type->is_float_scalar()) {
-                override.type = Override::Type::kFloat32;
+                if (type->Is<type::F16>()) {
+                    override.type = Override::Type::kFloat16;
+                } else {
+                    override.type = Override::Type::kFloat32;
+                }
             } else if (type->is_signed_integer_scalar()) {
                 override.type = Override::Type::kInt32;
             } else if (type->is_unsigned_integer_scalar()) {
@@ -270,6 +274,10 @@
                     [&](const type::I32*) { return Scalar(value->ValueAs<i32>()); },
                     [&](const type::U32*) { return Scalar(value->ValueAs<u32>()); },
                     [&](const type::F32*) { return Scalar(value->ValueAs<f32>()); },
+                    [&](const type::F16*) {
+                        // Default value of f16 override is also stored as float scalar.
+                        return Scalar(static_cast<float>(value->ValueAs<f16>()));
+                    },
                     [&](const type::Bool*) { return Scalar(value->ValueAs<bool>()); });
                 continue;
             }
diff --git a/src/tint/inspector/inspector_test.cc b/src/tint/inspector/inspector_test.cc
index b359074..de09369 100644
--- a/src/tint/inspector/inspector_test.cc
+++ b/src/tint/inspector/inspector_test.cc
@@ -908,18 +908,23 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, OverrideTypes) {
+    Enable(builtin::Extension::kF16);
+
     Override("bool_var", ty.bool_());
     Override("float_var", ty.f32());
     Override("u32_var", ty.u32());
     Override("i32_var", ty.i32());
+    Override("f16_var", ty.f16());
 
     MakePlainGlobalReferenceBodyFunction("bool_func", "bool_var", ty.bool_(), utils::Empty);
     MakePlainGlobalReferenceBodyFunction("float_func", "float_var", ty.f32(), utils::Empty);
     MakePlainGlobalReferenceBodyFunction("u32_func", "u32_var", ty.u32(), utils::Empty);
     MakePlainGlobalReferenceBodyFunction("i32_func", "i32_var", ty.i32(), utils::Empty);
+    MakePlainGlobalReferenceBodyFunction("f16_func", "f16_var", ty.f16(), utils::Empty);
 
     MakeCallerBodyFunction(
-        "ep_func", utils::Vector{std::string("bool_func"), "float_func", "u32_func", "i32_func"},
+        "ep_func",
+        utils::Vector{std::string("bool_func"), "float_func", "u32_func", "i32_func", "f16_func"},
         utils::Vector{
             Stage(ast::PipelineStage::kCompute),
             WorkgroupSize(1_i),
@@ -930,7 +935,7 @@
     auto result = inspector.GetEntryPoints();
 
     ASSERT_EQ(1u, result.size());
-    ASSERT_EQ(4u, result[0].overrides.size());
+    ASSERT_EQ(5u, result[0].overrides.size());
     EXPECT_EQ("bool_var", result[0].overrides[0].name);
     EXPECT_EQ(inspector::Override::Type::kBool, result[0].overrides[0].type);
     EXPECT_EQ("float_var", result[0].overrides[1].name);
@@ -939,6 +944,8 @@
     EXPECT_EQ(inspector::Override::Type::kUint32, result[0].overrides[2].type);
     EXPECT_EQ("i32_var", result[0].overrides[3].name);
     EXPECT_EQ(inspector::Override::Type::kInt32, result[0].overrides[3].type);
+    EXPECT_EQ("f16_var", result[0].overrides[4].name);
+    EXPECT_EQ(inspector::Override::Type::kFloat16, result[0].overrides[4].type);
 }
 
 TEST_F(InspectorGetEntryPointTest, OverrideInitialized) {
@@ -1572,7 +1579,7 @@
     EXPECT_EQ(100, result[OverrideId{6000}].AsI32());
 }
 
-TEST_F(InspectorGetOverrideDefaultValuesTest, Float) {
+TEST_F(InspectorGetOverrideDefaultValuesTest, F32) {
     Override("a", ty.f32(), Id(1_a));
     Override("b", ty.f32(), Expr(0_f), Id(20_a));
     Override("c", ty.f32(), Expr(-10_f), Id(300_a));
@@ -1609,6 +1616,46 @@
     EXPECT_FLOAT_EQ(150.0f, result[OverrideId{6000}].AsFloat());
 }
 
+TEST_F(InspectorGetOverrideDefaultValuesTest, F16) {
+    Enable(builtin::Extension::kF16);
+
+    Override("a", ty.f16(), Id(1_a));
+    Override("b", ty.f16(), Expr(0_h), Id(20_a));
+    Override("c", ty.f16(), Expr(-10_h), Id(300_a));
+    Override("d", Expr(15_h), Id(4000_a));
+    Override("3", Expr(42.0_h), Id(5000_a));
+    Override("e", ty.f16(), Mul(15_h, 10_a), Id(6000_a));
+
+    Inspector& inspector = Build();
+
+    auto result = inspector.GetOverrideDefaultValues();
+    ASSERT_EQ(6u, result.size());
+
+    ASSERT_TRUE(result.find(OverrideId{1}) != result.end());
+    EXPECT_TRUE(result[OverrideId{1}].IsNull());
+
+    ASSERT_TRUE(result.find(OverrideId{20}) != result.end());
+    // Default value of f16 override is also stored as float scalar.
+    EXPECT_TRUE(result[OverrideId{20}].IsFloat());
+    EXPECT_FLOAT_EQ(0.0f, result[OverrideId{20}].AsFloat());
+
+    ASSERT_TRUE(result.find(OverrideId{300}) != result.end());
+    EXPECT_TRUE(result[OverrideId{300}].IsFloat());
+    EXPECT_FLOAT_EQ(-10.0f, result[OverrideId{300}].AsFloat());
+
+    ASSERT_TRUE(result.find(OverrideId{4000}) != result.end());
+    EXPECT_TRUE(result[OverrideId{4000}].IsFloat());
+    EXPECT_FLOAT_EQ(15.0f, result[OverrideId{4000}].AsFloat());
+
+    ASSERT_TRUE(result.find(OverrideId{5000}) != result.end());
+    EXPECT_TRUE(result[OverrideId{5000}].IsFloat());
+    EXPECT_FLOAT_EQ(42.0f, result[OverrideId{5000}].AsFloat());
+
+    ASSERT_TRUE(result.find(OverrideId{6000}) != result.end());
+    EXPECT_TRUE(result[OverrideId{6000}].IsFloat());
+    EXPECT_FLOAT_EQ(150.0f, result[OverrideId{6000}].AsFloat());
+}
+
 TEST_F(InspectorGetConstantNameToIdMapTest, WithAndWithoutIds) {
     Override("v1", ty.f32(), Id(1_a));
     Override("v20", ty.f32(), Id(20_a));
diff --git a/src/tint/resolver/override_test.cc b/src/tint/resolver/override_test.cc
index fd0f649..c825969 100644
--- a/src/tint/resolver/override_test.cc
+++ b/src/tint/resolver/override_test.cc
@@ -66,10 +66,12 @@
 }
 
 TEST_F(ResolverOverrideTest, WithAndWithoutIds) {
+    Enable(builtin::Extension::kF16);
+
     auto* a = Override("a", ty.f32(), Expr(1_f));
-    auto* b = Override("b", ty.f32(), Expr(1_f));
-    auto* c = Override("c", ty.f32(), Expr(1_f), Id(2_u));
-    auto* d = Override("d", ty.f32(), Expr(1_f), Id(4_u));
+    auto* b = Override("b", ty.f16(), Expr(1_h));
+    auto* c = Override("c", ty.i32(), Expr(1_i), Id(2_u));
+    auto* d = Override("d", ty.u32(), Expr(1_u), Id(4_u));
     auto* e = Override("e", ty.f32(), Expr(1_f));
     auto* f = Override("f", ty.f32(), Expr(1_f), Id(1_u));
 
@@ -102,16 +104,6 @@
     EXPECT_EQ(r()->error(), "12:34 error: @id value must be between 0 and 65535");
 }
 
-TEST_F(ResolverOverrideTest, F16_TemporallyBan) {
-    Enable(builtin::Extension::kF16);
-
-    Override(Source{{12, 34}}, "a", ty.f16(), Expr(1_h), Id(1_u));
-
-    EXPECT_FALSE(r()->Resolve());
-
-    EXPECT_EQ(r()->error(), "12:34 error: 'override' of type f16 is not implemented yet");
-}
-
 TEST_F(ResolverOverrideTest, TransitiveReferences_DirectUse) {
     auto* a = Override("a", ty.f32());
     auto* b = Override("b", ty.f32(), Expr(1_f));
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index c3b8a3d..b005779d 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -788,11 +788,6 @@
         return false;
     }
 
-    if (storage_ty->Is<type::F16>()) {
-        AddError("'override' of type f16 is not implemented yet", decl->source);
-        return false;
-    }
-
     return true;
 }
 
diff --git a/src/tint/transform/substitute_override_test.cc b/src/tint/transform/substitute_override_test.cc
index 1b4646f..5deab72 100644
--- a/src/tint/transform/substitute_override_test.cc
+++ b/src/tint/transform/substitute_override_test.cc
@@ -84,15 +84,16 @@
 
 TEST_F(SubstituteOverrideTest, ImplicitId) {
     auto* src = R"(
+enable f16;
+
 override i_width: i32;
 override i_height = 1i;
 
 override f_width: f32;
 override f_height = 1.f;
 
-// TODO(crbug.com/tint/1473)
-// override h_width: f16;
-// override h_height = 1.h;
+override h_width: f16;
+override h_height = 1.h;
 
 override b_width: bool;
 override b_height = true;
@@ -106,6 +107,8 @@
 )";
 
     auto* expect = R"(
+enable f16;
+
 const i_width : i32 = 42i;
 
 const i_height = 11i;
@@ -114,6 +117,10 @@
 
 const f_height = 12.3999996185302734375f;
 
+const h_width : f16 = 9.3984375h;
+
+const h_height = 3.3984375h;
+
 const b_width : bool = true;
 
 const b_height = false;
@@ -131,10 +138,10 @@
     cfg.map.insert({OverrideId{1}, 11.0});
     cfg.map.insert({OverrideId{2}, 22.3});
     cfg.map.insert({OverrideId{3}, 12.4});
-    // cfg.map.insert({OverrideId{4}, 9.4});
-    // cfg.map.insert({OverrideId{5}, 3.4});
-    cfg.map.insert({OverrideId{4}, 1.0});
-    cfg.map.insert({OverrideId{5}, 0.0});
+    cfg.map.insert({OverrideId{4}, 9.4});
+    cfg.map.insert({OverrideId{5}, 3.4});
+    cfg.map.insert({OverrideId{6}, 1.0});
+    cfg.map.insert({OverrideId{7}, 0.0});
 
     DataMap data;
     data.Add<SubstituteOverride::Config>(cfg);
@@ -153,9 +160,8 @@
 @id(1) override f_width: f32;
 @id(9) override f_height = 1.f;
 
-// TODO(crbug.com/tint/1473)
-// @id(2) override h_width: f16;
-// @id(8) override h_height = 1.h;
+@id(2) override h_width: f16;
+@id(8) override h_height = 1.h;
 
 @id(3) override b_width: bool;
 @id(7) override b_height = true;
@@ -179,6 +185,10 @@
 
 const f_height = 12.3999996185302734375f;
 
+const h_width : f16 = 9.3984375h;
+
+const h_height = 3.3984375h;
+
 const b_width : bool = true;
 
 const b_height = false;