Add inspector support for DepthTexture reflection

BUG=tint:527

Change-Id: I4f017993ffa85515b5b646bd9cf15c4b6d50c441
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/43700
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index 088f5b1..f0b302e 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -33,6 +33,7 @@
 #include "src/semantic/variable.h"
 #include "src/type/access_control_type.h"
 #include "src/type/array_type.h"
+#include "src/type/depth_texture_type.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
 #include "src/type/matrix_type.h"
@@ -343,6 +344,7 @@
                          GetSampledTextureResourceBindings(entry_point));
   AppendResourceBindings(&result,
                          GetMultisampledTextureResourceBindings(entry_point));
+  AppendResourceBindings(&result, GetDepthTextureResourceBindings(entry_point));
 
   return result;
 }
@@ -470,6 +472,35 @@
   return GetStorageTextureResourceBindingsImpl(entry_point, false);
 }
 
+std::vector<ResourceBinding> Inspector::GetDepthTextureResourceBindings(
+    const std::string& entry_point) {
+  auto* func = FindEntryPointByName(entry_point);
+  if (!func) {
+    return {};
+  }
+
+  std::vector<ResourceBinding> result;
+  auto* func_sem = program_->Sem().Get(func);
+  for (auto& ref : func_sem->ReferencedDepthTextureVariables()) {
+    auto* var = ref.first;
+    auto* decl = var->Declaration();
+    auto binding_info = ref.second;
+
+    ResourceBinding entry;
+    entry.resource_type = ResourceBinding::ResourceType::kDepthTexture;
+    entry.bind_group = binding_info.group->value();
+    entry.binding = binding_info.binding->value();
+
+    auto* texture_type = decl->type()->UnwrapIfNeeded()->As<type::Texture>();
+    entry.dim = TypeTextureDimensionToResourceBindingTextureDimension(
+        texture_type->dim());
+
+    result.push_back(entry);
+  }
+
+  return result;
+}
+
 ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
   auto* func = program_->AST().Functions().Find(program_->Symbols().Get(name));
   if (!func) {
diff --git a/src/inspector/inspector.h b/src/inspector/inspector.h
index f706ae3..96f85e7 100644
--- a/src/inspector/inspector.h
+++ b/src/inspector/inspector.h
@@ -104,6 +104,7 @@
     kMulitsampledTexture,
     kReadOnlyStorageTexture,
     kWriteOnlyStorageTexture,
+    kDepthTexture,
   };
 
   /// Type of resource that is bound.
@@ -198,6 +199,11 @@
   std::vector<ResourceBinding> GetWriteOnlyStorageTextureResourceBindings(
       const std::string& entry_point);
 
+  /// @param entry_point name of the entry point to get information about.
+  /// @returns vector of all of the bindings for depth textures.
+  std::vector<ResourceBinding> GetDepthTextureResourceBindings(
+      const std::string& entry_point);
+
  private:
   const Program* program_;
   std::string error_;
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index f50a83f..9557bbc 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -463,8 +463,13 @@
   /// Adds a depth texture variable to the program
   /// @param name the name of the variable
   /// @param type the type to use
