transform: Propagate interpolate attributes
Transforms that handle entry point IO need to strip interpolate attributes when creating undecorated structures, and not strip them when recreating the IO parameters and return types. Bug: tint:746 Change-Id: Ifa7d3b9fe3950154689417ad387026ece3df81bb Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56243 Kokoro: Kokoro <noreply+kokoro@google.com> Auto-Submit: James Price <jrprice@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
545f4e0f77
commit
6a25bf944e
|
@ -84,7 +84,8 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
ast::DecorationList new_decorations = RemoveDecorations(
|
||||
&ctx, member->decorations(), [](const ast::Decoration* deco) {
|
||||
return deco
|
||||
->IsAnyOf<ast::BuiltinDecoration, ast::LocationDecoration>();
|
||||
->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
new_struct_members.push_back(
|
||||
ctx.dst->Member(ctx.Clone(member->symbol()),
|
||||
|
@ -155,6 +156,7 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
&ctx, member->Declaration()->decorations(),
|
||||
[](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
|
||||
|
@ -182,14 +184,9 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
func_const_initializer =
|
||||
ctx.dst->Construct(ctx.Clone(param_declared_ty), init_values);
|
||||
} else {
|
||||
ast::DecorationList new_decorations = RemoveDecorations(
|
||||
&ctx, param->Declaration()->decorations(),
|
||||
[](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
new_struct_members.push_back(ctx.dst->Member(
|
||||
param_name, ctx.Clone(param_declared_ty), new_decorations));
|
||||
new_struct_members.push_back(
|
||||
ctx.dst->Member(param_name, ctx.Clone(param_declared_ty),
|
||||
ctx.Clone(param->Declaration()->decorations())));
|
||||
func_const_initializer =
|
||||
ctx.dst->MemberAccessor(new_struct_param_symbol, param_name);
|
||||
}
|
||||
|
@ -249,6 +246,7 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
|||
&ctx, member->Declaration()->decorations(),
|
||||
[](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
auto symbol = ctx.Clone(member->Declaration()->symbol());
|
||||
|
|
|
@ -608,21 +608,103 @@ fn frag_main(tint_symbol : tint_symbol_1) -> tint_symbol_2 {
|
|||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(CanonicalizeEntryPointIOTest, InterpolateAttributes) {
|
||||
auto* src = R"(
|
||||
struct VertexOut {
|
||||
[[builtin(position)]] pos : vec4<f32>;
|
||||
[[location(1), interpolate(flat)]] loc1: f32;
|
||||
[[location(2), interpolate(linear, sample)]] loc2 : f32;
|
||||
[[location(3), interpolate(perspective, centroid)]] loc3 : f32;
|
||||
};
|
||||
|
||||
struct FragmentIn {
|
||||
[[location(1), interpolate(flat)]] loc1: f32;
|
||||
[[location(2), interpolate(linear, sample)]] loc2 : f32;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn vert_main() -> VertexOut {
|
||||
return VertexOut();
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main(inputs : FragmentIn,
|
||||
[[location(3), interpolate(perspective, centroid)]] loc3 : f32) {
|
||||
let x = inputs.loc1 + inputs.loc2 + loc3;
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
struct VertexOut {
|
||||
pos : vec4<f32>;
|
||||
loc1 : f32;
|
||||
loc2 : f32;
|
||||
loc3 : f32;
|
||||
};
|
||||
|
||||
struct FragmentIn {
|
||||
loc1 : f32;
|
||||
loc2 : f32;
|
||||
};
|
||||
|
||||
struct tint_symbol {
|
||||
[[location(1), interpolate(flat)]]
|
||||
loc1 : f32;
|
||||
[[location(2), interpolate(linear, sample)]]
|
||||
loc2 : f32;
|
||||
[[location(3), interpolate(perspective, centroid)]]
|
||||
loc3 : f32;
|
||||
[[builtin(position)]]
|
||||
pos : vec4<f32>;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn vert_main() -> tint_symbol {
|
||||
let tint_symbol_1 : VertexOut = VertexOut();
|
||||
return tint_symbol(tint_symbol_1.loc1, tint_symbol_1.loc2, tint_symbol_1.loc3, tint_symbol_1.pos);
|
||||
}
|
||||
|
||||
struct tint_symbol_3 {
|
||||
[[location(1), interpolate(flat)]]
|
||||
loc1 : f32;
|
||||
[[location(2), interpolate(linear, sample)]]
|
||||
loc2 : f32;
|
||||
[[location(3), interpolate(perspective, centroid)]]
|
||||
loc3 : f32;
|
||||
};
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main(tint_symbol_2 : tint_symbol_3) {
|
||||
let inputs : FragmentIn = FragmentIn(tint_symbol_2.loc1, tint_symbol_2.loc2);
|
||||
let loc3 : f32 = tint_symbol_2.loc3;
|
||||
let x = ((inputs.loc1 + inputs.loc2) + loc3);
|
||||
}
|
||||
)";
|
||||
|
||||
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]]
|
||||
struct FragmentInput {
|
||||
[[size(16), location(1)]] value : f32;
|
||||
[[builtin(position)]] [[align(32)]] coord : vec4<f32>;
|
||||
[[location(0), interpolate(linear, sample)]] [[align(128)]] loc0 : f32;
|
||||
};
|
||||
|
||||
struct FragmentOutput {
|
||||
[[size(16), location(1)]] value : f32;
|
||||
[[size(16), location(1), interpolate(flat)]] value : f32;
|
||||
};
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main(inputs : FragmentInput) -> FragmentOutput {
|
||||
return FragmentOutput(inputs.coord.x * inputs.value);
|
||||
return FragmentOutput(inputs.coord.x * inputs.value + inputs.loc0);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -633,6 +715,8 @@ struct FragmentInput {
|
|||
value : f32;
|
||||
[[align(32)]]
|
||||
coord : vec4<f32>;
|
||||
[[align(128)]]
|
||||
loc0 : f32;
|
||||
};
|
||||
|
||||
struct FragmentOutput {
|
||||
|
@ -641,6 +725,8 @@ struct FragmentOutput {
|
|||
};
|
||||
|
||||
struct tint_symbol_1 {
|
||||
[[location(0), interpolate(linear, sample)]]
|
||||
loc0 : f32;
|
||||
[[location(1)]]
|
||||
value : f32;
|
||||
[[builtin(position)]]
|
||||
|
@ -648,14 +734,14 @@ struct tint_symbol_1 {
|
|||
};
|
||||
|
||||
struct tint_symbol_2 {
|
||||
[[location(1)]]
|
||||
[[location(1), interpolate(flat)]]
|
||||
value : f32;
|
||||
};
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main(tint_symbol : tint_symbol_1) -> tint_symbol_2 {
|
||||
let inputs : FragmentInput = FragmentInput(tint_symbol.value, tint_symbol.coord);
|
||||
let tint_symbol_3 : FragmentOutput = FragmentOutput((inputs.coord.x * inputs.value));
|
||||
let inputs : FragmentInput = FragmentInput(tint_symbol.value, tint_symbol.coord, tint_symbol.loc0);
|
||||
let tint_symbol_3 : FragmentOutput = FragmentOutput(((inputs.coord.x * inputs.value) + inputs.loc0));
|
||||
return tint_symbol_2(tint_symbol_3.value);
|
||||
}
|
||||
)";
|
||||
|
|
|
@ -144,7 +144,8 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
|
|||
ast::DecorationList new_decorations = RemoveDecorations(
|
||||
&ctx, member->decorations(), [](const ast::Decoration* deco) {
|
||||
return deco
|
||||
->IsAnyOf<ast::BuiltinDecoration, ast::LocationDecoration>();
|
||||
->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
new_struct_members.push_back(
|
||||
ctx.dst->Member(ctx.Clone(member->symbol()),
|
||||
|
@ -313,6 +314,7 @@ Symbol Spirv::HoistToInputVariables(
|
|||
ast::DecorationList new_decorations =
|
||||
RemoveDecorations(&ctx, decorations, [](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
new_decorations.push_back(
|
||||
|
@ -370,6 +372,7 @@ void Spirv::HoistToOutputVariables(CloneContext& ctx,
|
|||
ast::DecorationList new_decorations =
|
||||
RemoveDecorations(&ctx, decorations, [](const ast::Decoration* deco) {
|
||||
return !deco->IsAnyOf<ast::BuiltinDecoration,
|
||||
ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
});
|
||||
new_decorations.push_back(
|
||||
|
|
|
@ -394,21 +394,100 @@ fn frag_main() {
|
|||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SpirvTest, HandleEntryPointIOTypes_InterpolateAttributes) {
|
||||
auto* src = R"(
|
||||
struct VertexOut {
|
||||
[[builtin(position)]] pos : vec4<f32>;
|
||||
[[location(1), interpolate(flat)]] loc1: f32;
|
||||
[[location(2), interpolate(linear, sample)]] loc2 : f32;
|
||||
[[location(3), interpolate(perspective, centroid)]] loc3 : f32;
|
||||
};
|
||||
|
||||
struct FragmentIn {
|
||||
[[location(1), interpolate(flat)]] loc1: f32;
|
||||
[[location(2), interpolate(linear, sample)]] loc2 : f32;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn vert_main() -> VertexOut {
|
||||
return VertexOut();
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main(inputs : FragmentIn,
|
||||
[[location(3), interpolate(perspective, centroid)]] loc3 : f32) {
|
||||
let x = inputs.loc1 + inputs.loc2 + loc3;
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
struct VertexOut {
|
||||
pos : vec4<f32>;
|
||||
loc1 : f32;
|
||||
loc2 : f32;
|
||||
loc3 : f32;
|
||||
};
|
||||
|
||||
struct FragmentIn {
|
||||
loc1 : f32;
|
||||
loc2 : f32;
|
||||
};
|
||||
|
||||
[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_1 : vec4<f32>;
|
||||
|
||||
[[location(1), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_2 : f32;
|
||||
|
||||
[[location(2), interpolate(linear, sample), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_3 : f32;
|
||||
|
||||
[[location(3), interpolate(perspective, centroid), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_4 : f32;
|
||||
|
||||
fn tint_symbol_5(tint_symbol : VertexOut) {
|
||||
tint_symbol_1 = tint_symbol.pos;
|
||||
tint_symbol_2 = tint_symbol.loc1;
|
||||
tint_symbol_3 = tint_symbol.loc2;
|
||||
tint_symbol_4 = tint_symbol.loc3;
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn vert_main() {
|
||||
tint_symbol_5(VertexOut());
|
||||
return;
|
||||
}
|
||||
|
||||
[[location(1), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_6 : f32;
|
||||
|
||||
[[location(2), interpolate(linear, sample), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_7 : f32;
|
||||
|
||||
[[location(3), interpolate(perspective, centroid), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_9 : f32;
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main() {
|
||||
let tint_symbol_8 : FragmentIn = FragmentIn(tint_symbol_6, tint_symbol_7);
|
||||
let x = ((tint_symbol_8.loc1 + tint_symbol_8.loc2) + tint_symbol_9);
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<Spirv>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SpirvTest, HandleEntryPointIOTypes_StructLayoutDecorations) {
|
||||
auto* src = R"(
|
||||
[[block]]
|
||||
struct FragmentInput {
|
||||
[[size(16), location(1)]] value : f32;
|
||||
[[builtin(position)]] [[align(32)]] coord : vec4<f32>;
|
||||
[[location(0), interpolate(linear, sample)]] [[align(128)]] loc0 : f32;
|
||||
};
|
||||
|
||||
struct FragmentOutput {
|
||||
[[size(16), location(1)]] value : f32;
|
||||
[[size(16), location(1), interpolate(flat)]] value : f32;
|
||||
};
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main(inputs : FragmentInput) -> FragmentOutput {
|
||||
return FragmentOutput(inputs.coord.x * inputs.value);
|
||||
return FragmentOutput(inputs.coord.x * inputs.value + inputs.loc0);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -419,6 +498,8 @@ struct FragmentInput {
|
|||
value : f32;
|
||||
[[align(32)]]
|
||||
coord : vec4<f32>;
|
||||
[[align(128)]]
|
||||
loc0 : f32;
|
||||
};
|
||||
|
||||
struct FragmentOutput {
|
||||
|
@ -430,16 +511,18 @@ struct FragmentOutput {
|
|||
|
||||
[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_1 : vec4<f32>;
|
||||
|
||||
[[location(1), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_4 : f32;
|
||||
[[location(0), interpolate(linear, sample), internal(disable_validation__ignore_storage_class)]] var<in> tint_symbol_2 : f32;
|
||||
|
||||
fn tint_symbol_5(tint_symbol_3 : FragmentOutput) {
|
||||
tint_symbol_4 = tint_symbol_3.value;
|
||||
[[location(1), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<out> tint_symbol_5 : f32;
|
||||
|
||||
fn tint_symbol_6(tint_symbol_4 : FragmentOutput) {
|
||||
tint_symbol_5 = tint_symbol_4.value;
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn frag_main() {
|
||||
let tint_symbol_2 : FragmentInput = FragmentInput(tint_symbol, tint_symbol_1);
|
||||
tint_symbol_5(FragmentOutput((tint_symbol_2.coord.x * tint_symbol_2.value)));
|
||||
let tint_symbol_3 : FragmentInput = FragmentInput(tint_symbol, tint_symbol_1, tint_symbol_2);
|
||||
tint_symbol_6(FragmentOutput(((tint_symbol_3.coord.x * tint_symbol_3.value) + tint_symbol_3.loc0)));
|
||||
return;
|
||||
}
|
||||
)";
|
||||
|
|
Loading…
Reference in New Issue