writer/msl: Implement invariant attribute
Report whether one was generated so that Dawn knows to use the `-fpreserve-invariance` compiler option. Bug: tint:772 Change-Id: Ife1eb05265646727dc864f12f983781af4df3777 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/57644 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
fd5829e5ea
commit
2c2aa2a76a
|
@ -84,9 +84,9 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
for (auto* member : struct_ty->members()) {
|
||||
ast::DecorationList new_decorations = RemoveDecorations(
|
||||
&ctx, member->decorations(), [](const ast::Decoration* deco) {
|
||||
return deco
|
||||
->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
return deco->IsAnyOf<
|
||||
ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::InvariantDecoration, ast::LocationDecoration>();
|
||||
});
|
||||
new_struct_members.push_back(
|
||||
ctx.dst->Member(ctx.Clone(member->symbol()),
|
||||
|
@ -156,9 +156,9 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
ast::DecorationList new_decorations = RemoveDecorations(
|
||||
&ctx, member->Declaration()->decorations(),
|
||||
[](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
return !deco->IsAnyOf<
|
||||
ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::InvariantDecoration, ast::LocationDecoration>();
|
||||
});
|
||||
|
||||
if (cfg->builtin_style == BuiltinStyle::kParameter &&
|
||||
|
@ -246,9 +246,9 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
ast::DecorationList new_decorations = RemoveDecorations(
|
||||
&ctx, member->Declaration()->decorations(),
|
||||
[](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
return !deco->IsAnyOf<
|
||||
ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::InvariantDecoration, ast::LocationDecoration>();
|
||||
});
|
||||
auto symbol = ctx.Clone(member->Declaration()->symbol());
|
||||
auto* member_ty = ctx.Clone(member->Declaration()->type());
|
||||
|
|
|
@ -691,6 +691,58 @@ fn frag_main(tint_symbol_2 : tint_symbol_3) {
|
|||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(CanonicalizeEntryPointIOTest, InvariantAttributes) {
|
||||
auto* src = R"(
|
||||
struct VertexOut {
|
||||
[[builtin(position), invariant]] pos : vec4<f32>;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main1() -> VertexOut {
|
||||
return VertexOut();
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main2() -> [[builtin(position), invariant]] vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
struct VertexOut {
|
||||
pos : vec4<f32>;
|
||||
};
|
||||
|
||||
struct tint_symbol {
|
||||
[[builtin(position), invariant]]
|
||||
pos : vec4<f32>;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main1() -> tint_symbol {
|
||||
let tint_symbol_1 : VertexOut = VertexOut();
|
||||
return tint_symbol(tint_symbol_1.pos);
|
||||
}
|
||||
|
||||
struct tint_symbol_2 {
|
||||
[[builtin(position), invariant]]
|
||||
value : vec4<f32>;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main2() -> tint_symbol_2 {
|
||||
return tint_symbol_2(vec4<f32>());
|
||||
}
|
||||
)";
|
||||
|
||||
DataMap data;
|
||||
data.Add<CanonicalizeEntryPointIO::Config>(
|
||||
CanonicalizeEntryPointIO::BuiltinStyle::kStructMember);
|
||||
auto got = Run<CanonicalizeEntryPointIO>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(CanonicalizeEntryPointIOTest, Struct_LayoutDecorations) {
|
||||
auto* src = R"(
|
||||
[[block]]
|
||||
|
|
|
@ -48,6 +48,7 @@ Result Generate(const Program* program, const Options& options) {
|
|||
result.success = impl->Generate();
|
||||
result.error = impl->error();
|
||||
result.msl = impl->result();
|
||||
result.has_invariant_attribute = impl->HasInvariant();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ struct Result {
|
|||
|
||||
/// True if the shader needs a UBO of buffer sizes.
|
||||
bool needs_storage_buffer_sizes = false;
|
||||
|
||||
/// True if the generated shader uses the invariant attribute.
|
||||
bool has_invariant_attribute = false;
|
||||
};
|
||||
|
||||
/// Generate MSL for a program, according to a set of configuration options. The
|
||||
|
|
|
@ -2134,6 +2134,9 @@ bool GeneratorImpl::EmitStructType(const sem::Struct* str) {
|
|||
return false;
|
||||
}
|
||||
out << " [[" << attr << "]]";
|
||||
} else if (deco->Is<ast::InvariantDecoration>()) {
|
||||
out << " [[invariant]]";
|
||||
has_invariant_ = true;
|
||||
} else if (!deco->IsAnyOf<ast::StructMemberOffsetDecoration,
|
||||
ast::StructMemberAlignDecoration,
|
||||
ast::StructMemberSizeDecoration>()) {
|
||||
|
|
|
@ -61,6 +61,9 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @returns true on successful generation; false otherwise
|
||||
bool Generate();
|
||||
|
||||
/// @returns true if an invariant attribute was generated
|
||||
bool HasInvariant() { return has_invariant_; }
|
||||
|
||||
/// Handles generating a declared type
|
||||
/// @param ty the declared type to generate
|
||||
/// @returns true if the declared type was emitted
|
||||
|
@ -302,6 +305,9 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// Name of atomicCompareExchangeWeak() helper for the given pointer storage
|
||||
/// class.
|
||||
StorageClassToString atomicCompareExchangeWeak_;
|
||||
|
||||
/// True if an invariant attribute has been generated.
|
||||
bool has_invariant_ = false;
|
||||
};
|
||||
|
||||
} // namespace msl
|
||||
|
|
|
@ -88,6 +88,55 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
MslBuiltinData{ast::Builtin::kSampleIndex, "sample_id"},
|
||||
MslBuiltinData{ast::Builtin::kSampleMask, "sample_mask"}));
|
||||
|
||||
TEST_F(MslGeneratorImplTest, HasInvariantAttribute_True) {
|
||||
auto* out = Structure(
|
||||
"Out", {Member("pos", ty.vec4<f32>(),
|
||||
{Builtin(ast::Builtin::kPosition), Invariant()})});
|
||||
Func("vert_main", ast::VariableList{}, ty.Of(out),
|
||||
{Return(Construct(ty.Of(out)))}, {Stage(ast::PipelineStage::kVertex)});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_TRUE(gen.HasInvariant());
|
||||
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
struct Out {
|
||||
float4 pos [[position]] [[invariant]];
|
||||
};
|
||||
|
||||
vertex Out vert_main() {
|
||||
return {};
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(MslGeneratorImplTest, HasInvariantAttribute_False) {
|
||||
auto* out = Structure("Out", {Member("pos", ty.vec4<f32>(),
|
||||
{Builtin(ast::Builtin::kPosition)})});
|
||||
Func("vert_main", ast::VariableList{}, ty.Of(out),
|
||||
{Return(Construct(ty.Of(out)))}, {Stage(ast::PipelineStage::kVertex)});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_FALSE(gen.HasInvariant());
|
||||
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
struct Out {
|
||||
float4 pos [[position]];
|
||||
};
|
||||
|
||||
vertex Out vert_main() {
|
||||
return {};
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace msl
|
||||
} // namespace writer
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
SKIP: FAILED
|
||||
#include <metal_stdlib>
|
||||
|
||||
../../src/writer/msl/generator_impl.cc:1990 internal compiler error: unhandled struct member attribute: invariant
|
||||
********************************************************************
|
||||
* The tint shader compiler has encountered an unexpected error. *
|
||||
* *
|
||||
* Please help us fix this issue by submitting a bug report at *
|
||||
* crbug.com/tint with the source program that triggered the bug. *
|
||||
********************************************************************
|
||||
using namespace metal;
|
||||
struct tint_symbol_1 {
|
||||
float4 value [[position]] [[invariant]];
|
||||
};
|
||||
|
||||
vertex tint_symbol_1 tint_symbol() {
|
||||
tint_symbol_1 const tint_symbol_2 = {.value=float4()};
|
||||
return tint_symbol_2;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
SKIP: FAILED
|
||||
#include <metal_stdlib>
|
||||
|
||||
../../src/writer/msl/generator_impl.cc:1990 internal compiler error: unhandled struct member attribute: invariant
|
||||
********************************************************************
|
||||
* The tint shader compiler has encountered an unexpected error. *
|
||||
* *
|
||||
* Please help us fix this issue by submitting a bug report at *
|
||||
* crbug.com/tint with the source program that triggered the bug. *
|
||||
********************************************************************
|
||||
using namespace metal;
|
||||
struct Out {
|
||||
float4 pos;
|
||||
};
|
||||
struct tint_symbol_1 {
|
||||
float4 pos [[position]] [[invariant]];
|
||||
};
|
||||
|
||||
vertex tint_symbol_1 tint_symbol() {
|
||||
Out const tint_symbol_2 = {};
|
||||
tint_symbol_1 const tint_symbol_3 = {.pos=tint_symbol_2.pos};
|
||||
return tint_symbol_3;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue