[tint] Implement support for r8unorm

Bug: dawn:2101
Change-Id: I0ebb48c577f114efd9e2564ac818c4869852a927
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/176042
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/cmd/common/helper.cc b/src/tint/cmd/common/helper.cc
index c043588..2e9ce37 100644
--- a/src/tint/cmd/common/helper.cc
+++ b/src/tint/cmd/common/helper.cc
@@ -453,6 +453,8 @@
             return "Rgba32Sint";
         case tint::inspector::ResourceBinding::TexelFormat::kRgba32Float:
             return "Rgba32Float";
+        case tint::inspector::ResourceBinding::TexelFormat::kR8Unorm:
+            return "R8Unorm";
         case tint::inspector::ResourceBinding::TexelFormat::kNone:
             return "None";
     }
diff --git a/src/tint/lang/core/core.def b/src/tint/lang/core/core.def
index f8deb52..7352a85 100644
--- a/src/tint/lang/core/core.def
+++ b/src/tint/lang/core/core.def
@@ -302,7 +302,8 @@
 
 // https://gpuweb.github.io/gpuweb/wgsl/#texel-formats
 match f32_texel_format
-  : texel_format.bgra8unorm
+  : texel_format.r8unorm
+  | texel_format.bgra8unorm
   | texel_format.rgba8unorm
   | texel_format.rgba8snorm
   | texel_format.rgba16float
diff --git a/src/tint/lang/core/intrinsic/data.cc b/src/tint/lang/core/intrinsic/data.cc
index 0fc6fe4..db57c64 100644
--- a/src/tint/lang/core/intrinsic/data.cc
+++ b/src/tint/lang/core/intrinsic/data.cc
@@ -1239,6 +1239,7 @@
 constexpr NumberMatcher kF32TexelFormatMatcher {
 /* match */ [](MatchState&, Number number) -> Number {
     switch (static_cast<core::TexelFormat>(number.Value())) {
+      case core::TexelFormat::kR8Unorm:
       case core::TexelFormat::kBgra8Unorm:
       case core::TexelFormat::kRgba8Unorm:
       case core::TexelFormat::kRgba8Snorm:
@@ -1252,7 +1253,7 @@
     }
   },
 /* print */ [](MatchState*, StyledText& out) {
-  out<< style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(" or ") << style::Enum("rgba32float");
+  out<< style::Enum("r8unorm")<< style::Plain(", ") << style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(" or ") << style::Enum("rgba32float");
   }
 };
 
diff --git a/src/tint/lang/core/texel_format.cc b/src/tint/lang/core/texel_format.cc
index c0f552a..1371c35 100644
--- a/src/tint/lang/core/texel_format.cc
+++ b/src/tint/lang/core/texel_format.cc
@@ -54,6 +54,9 @@
     if (str == "r32uint") {
         return TexelFormat::kR32Uint;
     }
+    if (str == "r8unorm") {
+        return TexelFormat::kR8Unorm;
+    }
     if (str == "rg32float") {
         return TexelFormat::kRg32Float;
     }
@@ -108,6 +111,8 @@
             return "r32sint";
         case TexelFormat::kR32Uint:
             return "r32uint";
+        case TexelFormat::kR8Unorm:
+            return "r8unorm";
         case TexelFormat::kRg32Float:
             return "rg32float";
         case TexelFormat::kRg32Sint:
diff --git a/src/tint/lang/core/texel_format.def b/src/tint/lang/core/texel_format.def
index 89e5f65..3d194a4 100644
--- a/src/tint/lang/core/texel_format.def
+++ b/src/tint/lang/core/texel_format.def
@@ -17,4 +17,7 @@
   rgba32uint
   rgba32sint
   rgba32float
+
+  // requires chromium_internal_graphite
+  r8unorm
 }
diff --git a/src/tint/lang/core/texel_format.h b/src/tint/lang/core/texel_format.h
index da6791d..6a9a4e2 100644
--- a/src/tint/lang/core/texel_format.h
+++ b/src/tint/lang/core/texel_format.h
@@ -50,6 +50,7 @@
     kR32Float,
     kR32Sint,
     kR32Uint,
+    kR8Unorm,
     kRg32Float,
     kRg32Sint,
     kRg32Uint,
@@ -83,9 +84,9 @@
 TexelFormat ParseTexelFormat(std::string_view str);
 
 constexpr std::string_view kTexelFormatStrings[] = {
-    "bgra8unorm", "r32float",    "r32sint",    "r32uint",    "rg32float",   "rg32sint",
-    "rg32uint",   "rgba16float", "rgba16sint", "rgba16uint", "rgba32float", "rgba32sint",
-    "rgba32uint", "rgba8sint",   "rgba8snorm", "rgba8uint",  "rgba8unorm",
+    "bgra8unorm", "r32float",   "r32sint",     "r32uint",    "r8unorm",    "rg32float",
+    "rg32sint",   "rg32uint",   "rgba16float", "rgba16sint", "rgba16uint", "rgba32float",
+    "rgba32sint", "rgba32uint", "rgba8sint",   "rgba8snorm", "rgba8uint",  "rgba8unorm",
 };
 
 }  // namespace tint::core
