[ast] Add texture types to the AST.

This CL adds the texture types into the AST.

Bug: tint:141
Change-Id: I8e95aa23849af737e63d9cacc8c57f23aedec73d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/26123
Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 2a25855..746985c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -323,6 +323,8 @@
     "src/ast/type/array_type.h",
     "src/ast/type/bool_type.cc",
     "src/ast/type/bool_type.h",
+    "src/ast/type/depth_texture_type.cc",
+    "src/ast/type/depth_texture_type.h",
     "src/ast/type/f32_type.cc",
     "src/ast/type/f32_type.h",
     "src/ast/type/i32_type.cc",
@@ -331,10 +333,16 @@
     "src/ast/type/matrix_type.h",
     "src/ast/type/pointer_type.cc",
     "src/ast/type/pointer_type.h",
+    "src/ast/type/sampled_texture_type.cc",
+    "src/ast/type/sampled_texture_type.h",
     "src/ast/type/sampler_type.cc",
     "src/ast/type/sampler_type.h",
+    "src/ast/type/storage_texture_type.cc",
+    "src/ast/type/storage_texture_type.h",
     "src/ast/type/struct_type.cc",
     "src/ast/type/struct_type.h",
+    "src/ast/type/texture_type.cc",
+    "src/ast/type/texture_type.h",
     "src/ast/type/type.cc",
     "src/ast/type/type.h",
     "src/ast/type/u32_type.cc",
@@ -712,11 +720,14 @@
     "src/ast/type/alias_type_test.cc",
     "src/ast/type/array_type_test.cc",
     "src/ast/type/bool_type_test.cc",
+    "src/ast/type/depth_texture_type_test.cc",
     "src/ast/type/f32_type_test.cc",
     "src/ast/type/i32_type_test.cc",
     "src/ast/type/matrix_type_test.cc",
     "src/ast/type/pointer_type_test.cc",
+    "src/ast/type/sampled_texture_type_test.cc",
     "src/ast/type/sampler_type_test.cc",
+    "src/ast/type/storage_texture_type_test.cc",
     "src/ast/type/struct_type_test.cc",
     "src/ast/type/u32_type_test.cc",
     "src/ast/type/vector_type_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3a9e778..c3b2e29 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -144,6 +144,8 @@
   ast/type/array_type.h
   ast/type/bool_type.cc
   ast/type/bool_type.h
+  ast/type/depth_texture_type.cc
+  ast/type/depth_texture_type.h
   ast/type/f32_type.cc
   ast/type/f32_type.h
   ast/type/i32_type.cc
@@ -152,10 +154,16 @@
   ast/type/matrix_type.h
   ast/type/pointer_type.cc
   ast/type/pointer_type.h
+  ast/type/sampled_texture_type.cc
+  ast/type/sampled_texture_type.h
   ast/type/sampler_type.cc
   ast/type/sampler_type.h
+  ast/type/storage_texture_type.cc
+  ast/type/storage_texture_type.h
   ast/type/struct_type.cc
   ast/type/struct_type.h
+  ast/type/texture_type.cc
+  ast/type/texture_type.h
   ast/type/type.cc
   ast/type/type.h
   ast/type/u32_type.cc
@@ -320,11 +328,14 @@
   ast/type/alias_type_test.cc
   ast/type/array_type_test.cc
   ast/type/bool_type_test.cc
+  ast/type/depth_texture_type_test.cc
   ast/type/f32_type_test.cc
   ast/type/i32_type_test.cc
   ast/type/matrix_type_test.cc
   ast/type/pointer_type_test.cc
+  ast/type/sampled_texture_type_test.cc
   ast/type/sampler_type_test.cc
+  ast/type/storage_texture_type_test.cc
   ast/type/struct_type_test.cc
   ast/type/u32_type_test.cc
   ast/type/vector_type_test.cc
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 285873d..ac021ae 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -47,6 +47,7 @@
   EXPECT_FALSE(at.IsPointer());
   EXPECT_FALSE(at.IsSampler());
   EXPECT_FALSE(at.IsStruct());
+  EXPECT_FALSE(at.IsTexture());
   EXPECT_FALSE(at.IsU32());
   EXPECT_FALSE(at.IsVector());
 }
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index d6e63e5..4783330 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -56,6 +56,7 @@
   EXPECT_FALSE(arr.IsPointer());
   EXPECT_FALSE(arr.IsSampler());
   EXPECT_FALSE(arr.IsStruct());
+  EXPECT_FALSE(arr.IsTexture());
   EXPECT_FALSE(arr.IsU32());
   EXPECT_FALSE(arr.IsVector());
 }
diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc
index e526c48..f3cc966 100644
--- a/src/ast/type/bool_type_test.cc
+++ b/src/ast/type/bool_type_test.cc
@@ -34,6 +34,7 @@
   EXPECT_FALSE(b.IsPointer());
   EXPECT_FALSE(b.IsSampler());
   EXPECT_FALSE(b.IsStruct());
+  EXPECT_FALSE(b.IsTexture());
   EXPECT_FALSE(b.IsU32());
   EXPECT_FALSE(b.IsVector());
 }
diff --git a/src/ast/type/depth_texture_type.cc b/src/ast/type/depth_texture_type.cc
new file mode 100644
index 0000000..f3f79f6
--- /dev/null
+++ b/src/ast/type/depth_texture_type.cc
@@ -0,0 +1,56 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/depth_texture_type.h"
+
+#include <cassert>
+#include <sstream>
+
+namespace tint {
+namespace ast {
+namespace type {
+namespace {
+
+#ifndef NDEBUG
+
+bool IsValidDepthDimension(TextureDimension dim) {
+  return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray ||
+         dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray;
+}
+
+#endif  // NDEBUG
+
+}  // namespace
+
+DepthTextureType::DepthTextureType(TextureDimension dim) : TextureType(dim) {
+  assert(IsValidDepthDimension(dim));
+}
+
+DepthTextureType::DepthTextureType(DepthTextureType&&) = default;
+
+DepthTextureType::~DepthTextureType() = default;
+
+bool DepthTextureType::IsDepth() const {
+  return true;
+}
+
+std::string DepthTextureType::type_name() const {
+  std::ostringstream out;
+  out << "__depth_texture_" << dim();
+  return out.str();
+}
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/depth_texture_type.h b/src/ast/type/depth_texture_type.h
new file mode 100644
index 0000000..2d02ee6
--- /dev/null
+++ b/src/ast/type/depth_texture_type.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_TYPE_DEPTH_TEXTURE_TYPE_H_
+#define SRC_AST_TYPE_DEPTH_TEXTURE_TYPE_H_
+
+#include <string>
+
+#include "src/ast/type/texture_type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+/// A depth texture type.
+class DepthTextureType : public TextureType {
+ public:
+  /// Constructor
+  /// @param dim the dimensionality of the texture
+  explicit DepthTextureType(TextureDimension dim);
+  /// Move constructor
+  DepthTextureType(DepthTextureType&&);
+  ~DepthTextureType() override;
+
+  /// @returns true if the type is a depth texture type
+  bool IsDepth() const override;
+
+  /// @returns the name for this type
+  std::string type_name() const override;
+};
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
+
+#endif  // SRC_AST_TYPE_DEPTH_TEXTURE_TYPE_H_
diff --git a/src/ast/type/depth_texture_type_test.cc b/src/ast/type/depth_texture_type_test.cc
new file mode 100644
index 0000000..6e79d41
--- /dev/null
+++ b/src/ast/type/depth_texture_type_test.cc
@@ -0,0 +1,62 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/depth_texture_type.h"
+
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+namespace {
+
+using DepthTextureTypeTest = testing::Test;
+
+TEST_F(DepthTextureTypeTest, Is) {
+  DepthTextureType d(TextureDimension::kCube);
+  EXPECT_FALSE(d.IsAlias());
+  EXPECT_FALSE(d.IsArray());
+  EXPECT_FALSE(d.IsBool());
+  EXPECT_FALSE(d.IsF32());
+  EXPECT_FALSE(d.IsI32());
+  EXPECT_FALSE(d.IsMatrix());
+  EXPECT_FALSE(d.IsPointer());
+  EXPECT_FALSE(d.IsSampler());
+  EXPECT_FALSE(d.IsStruct());
+  EXPECT_TRUE(d.IsTexture());
+  EXPECT_FALSE(d.IsU32());
+  EXPECT_FALSE(d.IsVector());
+}
+
+TEST_F(DepthTextureTypeTest, IsTextureType) {
+  DepthTextureType d(TextureDimension::kCube);
+  EXPECT_TRUE(d.IsDepth());
+  EXPECT_FALSE(d.IsSampled());
+  EXPECT_FALSE(d.IsStorage());
+}
+
+TEST_F(DepthTextureTypeTest, Dim) {
+  DepthTextureType d(TextureDimension::kCube);
+  EXPECT_EQ(d.dim(), TextureDimension::kCube);
+}
+
+TEST_F(DepthTextureTypeTest, TypeName) {
+  DepthTextureType d(TextureDimension::kCube);
+  EXPECT_EQ(d.type_name(), "__depth_texture_cube");
+}
+
+}  // namespace
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc
index 30a8d04..fc42b00 100644
--- a/src/ast/type/f32_type_test.cc
+++ b/src/ast/type/f32_type_test.cc
@@ -34,6 +34,7 @@
   EXPECT_FALSE(f.IsPointer());
   EXPECT_FALSE(f.IsSampler());
   EXPECT_FALSE(f.IsStruct());
+  EXPECT_FALSE(f.IsTexture());
   EXPECT_FALSE(f.IsU32());
   EXPECT_FALSE(f.IsVector());
 }
diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc
index 8408ca9..f69958d 100644
--- a/src/ast/type/i32_type_test.cc
+++ b/src/ast/type/i32_type_test.cc
@@ -34,6 +34,7 @@
   EXPECT_FALSE(i.IsPointer());
   EXPECT_FALSE(i.IsSampler());
   EXPECT_FALSE(i.IsStruct());
+  EXPECT_FALSE(i.IsTexture());
   EXPECT_FALSE(i.IsU32());
   EXPECT_FALSE(i.IsVector());
 }
diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc
index 888d27f..c659e40 100644
--- a/src/ast/type/matrix_type_test.cc
+++ b/src/ast/type/matrix_type_test.cc
@@ -44,6 +44,7 @@
   EXPECT_FALSE(m.IsPointer());
   EXPECT_FALSE(m.IsSampler());
   EXPECT_FALSE(m.IsStruct());
+  EXPECT_FALSE(m.IsTexture());
   EXPECT_FALSE(m.IsU32());
   EXPECT_FALSE(m.IsVector());
 }
diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc
index 4e09c95..0d825f5 100644
--- a/src/ast/type/pointer_type_test.cc
+++ b/src/ast/type/pointer_type_test.cc
@@ -43,6 +43,7 @@
   EXPECT_TRUE(p.IsPointer());
   EXPECT_FALSE(p.IsSampler());
   EXPECT_FALSE(p.IsStruct());
+  EXPECT_FALSE(p.IsTexture());
   EXPECT_FALSE(p.IsU32());
   EXPECT_FALSE(p.IsVector());
 }
diff --git a/src/ast/type/sampled_texture_type.cc b/src/ast/type/sampled_texture_type.cc
new file mode 100644
index 0000000..0ef5578
--- /dev/null
+++ b/src/ast/type/sampled_texture_type.cc
@@ -0,0 +1,45 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/sampled_texture_type.h"
+
+#include <cassert>
+#include <sstream>
+
+namespace tint {
+namespace ast {
+namespace type {
+
+SampledTextureType::SampledTextureType(TextureDimension dim, Type* type)
+    : TextureType(dim), type_(type) {
+  assert(type_);
+}
+
+SampledTextureType::SampledTextureType(SampledTextureType&&) = default;
+
+SampledTextureType::~SampledTextureType() = default;
+
+bool SampledTextureType::IsSampled() const {
+  return true;
+}
+
+std::string SampledTextureType::type_name() const {
+  std::ostringstream out;
+  out << "__sampled_texture_" << dim() << type_->type_name();
+  return out.str();
+}
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/sampled_texture_type.h b/src/ast/type/sampled_texture_type.h
new file mode 100644
index 0000000..e387b87
--- /dev/null
+++ b/src/ast/type/sampled_texture_type.h
@@ -0,0 +1,54 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_TYPE_SAMPLED_TEXTURE_TYPE_H_
+#define SRC_AST_TYPE_SAMPLED_TEXTURE_TYPE_H_
+
+#include <string>
+
+#include "src/ast/type/texture_type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+/// A sampled texture type.
+class SampledTextureType : public TextureType {
+ public:
+  /// Constructor
+  /// @param dim the dimensionality of the texture
+  /// @param type the data type of the sampled texture
+  SampledTextureType(TextureDimension dim, Type* type);
+  /// Move constructor
+  SampledTextureType(SampledTextureType&&);
+  ~SampledTextureType() override;
+
+  /// @returns true if the type is a sampled texture type
+  bool IsSampled() const override;
+
+  /// @returns the subtype of the sampled texture
+  Type* type() const { return type_; }
+
+  /// @returns the name for this type
+  std::string type_name() const override;
+
+ private:
+  Type* type_ = nullptr;
+};
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
+
+#endif  // SRC_AST_TYPE_SAMPLED_TEXTURE_TYPE_H_
diff --git a/src/ast/type/sampled_texture_type_test.cc b/src/ast/type/sampled_texture_type_test.cc
new file mode 100644
index 0000000..ce10639
--- /dev/null
+++ b/src/ast/type/sampled_texture_type_test.cc
@@ -0,0 +1,73 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/sampled_texture_type.h"
+
+#include "gtest/gtest.h"
+#include "src/ast/type/f32_type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+namespace {
+
+using SampledTextureTypeTest = testing::Test;
+
+TEST_F(SampledTextureTypeTest, Is) {
+  F32Type f32;
+  SampledTextureType s(TextureDimension::kCube, &f32);
+  EXPECT_FALSE(s.IsAlias());
+  EXPECT_FALSE(s.IsArray());
+  EXPECT_FALSE(s.IsBool());
+  EXPECT_FALSE(s.IsF32());
+  EXPECT_FALSE(s.IsI32());
+  EXPECT_FALSE(s.IsMatrix());
+  EXPECT_FALSE(s.IsPointer());
+  EXPECT_FALSE(s.IsSampler());
+  EXPECT_FALSE(s.IsStruct());
+  EXPECT_TRUE(s.IsTexture());
+  EXPECT_FALSE(s.IsU32());
+  EXPECT_FALSE(s.IsVector());
+}
+
+TEST_F(SampledTextureTypeTest, IsTextureType) {
+  F32Type f32;
+  SampledTextureType s(TextureDimension::kCube, &f32);
+  EXPECT_FALSE(s.IsDepth());
+  EXPECT_TRUE(s.IsSampled());
+  EXPECT_FALSE(s.IsStorage());
+}
+
+TEST_F(SampledTextureTypeTest, Dim) {
+  F32Type f32;
+  SampledTextureType s(TextureDimension::k3d, &f32);
+  EXPECT_EQ(s.dim(), TextureDimension::k3d);
+}
+
+TEST_F(SampledTextureTypeTest, Type) {
+  F32Type f32;
+  SampledTextureType s(TextureDimension::k3d, &f32);
+  EXPECT_EQ(s.type(), &f32);
+}
+
+TEST_F(SampledTextureTypeTest, TypeName) {
+  F32Type f32;
+  SampledTextureType s(TextureDimension::k3d, &f32);
+  EXPECT_EQ(s.type_name(), "__sampled_texture_3d__f32");
+}
+
+}  // namespace
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc
index bcbd5f6..60921ed 100644
--- a/src/ast/type/sampler_type_test.cc
+++ b/src/ast/type/sampler_type_test.cc
@@ -45,6 +45,7 @@
   EXPECT_FALSE(s.IsPointer());
   EXPECT_TRUE(s.IsSampler());
   EXPECT_FALSE(s.IsStruct());
+  EXPECT_FALSE(s.IsTexture());
   EXPECT_FALSE(s.IsU32());
   EXPECT_FALSE(s.IsVector());
 }
diff --git a/src/ast/type/storage_texture_type.cc b/src/ast/type/storage_texture_type.cc
new file mode 100644
index 0000000..fe5f293
--- /dev/null
+++ b/src/ast/type/storage_texture_type.cc
@@ -0,0 +1,184 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/storage_texture_type.h"
+
+#include <cassert>
+#include <sstream>
+
+namespace tint {
+namespace ast {
+namespace type {
+namespace {
+
+#ifndef NDEBUG
+
+bool IsValidStorageDimension(TextureDimension dim) {
+  return dim == TextureDimension::k1d || dim == TextureDimension::k1dArray ||
+         dim == TextureDimension::k2d || dim == TextureDimension::k2dArray ||
+         dim == TextureDimension::k3d;
+}
+
+#endif  // NDEBUG
+  
+}  // namespace
+
+std::ostream& operator<<(std::ostream& out, StorageAccess access) {
+  switch (access) {
+    case StorageAccess::kRead:
+      out << "read";
+      break;
+    case StorageAccess::kWrite:
+      out << "write";
+      break;
+  }
+  return out;
+}
+
+std::ostream& operator<<(std::ostream& out, ImageFormat format) {
+  switch (format) {
+    case ImageFormat::kR8Unorm:
+      out << "r8unorm";
+      break;
+    case ImageFormat::kR8Snorm:
+      out << "r8snorm";
+      break;
+    case ImageFormat::kR8Uint:
+      out << "r8uint";
+      break;
+    case ImageFormat::kR8Sint:
+      out << "r8sint";
+      break;
+    case ImageFormat::kR16Uint:
+      out << "r16uint";
+      break;
+    case ImageFormat::kR16Sint:
+      out << "r16sint";
+      break;
+    case ImageFormat::kR16Float:
+      out << "r16float";
+      break;
+    case ImageFormat::kRg8Unorm:
+      out << "rg8unorm";
+      break;
+    case ImageFormat::kRg8Snorm:
+      out << "rg8snorm";
+      break;
+    case ImageFormat::kRg8Uint:
+      out << "rg8uint";
+      break;
+    case ImageFormat::kRg8Sint:
+      out << "rg8sint";
+      break;
+    case ImageFormat::kR32Uint:
+      out << "r32uint";
+      break;
+    case ImageFormat::kR32Sint:
+      out << "r32sint";
+      break;
+    case ImageFormat::kR32Float:
+      out << "r32float";
+      break;
+    case ImageFormat::kRg16Uint:
+      out << "rg16uint";
+      break;
+    case ImageFormat::kRg16Sint:
+      out << "rg16sint";
+      break;
+    case ImageFormat::kRg16Float:
+      out << "rg16float";
+      break;
+    case ImageFormat::kRgba8Unorm:
+      out << "rgba8unorm";
+      break;
+    case ImageFormat::kRgba8UnormSrgb:
+      out << "rgba8unorm-srgb";
+      break;
+    case ImageFormat::kRgba8Snorm:
+      out << "rgba8snorm";
+      break;
+    case ImageFormat::kRgba8Uint:
+      out << "rgba8uint";
+      break;
+    case ImageFormat::kRgba8Sint:
+      out << "rgba8sint";
+      break;
+    case ImageFormat::kBgra8Unorm:
+      out << "bgra8unorm";
+      break;
+    case ImageFormat::kBgra8UnormSrgb:
+      out << "rbgra8unorm-srgb";
+      break;
+    case ImageFormat::kRgb10A2Unorm:
+      out << "rgb10a2unorm";
+      break;
+    case ImageFormat::kRg11B10Float:
+      out << "rg11b10float";
+      break;
+    case ImageFormat::kRg32Uint:
+      out << "rg32uint";
+      break;
+    case ImageFormat::kRg32Sint:
+      out << "rg32sint";
+      break;
+    case ImageFormat::kRg32Float:
+      out << "rg32float";
+      break;
+    case ImageFormat::kRgba16Uint:
+      out << "rgba16uint";
+      break;
+    case ImageFormat::kRgba16Sint:
+      out << "rgba16sint";
+      break;
+    case ImageFormat::kRgba16Float:
+      out << "rgba16float";
+      break;
+    case ImageFormat::kRgba32Uint:
+      out << "rgba32uint";
+      break;
+    case ImageFormat::kRgba32Sint:
+      out << "rgba32sint";
+      break;
+    case ImageFormat::kRgba32Float:
+      out << "rgba32float";
+      break;
+  }
+  return out;
+}
+
+StorageTextureType::StorageTextureType(TextureDimension dim,
+                                       StorageAccess access,
+                                       ImageFormat format)
+    : TextureType(dim), storage_access_(access), image_format_(format) {
+  assert(IsValidStorageDimension(dim));
+}
+
+StorageTextureType::StorageTextureType(StorageTextureType&&) = default;
+
+StorageTextureType::~StorageTextureType() = default;
+
+bool StorageTextureType::IsStorage() const {
+  return true;
+}
+
+std::string StorageTextureType::type_name() const {
+  std::ostringstream out;
+  out << "__storage_texture_" << storage_access_ << "_" << dim() << "_"
+      << image_format_;
+  return out.str();
+}
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/storage_texture_type.h b/src/ast/type/storage_texture_type.h
new file mode 100644
index 0000000..2c27ffd
--- /dev/null
+++ b/src/ast/type/storage_texture_type.h
@@ -0,0 +1,109 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_TYPE_STORAGE_TEXTURE_TYPE_H_
+#define SRC_AST_TYPE_STORAGE_TEXTURE_TYPE_H_
+
+#include <string>
+
+#include "src/ast/type/texture_type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+/// The access value of the storage texture
+enum class StorageAccess { kRead, kWrite };
+std::ostream& operator<<(std::ostream& out, StorageAccess dim);
+
+/// The image format in the storage texture
+enum class ImageFormat {
+  kR8Unorm,
+  kR8Snorm,
+  kR8Uint,
+  kR8Sint,
+  kR16Uint,
+  kR16Sint,
+  kR16Float,
+  kRg8Unorm,
+  kRg8Snorm,
+  kRg8Uint,
+  kRg8Sint,
+  kR32Uint,
+  kR32Sint,
+  kR32Float,
+  kRg16Uint,
+  kRg16Sint,
+  kRg16Float,
+  kRgba8Unorm,
+  kRgba8UnormSrgb,
+  kRgba8Snorm,
+  kRgba8Uint,
+  kRgba8Sint,
+  kBgra8Unorm,
+  kBgra8UnormSrgb,
+  kRgb10A2Unorm,
+  kRg11B10Float,
+  kRg32Uint,
+  kRg32Sint,
+  kRg32Float,
+  kRgba16Uint,
+  kRgba16Sint,
+  kRgba16Float,
+  kRgba32Uint,
+  kRgba32Sint,
+  kRgba32Float,
+};
+std::ostream& operator<<(std::ostream& out, ImageFormat dim);
+
+/// A storage texture type.
+class StorageTextureType : public TextureType {
+ public:
+  /// Constructor
+  /// @param dim the dimensionality of the texture
+  /// @param access the access type for the texture
+  /// @param format the image format of the texture
+  explicit StorageTextureType(TextureDimension dim,
+                              StorageAccess access,
+                              ImageFormat format);
+  /// Move constructor
+  StorageTextureType(StorageTextureType&&);
+  ~StorageTextureType() override;
+
+  /// @returns true if the type is a storage texture type
+  bool IsStorage() const override;
+
+  /// @returns the subtype of the sampled texture
+  Type* type() const { return type_; }
+
+  /// @returns the storage access
+  StorageAccess access() const { return storage_access_; }
+
+  /// @returns the image format
+  ImageFormat image_format() const { return image_format_; }
+
+  /// @returns the name for this type
+  std::string type_name() const override;
+
+ private:
+  Type* type_ = nullptr;
+  StorageAccess storage_access_ = StorageAccess::kRead;
+  ImageFormat image_format_ = ImageFormat::kRgba32Float;
+};
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
+
+#endif  // SRC_AST_TYPE_STORAGE_TEXTURE_TYPE_H_
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
new file mode 100644
index 0000000..6c834a0
--- /dev/null
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -0,0 +1,78 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/storage_texture_type.h"
+
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+namespace {
+
+using StorageTextureTypeTest = testing::Test;
+
+TEST_F(StorageTextureTypeTest, Is) {
+  StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead,
+                       ImageFormat::kRgba32Float);
+  EXPECT_FALSE(s.IsAlias());
+  EXPECT_FALSE(s.IsArray());
+  EXPECT_FALSE(s.IsBool());
+  EXPECT_FALSE(s.IsF32());
+  EXPECT_FALSE(s.IsI32());
+  EXPECT_FALSE(s.IsMatrix());
+  EXPECT_FALSE(s.IsPointer());
+  EXPECT_FALSE(s.IsSampler());
+  EXPECT_FALSE(s.IsStruct());
+  EXPECT_TRUE(s.IsTexture());
+  EXPECT_FALSE(s.IsU32());
+  EXPECT_FALSE(s.IsVector());
+}
+
+TEST_F(StorageTextureTypeTest, IsTextureType) {
+  StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead,
+                       ImageFormat::kRgba32Float);
+  EXPECT_FALSE(s.IsDepth());
+  EXPECT_FALSE(s.IsSampled());
+  EXPECT_TRUE(s.IsStorage());
+}
+
+TEST_F(StorageTextureTypeTest, Dim) {
+  StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead,
+                       ImageFormat::kRgba32Float);
+  EXPECT_EQ(s.dim(), TextureDimension::k2dArray);
+}
+
+TEST_F(StorageTextureTypeTest, Access) {
+  StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead,
+                       ImageFormat::kRgba32Float);
+  EXPECT_EQ(s.access(), StorageAccess::kRead);
+}
+
+TEST_F(StorageTextureTypeTest, Format) {
+  StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead,
+                       ImageFormat::kRgba32Float);
+  EXPECT_EQ(s.image_format(), ImageFormat::kRgba32Float);
+}
+
+TEST_F(StorageTextureTypeTest, TypeName) {
+  StorageTextureType s(TextureDimension::k2dArray, StorageAccess::kRead,
+                       ImageFormat::kRgba32Float);
+  EXPECT_EQ(s.type_name(), "__storage_texture_read_2d_array_rgba32float");
+}
+
+}  // namespace
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 9df6e7d..3177047 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -45,6 +45,7 @@
   EXPECT_FALSE(s.IsPointer());
   EXPECT_FALSE(s.IsSampler());
   EXPECT_TRUE(s.IsStruct());
+  EXPECT_FALSE(s.IsTexture());
   EXPECT_FALSE(s.IsU32());
   EXPECT_FALSE(s.IsVector());
 }
diff --git a/src/ast/type/texture_type.cc b/src/ast/type/texture_type.cc
new file mode 100644
index 0000000..a5a4e1e
--- /dev/null
+++ b/src/ast/type/texture_type.cc
@@ -0,0 +1,112 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type/texture_type.h"
+
+#include <cassert>
+
+#include "src/ast/type/depth_texture_type.h"
+#include "src/ast/type/sampled_texture_type.h"
+#include "src/ast/type/storage_texture_type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+std::ostream& operator<<(std::ostream& out, TextureDimension dim) {
+  switch (dim) {
+    case TextureDimension::k1d:
+      out << "1d";
+      break;
+    case TextureDimension::k1dArray:
+      out << "1d_array";
+      break;
+    case TextureDimension::k2d:
+      out << "2d";
+      break;
+    case TextureDimension::k2dArray:
+      out << "2d_array";
+      break;
+    case TextureDimension::k2dMs:
+      out << "2d_ms";
+      break;
+    case TextureDimension::k2dMsArray:
+      out << "2d_ms_array";
+      break;
+    case TextureDimension::k3d:
+      out << "3d";
+      break;
+    case TextureDimension::kCube:
+      out << "cube";
+      break;
+    case TextureDimension::kCubeArray:
+      out << "cube_array";
+      break;
+  }
+  return out;
+}
+
+TextureType::TextureType(TextureDimension dim) : dim_(dim) {}
+
+TextureType::TextureType(TextureType&&) = default;
+
+TextureType::~TextureType() = default;
+
+bool TextureType::IsTexture() const {
+  return true;
+}
+
+bool TextureType::IsDepth() const {
+  return false;
+}
+bool TextureType::IsStorage() const {
+  return false;
+}
+bool TextureType::IsSampled() const {
+  return false;
+}
+
+const DepthTextureType* TextureType::AsDepth() const {
+  assert(IsDepth());
+  return static_cast<const DepthTextureType*>(this);
+}
+
+const SampledTextureType* TextureType::AsSampled() const {
+  assert(IsSampled());
+  return static_cast<const SampledTextureType*>(this);
+}
+
+const StorageTextureType* TextureType::AsStorage() const {
+  assert(IsStorage());
+  return static_cast<const StorageTextureType*>(this);
+}
+
+DepthTextureType* TextureType::AsDepth() {
+  assert(IsDepth());
+  return static_cast<DepthTextureType*>(this);
+}
+
+SampledTextureType* TextureType::AsSampled() {
+  assert(IsSampled());
+  return static_cast<SampledTextureType*>(this);
+}
+
+StorageTextureType* TextureType::AsStorage() {
+  assert(IsStorage());
+  return static_cast<StorageTextureType*>(this);
+}
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/texture_type.h b/src/ast/type/texture_type.h
new file mode 100644
index 0000000..37ca7e1
--- /dev/null
+++ b/src/ast/type/texture_type.h
@@ -0,0 +1,99 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_TYPE_TEXTURE_TYPE_H_
+#define SRC_AST_TYPE_TEXTURE_TYPE_H_
+
+#include <ostream>
+#include <string>
+
+#include "src/ast/type/type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+class DepthTextureType;
+class SampledTextureType;
+class StorageTextureType;
+
+/// The dimensionality of the texture
+enum class TextureDimension {
+  /// 1 dimensional texture
+  k1d,
+  /// 1 dimenstional array texture
+  k1dArray,
+  /// 2 dimensional texture
+  k2d,
+  /// 2 dimensional array texture
+  k2dArray,
+  /// 2 dimensional multi-sampled texture
+  k2dMs,
+  /// 2 dimensional multi-sampled array texture
+  k2dMsArray,
+  /// 3 dimensional texture
+  k3d,
+  /// cube texture
+  kCube,
+  /// cube array texture
+  kCubeArray,
+};
+std::ostream& operator<<(std::ostream& out, TextureDimension dim);
+
+/// A texture type.
+class TextureType : public Type {
+ public:
+  /// Constructor
+  /// @param dim the dimensionality of the texture
+  explicit TextureType(TextureDimension dim);
+  /// Move constructor
+  TextureType(TextureType&&);
+  ~TextureType() override;
+
+  /// @returns true if the type is a texture type
+  bool IsTexture() const override;
+
+  /// @returns the texture dimension
+  TextureDimension dim() const { return dim_; }
+
+  /// @returns true if this is a depth texture
+  virtual bool IsDepth() const;
+  /// @returns true if this is a storage texture
+  virtual bool IsStorage() const;
+  /// @returns true if this is a sampled texture
+  virtual bool IsSampled() const;
+
+  /// @returns the texture as a depth texture
+  const DepthTextureType* AsDepth() const;
+  /// @returns the texture as a sampled texture
+  const SampledTextureType* AsSampled() const;
+  /// @returns the texture as a storage texture
+  const StorageTextureType* AsStorage() const;
+
+  /// @returns the texture as a depth texture
+  DepthTextureType* AsDepth();
+  /// @returns the texture as a sampled texture
+  SampledTextureType* AsSampled();
+  /// @returns the texture as a storage texture
+  StorageTextureType* AsStorage();
+
+ private:
+  TextureDimension dim_ = TextureDimension::k1d;
+};
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
+
+#endif  // SRC_AST_TYPE_TEXTURE_TYPE_H_
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index fb7d277..f9b9e03 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -25,6 +25,7 @@
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/sampler_type.h"
 #include "src/ast/type/struct_type.h"
