writer/msl: Only use [[invariant]] on MSL 2.1+
This is not supported on older versions.
This behavior was agreed by the WGSL core group:
https://github.com/gpuweb/gpuweb/issues/893#issuecomment-745537465
Bug: tint:1327
Change-Id: I1a0459068c438e625ae9d99fe4a044a96f2db57e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/71684
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index ddb3f17..4982639 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -240,6 +240,18 @@
line();
}
+ if (!invariant_define_name_.empty()) {
+ // 'invariant' attribute requires MSL 2.1 or higher.
+ // WGSL can ignore the invariant attribute on pre MSL 2.1 devices.
+ // See: https://github.com/gpuweb/gpuweb/issues/893#issuecomment-745537465
+ line(&helpers_) << "#if __METAL_VERSION__ >= 210";
+ line(&helpers_) << "#define " << invariant_define_name_ << " [[invariant]]";
+ line(&helpers_) << "#else";
+ line(&helpers_) << "#define " << invariant_define_name_;
+ line(&helpers_) << "#endif";
+ line(&helpers_);
+ }
+
if (!helpers_.lines.empty()) {
current_buffer_->Insert("", helpers_insertion_point++, 0);
current_buffer_->Insert(helpers_, helpers_insertion_point++, 0);
@@ -2504,8 +2516,10 @@
}
out << " [[" << attr << "]]";
} else if (deco->Is<ast::InvariantDecoration>()) {
- out << " [[invariant]]";
- has_invariant_ = true;
+ if (invariant_define_name_.empty()) {
+ invariant_define_name_ = UniqueIdentifier("TINT_INVARIANT");
+ }
+ out << " " << invariant_define_name_;
} else if (!deco->IsAnyOf<ast::StructMemberOffsetDecoration,
ast::StructMemberAlignDecoration,
ast::StructMemberSizeDecoration>()) {
diff --git a/src/writer/msl/generator_impl.h b/src/writer/msl/generator_impl.h
index 710b8e2..da99716 100644
--- a/src/writer/msl/generator_impl.h
+++ b/src/writer/msl/generator_impl.h
@@ -98,7 +98,7 @@
bool Generate();
/// @returns true if an invariant attribute was generated
- bool HasInvariant() { return has_invariant_; }
+ bool HasInvariant() { return !invariant_define_name_.empty(); }
/// @returns a map from entry point to list of required workgroup allocations
const std::unordered_map<std::string, std::vector<uint32_t>>&
@@ -410,8 +410,9 @@
/// class.
StorageClassToString atomicCompareExchangeWeak_;
- /// True if an invariant attribute has been generated.
- bool has_invariant_ = false;
+ /// Unique name of the 'TINT_INVARIANT' preprocessor define. Non-empty only if
+ /// an invariant attribute has been generated.
+ std::string invariant_define_name_;
/// True if matrix-packed_vector operator overloads have been generated.
bool matrix_packed_vector_overloads_ = false;
diff --git a/src/writer/msl/generator_impl_test.cc b/src/writer/msl/generator_impl_test.cc
index 121321c..8aa2891 100644
--- a/src/writer/msl/generator_impl_test.cc
+++ b/src/writer/msl/generator_impl_test.cc
@@ -95,8 +95,15 @@
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
using namespace metal;
+
+#if __METAL_VERSION__ >= 210
+#define TINT_INVARIANT [[invariant]]
+#else
+#define TINT_INVARIANT
+#endif
+
struct Out {
- float4 pos [[position]] [[invariant]];
+ float4 pos [[position]] TINT_INVARIANT;
};
vertex Out vert_main() {
diff --git a/test/shader_io/invariant.wgsl.expected.msl b/test/shader_io/invariant.wgsl.expected.msl
index c9eb97e..5982216 100644
--- a/test/shader_io/invariant.wgsl.expected.msl
+++ b/test/shader_io/invariant.wgsl.expected.msl
@@ -1,8 +1,15 @@
#include <metal_stdlib>
using namespace metal;
+
+#if __METAL_VERSION__ >= 210
+#define TINT_INVARIANT [[invariant]]
+#else
+#define TINT_INVARIANT
+#endif
+
struct tint_symbol_1 {
- float4 value [[position]] [[invariant]];
+ float4 value [[position]] TINT_INVARIANT;
};
float4 tint_symbol_inner() {
diff --git a/test/shader_io/invariant_struct_member.wgsl.expected.msl b/test/shader_io/invariant_struct_member.wgsl.expected.msl
index a2c44a7..c85f9a1 100644
--- a/test/shader_io/invariant_struct_member.wgsl.expected.msl
+++ b/test/shader_io/invariant_struct_member.wgsl.expected.msl
@@ -1,11 +1,18 @@
#include <metal_stdlib>
using namespace metal;
+
+#if __METAL_VERSION__ >= 210
+#define TINT_INVARIANT [[invariant]]
+#else
+#define TINT_INVARIANT
+#endif
+
struct Out {
float4 pos;
};
struct tint_symbol_1 {
- float4 pos [[position]] [[invariant]];
+ float4 pos [[position]] TINT_INVARIANT;
};
Out tint_symbol_inner() {