diff --git a/src/tint/lang/core/texel_format_bench.cc b/src/tint/lang/core/texel_format_bench.cc
index 90e7795..33f4455 100644
--- a/src/tint/lang/core/texel_format_bench.cc
+++ b/src/tint/lang/core/texel_format_bench.cc
@@ -45,30 +45,32 @@
 
 void TexelFormatParser(::benchmark::State& state) {
     const char* kStrings[] = {
-        "bgraunccrm",     "blranr3",      "bVra8unorm",   "bgra8unorm",   "bgra1unorm",
-        "bgrJqqnorm",     "bgr7ll8unorm", "qq32lppHat",   "c2fov",        "r32Goat",
-        "r32float",       "r3viiloat",    "r3WWflo8t",    "rxxfMoat",     "rXsingg",
-        "3siXt",          "r32s3nt",      "r32sint",      "E32sint",      "rPTTsint",
-        "r32sidxx",       "r442uint",     "r3SSuiVVt",    "R32R22t",      "r32uint",
-        "rFui9t",         "r32int",       "VOORRHnt",     "rgy2foat",     "l77nnrr2floGt",
-        "rg42fl00at",     "rg32float",    "rgoofat",      "rgzzflot",     "g11p2fliia",
-        "XXg32sint",      "rII39955nnnt", "aagHH2sinYSS", "rg32sint",     "rkk3it",
-        "gj3sRRn",        "r3bsnt",       "rg32jint",     "rg32unt",      "rgqint",
-        "rg32uint",       "rg32inNN",     "g3vvint",      "rg2uQQnt",     "rga16floft",
-        "rgja16float",    "rgNNww16f2oa", "rgba16float",  "rgba16flot",   "rgba16rrloat",
-        "rgGa16float",    "rgba16sFFnt",  "g16sEnt",      "rgb16rrint",   "rgba16sint",
-        "gba16sit",       "rXa1DsiJJt",   "rgasint",      "rg111kin",     "rgb16uint",
-        "rgJa16uit",      "rgba16uint",   "rgca16uint",   "rgba16Oint",   "KKgba__v6uintt",
-        "rgb832fxx5t",    "rgbaqq__lat",  "rgba32qloat",  "rgba32float",  "33gbO2floa66",
-        "rgboott6QQloat", "66ba32float",  "xba32zzinO6",  "ryyba32sint",  "rbZ32HinZ",
-        "rgba32sint",     "rgba3s4WWnq",  "rgba32sOOt",   "oogba2Yin",    "ga32unt",
-        "Fga32uint",      "rgb32uinw",    "rgba32uint",   "rgGf32uit",    "rgbaqKKuint",
-        "rFba32ummnt",    "rgba8snt",     "rgq8sint",     "rbbba8bin",    "rgba8sint",
-        "rgbisint",       "rgq8sinOO",    "rgbaTTvvint",  "rgFFa8snorm",  "rg00QsnPrm",
-        "rgbaPsnorm",     "rgba8snorm",   "rgb77ssnorm",  "rgba8snbbRRC", "rgbXX8snorm",
-        "qgCCOO8iOOt",    "rsauuinL",     "rgXa8uint",    "rgba8uint",    "rgba8int",
-        "rgbunqq",        "rg22a8uint",   "rybXX0nzzrm",  "rgVVa8iorP",   "rbaCunnnrm",
-        "rgba8unorm",     "ba8unoqqHHA",  "rga8unorm",    "rgfa8uKKo",
+        "bgraunccrm",    "blranr3",       "bVra8unorm",    "bgra8unorm",   "bgra1unorm",
+        "bgrJqqnorm",    "bgr7ll8unorm",  "qq32lppHat",    "c2fov",        "r32Goat",
+        "r32float",      "r3viiloat",     "r3WWflo8t",     "rxxfMoat",     "rXsingg",
+        "3siXt",         "r32s3nt",       "r32sint",       "E32sint",      "rPTTsint",
+        "r32sidxx",      "r442uint",      "r3SSuiVVt",     "R32R22t",      "r32uint",
+        "rFui9t",        "r32int",        "VOORRHnt",      "r8noym",       "lln8rrn77rm",
+        "r8un4r00",      "r8unorm",       "8noom",         "zznorm",       "riiuppo1",
+        "rg32floaXX",    "rg355flo99nII", "rrr32floSSaHH", "rg32float",    "kk3Hoat",
+        "jg2loaRR",      "rg2loab",       "rg32jint",      "rg32snt",      "rgqint",
+        "rg32sint",      "rg32inNN",      "g3vvint",       "rg2sQQnt",     "rg3furt",
+        "rgj2uint",      "rg3wNN82t",     "rg32uint",      "rg32unt",      "rgrr2uint",
+        "rG32uint",      "FFgba16float",  "rEb16loa",      "rga16frroat",  "rgba16float",
+        "rgba6loat",     "Xba1JJfDoat",   "rga6fl8a",      "rg111kin",     "rgb16sint",
+        "rgJa16sit",     "rgba16sint",    "rgca16sint",    "rgba16Oint",   "KKgba__v6sintt",
+        "rg5a16xxnt",    "__ba1uqqFt",    "rgbqq6uint",    "rgba16uint",   "33ba16u66nt",
+        "rtt6a1QQooint", "r66ba1uint",    "rgbx266loaOz",  "yygba32float", "gba3ZZHoat",
+        "rgba32float",   "WWga32floq4t",  "rgba3OOfoat",   "rYoha2flat",   "ga32snt",
+        "Fga32sint",     "rgb32sinw",     "rgba32sint",    "rgGf32sit",    "rgbaqKKsint",
+        "rFba32smmnt",   "rgba32uit",     "rqba3uint",     "rgbabb2uin",   "rgba32uint",
+        "rba32iint",     "qgba32uiOt",    "rgba32uiTTvv",  "rgbaFFsint",   "rgQa00siP",
+        "rgPa8sint",     "rgba8sint",     "rgssa77snt",    "Cgbbb8siRRt",  "rgba8sinXX",
+        "CqgbaOOsnorm",  "rgbu8ssrL",     "rgba8Xnorm",    "rgba8snorm",   "rgba8snrm",
+        "ba8sqqor",      "rgba8snor22",   "rzzyaXui0t",    "rPbi8uint",    "rgaCnnint",
+        "rgba8uint",     "bqqAAuinHH",    "rgba8unt",      "rgb8uiKf",     "raggunorm",
+        "rgb8unorm",     "rgba8uTNo4m",   "rgba8unorm",    "rgla8unppr7",  "rg8zznNNrm",
+        "bXXbauuuorm",
     };
     for (auto _ : state) {
         for (auto* str : kStrings) {
diff --git a/src/tint/lang/core/texel_format_test.cc b/src/tint/lang/core/texel_format_test.cc
index 1500656..ae49396 100644
--- a/src/tint/lang/core/texel_format_test.cc
+++ b/src/tint/lang/core/texel_format_test.cc
@@ -59,42 +59,43 @@
 static constexpr Case kValidCases[] = {
     {"bgra8unorm", TexelFormat::kBgra8Unorm},   {"r32float", TexelFormat::kR32Float},
     {"r32sint", TexelFormat::kR32Sint},         {"r32uint", TexelFormat::kR32Uint},
-    {"rg32float", TexelFormat::kRg32Float},     {"rg32sint", TexelFormat::kRg32Sint},
-    {"rg32uint", TexelFormat::kRg32Uint},       {"rgba16float", TexelFormat::kRgba16Float},
-    {"rgba16sint", TexelFormat::kRgba16Sint},   {"rgba16uint", TexelFormat::kRgba16Uint},
-    {"rgba32float", TexelFormat::kRgba32Float}, {"rgba32sint", TexelFormat::kRgba32Sint},
-    {"rgba32uint", TexelFormat::kRgba32Uint},   {"rgba8sint", TexelFormat::kRgba8Sint},
-    {"rgba8snorm", TexelFormat::kRgba8Snorm},   {"rgba8uint", TexelFormat::kRgba8Uint},
-    {"rgba8unorm", TexelFormat::kRgba8Unorm},
+    {"r8unorm", TexelFormat::kR8Unorm},         {"rg32float", TexelFormat::kRg32Float},
+    {"rg32sint", TexelFormat::kRg32Sint},       {"rg32uint", TexelFormat::kRg32Uint},
+    {"rgba16float", TexelFormat::kRgba16Float}, {"rgba16sint", TexelFormat::kRgba16Sint},
+    {"rgba16uint", TexelFormat::kRgba16Uint},   {"rgba32float", TexelFormat::kRgba32Float},
+    {"rgba32sint", TexelFormat::kRgba32Sint},   {"rgba32uint", TexelFormat::kRgba32Uint},
+    {"rgba8sint", TexelFormat::kRgba8Sint},     {"rgba8snorm", TexelFormat::kRgba8Snorm},
+    {"rgba8uint", TexelFormat::kRgba8Uint},     {"rgba8unorm", TexelFormat::kRgba8Unorm},
 };
 
 static constexpr Case kInvalidCases[] = {
-    {"bgraunccrm", TexelFormat::kUndefined},      {"blranr3", TexelFormat::kUndefined},
-    {"bVra8unorm", TexelFormat::kUndefined},      {"132float", TexelFormat::kUndefined},
-    {"32Jlqqat", TexelFormat::kUndefined},        {"ll3277loat", TexelFormat::kUndefined},
-    {"ppqq2snHH", TexelFormat::kUndefined},       {"r3cv", TexelFormat::kUndefined},
-    {"b2siGt", TexelFormat::kUndefined},          {"r32uiivt", TexelFormat::kUndefined},
-    {"8WW2uint", TexelFormat::kUndefined},        {"rxxuint", TexelFormat::kUndefined},
-    {"rX2flggat", TexelFormat::kUndefined},       {"rg3XVut", TexelFormat::kUndefined},
-    {"3g32float", TexelFormat::kUndefined},       {"rg3Esint", TexelFormat::kUndefined},
-    {"PP32TTint", TexelFormat::kUndefined},       {"xxg32ddnt", TexelFormat::kUndefined},
-    {"44g32uint", TexelFormat::kUndefined},       {"rSS32uinVV", TexelFormat::kUndefined},
-    {"R322Rint", TexelFormat::kUndefined},        {"rgba16fF9a", TexelFormat::kUndefined},
-    {"rgba16floa", TexelFormat::kUndefined},      {"rOObVR16floH", TexelFormat::kUndefined},
-    {"ryba1sint", TexelFormat::kUndefined},       {"r77ba1nnsllrrt", TexelFormat::kUndefined},
-    {"rgb4006sint", TexelFormat::kUndefined},     {"rb1uioot", TexelFormat::kUndefined},
-    {"rga1uzznt", TexelFormat::kUndefined},       {"r11b1uppiit", TexelFormat::kUndefined},
-    {"rgba32fXXoat", TexelFormat::kUndefined},    {"rgbII99355float", TexelFormat::kUndefined},
-    {"rgbaa32fSSrHHYt", TexelFormat::kUndefined}, {"rbkk2Hit", TexelFormat::kUndefined},
-    {"jgba3sgRR", TexelFormat::kUndefined},       {"rgbab2si", TexelFormat::kUndefined},
-    {"rgba32jint", TexelFormat::kUndefined},      {"rba32uint", TexelFormat::kUndefined},
-    {"rgba2uqn", TexelFormat::kUndefined},        {"rbaNNsint", TexelFormat::kUndefined},
-    {"rga8invv", TexelFormat::kUndefined},        {"gba8sQQnt", TexelFormat::kUndefined},
-    {"rgbsnrrff", TexelFormat::kUndefined},       {"rgba8snojm", TexelFormat::kUndefined},
-    {"NNgba8sww2m", TexelFormat::kUndefined},     {"rgba8uit", TexelFormat::kUndefined},
-    {"rrgba8uint", TexelFormat::kUndefined},      {"rgba8uiGt", TexelFormat::kUndefined},
-    {"rgba8unFFrm", TexelFormat::kUndefined},     {"g8unErm", TexelFormat::kUndefined},
-    {"rgb8urrorm", TexelFormat::kUndefined},
+    {"bgraunccrm", TexelFormat::kUndefined},     {"blranr3", TexelFormat::kUndefined},
+    {"bVra8unorm", TexelFormat::kUndefined},     {"132float", TexelFormat::kUndefined},
+    {"32Jlqqat", TexelFormat::kUndefined},       {"ll3277loat", TexelFormat::kUndefined},
+    {"ppqq2snHH", TexelFormat::kUndefined},      {"r3cv", TexelFormat::kUndefined},
+    {"b2siGt", TexelFormat::kUndefined},         {"r32uiivt", TexelFormat::kUndefined},
+    {"8WW2uint", TexelFormat::kUndefined},       {"rxxuint", TexelFormat::kUndefined},
+    {"rXnorgg", TexelFormat::kUndefined},        {"8noXm", TexelFormat::kUndefined},
+    {"r8un3rm", TexelFormat::kUndefined},        {"rg32floEt", TexelFormat::kUndefined},
+    {"rgTTP2loat", TexelFormat::kUndefined},     {"ddg32loxxt", TexelFormat::kUndefined},
+    {"44g32sint", TexelFormat::kUndefined},      {"rSS32sinVV", TexelFormat::kUndefined},
+    {"R322Rint", TexelFormat::kUndefined},       {"gF29int", TexelFormat::kUndefined},
+    {"rg3uint", TexelFormat::kUndefined},        {"ROOgH2iVt", TexelFormat::kUndefined},
+    {"rgya16flot", TexelFormat::kUndefined},     {"rrgba16flll77Gt", TexelFormat::kUndefined},
+    {"rgba46fl00at", TexelFormat::kUndefined},   {"rb1sioot", TexelFormat::kUndefined},
+    {"rga1szznt", TexelFormat::kUndefined},      {"r11b1sppiit", TexelFormat::kUndefined},
+    {"XXgba16uint", TexelFormat::kUndefined},    {"IIgb9916nni55t", TexelFormat::kUndefined},
+    {"rYbaSSrruiHHat", TexelFormat::kUndefined}, {"gHkkfloat", TexelFormat::kUndefined},
+    {"jRRba3fgat", TexelFormat::kUndefined},     {"rba32flbt", TexelFormat::kUndefined},
+    {"rgba32jint", TexelFormat::kUndefined},     {"rba32sint", TexelFormat::kUndefined},
+    {"rgba2sqn", TexelFormat::kUndefined},       {"rgba3NNuit", TexelFormat::kUndefined},
+    {"rga3vvint", TexelFormat::kUndefined},      {"rgba32uinQ", TexelFormat::kUndefined},
+    {"rgbasirf", TexelFormat::kUndefined},       {"rgbajsint", TexelFormat::kUndefined},
+    {"wNNgbasin2", TexelFormat::kUndefined},     {"rgba8snrm", TexelFormat::kUndefined},
+    {"rgba8srrorm", TexelFormat::kUndefined},    {"rgba8Gnorm", TexelFormat::kUndefined},
+    {"rgba8uFFnt", TexelFormat::kUndefined},     {"Ega8un", TexelFormat::kUndefined},
+    {"rgrr8uint", TexelFormat::kUndefined},      {"gba8unom", TexelFormat::kUndefined},
+    {"rXa8DnoJJm", TexelFormat::kUndefined},     {"rganorm", TexelFormat::kUndefined},
 };
 
 using TexelFormatParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/lang/core/type/storage_texture.cc b/src/tint/lang/core/type/storage_texture.cc
index 879ff99..ea7c9ca 100644
--- a/src/tint/lang/core/type/storage_texture.cc
+++ b/src/tint/lang/core/type/storage_texture.cc
@@ -80,6 +80,7 @@
             return type_mgr.Get<I32>();
         }
 
+        case core::TexelFormat::kR8Unorm:
         case core::TexelFormat::kBgra8Unorm:
         case core::TexelFormat::kRgba8Unorm:
         case core::TexelFormat::kRgba8Snorm:
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 6ecc839..21ff1b8 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -274,8 +274,9 @@
             "GLSL", builder_.AST(), diagnostics_,
             Vector{
                 wgsl::Extension::kChromiumDisableUniformityAnalysis,
-                wgsl::Extension::kChromiumInternalDualSourceBlending,
                 wgsl::Extension::kChromiumExperimentalPushConstant,
+                wgsl::Extension::kChromiumInternalDualSourceBlending,
+                wgsl::Extension::kChromiumInternalGraphite,
                 wgsl::Extension::kF16,
             })) {
         return false;
@@ -2028,6 +2029,9 @@
             case core::TexelFormat::kRgba32Float:
                 out << "rgba32f";
                 break;
+            case core::TexelFormat::kR8Unorm:
+                out << "r8";
+                break;
             case core::TexelFormat::kUndefined:
                 TINT_ICE() << "invalid texel format";
                 return;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
index 658beeb..387ddb9 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
@@ -105,8 +105,9 @@
 
 const char kTempNamePrefix[] = "tint_tmp";
 
-const char* image_format_to_rwtexture_type(core::TexelFormat image_format) {
+const char* ImageFormatToRWtextureType(core::TexelFormat image_format) {
     switch (image_format) {
+        case core::TexelFormat::kR8Unorm:
         case core::TexelFormat::kBgra8Unorm:
         case core::TexelFormat::kRgba8Unorm:
         case core::TexelFormat::kRgba8Snorm:
@@ -388,11 +389,12 @@
             "HLSL", builder_.AST(), diagnostics_,
             Vector{
                 wgsl::Extension::kChromiumDisableUniformityAnalysis,
+                wgsl::Extension::kChromiumExperimentalPixelLocal,
                 wgsl::Extension::kChromiumExperimentalPushConstant,
                 wgsl::Extension::kChromiumExperimentalSubgroups,
-                wgsl::Extension::kF16,
                 wgsl::Extension::kChromiumInternalDualSourceBlending,
-                wgsl::Extension::kChromiumExperimentalPixelLocal,
+                wgsl::Extension::kChromiumInternalGraphite,
+                wgsl::Extension::kF16,
             })) {
         return false;
     }
@@ -3459,7 +3461,7 @@
             return false;
         }
         out << "RasterizerOrderedTexture2D";
-        auto* component = image_format_to_rwtexture_type(storage->texel_format());
+        auto* component = ImageFormatToRWtextureType(storage->texel_format());
         if (TINT_UNLIKELY(!component)) {
             TINT_ICE() << "Unsupported StorageTexture TexelFormat: "
                        << static_cast<int>(storage->texel_format());
@@ -4460,7 +4462,7 @@
             }
 
             if (storage) {
-                auto* component = image_format_to_rwtexture_type(storage->texel_format());
+                auto* component = ImageFormatToRWtextureType(storage->texel_format());
                 if (TINT_UNLIKELY(!component)) {
                     TINT_ICE() << "Unsupported StorageTexture TexelFormat: "
                                << static_cast<int>(storage->texel_format());
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index c2442f5..9a574b7 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -273,10 +273,11 @@
             "MSL", builder_.AST(), diagnostics_,
             Vector{
                 wgsl::Extension::kChromiumDisableUniformityAnalysis,
+                wgsl::Extension::kChromiumExperimentalFramebufferFetch,
                 wgsl::Extension::kChromiumExperimentalPixelLocal,
                 wgsl::Extension::kChromiumExperimentalSubgroups,
-                wgsl::Extension::kChromiumExperimentalFramebufferFetch,
                 wgsl::Extension::kChromiumInternalDualSourceBlending,
+                wgsl::Extension::kChromiumInternalGraphite,
                 wgsl::Extension::kChromiumInternalRelaxedUniformLayout,
                 wgsl::Extension::kF16,
             })) {
diff --git a/src/tint/lang/spirv/intrinsic/data.cc b/src/tint/lang/spirv/intrinsic/data.cc
index 27b7ab3..b00c77c 100644
--- a/src/tint/lang/spirv/intrinsic/data.cc
+++ b/src/tint/lang/spirv/intrinsic/data.cc
@@ -1014,6 +1014,7 @@
 constexpr NumberMatcher kF32TexelFormatMatcher {
 /* match */ [](MatchState&, Number number) -> Number {
     switch (static_cast<core::TexelFormat>(number.Value())) {
+      case core::TexelFormat::kR8Unorm:
       case core::TexelFormat::kBgra8Unorm:
       case core::TexelFormat::kRgba8Unorm:
       case core::TexelFormat::kRgba8Snorm:
@@ -1027,7 +1028,7 @@
     }
   },
 /* print */ [](MatchState*, StyledText& out) {
-  out<< style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(" or ") << style::Enum("rgba32float");
+  out<< style::Enum("r8unorm")<< style::Plain(", ") << style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(" or ") << style::Enum("rgba32float");
   }
 };
 
diff --git a/src/tint/lang/spirv/spirv.def b/src/tint/lang/spirv/spirv.def
index 96fb6c4..9dabb13 100644
--- a/src/tint/lang/spirv/spirv.def
+++ b/src/tint/lang/spirv/spirv.def
@@ -99,7 +99,8 @@
   | sampler_comparison
 
 match f32_texel_format
-  : texel_format.bgra8unorm
+  : texel_format.r8unorm
+  | texel_format.bgra8unorm
   | texel_format.rgba8unorm
   | texel_format.rgba8snorm
   | texel_format.rgba16float
diff --git a/src/tint/lang/spirv/writer/ast_printer/builder.cc b/src/tint/lang/spirv/writer/ast_printer/builder.cc
index a412f49..9673668 100644
--- a/src/tint/lang/spirv/writer/ast_printer/builder.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/builder.cc
@@ -279,8 +279,9 @@
                 wgsl::Extension::kChromiumDisableUniformityAnalysis,
                 wgsl::Extension::kChromiumExperimentalPushConstant,
                 wgsl::Extension::kChromiumExperimentalSubgroups,
-                wgsl::Extension::kF16,
                 wgsl::Extension::kChromiumInternalDualSourceBlending,
+                wgsl::Extension::kChromiumInternalGraphite,
+                wgsl::Extension::kF16,
             })) {
         return false;
     }
