tint: Add inspection of pixel_local var member types.
Bug: dawn:1704
Change-Id: I65195364f546125c66de849acd9c3f8d7e62fbb0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/150823
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/tint/lang/wgsl/inspector/entry_point.h b/src/tint/lang/wgsl/inspector/entry_point.h
index 8c3161d..7d8e242 100644
--- a/src/tint/lang/wgsl/inspector/entry_point.h
+++ b/src/tint/lang/wgsl/inspector/entry_point.h
@@ -45,6 +45,14 @@
kUnknown,
};
+/// Types of `pixel_local` variable members.
+enum class PixelLocalMemberType : uint8_t {
+ kF32,
+ kU32,
+ kI32,
+ kUnknown,
+};
+
/// Type of interpolation of a stage variable.
enum class InterpolationType : uint8_t { kPerspective, kLinear, kFlat, kUnknown };
@@ -146,6 +154,9 @@
std::vector<StageVariable> output_variables;
/// List of the pipeline overridable constants accessed via this entry point.
std::vector<Override> overrides;
+ /// List of the variable types used in the `pixel_local` block accessed by this entry point (if
+ /// any).
+ std::vector<PixelLocalMemberType> pixel_local_members;
/// Does the entry point use the sample_mask builtin as an input builtin
/// variable.
bool input_sample_mask_used = false;
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index 8a6b0d1..7688ece 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -150,6 +150,7 @@
}
case ast::PipelineStage::kFragment: {
entry_point.stage = PipelineStage::kFragment;
+ entry_point.pixel_local_members = ComputePixelLocalMemberTypes(func);
break;
}
case ast::PipelineStage::kVertex: {
@@ -903,6 +904,37 @@
return total_size;
}
+std::vector<PixelLocalMemberType> Inspector::ComputePixelLocalMemberTypes(
+ const ast::Function* func) const {
+ auto* func_sem = program_->Sem().Get(func);
+ for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) {
+ if (var->AddressSpace() != core::AddressSpace::kPixelLocal) {
+ continue;
+ }
+
+ auto* str = var->Type()->UnwrapRef()->As<sem::Struct>();
+
+ std::vector<PixelLocalMemberType> types;
+ types.reserve(str->Members().Length());
+ for (auto* member : str->Members()) {
+ PixelLocalMemberType type = Switch(
+ member->Type(), //
+ [&](const core::type::F32*) { return PixelLocalMemberType::kF32; },
+ [&](const core::type::I32*) { return PixelLocalMemberType::kI32; },
+ [&](const core::type::U32*) { return PixelLocalMemberType::kU32; },
+ [&](Default) {
+ TINT_UNREACHABLE() << "unhandled component type";
+ return PixelLocalMemberType::kUnknown;
+ });
+ types.push_back(type);
+ }
+
+ return types;
+ }
+
+ return {};
+}
+
template <size_t N, typename F>
void Inspector::GetOriginatingResources(std::array<const ast::Expression*, N> exprs, F&& callback) {
if (TINT_UNLIKELY(!program_->IsValid())) {
diff --git a/src/tint/lang/wgsl/inspector/inspector.h b/src/tint/lang/wgsl/inspector/inspector.h
index 0c7a612..e1f6d6e 100644
--- a/src/tint/lang/wgsl/inspector/inspector.h
+++ b/src/tint/lang/wgsl/inspector/inspector.h
@@ -222,6 +222,10 @@
/// @returns the total size in bytes of all Workgroup storage-class storage accessed via func.
uint32_t ComputeWorkgroupStorageSize(const ast::Function* func) const;
+ /// @param func the root function of the callgraph to consider for the computation
+ /// @returns the list of member types for the `pixel_local` variable accessed via func, if any.
+ std::vector<PixelLocalMemberType> ComputePixelLocalMemberTypes(const ast::Function* func) const;
+
/// For a N-uple of expressions, resolve to the appropriate global resources
/// and call 'cb'.
/// 'cb' may be called multiple times.
diff --git a/src/tint/lang/wgsl/inspector/inspector_test.cc b/src/tint/lang/wgsl/inspector/inspector_test.cc
index f887f15..ad171bd 100644
--- a/src/tint/lang/wgsl/inspector/inspector_test.cc
+++ b/src/tint/lang/wgsl/inspector/inspector_test.cc
@@ -1515,6 +1515,59 @@
EXPECT_EQ(InterpolationSampling::kCenter, result[0].input_variables[0].interpolation_sampling);
}
+TEST_F(InspectorGetEntryPointTest, PixelLocalMemberDefault) {
+ // @fragment fn foo() {}
+ MakeEmptyBodyFunction("foo", Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ Inspector& inspector = Build();
+ auto result = inspector.GetEntryPoints();
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ(0u, result[0].pixel_local_members.size());
+}
+
+TEST_F(InspectorGetEntryPointTest, PixelLocalMemberTypes) {
+ // enable chromium_experimental_pixel_local;
+ // struct Ure {
+ // toto : u32;
+ // titi : f32;
+ // tata: i32;
+ // tonton : u32; // Check having the same type multiple times
+ // }
+ // var<pixel_local> pls : Ure;
+ // @fragment fn foo() { _ = pls; }
+
+ Enable(core::Extension::kChromiumExperimentalPixelLocal);
+ Structure("Ure", Vector{
+ Member("toto", ty.u32()),
+ Member("titi", ty.f32()),
+ Member("tata", ty.i32()),
+ Member("tonton", ty.u32()),
+ });
+ GlobalVar("pls", core::AddressSpace::kPixelLocal, ty("Ure"));
+ Func("foo", tint::Empty, ty.void_(),
+ Vector{
+ Assign(Phony(), "pls"),
+ },
+ Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ Inspector& inspector = Build();
+ auto result = inspector.GetEntryPoints();
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+
+ ASSERT_EQ(1u, result.size());
+ ASSERT_EQ(4u, result[0].pixel_local_members.size());
+ ASSERT_EQ(PixelLocalMemberType::kU32, result[0].pixel_local_members[0]);
+ ASSERT_EQ(PixelLocalMemberType::kF32, result[0].pixel_local_members[1]);
+ ASSERT_EQ(PixelLocalMemberType::kI32, result[0].pixel_local_members[2]);
+ ASSERT_EQ(PixelLocalMemberType::kU32, result[0].pixel_local_members[3]);
+}
+
TEST_P(InspectorGetEntryPointInterpolateTest, Test) {
auto& params = GetParam();
Structure("in_struct",