+#include "src/ast/type/texture_type.h"
 #include "src/ast/type/u32_type.h"
 #include "src/ast/type/vector_type.h"
 #include "src/ast/type/void_type.h"
@@ -92,6 +93,10 @@
   return false;
 }
 
+bool Type::IsTexture() const {
+  return false;
+}
+
 bool Type::IsU32() const {
   return false;
 }
@@ -189,6 +194,11 @@
   return static_cast<const StructType*>(this);
 }
 
+const TextureType* Type::AsTexture() const {
+  assert(IsTexture());
+  return static_cast<const TextureType*>(this);
+}
+
 const U32Type* Type::AsU32() const {
   assert(IsU32());
   return static_cast<const U32Type*>(this);
@@ -249,6 +259,11 @@
   return static_cast<StructType*>(this);
 }
 
+TextureType* Type::AsTexture() {
+  assert(IsTexture());
+  return static_cast<TextureType*>(this);
+}
+
 U32Type* Type::AsU32() {
   assert(IsU32());
   return static_cast<U32Type*>(this);
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index fc30c9d..e506c4d 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -30,6 +30,7 @@
 class PointerType;
 class SamplerType;
 class StructType;
+class TextureType;
 class U32Type;
 class VectorType;
 class VoidType;
@@ -59,6 +60,8 @@
   virtual bool IsSampler() const;
   /// @returns true if the type is a struct type
   virtual bool IsStruct() const;
+  /// @returns true if the type is a texture type
+  virtual bool IsTexture() const;
   /// @returns true if the type is a u32 type
   virtual bool IsU32() const;
   /// @returns true if the type is a vec type
@@ -126,6 +129,8 @@
   const SamplerType* AsSampler() const;
   /// @returns the type as a struct type
   const StructType* AsStruct() const;
+  /// @returns the type as a texture type
+  const TextureType* AsTexture() const;
   /// @returns the type as a u32 type
   const U32Type* AsU32() const;
   /// @returns the type as a vector type
@@ -151,6 +156,8 @@
   SamplerType* AsSampler();
   /// @returns the type as a struct type
   StructType* AsStruct();
+  /// @returns the type as a texture type
+  TextureType* AsTexture();
   /// @returns the type as a u32 type
   U32Type* AsU32();
   /// @returns the type as a vector type
diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc
index 6342ce6..7c42772 100644
--- a/src/ast/type/u32_type_test.cc
+++ b/src/ast/type/u32_type_test.cc
@@ -34,6 +34,7 @@
   EXPECT_FALSE(u.IsPointer());
   EXPECT_FALSE(u.IsSampler());
   EXPECT_FALSE(u.IsStruct());
+  EXPECT_FALSE(u.IsTexture());
   EXPECT_TRUE(u.IsU32());
   EXPECT_FALSE(u.IsVector());
 }
diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc
index b6108c6..baa1342 100644
--- a/src/ast/type/vector_type_test.cc
+++ b/src/ast/type/vector_type_test.cc
@@ -43,6 +43,7 @@
   EXPECT_FALSE(v.IsPointer());
   EXPECT_FALSE(v.IsSampler());
   EXPECT_FALSE(v.IsStruct());
+  EXPECT_FALSE(v.IsTexture());
   EXPECT_FALSE(v.IsU32());
   EXPECT_TRUE(v.IsVector());
 }