@@ -4109,6 +4110,9 @@
         case core::TexelFormat::kBgra8Unorm:
             TINT_ICE() << "bgra8unorm should have been polyfilled to rgba8unorm";
             return SpvImageFormatUnknown;
+        case core::TexelFormat::kR8Unorm:
+            module_.PushCapability(SpvCapabilityStorageImageExtendedFormats);
+            return SpvImageFormatR8;
         case core::TexelFormat::kR32Uint:
             return SpvImageFormatR32ui;
         case core::TexelFormat::kR32Sint:
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index 9fc98fd..c38f018 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -2228,6 +2228,9 @@
             case core::TexelFormat::kBgra8Unorm:
                 TINT_ICE() << "bgra8unorm should have been polyfilled to rgba8unorm";
                 return SpvImageFormatUnknown;
+            case core::TexelFormat::kR8Unorm:
+                module_.PushCapability(SpvCapabilityStorageImageExtendedFormats);
+                return SpvImageFormatR8;
             case core::TexelFormat::kR32Uint:
                 return SpvImageFormatR32ui;
             case core::TexelFormat::kR32Sint:
diff --git a/src/tint/lang/wgsl/inspector/resource_binding.cc b/src/tint/lang/wgsl/inspector/resource_binding.cc
index 810e544..0cf21bb 100644
--- a/src/tint/lang/wgsl/inspector/resource_binding.cc
+++ b/src/tint/lang/wgsl/inspector/resource_binding.cc
@@ -120,6 +120,8 @@
             return ResourceBinding::TexelFormat::kRgba32Sint;
         case core::TexelFormat::kRgba32Float:
             return ResourceBinding::TexelFormat::kRgba32Float;