-  void AddDepthTexture(const std::string& name, type::Type* type) {
-    Global(name, type, ast::StorageClass::kUniformConstant);
+  /// @param group the binding/group to use for the depth texture
+  /// @param binding the binding number to use for the depth texture
+  void AddDepthTexture(const std::string& name,
+                       type::Type* type,
+                       uint32_t group,
+                       uint32_t binding) {
+    AddBinding(name, type, ast::StorageClass::kUniformConstant, group, binding);
   }
 
   /// Generates a function that references a specific sampler variable
@@ -759,6 +764,13 @@
       public testing::TestWithParam<GetMultisampledTextureTestParams> {};
 class InspectorGetStorageTextureResourceBindingsTest : public InspectorHelper,
                                                        public testing::Test {};
+struct GetDepthTextureTestParams {
+  type::TextureDimension type_dim;
+  inspector::ResourceBinding::TextureDimension inspector_dim;
+};
+class InspectorGetDepthTextureResourceBindingsTestWithParam
+    : public InspectorHelper,
+      public testing::TestWithParam<GetDepthTextureTestParams> {};
 
 typedef std::tuple<type::TextureDimension, ResourceBinding::TextureDimension>
     DimensionParams;
@@ -1428,8 +1440,8 @@
 
   auto* cs_depth_texture_type =
       MakeDepthTextureType(type::TextureDimension::k2d);
-  AddDepthTexture("cs_texture", cs_depth_texture_type);
-  AddComparisonSampler("cs_var", 3, 1);
+  AddDepthTexture("cs_texture", cs_depth_texture_type, 3, 1);
+  AddComparisonSampler("cs_var", 3, 2);
   AddGlobalVariable("cs_coords", ty.vec2<f32>());
   AddGlobalVariable("cs_depth", ty.f32());
   MakeComparisonSamplerReferenceBodyFunction(
@@ -1445,7 +1457,7 @@
 
   auto result = inspector.GetResourceBindings("ep_func");
   ASSERT_FALSE(inspector.has_error()) << inspector.error();
-  ASSERT_EQ(6u, result.size());
+  ASSERT_EQ(7u, result.size());
 
   EXPECT_EQ(ResourceBinding::ResourceType::kUniformBuffer,
             result[0].resource_type);
@@ -1469,12 +1481,17 @@
   EXPECT_EQ(ResourceBinding::ResourceType::kComparisonSampler,
             result[4].resource_type);
   EXPECT_EQ(3u, result[4].bind_group);
-  EXPECT_EQ(1u, result[4].binding);
+  EXPECT_EQ(2u, result[4].binding);
 
   EXPECT_EQ(ResourceBinding::ResourceType::kSampledTexture,
             result[5].resource_type);
   EXPECT_EQ(2u, result[5].bind_group);
   EXPECT_EQ(0u, result[5].binding);
+
+  EXPECT_EQ(ResourceBinding::ResourceType::kDepthTexture,
+            result[6].resource_type);
+  EXPECT_EQ(3u, result[6].bind_group);
+  EXPECT_EQ(1u, result[6].binding);
 }
 
 TEST_F(InspectorGetUniformBufferResourceBindingsTest, MissingEntryPoint) {
@@ -2118,7 +2135,7 @@
 
 TEST_F(InspectorGetSamplerResourceBindingsTest, SkipsComparisonSamplers) {
   auto* depth_texture_type = MakeDepthTextureType(type::TextureDimension::k2d);
-  AddDepthTexture("foo_texture", depth_texture_type);
+  AddDepthTexture("foo_texture", depth_texture_type, 0, 0);
   AddComparisonSampler("foo_sampler", 0, 1);
   AddGlobalVariable("foo_coords", ty.vec2<f32>());
   AddGlobalVariable("foo_depth", ty.f32());
@@ -2139,7 +2156,7 @@
 
 TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, Simple) {
   auto* depth_texture_type = MakeDepthTextureType(type::TextureDimension::k2d);
-  AddDepthTexture("foo_texture", depth_texture_type);
+  AddDepthTexture("foo_texture", depth_texture_type, 0, 0);
   AddComparisonSampler("foo_sampler", 0, 1);
   AddGlobalVariable("foo_coords", ty.vec2<f32>());
   AddGlobalVariable("foo_depth", ty.f32());
@@ -2178,7 +2195,7 @@
 
 TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, InFunction) {
   auto* depth_texture_type = MakeDepthTextureType(type::TextureDimension::k2d);
-  AddDepthTexture("foo_texture", depth_texture_type);
+  AddDepthTexture("foo_texture", depth_texture_type, 0, 0);
   AddComparisonSampler("foo_sampler", 0, 1);
   AddGlobalVariable("foo_coords", ty.vec2<f32>());
   AddGlobalVariable("foo_depth", ty.f32());
@@ -2207,7 +2224,7 @@
 
 TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, UnknownEntryPoint) {
   auto* depth_texture_type = MakeDepthTextureType(type::TextureDimension::k2d);
-  AddDepthTexture("foo_texture", depth_texture_type);
+  AddDepthTexture("foo_texture", depth_texture_type, 0, 0);
   AddComparisonSampler("foo_sampler", 0, 1);
   AddGlobalVariable("foo_coords", ty.vec2<f32>());
   AddGlobalVariable("foo_depth", ty.f32());
@@ -2685,6 +2702,51 @@
                             ResourceBinding::ImageFormat::kRgba32Float,
                             ResourceBinding::SampledKind::kFloat))));
 
