Add test, shuffle code before changes.
Add a disabled regression test for the issue, the code is moved to group
the three methods together. The two moved functions are only called from
`GetSamplerTextureUses` so this just moves them together to make working
with them easier.
Bug: 380433758
Change-Id: I0b61a8debafd28d63bcd316d62c01b5ebccf60c5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/223514
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index 6382d60..bae62ee 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -603,6 +603,129 @@
return it->second;
}
+void Inspector::GenerateSamplerTargets() {
+ // Do not re-generate, since |program_| should not change during the lifetime
+ // of the inspector.
+ if (sampler_targets_ != nullptr) {
+ return;
+ }
+
+ sampler_targets_ =
+ std::make_unique<std::unordered_map<std::string, UniqueVector<SamplerTexturePair, 4>>>();
+
+ auto& sem = program_.Sem();
+
+ for (auto* node : program_.ASTNodes().Objects()) {
+ auto* c = node->As<ast::CallExpression>();
+ if (!c) {
+ continue;
+ }
+
+ auto* call = sem.Get(c)->UnwrapMaterialize()->As<sem::Call>();
+ if (!call) {
+ continue;
+ }
+
+ auto* i = call->Target()->As<sem::BuiltinFn>();
+ if (!i) {
+ continue;
+ }
+
+ const auto& signature = i->Signature();
+ int sampler_index = signature.IndexOf(core::ParameterUsage::kSampler);
+ if (sampler_index == -1) {
+ continue;
+ }
+
+ int texture_index = signature.IndexOf(core::ParameterUsage::kTexture);
+ if (texture_index == -1) {
+ continue;
+ }
+
+ auto* call_func = call->Stmt()->Function();
+ Vector<const sem::Function*, 4> entry_points;
+ if (call_func->Declaration()->IsEntryPoint()) {
+ entry_points = {call_func};
+ } else {
+ entry_points = call_func->AncestorEntryPoints();
+ }
+
+ if (entry_points.IsEmpty()) {
+ continue;
+ }
+
+ auto* t = c->args[static_cast<size_t>(texture_index)];
+ auto* s = c->args[static_cast<size_t>(sampler_index)];
+
+ GetOriginatingResources(
+ std::array<const ast::Expression*, 2>{t, s},
+ [&](std::array<const sem::GlobalVariable*, 2> globals) {
+ auto texture_binding_point = *globals[0]->Attributes().binding_point;
+ auto sampler_binding_point = *globals[1]->Attributes().binding_point;
+
+ for (auto* entry_point : entry_points) {
+ const auto& ep_name = entry_point->Declaration()->name->symbol.Name();
+ (*sampler_targets_)[ep_name].Add(
+ {sampler_binding_point, texture_binding_point});
+ }
+ });
+ }
+}
+
+template <size_t N, typename F>
+void Inspector::GetOriginatingResources(std::array<const ast::Expression*, N> exprs, F&& callback) {
+ if (DAWN_UNLIKELY(!program_.IsValid())) {
+ TINT_ICE() << "attempting to get originating resources in invalid program";
+ return;
+ }
+
+ auto& sem = program_.Sem();
+
+ std::array<const sem::GlobalVariable*, N> globals{};
+ std::array<const sem::Parameter*, N> parameters{};
+ UniqueVector<const ast::CallExpression*, 8> callsites;
+
+ for (size_t i = 0; i < N; i++) {
+ const sem::Variable* root_ident = sem.GetVal(exprs[i])->RootIdentifier();
+ if (auto* global = root_ident->As<sem::GlobalVariable>()) {
+ globals[i] = global;
+ } else if (auto* param = root_ident->As<sem::Parameter>()) {
+ auto* func = tint::As<sem::Function>(param->Owner());
+ if (func->CallSites().IsEmpty()) {
+ // One or more of the expressions is a parameter, but this function
+ // is not called. Ignore.
+ return;
+ }
+ for (auto* call : func->CallSites()) {
+ callsites.Add(call->Declaration());
+ }
+ parameters[i] = param;
+ } else {
+ TINT_ICE() << "cannot resolve originating resource with expression type "
+ << exprs[i]->TypeInfo().name;
+ return;
+ }
+ }
+
+ if (callsites.Length()) {
+ for (auto* call_expr : callsites) {
+ // Make a copy of the expressions for this callsite
+ std::array<const ast::Expression*, N> call_exprs = exprs;
+ // Patch all the parameter expressions with their argument
+ for (size_t i = 0; i < N; i++) {
+ if (auto* param = parameters[i]) {
+ call_exprs[i] = call_expr->args[param->Index()];
+ }
+ }
+ // Now call GetOriginatingResources() with from the callsite
+ GetOriginatingResources(call_exprs, callback);
+ }
+ } else {
+ // All the expressions resolved to globals
+ callback(globals);
+ }
+}
+
std::vector<SamplerTexturePair> Inspector::GetSamplerTextureUses(const std::string& entry_point,
const BindingPoint& placeholder) {
auto* func = FindEntryPointByName(entry_point);
@@ -879,75 +1002,6 @@
return result;
}
-void Inspector::GenerateSamplerTargets() {
- // Do not re-generate, since |program_| should not change during the lifetime
- // of the inspector.
- if (sampler_targets_ != nullptr) {
- return;
- }
-
- sampler_targets_ =
- std::make_unique<std::unordered_map<std::string, UniqueVector<SamplerTexturePair, 4>>>();
-
- auto& sem = program_.Sem();
-
- for (auto* node : program_.ASTNodes().Objects()) {
- auto* c = node->As<ast::CallExpression>();
- if (!c) {
- continue;
- }
-
- auto* call = sem.Get(c)->UnwrapMaterialize()->As<sem::Call>();
- if (!call) {
- continue;
- }
-
- auto* i = call->Target()->As<sem::BuiltinFn>();
- if (!i) {
- continue;
- }
-
- const auto& signature = i->Signature();
- int sampler_index = signature.IndexOf(core::ParameterUsage::kSampler);
- if (sampler_index == -1) {
- continue;
- }
-
- int texture_index = signature.IndexOf(core::ParameterUsage::kTexture);
- if (texture_index == -1) {
- continue;
- }
-
- auto* call_func = call->Stmt()->Function();
- Vector<const sem::Function*, 4> entry_points;
- if (call_func->Declaration()->IsEntryPoint()) {
- entry_points = {call_func};
- } else {
- entry_points = call_func->AncestorEntryPoints();
- }
-
- if (entry_points.IsEmpty()) {
- continue;
- }
-
- auto* t = c->args[static_cast<size_t>(texture_index)];
- auto* s = c->args[static_cast<size_t>(sampler_index)];
-
- GetOriginatingResources(
- std::array<const ast::Expression*, 2>{t, s},
- [&](std::array<const sem::GlobalVariable*, 2> globals) {
- auto texture_binding_point = *globals[0]->Attributes().binding_point;
- auto sampler_binding_point = *globals[1]->Attributes().binding_point;
-
- for (auto* entry_point : entry_points) {
- const auto& ep_name = entry_point->Declaration()->name->symbol.Name();
- (*sampler_targets_)[ep_name].Add(
- {sampler_binding_point, texture_binding_point});
- }
- });
- }
-}
-
std::tuple<InterpolationType, InterpolationSampling> Inspector::CalculateInterpolationData(
VectorRef<const ast::Attribute*> attributes) const {
auto* interpolation_attribute = ast::GetAttribute<ast::InterpolateAttribute>(attributes);
@@ -1067,60 +1121,6 @@
return {};
}
-template <size_t N, typename F>
-void Inspector::GetOriginatingResources(std::array<const ast::Expression*, N> exprs, F&& callback) {
- if (DAWN_UNLIKELY(!program_.IsValid())) {
- TINT_ICE() << "attempting to get originating resources in invalid program";
- return;
- }
-
- auto& sem = program_.Sem();
-
- std::array<const sem::GlobalVariable*, N> globals{};
- std::array<const sem::Parameter*, N> parameters{};
- UniqueVector<const ast::CallExpression*, 8> callsites;
-
- for (size_t i = 0; i < N; i++) {
- const sem::Variable* root_ident = sem.GetVal(exprs[i])->RootIdentifier();
- if (auto* global = root_ident->As<sem::GlobalVariable>()) {
- globals[i] = global;
- } else if (auto* param = root_ident->As<sem::Parameter>()) {
- auto* func = tint::As<sem::Function>(param->Owner());
- if (func->CallSites().IsEmpty()) {
- // One or more of the expressions is a parameter, but this function
- // is not called. Ignore.
- return;
- }
- for (auto* call : func->CallSites()) {
- callsites.Add(call->Declaration());
- }
- parameters[i] = param;
- } else {
- TINT_ICE() << "cannot resolve originating resource with expression type "
- << exprs[i]->TypeInfo().name;
- return;
- }
- }
-
- if (callsites.Length()) {
- for (auto* call_expr : callsites) {
- // Make a copy of the expressions for this callsite
- std::array<const ast::Expression*, N> call_exprs = exprs;
- // Patch all the parameter expressions with their argument
- for (size_t i = 0; i < N; i++) {
- if (auto* param = parameters[i]) {
- call_exprs[i] = call_expr->args[param->Index()];
- }
- }
- // Now call GetOriginatingResources() with from the callsite
- GetOriginatingResources(call_exprs, callback);
- }
- } else {
- // All the expressions resolved to globals
- callback(globals);
- }
-}
-
std::vector<Inspector::LevelSampleInfo> Inspector::GetTextureQueries(const std::string& ep_name) {
const auto* ep = FindEntryPointByName(ep_name);
if (!ep) {
diff --git a/src/tint/lang/wgsl/inspector/inspector_test.cc b/src/tint/lang/wgsl/inspector/inspector_test.cc
index 6a93800..8cea0aa 100644
--- a/src/tint/lang/wgsl/inspector/inspector_test.cc
+++ b/src/tint/lang/wgsl/inspector/inspector_test.cc
@@ -3508,6 +3508,56 @@
ASSERT_EQ(0u, result.Length());
}
+// Regression test for crbug.com/dawn/380433758.
+TEST_F(InspectorGetSamplerTextureUsesTest, DISABLED_DiamondSampler) {
+ std::string shader = R"(
+fn sample(t: texture_2d<f32>, s: sampler) -> vec4f {
+ return textureSampleLevel(t, s, vec2f(0), 0);
+}
+
+fn useCombos0() -> vec4f {
+ return sample(tex0_0, smp0_0);
+}
+
+fn useCombos1() -> vec4f {
+ return sample(tex1_15, smp0_0);
+}
+
+@group(0) @binding(0) var tex0_0: texture_2d<f32>;
+@group(0) @binding(1) var tex1_15: texture_2d<f32>;
+@group(0) @binding(2) var smp0_0: sampler;
+
+@vertex fn vs() -> @builtin(position) vec4f {
+ return useCombos0();
+}
+
+@fragment fn fs() -> @location(0) vec4f {
+ return vec4f(useCombos1());
+})";
+
+ Inspector& inspector = Initialize(shader);
+ {
+ auto result = inspector.GetSamplerTextureUses("vs");
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+ ASSERT_EQ(1u, result.Length());
+
+ EXPECT_EQ(0u, result[0].sampler_binding_point.group);
+ EXPECT_EQ(2u, result[0].sampler_binding_point.binding);
+ EXPECT_EQ(0u, result[0].texture_binding_point.group);
+ EXPECT_EQ(0u, result[0].texture_binding_point.binding);
+ }
+ {
+ auto result = inspector.GetSamplerTextureUses("fs");
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+ ASSERT_EQ(1u, result.Length());
+
+ EXPECT_EQ(0u, result[0].sampler_binding_point.group);
+ EXPECT_EQ(2u, result[0].sampler_binding_point.binding);
+ EXPECT_EQ(0u, result[0].texture_binding_point.group);
+ EXPECT_EQ(1u, result[0].texture_binding_point.binding);
+ }
+}
+
TEST_F(InspectorGetSamplerTextureUsesTest, Simple) {
std::string shader = R"(
@group(0) @binding(1) var mySampler: sampler;