+        case core::TexelFormat::kR8Unorm:
+            return ResourceBinding::TexelFormat::kR8Unorm;
         case core::TexelFormat::kUndefined:
             return ResourceBinding::TexelFormat::kNone;
     }
diff --git a/src/tint/lang/wgsl/inspector/resource_binding.h b/src/tint/lang/wgsl/inspector/resource_binding.h
index 86fb720..1c1f801 100644
--- a/src/tint/lang/wgsl/inspector/resource_binding.h
+++ b/src/tint/lang/wgsl/inspector/resource_binding.h
@@ -80,6 +80,7 @@
         kRgba32Uint,
         kRgba32Sint,
         kRgba32Float,
+        kR8Unorm,
         kNone,
     };
 
diff --git a/src/tint/lang/wgsl/intrinsic/data.cc b/src/tint/lang/wgsl/intrinsic/data.cc
index f5ec9db..3a84f91 100644
--- a/src/tint/lang/wgsl/intrinsic/data.cc
+++ b/src/tint/lang/wgsl/intrinsic/data.cc
@@ -1529,6 +1529,7 @@
 constexpr NumberMatcher kF32TexelFormatMatcher {
 /* match */ [](MatchState&, Number number) -> Number {
     switch (static_cast<core::TexelFormat>(number.Value())) {
+      case core::TexelFormat::kR8Unorm:
       case core::TexelFormat::kBgra8Unorm:
       case core::TexelFormat::kRgba8Unorm:
       case core::TexelFormat::kRgba8Snorm:
@@ -1542,7 +1543,7 @@
     }
   },
 /* print */ [](MatchState*, StyledText& out) {
-  out<< style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(" or ") << style::Enum("rgba32float");
+  out<< style::Enum("r8unorm")<< style::Plain(", ") << style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(" or ") << style::Enum("rgba32float");
   }
 };
 