+TEST_P(InspectorGetDepthTextureResourceBindingsTestWithParam,
+       textureDimensions) {
+  auto* depth_texture_type = MakeDepthTextureType(GetParam().type_dim);
+  AddDepthTexture("dt", depth_texture_type, 0, 0);
+  AddGlobalVariable("dt_level", ty.i32());
+
+  Func("ep", ast::VariableList(), ty.void_(),
+       ast::StatementList{
+           create<ast::CallStatement>(
+               Call("textureDimensions", "dt", "dt_level")),
+       },
+       ast::FunctionDecorationList{
+           create<ast::StageDecoration>(ast::PipelineStage::kVertex),
+       });
+
+  Inspector& inspector = Build();
+
+  auto result = inspector.GetDepthTextureResourceBindings("ep");
+  ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+  EXPECT_EQ(ResourceBinding::ResourceType::kDepthTexture,
+            result[0].resource_type);
+  ASSERT_EQ(1u, result.size());
+  EXPECT_EQ(0u, result[0].bind_group);
+  EXPECT_EQ(0u, result[0].binding);
+  EXPECT_EQ(GetParam().inspector_dim, result[0].dim);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    InspectorGetDepthTextureResourceBindingsTest,
+    InspectorGetDepthTextureResourceBindingsTestWithParam,
+    testing::Values(
+        GetDepthTextureTestParams{
+            type::TextureDimension::k2d,
+            inspector::ResourceBinding::TextureDimension::k2d},
+        GetDepthTextureTestParams{
+            type::TextureDimension::k2dArray,
+            inspector::ResourceBinding::TextureDimension::k2dArray},
+        GetDepthTextureTestParams{
+            type::TextureDimension::kCube,
+            inspector::ResourceBinding::TextureDimension::kCube},
+        GetDepthTextureTestParams{
+            type::TextureDimension::kCubeArray,
+            inspector::ResourceBinding::TextureDimension::kCubeArray}));
+
 }  // namespace
 }  // namespace inspector
 }  // namespace tint
diff --git a/src/semantic/function.h b/src/semantic/function.h
index 08904ff..c8d119c 100644
--- a/src/semantic/function.h
+++ b/src/semantic/function.h
@@ -126,6 +126,11 @@
   /// @returns the referenced storage textures
   VariableBindings ReferencedStorageTextureVariables() const;
 
+  /// Retrieves any referenced depth texture variables. Note, the variables
+  /// must be decorated with both binding and group decorations.
+  /// @returns the referenced storage textures
+  VariableBindings ReferencedDepthTextureVariables() const;
+
   /// Retrieves any locally referenced builtin variables
   /// @returns the <variable, decoration> pairs.
   std::vector<std::pair<const Variable*, ast::BuiltinDecoration*>>
diff --git a/src/semantic/sem_function.cc b/src/semantic/sem_function.cc
index 13c8e8c..83c90c3 100644
--- a/src/semantic/sem_function.cc
+++ b/src/semantic/sem_function.cc
@@ -22,6 +22,7 @@
 #include "src/ast/variable.h"
 #include "src/ast/variable_decoration.h"
 #include "src/semantic/variable.h"
+#include "src/type/depth_texture_type.h"
 #include "src/type/multisampled_texture_type.h"
 #include "src/type/sampled_texture_type.h"
 #include "src/type/storage_texture_type.h"
