Import Tint changes from Dawn
Changes:
- daca5564356a92bb0981c17833c97502b26241e7 [tint][resolver]: Require @blend_src on all or none of th... by Corentin Wallez <cwallez@chromium.org>
- b57b92d4bf6a402f874ae64149892a934c6834b6 Enable dp4a: set to shipped-with-kill-switch by David Neto <dneto@google.com>
- eb5304ca62ed17e2dd473c4f4ffdc24fae16388e Fix missing member in reflection of tint::spirv::writer::... by Corentin Wallez <cwallez@chromium.org>
- 0a49383188b7bb1baa7f0c932070ce2130711553 [tint][utils] Optimize ScopeStack by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: daca5564356a92bb0981c17833c97502b26241e7
Change-Id: Ic291b1670c2d3a676eeecc1096d19c57a288fd67
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/172328
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/spirv/writer/common/options.h b/src/tint/lang/spirv/writer/common/options.h
index 79ec0e7..494369c 100644
--- a/src/tint/lang/spirv/writer/common/options.h
+++ b/src/tint/lang/spirv/writer/common/options.h
@@ -160,6 +160,7 @@
use_zero_initialize_workgroup_memory_extension,
emit_vertex_point_size,
clamp_frag_depth,
+ pass_matrix_by_pointer,
experimental_require_subgroup_uniform_control_flow,
polyfill_dot_4x8_packed,
disable_polyfill_integer_div_mod,
diff --git a/src/tint/lang/wgsl/features/status.cc b/src/tint/lang/wgsl/features/status.cc
index 334c1b6..2f592a1 100644
--- a/src/tint/lang/wgsl/features/status.cc
+++ b/src/tint/lang/wgsl/features/status.cc
@@ -36,7 +36,6 @@
////////////////////////////////////////////////////////////////////
// Experimental features
///////////////////////////////////////////////////////////////////
- case LanguageFeature::kPacked4X8IntegerDotProduct:
case LanguageFeature::kPointerCompositeAccess:
case LanguageFeature::kReadonlyAndReadwriteStorageTextures:
return FeatureStatus::kExperimental;
@@ -44,6 +43,7 @@
////////////////////////////////////////////////////////////////////
// Enabled features
////////////////////////////////////////////////////////////////////
+ case LanguageFeature::kPacked4X8IntegerDotProduct:
case LanguageFeature::kUnrestrictedPointerParameters:
return FeatureStatus::kShippedWithKillswitch;
diff --git a/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc b/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
index 67a3aab..ab8677e 100644
--- a/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
+++ b/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
@@ -215,6 +215,49 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(DualSourceBlendingExtensionTests, MixedBlendSrcAndNonBlendSrcOnLocationZero_Struct) {
+ // struct S {
+ // @location(0) a : vec4<f32>,
+ // @location(0) @blend_src(1) b : vec4<f32>,
+ // };
+ Structure("S", Vector{
+ Member("a", ty.vec4<f32>(),
+ Vector{
+ Location(Source{{12, 34}}, 0_a),
+ }),
+ Member("b", ty.vec4<f32>(),
+ Vector{Location(0_a), BlendSrc(Source{{56, 78}}, 1_a)}),
+ });
+
+ EXPECT_TRUE(r()->Resolve());
+}
+
+TEST_F(DualSourceBlendingExtensionTests,
+ MixedBlendSrcAndNonBlendSrcOnLocationZero_StructUsedInEntryPoint) {
+ // struct S {
+ // @location(0) a : vec4<f32>,
+ // @location(0) @blend_src(1) b : vec4<f32>,
+ // };
+ // fn F() -> S { return S(); }
+ Structure("S", Vector{
+ Member("a", ty.vec4<f32>(),
+ Vector{
+ Location(Source{{12, 34}}, 0_a),
+ }),
+ Member("b", ty.vec4<f32>(),
+ Vector{Location(0_a), BlendSrc(Source{{56, 78}}, 1_a)}),
+ });
+ Func("F", Empty, ty("S"), Vector{Return(Call("S"))},
+ Vector{Stage(ast::PipelineStage::kFragment)});
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: use of @blend_src requires all the output @location attributes of the entry point to be paired with a @blend_src attribute
+56:78 note: use of @blend_src here
+note: while analyzing entry point 'F')");
+}
+
class DualSourceBlendingExtensionTestWithParams : public ResolverTestWithParam<int> {
public:
DualSourceBlendingExtensionTestWithParams() {
@@ -224,7 +267,7 @@
// Rendering to multiple render targets while using dual source blending should fail.
TEST_P(DualSourceBlendingExtensionTestWithParams,
- MultipleRenderTargetsNotAllowed_BlendSrcThenNonZeroLocation) {
+ MultipleRenderTargetsNotAllowed_BlendSrcAndNoBlendSrc) {
// struct S {
// @location(0) @blend_src(0) a : vec4<f32>,
// @location(0) @blend_src(1) b : vec4<f32>,
@@ -241,9 +284,10 @@
Vector{Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- R"(1:2 error: pipeline cannot use both non-zero @blend_src and non-zero @location
-3:4 note: non-zero @location declared here
+ EXPECT_EQ(
+ r()->error(),
+ R"(3:4 error: use of @blend_src requires all the output @location attributes of the entry point to be paired with a @blend_src attribute
+1:2 note: use of @blend_src here
note: while analyzing entry point 'F')");
}
@@ -265,9 +309,10 @@
Vector{Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- R"(3:4 error: pipeline cannot use both non-zero @blend_src and non-zero @location
-1:2 note: non-zero @location declared here
+ EXPECT_EQ(
+ r()->error(),
+ R"(1:2 error: use of @blend_src requires all the output @location attributes of the entry point to be paired with a @blend_src attribute
+note: use of @blend_src here
5:6 note: while analyzing entry point 'F')");
}
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 907a3c4..0201bb4 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -1149,7 +1149,8 @@
Hashset<core::BuiltinValue, 4> builtins;
Hashset<std::pair<uint32_t, uint32_t>, 8> locations_and_blend_srcs;
const ast::LocationAttribute* first_nonzero_location = nullptr;
- const ast::BlendSrcAttribute* first_nonzero_blend_src = nullptr;
+ const ast::BlendSrcAttribute* first_blend_src = nullptr;
+ const ast::LocationAttribute* first_location_without_blend_src = nullptr;
Hashset<uint32_t, 4> colors;
enum class ParamOrRetType {
kParameter,
@@ -1311,16 +1312,28 @@
}
}
+ if (blend_src_attribute) {
+ first_blend_src = blend_src_attribute;
+ } else if (location_attribute) {
+ first_location_without_blend_src = location_attribute;
+ }
+
+ if (first_blend_src && first_location_without_blend_src) {
+ AddError(
+ "use of @blend_src requires all the output @location attributes of the entry "
+ "point to be paired with a @blend_src attribute",
+ first_location_without_blend_src->source);
+ AddNote("use of @blend_src here", first_blend_src->source);
+ return false;
+ }
+
if (location_attribute) {
if (!first_nonzero_location && location > 0u) {
first_nonzero_location = location_attribute;
}
- if (!first_nonzero_blend_src && blend_src > 0u) {
- first_nonzero_blend_src = blend_src_attribute;
- }
- if (first_nonzero_location && first_nonzero_blend_src) {
- AddError("pipeline cannot use both non-zero @blend_src and non-zero @location",
- first_nonzero_blend_src->source);
+ if (first_nonzero_location && first_blend_src) {
+ AddError("pipeline cannot use both a @blend_src and non-zero @location",
+ first_blend_src->source);
AddNote("non-zero @location declared here", first_nonzero_location->source);
return false;
}
@@ -1416,7 +1429,8 @@
builtins.Clear();
locations_and_blend_srcs.Clear();
first_nonzero_location = nullptr;
- first_nonzero_blend_src = nullptr;
+ first_blend_src = nullptr;
+ first_location_without_blend_src = nullptr;
if (!func->ReturnType()->Is<core::type::Void>()) {
if (!validate_entry_point_attributes(decl->return_type_attributes, func->ReturnType(),
@@ -2226,7 +2240,7 @@
return false;
}
- Hashset<std::pair<uint32_t, uint32_t>, 8> locations_and_blend_srcs;
+ Hashset<std::pair<uint32_t, std::optional<uint32_t>>, 8> locations_and_blend_srcs;
Hashset<uint32_t, 4> colors;
for (auto* member : str->Members()) {
if (auto* r = member->Type()->As<sem::Array>()) {
@@ -2330,17 +2344,16 @@
return false;
}
- // Ensure all locations and index pairs are unique
+ // Ensure all locations and optional blend_src pairs are unique
if (location_attribute) {
uint32_t location = member->Attributes().location.value();
- uint32_t blend_src = member->Attributes().blend_src.value_or(0);
+ std::optional<uint32_t> blend_src = member->Attributes().blend_src;
- std::pair<uint32_t, uint32_t> location_and_blend_src(location, blend_src);
- if (!locations_and_blend_srcs.Add(location_and_blend_src)) {
+ if (!locations_and_blend_srcs.Add(std::make_pair(location, blend_src))) {
StringStream err;
err << "@location(" << location << ") ";
- if (blend_src_attribute) {
- err << "@blend_src(" << blend_src << ") ";
+ if (blend_src) {
+ err << "@blend_src(" << blend_src.value() << ") ";
}
err << "appears multiple times";
AddError(err.str(), location_attribute->source);
diff --git a/src/tint/utils/containers/scope_stack.h b/src/tint/utils/containers/scope_stack.h
index 35a070e..e87bff5 100644
--- a/src/tint/utils/containers/scope_stack.h
+++ b/src/tint/utils/containers/scope_stack.h
@@ -31,6 +31,7 @@
#include "src/tint/utils/containers/hashmap.h"
#include "src/tint/utils/containers/vector.h"
+#include "src/tint/utils/macros/compiler.h"
namespace tint {
@@ -39,13 +40,22 @@
template <class K, class V>
class ScopeStack {
public:
+ ScopeStack() { Push(); }
+
/// Push a new scope on to the stack
- void Push() { stack_.Push({}); }
+ void Push() {
+ depth_++;
+ if (TINT_LIKELY(stack_.Length() >= depth_)) {
+ Top().Clear();
+ } else {
+ stack_.Push({});
+ }
+ }
/// Pop the scope off the top of the stack
void Pop() {
- if (stack_.Length() > 1) {
- stack_.Pop();
+ if (depth_ > 1) {
+ depth_--;
}
}
@@ -55,12 +65,11 @@
/// @returns the old value if there was an existing key at the top of the
/// stack, otherwise the zero initializer for type T.
V Set(const K& key, V val) {
- auto& back = stack_.Back();
- if (auto el = back.Find(key)) {
+ if (auto el = Top().Find(key)) {
std::swap(val, *el);
return val;
}
- back.Add(key, val);
+ Top().Add(key, val);
return {};
}
@@ -68,8 +77,8 @@
/// @param key the key to look for
/// @returns the value, or the zero initializer if the value was not found
V Get(const K& key) const {
- for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) {
- if (auto val = iter->Find(key)) {
+ for (size_t i = depth_; i > 0; i--) {
+ if (auto val = stack_[i - 1].Find(key)) {
return *val;
}
}
@@ -79,16 +88,24 @@
/// Return the top scope of the stack.
/// @returns the top scope of the stack
- const Hashmap<K, V, 4>& Top() const { return stack_.Back(); }
+ const Hashmap<K, V, 4>& Top() const { return stack_[depth_ - 1]; }
+
+ /// Return the top scope of the stack.
+ /// @returns the top scope of the stack
+ Hashmap<K, V, 4>& Top() { return stack_[depth_ - 1]; }
/// Clear the scope stack.
void Clear() {
- stack_.Clear();
- stack_.Push({});
+ depth_ = 1;
+ stack_.Resize(1);
+ stack_.Front().Clear();
}
private:
- Vector<Hashmap<K, V, 4>, 8> stack_ = {{}};
+ Vector<Hashmap<K, V, 4>, 8> stack_;
+ /// The active count in stack. We don't push and pop the stack to avoid frequent re-allocations
+ /// of the hashmaps.
+ size_t depth_ = 0;
};
} // namespace tint