diff --git a/src/tint/lang/wgsl/resolver/BUILD.bazel b/src/tint/lang/wgsl/resolver/BUILD.bazel
index 51904b9..9893abb 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.bazel
+++ b/src/tint/lang/wgsl/resolver/BUILD.bazel
@@ -121,6 +121,7 @@
     "f16_extension_test.cc",
     "framebuffer_fetch_extension_test.cc",
     "function_validation_test.cc",
+    "graphite_extension_test.cc",
     "host_shareable_validation_test.cc",
     "increment_decrement_validation_test.cc",
     "inferred_type_test.cc",
diff --git a/src/tint/lang/wgsl/resolver/BUILD.cmake b/src/tint/lang/wgsl/resolver/BUILD.cmake
index 6cb53ed..429b9c0 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.cmake
+++ b/src/tint/lang/wgsl/resolver/BUILD.cmake
@@ -119,6 +119,7 @@
   lang/wgsl/resolver/f16_extension_test.cc
   lang/wgsl/resolver/framebuffer_fetch_extension_test.cc
   lang/wgsl/resolver/function_validation_test.cc
+  lang/wgsl/resolver/graphite_extension_test.cc
   lang/wgsl/resolver/host_shareable_validation_test.cc
   lang/wgsl/resolver/increment_decrement_validation_test.cc
   lang/wgsl/resolver/inferred_type_test.cc
