Fix texture-only arg in combine samplers transform.
When a function has an unused texture-only or sampler-only argument,
and no used texture/sampler pairs, the CombineSamplers transform was
failing to remove it from the argument list. The reason is an
incorrect early-out when no texture/sampler pairs are found.
https://dawn-review.googlesource.com/c/dawn/+/154181 attempted to
fix this by adding the unused arguments back as texture/sampler
solo pairs in CollectTextureSamplerPairs(). However, this is
problematic for a number of reasons.
This CL essentially reverts that change, and removes the incorrect
early-out, causing unused texture and sampler parameters to be
(correctly) removed.
Bug: chromium:356298370
Change-Id: If69e4d69dbf308637689622094193a285f9c3a46
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/202155
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
index 0bc3df8..583b4b5 100644
--- a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
@@ -46,7 +46,7 @@
namespace {
bool IsGlobal(const tint::sem::VariablePair& pair) {
- return (!pair.first || tint::Is<tint::sem::GlobalVariable>(pair.first)) &&
+ return tint::Is<tint::sem::GlobalVariable>(pair.first) &&
(!pair.second || tint::Is<tint::sem::GlobalVariable>(pair.second));
}
@@ -104,7 +104,7 @@
/// Creates a combined sampler global variables.
/// (Note this is actually a Texture node at the AST level, but it will be
/// written as the corresponding sampler (eg., sampler2D) on GLSL output.)
- /// @param texture_var the texture (global) variable
+ /// @param texture_var the texture (global) variable (must be non-null)
/// @param sampler_var the sampler (global) variable
/// @param name the default name to use (may be overridden by map lookup)
/// @returns the newly-created global variable
@@ -112,11 +112,9 @@
const sem::Variable* sampler_var,
std::string name) {
binding::CombinedTextureSamplerPair st_pair;
- if (texture_var) {
- st_pair.texture = *texture_var->As<sem::GlobalVariable>()->Attributes().binding_point;
- } else {
- st_pair.texture = bindings->placeholder_sampler_bind_point;
- }
+
+ TINT_ASSERT(texture_var);
+ st_pair.texture = *texture_var->As<sem::GlobalVariable>()->Attributes().binding_point;
if (sampler_var) {
st_pair.sampler = *sampler_var->As<sem::GlobalVariable>()->Attributes().binding_point;
@@ -149,24 +147,17 @@
/// Creates Identifier for a given texture and sampler variable pair.
/// Depth textures with no samplers are turned into the corresponding
/// f32 texture (e.g., texture_depth_2d -> texture_2d<f32>).
- /// Either texture or sampler could be nullptr, but cannot be nullptr at the same time.
- /// The texture can only be nullptr, when the sampler is a dangling function parameter.
/// @param texture the texture variable of interest
/// @param sampler the texture variable of interest
/// @returns the newly-created type
ast::Type CreateCombinedASTTypeFor(const sem::Variable* texture, const sem::Variable* sampler) {
- if (texture) {
- const core::type::Type* texture_type = texture->Type()->UnwrapRef();
- const core::type::DepthTexture* depth = texture_type->As<core::type::DepthTexture>();
- if (depth && !sampler) {
- return ctx.dst->ty.sampled_texture(depth->dim(), ctx.dst->ty.f32());
- }
- return CreateASTTypeFor(ctx, texture_type);
+ const core::type::Type* texture_type = texture->Type()->UnwrapRef();
+ const core::type::DepthTexture* depth = texture_type->As<core::type::DepthTexture>();
+ if (depth && !sampler) {
+ return ctx.dst->ty.sampled_texture(depth->dim(), ctx.dst->ty.f32());
}
- TINT_ASSERT(sampler != nullptr);
- const core::type::Type* sampler_type = sampler->Type()->UnwrapRef();
- return CreateASTTypeFor(ctx, sampler_type);
+ return CreateASTTypeFor(ctx, texture_type);
}
/// Insert a new texture/sampler pair into the combined samplers maps (global or local, as
@@ -179,16 +170,9 @@
tint::Vector<const ast::Parameter*, 8>* params) {
const sem::Variable* texture_var = pair.first;
const sem::Variable* sampler_var = pair.second;
- std::string name = "";
-
- if (texture_var) {
- name = texture_var->Declaration()->name->symbol.Name();
- }
+ std::string name = texture_var->Declaration()->name->symbol.Name();
if (sampler_var) {
- if (!name.empty()) {
- name += "_";
- }
- name += sampler_var->Declaration()->name->symbol.Name();
+ name += "_" + sampler_var->Declaration()->name->symbol.Name();
}
if (IsGlobal(pair)) {
// Both texture and sampler are global; add a new global variable
@@ -247,10 +231,6 @@
// separate textures & samplers. Create new combined globals where found.
ctx.ReplaceAll([&](const ast::Function* ast_fn) -> const ast::Function* {
if (auto* fn = sem.Get(ast_fn)) {
- auto pairs = fn->TextureSamplerPairs();
- if (pairs.IsEmpty()) {
- return nullptr;
- }
Vector<const ast::Parameter*, 8> params;
for (auto pair : fn->TextureSamplerPairs()) {
if (!pair.second) {
diff --git a/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc b/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc
index a8f2cb0..61ff10a 100644
--- a/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/combine_samplers_test.cc
@@ -1036,14 +1036,12 @@
}
)";
auto* expect = R"(
-fn f(tex_1 : texture_2d<f32>) -> u32 {
+fn f() -> u32 {
return 1u;
}
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
-
fn main() {
- _ = f(t_1);
+ _ = f();
}
)";
@@ -1068,14 +1066,12 @@
}
)";
auto* expect = R"(
-fn f(sampler1_1 : sampler) -> u32 {
+fn f() -> u32 {
return 1u;
}
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
-
fn main() {
- _ = f(s_1);
+ _ = f();
}
)";
@@ -1102,16 +1098,12 @@
}
)";
auto* expect = R"(
-fn f(sampler1_1 : sampler, tex_1 : texture_2d<f32>) -> u32 {
+fn f() -> u32 {
return 1u;
}
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
-
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
-
fn main() {
- _ = f(s_1, t_1);
+ _ = f();
}
)";
@@ -1140,18 +1132,14 @@
}
)";
auto* expect = R"(
-fn f(sampler1_1 : sampler, tex3_1 : texture_2d_array<f32>, tex1_1 : texture_2d<f32>) -> u32 {
+fn f(tex3_1 : texture_2d_array<f32>) -> u32 {
return (1u + textureNumLayers(tex3_1));
}
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
-
@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t2_1 : texture_2d_array<f32>;
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t1_1 : texture_2d<f32>;
-
fn main() {
- _ = f(s_1, t2_1, t1_1);
+ _ = f(t2_1);
}
)";
@@ -1180,18 +1168,16 @@
}
)";
auto* expect = R"(
-fn f_nested(tex_1 : texture_2d<f32>) -> u32 {
+fn f_nested() -> u32 {
return 1u;
}
-fn f(tex_2 : texture_2d<f32>) -> u32 {
- return f_nested(tex_2);
+fn f() -> u32 {
+ return f_nested();
}
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
-
fn main() {
- _ = f(t_1);
+ _ = f();
}
)";
@@ -1223,20 +1209,59 @@
)";
auto* expect =
R"(
-fn f_nested(sampler1_1 : sampler, tex_1 : texture_2d<f32>) -> u32 {
+fn f_nested() -> u32 {
return 1u;
}
-fn f(sampler1_2 : sampler, tex_2 : texture_2d<f32>) -> u32 {
- return f_nested(sampler1_2, tex_2);
+fn f() -> u32 {
+ return f_nested();
}
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var s_1 : sampler;
-
-@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var t_1 : texture_2d<f32>;
-
fn main() {
- _ = f(s_1, t_1);
+ _ = f();
+}
+)";
+
+ ast::transform::DataMap data;
+ Bindings binding;
+ data.Add<Bindings>(binding);
+ auto got = Run<CombineSamplers>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CombineSamplersTest, UnusedTextureAndSamplerFunctionParameter_Nested2) {
+ auto* src = R"(
+@group(0) @binding(1) var texture1 : texture_2d<f32>;
+@group(0) @binding(2) var texture2 : texture_2d<f32>;
+@group(0) @binding(3) var sampler1 : sampler;
+
+fn sample(t : texture_2d<f32>, s : sampler, coords : vec2<f32>, unused : texture_2d<f32>) -> vec4<f32> {
+ return textureSample(t, s, coords);
+}
+
+@fragment
+fn main(@location(0) coords : vec2<f32>) -> @location(0) vec4<f32> {
+ var a = sample(texture1, sampler1, coords, texture1);
+ var b = sample(texture1, sampler1, coords, texture2);
+ return a + b;
+}
+)";
+ auto* expect =
+ R"(
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var placeholder_sampler : sampler;
+
+fn sample(t_s : texture_2d<f32>, coords : vec2<f32>) -> vec4<f32> {
+ return textureSample(t_s, placeholder_sampler, coords);
+}
+
+@group(0) @binding(0) @internal(disable_validation__binding_point_collision) var texture1_sampler1 : texture_2d<f32>;
+
+@fragment
+fn main(@location(0) coords : vec2<f32>) -> @location(0) vec4<f32> {
+ var a = sample(texture1_sampler1, coords);
+ var b = sample(texture1_sampler1, coords);
+ return (a + b);
}
)";
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 6945b28..00657e9 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -3143,48 +3143,19 @@
// argument passed to the current function. Leave global variables
// as-is. Then add the mapped pair to the current function's list of
// texture/sampler pairs.
-
- Hashset<const sem::Variable*, 4> texture_sampler_set;
-
for (sem::VariablePair pair : func->TextureSamplerPairs()) {
const sem::Variable* texture = pair.first;
const sem::Variable* sampler = pair.second;
- if (auto* param = As<sem::Parameter>(texture)) {
+ if (auto* param = texture->As<sem::Parameter>()) {
texture = args[param->Index()]->UnwrapLoad()->As<sem::VariableUser>()->Variable();
- texture_sampler_set.Add(texture);
}
- if (auto* param = As<sem::Parameter>(sampler)) {
- sampler = args[param->Index()]->UnwrapLoad()->As<sem::VariableUser>()->Variable();
- texture_sampler_set.Add(sampler);
+ if (sampler) {
+ if (auto* param = sampler->As<sem::Parameter>()) {
+ sampler = args[param->Index()]->UnwrapLoad()->As<sem::VariableUser>()->Variable();
+ }
}
current_function_->AddTextureSamplerPair(texture, sampler);
}
-
- // Add any possible texture/sampler not essentially passed to builtins from the function param.
- // This could be unused texture/sampler or texture/sampler passed to builtins that are emulated.
-
- const auto& signature = func->Signature();
-
- for (size_t i = 0; i < signature.parameters.Length(); i++) {
- auto* param = signature.parameters[i];
- if (param->Type()->Is<core::type::Texture>()) {
- auto* user = args[i]->UnwrapLoad()->As<sem::VariableUser>();
- auto* texture = user->Variable();
- if (!texture_sampler_set.Contains(texture)) {
- current_function_->AddTextureSamplerPair(texture, nullptr);
- func->AddTextureSamplerPair(param, nullptr);
- texture_sampler_set.Add(texture);
- }
- } else if (param->Type()->Is<core::type::Sampler>()) {
- auto* user = args[i]->UnwrapLoad()->As<sem::VariableUser>();
- auto* sampler = user->Variable();
- if (!texture_sampler_set.Contains(sampler)) {
- current_function_->AddTextureSamplerPair(nullptr, sampler);
- func->AddTextureSamplerPair(nullptr, param);
- texture_sampler_set.Add(sampler);
- }
- }
- }
}
sem::ValueExpression* Resolver::Literal(const ast::LiteralExpression* literal) {
diff --git a/src/tint/lang/wgsl/resolver/resolver_test.cc b/src/tint/lang/wgsl/resolver/resolver_test.cc
index b052239..1c4b861 100644
--- a/src/tint/lang/wgsl/resolver/resolver_test.cc
+++ b/src/tint/lang/wgsl/resolver/resolver_test.cc
@@ -2339,27 +2339,13 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto inner_pairs = Sem().Get(inner_func)->TextureSamplerPairs();
- ASSERT_EQ(inner_pairs.Length(), 2u);
- auto* inner_pair_texture = As<sem::Parameter>(inner_pairs[0].first);
- ASSERT_NE(inner_pair_texture, nullptr);
- EXPECT_EQ(inner_pair_texture->Index(), 1u);
- auto* inner_pair_sampler = As<sem::Parameter>(inner_pairs[1].second);
- ASSERT_NE(inner_pair_sampler, nullptr);
- EXPECT_EQ(inner_pair_sampler->Index(), 2u);
+ ASSERT_EQ(inner_pairs.Length(), 0u);
auto middle_pairs = Sem().Get(middle_func)->TextureSamplerPairs();
- ASSERT_EQ(middle_pairs.Length(), 2u);
- auto* middle_pair_texture = As<sem::Parameter>(middle_pairs[0].first);
- ASSERT_NE(middle_pair_texture, nullptr);
- EXPECT_EQ(middle_pair_texture->Index(), 2u);
- auto* middle_pair_sampler = As<sem::Parameter>(middle_pairs[1].second);
- ASSERT_NE(middle_pair_sampler, nullptr);
- EXPECT_EQ(middle_pair_sampler->Index(), 1u);
+ ASSERT_EQ(middle_pairs.Length(), 0u);
auto outer_pairs = Sem().Get(outer_func)->TextureSamplerPairs();
- ASSERT_EQ(outer_pairs.Length(), 2u);
- EXPECT_TRUE(outer_pairs[0].first != nullptr);
- EXPECT_TRUE(outer_pairs[1].second != nullptr);
+ ASSERT_EQ(outer_pairs.Length(), 0u);
}
TEST_F(ResolverTest, TextureSampler_TextureDimensions) {
diff --git a/src/tint/lang/wgsl/sem/function.h b/src/tint/lang/wgsl/sem/function.h
index 88b3c3d..56d0769 100644
--- a/src/tint/lang/wgsl/sem/function.h
+++ b/src/tint/lang/wgsl/sem/function.h
@@ -142,10 +142,10 @@
/// that this function uses (directly or indirectly). These can only
/// be parameters to this function or global variables. Uniqueness is
/// ensured by texture_sampler_pairs_ being a UniqueVector.
- /// @param texture the texture (null indicates a sampler-only reference)
+ /// @param texture the texture (must be non-null)
/// @param sampler the sampler (null indicates a texture-only reference)
void AddTextureSamplerPair(const sem::Variable* texture, const sem::Variable* sampler) {
- TINT_ASSERT(texture || sampler);
+ TINT_ASSERT(texture != nullptr);
texture_sampler_pairs_.Add(VariablePair(texture, sampler));
}