@@ -43,6 +44,21 @@
   return parameters;
 }
 
+std::tuple<ast::BindingDecoration*, ast::GroupDecoration*> GetBindingAndGroup(
+    const Variable* var) {
+  ast::BindingDecoration* binding = nullptr;
+  ast::GroupDecoration* group = nullptr;
+  for (auto* deco : var->Declaration()->decorations()) {
+    if (auto* b = deco->As<ast::BindingDecoration>()) {
+      binding = b;
+    }
+    if (auto* s = deco->As<ast::GroupDecoration>()) {
+      group = s;
+    }
+  }
+  return {binding, group};
+}
+
 }  // namespace
 
 Function::Function(ast::Function* declaration,
@@ -82,13 +98,7 @@
 
     ast::BindingDecoration* binding = nullptr;
     ast::GroupDecoration* group = nullptr;
-    for (auto* deco : var->Declaration()->decorations()) {
-      if (auto* b = deco->As<ast::BindingDecoration>()) {
-        binding = b;
-      } else if (auto* g = deco->As<ast::GroupDecoration>()) {
-        group = g;
-      }
-    }
+    std::tie(binding, group) = GetBindingAndGroup(var);
     if (binding == nullptr || group == nullptr) {
       continue;
     }
@@ -108,13 +118,7 @@
 
     ast::BindingDecoration* binding = nullptr;
     ast::GroupDecoration* group = nullptr;
-    for (auto* deco : var->Declaration()->decorations()) {
-      if (auto* b = deco->As<ast::BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<ast::GroupDecoration>()) {
-        group = s;
-      }
-    }
+    std::tie(binding, group) = GetBindingAndGroup(var);
     if (binding == nullptr || group == nullptr) {
       continue;
     }
@@ -169,13 +173,29 @@
 
     ast::BindingDecoration* binding = nullptr;
     ast::GroupDecoration* group = nullptr;
-    for (auto* deco : var->Declaration()->decorations()) {
-      if (auto* b = deco->As<ast::BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<ast::GroupDecoration>()) {
-        group = s;
-      }
+    std::tie(binding, group) = GetBindingAndGroup(var);
+    if (binding == nullptr || group == nullptr) {
+      continue;
     }
+
+    ret.push_back({var, BindingInfo{binding, group}});
+  }
+  return ret;
+}
+
+Function::VariableBindings Function::ReferencedDepthTextureVariables() const {
+  VariableBindings ret;
+
+  for (auto* var : ReferencedModuleVariables()) {
+    auto* unwrapped_type = var->Declaration()->type()->UnwrapIfNeeded();
+    auto* storage_texture = unwrapped_type->As<type::DepthTexture>();
+    if (storage_texture == nullptr) {
+      continue;
+    }
+
+    ast::BindingDecoration* binding = nullptr;
+    ast::GroupDecoration* group = nullptr;
+    std::tie(binding, group) = GetBindingAndGroup(var);
     if (binding == nullptr || group == nullptr) {
       continue;
     }
@@ -222,14 +242,7 @@
 
     ast::BindingDecoration* binding = nullptr;
     ast::GroupDecoration* group = nullptr;
-    for (auto* deco : var->Declaration()->decorations()) {
-      if (auto* b = deco->As<ast::BindingDecoration>()) {
-        binding = b;
-      }
-      if (auto* s = deco->As<ast::GroupDecoration>()) {
-        group = s;
-      }
-    }
+    std::tie(binding, group) = GetBindingAndGroup(var);
     if (binding == nullptr || group == nullptr) {
       continue;
     }
@@ -259,13 +272,7 @@
 
     ast::BindingDecoration* binding = nullptr;
     ast::GroupDecoration* group = nullptr;
-    for (auto* deco : var->Declaration()->decorations()) {
-      if (auto* b = deco->As<ast::BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<ast::GroupDecoration>()) {
-        group = s;
-      }
-    }
+    std::tie(binding, group) = GetBindingAndGroup(var);
     if (binding == nullptr || group == nullptr) {
       continue;
     }