diff --git a/src/tint/lang/wgsl/resolver/BUILD.gn b/src/tint/lang/wgsl/resolver/BUILD.gn
index 18cab8b..9456dbb 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.gn
+++ b/src/tint/lang/wgsl/resolver/BUILD.gn
@@ -121,6 +121,7 @@
       "f16_extension_test.cc",
       "framebuffer_fetch_extension_test.cc",
       "function_validation_test.cc",
+      "graphite_extension_test.cc",
       "host_shareable_validation_test.cc",
       "increment_decrement_validation_test.cc",
       "inferred_type_test.cc",
diff --git a/src/tint/lang/wgsl/resolver/graphite_extension_test.cc b/src/tint/lang/wgsl/resolver/graphite_extension_test.cc
new file mode 100644
index 0000000..71f727e
--- /dev/null
+++ b/src/tint/lang/wgsl/resolver/graphite_extension_test.cc
@@ -0,0 +1,72 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/core/access.h"
+#include "src/tint/lang/core/texel_format.h"
+#include "src/tint/lang/core/type/texture_dimension.h"
+#include "src/tint/lang/wgsl/resolver/resolver.h"
+#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+
+#include "gmock/gmock.h"
+
+namespace tint::resolver {
+namespace {
+
+using namespace tint::core::fluent_types;     // NOLINT
+using namespace tint::core::number_suffixes;  // NOLINT
+
+using ResolverGraphiteExtensionTest = ResolverTest;
+
+TEST_F(ResolverGraphiteExtensionTest, r8unorm_UseWithoutExtension) {
+    // @group(0) @binding(0) var T: texture_storage_2d<r8unorm, write>;
+
+    GlobalVar("T",
+              ty.storage_texture(core::type::TextureDimension::k2d, core::TexelFormat::kR8Unorm,
+                                 core::Access::kWrite),
+              Vector{Group(0_a), Binding(0_a)});
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(),
+              R"(error: 'r8unorm' requires the 'chromium_internal_graphite' extension)");
+}
+
+TEST_F(ResolverGraphiteExtensionTest, r8unorm_UseWithExtension) {
+    // enable chromium_internal_graphite;
+    // @group(0) @binding(0) var T: texture_storage_3d<r8unorm, read_write>;
+
+    Enable(Source{{12, 34}}, wgsl::Extension::kChromiumInternalGraphite);
+
+    GlobalVar("T",
+              ty.storage_texture(core::type::TextureDimension::k2d, core::TexelFormat::kR8Unorm,
+                                 core::Access::kWrite),
+              Vector{Group(0_a), Binding(0_a)});
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+}  // namespace
+}  // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 945fd29..b1a1775 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -37,6 +37,7 @@
 #include "src/tint/lang/core/builtin_type.h"
 #include "src/tint/lang/core/constant/scalar.h"
 #include "src/tint/lang/core/fluent_types.h"
