Add Inspector class

This class is used to examine a module and get information about its
contents. This is the getting side of shader of reflection. Future
work will add transforms that perform the setting side of reflection.

In addition to the basic class and infrastructure, this CL adds a
GetEntryPoints() function demonstrate it works. More functionality
will be added in later CLs.

BUG=tint:257

Change-Id: If41dbb6c93302e0332754c086c75729d6ffe04d0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/29320
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ryan Harrison 2020-10-05 14:52:36 +00:00 committed by Commit Bot service account
parent 60a272a86e
commit 1a9a2dd07d
5 changed files with 220 additions and 1 deletions

View File

@ -369,6 +369,8 @@ source_set("libtint_core_src") {
"src/ast/workgroup_decoration.h", "src/ast/workgroup_decoration.h",
"src/context.cc", "src/context.cc",
"src/context.h", "src/context.h",
"src/inspector.cc",
"src/inspector.h",
"src/reader/reader.cc", "src/reader/reader.cc",
"src/reader/reader.h", "src/reader/reader.h",
"src/scope_stack.h", "src/scope_stack.h",
@ -750,6 +752,7 @@ source_set("tint_unittests_core_src") {
"src/ast/variable_decl_statement_test.cc", "src/ast/variable_decl_statement_test.cc",
"src/ast/variable_test.cc", "src/ast/variable_test.cc",
"src/ast/workgroup_decoration_test.cc", "src/ast/workgroup_decoration_test.cc",
"src/inspector_test.cc",
"src/scope_stack_test.cc", "src/scope_stack_test.cc",
"src/transform/bound_array_accessors_transform_test.cc", "src/transform/bound_array_accessors_transform_test.cc",
"src/transform/vertex_pulling_transform_test.cc", "src/transform/vertex_pulling_transform_test.cc",

View File

@ -188,8 +188,10 @@ set(TINT_LIB_SRCS
ast/variable_decl_statement.h ast/variable_decl_statement.h
ast/workgroup_decoration.cc ast/workgroup_decoration.cc
ast/workgroup_decoration.h ast/workgroup_decoration.h
context.h
context.cc context.cc
context.h
inspector.cc
inspector.h
reader/reader.cc reader/reader.cc
reader/reader.h reader/reader.h
scope_stack.h scope_stack.h
@ -360,6 +362,7 @@ set(TINT_TEST_SRCS
ast/variable_decl_statement_test.cc ast/variable_decl_statement_test.cc
ast/variable_test.cc ast/variable_test.cc
ast/workgroup_decoration_test.cc ast/workgroup_decoration_test.cc
inspector_test.cc
scope_stack_test.cc scope_stack_test.cc
transform/bound_array_accessors_transform_test.cc transform/bound_array_accessors_transform_test.cc
transform/vertex_pulling_transform_test.cc transform/vertex_pulling_transform_test.cc

38
src/inspector.cc Normal file
View File

@ -0,0 +1,38 @@
// 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/inspector.h"
#include "src/ast/function.h"
namespace tint {
namespace inspector {
Inspector::Inspector(const ast::Module& module) : module_(module) {}
Inspector::~Inspector() = default;
std::vector<EntryPoint> Inspector::GetEntryPoints() {
std::vector<EntryPoint> result;
for (const auto& func : module_.functions()) {
if (func->IsEntryPoint()) {
result.push_back({func->name(), func->pipeline_stage()});
}
}
return result;
}
} // namespace inspector
} // namespace tint

59
src/inspector.h Normal file
View File

@ -0,0 +1,59 @@
// 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_INSPECTOR_H_
#define SRC_INSPECTOR_H_
#include <memory>
#include <string>
#include <vector>
#include "src/ast/module.h"
#include "src/ast/pipeline_stage.h"
namespace tint {
namespace inspector {
struct EntryPoint {
/// The entry point name
std::string name;
/// The entry point stage
ast::PipelineStage stage = ast::PipelineStage::kNone;
};
/// Extracts information from a module
class Inspector {
public:
/// Constructor
/// @param module Shader module to extract information from.
explicit Inspector(const ast::Module& module);
~Inspector();
/// @returns error messages from the Inspector
const std::string& error() { return error_; }
/// @returns true if an error was encountered
bool has_error() const { return !error_.empty(); }
/// @returns vector of entry point information
std::vector<EntryPoint> GetEntryPoints();
private:
const ast::Module& module_;
std::string error_;
};
} // namespace inspector
} // namespace tint
#endif // SRC_INSPECTOR_H_

116
src/inspector_test.cc Normal file
View File

@ -0,0 +1,116 @@
// 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/inspector.h"
#include "gtest/gtest.h"
#include "src/ast/function.h"
#include "src/ast/pipeline_stage.h"
#include "src/ast/stage_decoration.h"
#include "src/ast/type/void_type.h"
#include "src/context.h"
namespace tint {
namespace inspector {
namespace {
class InspectorHelper {
public:
InspectorHelper()
: mod_(std::make_unique<ast::Module>()),
inspector_(std::make_unique<Inspector>(*mod_)) {}
void AddFunction(const std::string& name, ast::PipelineStage stage) {
auto func = std::make_unique<ast::Function>(
name, ast::VariableList{},
ctx_.type_mgr().Get(std::make_unique<ast::type::VoidType>()));
if (stage != ast::PipelineStage::kNone) {
func->add_decoration(std::make_unique<ast::StageDecoration>(stage));
}
mod()->AddFunction(std::move(func));
}
Context* ctx() { return &ctx_; }
ast::Module* mod() { return mod_.get(); }
Inspector* inspector() { return inspector_.get(); }
private:
Context ctx_;
std::unique_ptr<ast::Module> mod_;
std::unique_ptr<Inspector> inspector_;
};
class InspectorTest : public InspectorHelper, public testing::Test {};
class InspectorGetEntryPointTest : public InspectorTest {};
TEST_F(InspectorGetEntryPointTest, NoFunctions) {
auto result = inspector()->GetEntryPoints();
ASSERT_FALSE(inspector()->has_error());
EXPECT_EQ(0u, result.size());
}
TEST_F(InspectorGetEntryPointTest, NoEntryPoints) {
AddFunction("foo", ast::PipelineStage::kNone);
auto result = inspector()->GetEntryPoints();
ASSERT_FALSE(inspector()->has_error());
EXPECT_EQ(0u, result.size());
}
TEST_F(InspectorGetEntryPointTest, OneEntryPoint) {
AddFunction("foo", ast::PipelineStage::kVertex);
auto result = inspector()->GetEntryPoints();
ASSERT_FALSE(inspector()->has_error());
EXPECT_EQ(1u, result.size());
EXPECT_EQ("foo", result[0].name);
EXPECT_EQ(ast::PipelineStage::kVertex, result[0].stage);
}
TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) {
AddFunction("foo", ast::PipelineStage::kVertex);
AddFunction("bar", ast::PipelineStage::kCompute);
auto result = inspector()->GetEntryPoints();
ASSERT_FALSE(inspector()->has_error());
EXPECT_EQ(2u, result.size());
EXPECT_EQ("foo", result[0].name);
EXPECT_EQ(ast::PipelineStage::kVertex, result[0].stage);
EXPECT_EQ("bar", result[1].name);
EXPECT_EQ(ast::PipelineStage::kCompute, result[1].stage);
}
TEST_F(InspectorGetEntryPointTest, MixFunctionsAndEntryPoints) {
AddFunction("foo", ast::PipelineStage::kVertex);
AddFunction("func", ast::PipelineStage::kNone);
AddFunction("bar", ast::PipelineStage::kCompute);
auto result = inspector()->GetEntryPoints();
EXPECT_FALSE(inspector()->has_error());
EXPECT_EQ(2u, result.size());
EXPECT_EQ("foo", result[0].name);
EXPECT_EQ(ast::PipelineStage::kVertex, result[0].stage);
EXPECT_EQ("bar", result[1].name);
EXPECT_EQ(ast::PipelineStage::kCompute, result[1].stage);
}
} // namespace
} // namespace inspector
} // namespace tint