+#include "src/tint/lang/core/texel_format.h"
 #include "src/tint/lang/core/type/abstract_float.h"
 #include "src/tint/lang/core/type/abstract_int.h"
 #include "src/tint/lang/core/type/array.h"
diff --git a/src/tint/lang/wgsl/resolver/unresolved_identifier_test.cc b/src/tint/lang/wgsl/resolver/unresolved_identifier_test.cc
index fe16964..98aa12d 100644
--- a/src/tint/lang/wgsl/resolver/unresolved_identifier_test.cc
+++ b/src/tint/lang/wgsl/resolver/unresolved_identifier_test.cc
@@ -70,7 +70,7 @@
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(), R"(12:34 error: unresolved texel format 'rba8unorm'
 12:34 note: Did you mean 'rgba8unorm'?
-Possible values: 'bgra8unorm', 'r32float', 'r32sint', 'r32uint', 'rg32float', 'rg32sint', 'rg32uint', 'rgba16float', 'rgba16sint', 'rgba16uint', 'rgba32float', 'rgba32sint', 'rgba32uint', 'rgba8sint', 'rgba8snorm', 'rgba8uint', 'rgba8unorm')");
+Possible values: 'bgra8unorm', 'r32float', 'r32sint', 'r32uint', 'r8unorm', 'rg32float', 'rg32sint', 'rg32uint', 'rgba16float', 'rgba16sint', 'rgba16uint', 'rgba32float', 'rgba32sint', 'rgba32uint', 'rgba8sint', 'rgba8snorm', 'rgba8uint', 'rgba8unorm')");
 }
 
 TEST_F(ResolverUnresolvedIdentifierSuggestions, AccessMode) {
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index c852f7f..c6412ff 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -115,22 +115,23 @@
 bool IsValidStorageTextureTexelFormat(core::TexelFormat format) {
     switch (format) {
         case core::TexelFormat::kBgra8Unorm:
-        case core::TexelFormat::kR32Uint:
-        case core::TexelFormat::kR32Sint:
         case core::TexelFormat::kR32Float:
-        case core::TexelFormat::kRg32Uint:
-        case core::TexelFormat::kRg32Sint:
+        case core::TexelFormat::kR32Sint:
+        case core::TexelFormat::kR32Uint:
+        case core::TexelFormat::kR8Unorm:
         case core::TexelFormat::kRg32Float:
-        case core::TexelFormat::kRgba8Unorm:
+        case core::TexelFormat::kRg32Sint:
+        case core::TexelFormat::kRg32Uint:
+        case core::TexelFormat::kRgba16Float:
+        case core::TexelFormat::kRgba16Sint:
+        case core::TexelFormat::kRgba16Uint:
+        case core::TexelFormat::kRgba32Float:
+        case core::TexelFormat::kRgba32Sint:
+        case core::TexelFormat::kRgba32Uint:
+        case core::TexelFormat::kRgba8Sint:
         case core::TexelFormat::kRgba8Snorm:
         case core::TexelFormat::kRgba8Uint:
-        case core::TexelFormat::kRgba8Sint:
-        case core::TexelFormat::kRgba16Uint:
-        case core::TexelFormat::kRgba16Sint:
-        case core::TexelFormat::kRgba16Float:
-        case core::TexelFormat::kRgba32Uint:
-        case core::TexelFormat::kRgba32Sint:
-        case core::TexelFormat::kRgba32Float:
+        case core::TexelFormat::kRgba8Unorm:
             return true;
         default:
             return false;
@@ -363,21 +364,18 @@
         case core::Access::kRead:
             if (!allowed_features_.features.count(
                     wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures)) {
-                AddError(source) <<
-
-                    "read-only storage textures require the "
-                    "readonly_and_readwrite_storage_textures language feature, which is not "
-                    "allowed in the current environment";
+                AddError(source) << "read-only storage textures require the "
+                                    "readonly_and_readwrite_storage_textures language feature, "
+                                    "which is not allowed in the current environment";
                 return false;
             }
             break;
         case core::Access::kReadWrite:
             if (!allowed_features_.features.count(
                     wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures)) {
-                AddError(source)
-                    << "read-write storage textures require the "
-                       "readonly_and_readwrite_storage_textures language feature, which is not "
-                       "allowed in the current environment";
+                AddError(source) << "read-write storage textures require the "
+                                    "readonly_and_readwrite_storage_textures language feature, "
+                                    "which is not allowed in the current environment";
                 return false;
             }
             break;
@@ -388,6 +386,13 @@
             return false;
     }
 
+    if (TINT_UNLIKELY(t->texel_format() == core::TexelFormat::kR8Unorm &&
+                      !enabled_extensions_.Contains(wgsl::Extension::kChromiumInternalGraphite))) {
+        AddError(source) << style::Enum(core::TexelFormat::kR8Unorm) << " requires the "
+                         << style::Code(wgsl::Extension::kChromiumInternalGraphite) << " extension";
+        return false;
+    }
+
     if (!IsValidStorageTextureDimension(t->dim())) {
         AddError(source) << "cube dimensions for storage textures are not supported";
         return false;
diff --git a/src/tint/lang/wgsl/wgsl.def b/src/tint/lang/wgsl/wgsl.def
index b851cdb..e61ab87 100644
--- a/src/tint/lang/wgsl/wgsl.def
+++ b/src/tint/lang/wgsl/wgsl.def
@@ -197,7 +197,8 @@
 
 // https://gpuweb.github.io/gpuweb/wgsl/#texel-formats
 match f32_texel_format
-  : texel_format.bgra8unorm
+  : texel_format.r8unorm
+  | texel_format.bgra8unorm
   | texel_format.rgba8unorm
   | texel_format.rgba8snorm
   | texel_format.rgba16float