Require vertex shaders to return builtin(position)

Fixup many tests that were just returning void.

Change-Id: Ic93db5b187c679dc1c24a356b48a64e41ba9a823
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48560
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-04-21 16:13:42 +00:00 committed by Commit Bot service account
parent 98c2cf0e91
commit 2dd393729c
26 changed files with 357 additions and 281 deletions

View File

@ -771,7 +771,7 @@ TEST_F(InspectorGetEntryPointTest, NoEntryPoints) {
TEST_F(InspectorGetEntryPointTest, OneEntryPoint) { TEST_F(InspectorGetEntryPointTest, OneEntryPoint) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"foo", ast::DecorationList{ "foo", ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
// TODO(dsinclair): Update to run the namer transform when available. // TODO(dsinclair): Update to run the namer transform when available.
@ -784,13 +784,13 @@ TEST_F(InspectorGetEntryPointTest, OneEntryPoint) {
ASSERT_EQ(1u, result.size()); ASSERT_EQ(1u, result.size());
EXPECT_EQ("foo", result[0].name); EXPECT_EQ("foo", result[0].name);
EXPECT_EQ("foo", result[0].remapped_name); EXPECT_EQ("foo", result[0].remapped_name);
EXPECT_EQ(ast::PipelineStage::kVertex, result[0].stage); EXPECT_EQ(ast::PipelineStage::kFragment, result[0].stage);
} }
TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) { TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"foo", ast::DecorationList{ "foo", ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
@ -808,7 +808,7 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) {
ASSERT_EQ(2u, result.size()); ASSERT_EQ(2u, result.size());
EXPECT_EQ("foo", result[0].name); EXPECT_EQ("foo", result[0].name);
EXPECT_EQ("foo", result[0].remapped_name); EXPECT_EQ("foo", result[0].remapped_name);
EXPECT_EQ(ast::PipelineStage::kVertex, result[0].stage); EXPECT_EQ(ast::PipelineStage::kFragment, result[0].stage);
EXPECT_EQ("bar", result[1].name); EXPECT_EQ("bar", result[1].name);
EXPECT_EQ("bar", result[1].remapped_name); EXPECT_EQ("bar", result[1].remapped_name);
EXPECT_EQ(ast::PipelineStage::kCompute, result[1].stage); EXPECT_EQ(ast::PipelineStage::kCompute, result[1].stage);
@ -820,7 +820,7 @@ TEST_F(InspectorGetEntryPointTest, MixFunctionsAndEntryPoints) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"foo", {"func"}, "foo", {"func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kCompute),
}); });
MakeCallerBodyFunction( MakeCallerBodyFunction(
@ -839,7 +839,7 @@ TEST_F(InspectorGetEntryPointTest, MixFunctionsAndEntryPoints) {
ASSERT_EQ(2u, result.size()); ASSERT_EQ(2u, result.size());
EXPECT_EQ("foo", result[0].name); EXPECT_EQ("foo", result[0].name);
EXPECT_EQ("foo", result[0].remapped_name); EXPECT_EQ("foo", result[0].remapped_name);
EXPECT_EQ(ast::PipelineStage::kVertex, result[0].stage); EXPECT_EQ(ast::PipelineStage::kCompute, result[0].stage);
EXPECT_EQ("bar", result[1].name); EXPECT_EQ("bar", result[1].name);
EXPECT_EQ("bar", result[1].remapped_name); EXPECT_EQ("bar", result[1].remapped_name);
EXPECT_EQ(ast::PipelineStage::kFragment, result[1].stage); EXPECT_EQ(ast::PipelineStage::kFragment, result[1].stage);
@ -848,7 +848,7 @@ TEST_F(InspectorGetEntryPointTest, MixFunctionsAndEntryPoints) {
TEST_F(InspectorGetEntryPointTest, DefaultWorkgroupSize) { TEST_F(InspectorGetEntryPointTest, DefaultWorkgroupSize) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"foo", ast::DecorationList{ "foo", ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kCompute),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -890,7 +890,7 @@ TEST_F(InspectorGetEntryPointTest, NoInOutVariables) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"foo", {"func"}, "foo", {"func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1172,7 +1172,7 @@ TEST_F(InspectorGetEntryPointTest, EntryPointInOutVariables_Legacy) {
MakeInOutVariableBodyFunction( MakeInOutVariableBodyFunction(
"foo", {{"in_var", "out_var"}}, "foo", {{"in_var", "out_var"}},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1204,7 +1204,7 @@ TEST_F(InspectorGetEntryPointTest, FunctionInOutVariables_Legacy) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"foo", {"func"}, "foo", {"func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1236,7 +1236,7 @@ TEST_F(InspectorGetEntryPointTest, RepeatedInOutVariables_Legacy) {
MakeInOutVariableCallerBodyFunction( MakeInOutVariableCallerBodyFunction(
"foo", "func", {{"in_var", "out_var"}}, "foo", "func", {{"in_var", "out_var"}},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1266,7 +1266,7 @@ TEST_F(InspectorGetEntryPointTest, EntryPointMultipleInOutVariables_Legacy) {
MakeInOutVariableBodyFunction( MakeInOutVariableBodyFunction(
"foo", {{"in_var", "out_var"}, {"in2_var", "out2_var"}}, "foo", {{"in_var", "out_var"}, {"in2_var", "out2_var"}},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1307,7 +1307,7 @@ TEST_F(InspectorGetEntryPointTest, FunctionMultipleInOutVariables_Legacy) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"foo", {"func"}, "foo", {"func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1345,7 +1345,7 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutVariables_Legacy) {
MakeInOutVariableBodyFunction( MakeInOutVariableBodyFunction(
"foo", {{"in_var", "out2_var"}}, "foo", {{"in_var", "out2_var"}},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
MakeInOutVariableBodyFunction( MakeInOutVariableBodyFunction(
@ -1405,7 +1405,7 @@ TEST_F(InspectorGetEntryPointTest,
MakeInOutVariableCallerBodyFunction( MakeInOutVariableCallerBodyFunction(
"foo", "func", {{"in_var", "out_var"}}, "foo", "func", {{"in_var", "out_var"}},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
MakeCallerBodyFunction( MakeCallerBodyFunction(
@ -1476,7 +1476,7 @@ TEST_F(InspectorGetEntryPointTest, BuiltInsNotStageVariables_Legacy) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"foo", {"func"}, "foo", {"func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
// TODO(dsinclair): Update to run the namer transform when available. // TODO(dsinclair): Update to run the namer transform when available.
@ -1670,7 +1670,7 @@ TEST_F(InspectorGetResourceBindingsTest, Empty) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {}, "ep_func", {},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1739,7 +1739,7 @@ TEST_F(InspectorGetResourceBindingsTest, Simple) {
{"ub_func", "sb_func", "rosb_func", "s_func", "cs_func", "st_func", {"ub_func", "sb_func", "rosb_func", "s_func", "cs_func", "st_func",
"rost_func"}, "rost_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1812,7 +1812,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, NonEntryPointFunc) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"ub_func"}, "ep_func", {"ub_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1837,7 +1837,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, MissingBlockDeco) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"ub_func"}, "ep_func", {"ub_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1857,7 +1857,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, Simple) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"ub_func"}, "ep_func", {"ub_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1885,7 +1885,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleMembers) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"ub_func"}, "ep_func", {"ub_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1913,7 +1913,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, ContainingPadding) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"ub_func"}, "ep_func", {"ub_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1955,7 +1955,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleUniformBuffers) {
FuncCall("ub_baz_func"), FuncCall("ub_baz_func"),
create<ast::ReturnStatement>()}, create<ast::ReturnStatement>()},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1999,7 +1999,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, ContainingArray) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"ub_func"}, "ep_func", {"ub_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2028,7 +2028,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, Simple) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2058,7 +2058,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, MultipleMembers) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2105,7 +2105,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, MultipleStorageBuffers) {
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2148,7 +2148,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, ContainingArray) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2177,7 +2177,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, ContainingRuntimeArray) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2207,7 +2207,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, ContainingPadding) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2236,7 +2236,7 @@ TEST_F(InspectorGetStorageBufferResourceBindingsTest, SkipReadOnly) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2258,7 +2258,7 @@ TEST_F(InspectorGetReadOnlyStorageBufferResourceBindingsTest, Simple) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2306,7 +2306,7 @@ TEST_F(InspectorGetReadOnlyStorageBufferResourceBindingsTest,
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2349,7 +2349,7 @@ TEST_F(InspectorGetReadOnlyStorageBufferResourceBindingsTest, ContainingArray) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2379,7 +2379,7 @@ TEST_F(InspectorGetReadOnlyStorageBufferResourceBindingsTest,
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2408,7 +2408,7 @@ TEST_F(InspectorGetReadOnlyStorageBufferResourceBindingsTest, SkipNonReadOnly) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"sb_func"}, "ep_func", {"sb_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2428,7 +2428,7 @@ TEST_F(InspectorGetSamplerResourceBindingsTest, Simple) {
MakeSamplerReferenceBodyFunction( MakeSamplerReferenceBodyFunction(
"ep", "foo_texture", "foo_sampler", "foo_coords", ty.f32(), "ep", "foo_texture", "foo_sampler", "foo_coords", ty.f32(),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2444,8 +2444,9 @@ TEST_F(InspectorGetSamplerResourceBindingsTest, Simple) {
TEST_F(InspectorGetSamplerResourceBindingsTest, NoSampler) { TEST_F(InspectorGetSamplerResourceBindingsTest, NoSampler) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"ep_func", ast::DecorationList{ "ep_func",
create<ast::StageDecoration>(ast::PipelineStage::kVertex), ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2469,7 +2470,7 @@ TEST_F(InspectorGetSamplerResourceBindingsTest, InFunction) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"foo_func"}, "ep_func", {"foo_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2493,7 +2494,7 @@ TEST_F(InspectorGetSamplerResourceBindingsTest, UnknownEntryPoint) {
MakeSamplerReferenceBodyFunction( MakeSamplerReferenceBodyFunction(
"ep", "foo_texture", "foo_sampler", "foo_coords", ty.f32(), "ep", "foo_texture", "foo_sampler", "foo_coords", ty.f32(),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2512,7 +2513,7 @@ TEST_F(InspectorGetSamplerResourceBindingsTest, SkipsComparisonSamplers) {
MakeComparisonSamplerReferenceBodyFunction( MakeComparisonSamplerReferenceBodyFunction(
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", ty.f32(), "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", ty.f32(),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2533,7 +2534,7 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, Simple) {
MakeComparisonSamplerReferenceBodyFunction( MakeComparisonSamplerReferenceBodyFunction(
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", ty.f32(), "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", ty.f32(),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2550,8 +2551,9 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, Simple) {
TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, NoSampler) { TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, NoSampler) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"ep_func", ast::DecorationList{ "ep_func",
create<ast::StageDecoration>(ast::PipelineStage::kVertex), ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2576,7 +2578,7 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, InFunction) {
MakeCallerBodyFunction( MakeCallerBodyFunction(
"ep_func", {"foo_func"}, "ep_func", {"foo_func"},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2601,7 +2603,7 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, UnknownEntryPoint) {
MakeComparisonSamplerReferenceBodyFunction( MakeComparisonSamplerReferenceBodyFunction(
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", ty.f32(), "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", ty.f32(),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2620,7 +2622,7 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, SkipsSamplers) {
MakeSamplerReferenceBodyFunction( MakeSamplerReferenceBodyFunction(
"ep", "foo_texture", "foo_sampler", "foo_coords", ty.f32(), "ep", "foo_texture", "foo_sampler", "foo_coords", ty.f32(),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2634,7 +2636,7 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, SkipsSamplers) {
TEST_F(InspectorGetSampledTextureResourceBindingsTest, Empty) { TEST_F(InspectorGetSampledTextureResourceBindingsTest, Empty) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"foo", ast::DecorationList{ "foo", ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2657,7 +2659,7 @@ TEST_P(InspectorGetSampledTextureResourceBindingsTestWithParam, textureSample) {
"ep", "foo_texture", "foo_sampler", "foo_coords", "ep", "foo_texture", "foo_sampler", "foo_coords",
GetBaseType(GetParam().sampled_kind), GetBaseType(GetParam().sampled_kind),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2716,7 +2718,7 @@ TEST_P(InspectorGetSampledArrayTextureResourceBindingsTestWithParam,
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index", "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
GetBaseType(GetParam().sampled_kind), GetBaseType(GetParam().sampled_kind),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2761,7 +2763,7 @@ TEST_P(InspectorGetMultisampledTextureResourceBindingsTestWithParam,
"foo_coords", "foo_sample_index")), "foo_coords", "foo_sample_index")),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2805,7 +2807,7 @@ INSTANTIATE_TEST_SUITE_P(
TEST_F(InspectorGetMultisampledArrayTextureResourceBindingsTest, Empty) { TEST_F(InspectorGetMultisampledArrayTextureResourceBindingsTest, Empty) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"foo", ast::DecorationList{ "foo", ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2830,7 +2832,7 @@ TEST_P(InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam,
"ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index", "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
GetBaseType(GetParam().sampled_kind), GetBaseType(GetParam().sampled_kind),
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2867,7 +2869,7 @@ INSTANTIATE_TEST_SUITE_P(
TEST_F(InspectorGetStorageTextureResourceBindingsTest, Empty) { TEST_F(InspectorGetStorageTextureResourceBindingsTest, Empty) {
MakeEmptyBodyFunction( MakeEmptyBodyFunction(
"ep", ast::DecorationList{ "ep", ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -2924,7 +2926,7 @@ TEST_P(InspectorGetStorageTextureResourceBindingsTestWithParam, Simple) {
MakeStorageTextureBodyFunction( MakeStorageTextureBodyFunction(
"ep", "st_var", dim_type, "ep", "st_var", dim_type,
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -3026,7 +3028,7 @@ TEST_P(InspectorGetDepthTextureResourceBindingsTestWithParam,
Call("textureDimensions", "dt", "dt_level")), Call("textureDimensions", "dt", "dt_level")),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
Inspector& inspector = Build(); Inspector& inspector = Build();

View File

@ -36,7 +36,7 @@ TEST_F(ParserTest, Parses) {
Source::File file("test.wgsl", R"( Source::File file("test.wgsl", R"(
[[location(0)]] var<out> gl_FragColor : vec4<f32>; [[location(0)]] var<out> gl_FragColor : vec4<f32>;
[[stage(vertex)]] [[stage(fragment)]]
fn main() { fn main() {
gl_FragColor = vec4<f32>(.4, .2, .3, 1.); gl_FragColor = vec4<f32>(.4, .2, .3, 1.);
} }

View File

@ -94,7 +94,7 @@ TEST_P(FunctionReturnTypeDecorationTest, IsValid) {
Func("main", ast::VariableList{}, ty.f32(), Func("main", ast::VariableList{}, ty.f32(),
ast::StatementList{create<ast::ReturnStatement>(Expr(1.f))}, ast::StatementList{create<ast::ReturnStatement>(Expr(1.f))},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex)}, create<ast::StageDecoration>(ast::PipelineStage::kCompute)},
ast::DecorationList{createDecoration({}, *this, params.kind)}); ast::DecorationList{createDecoration({}, *this, params.kind)});
if (params.should_pass) { if (params.should_pass) {

View File

@ -32,7 +32,7 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Location) {
// [[stage(vertex)]] // [[stage(vertex)]]
// fn main() -> [[location(0)]] f32 { return 1.0; } // fn main() -> [[location(0)]] f32 { return 1.0; }
Func(Source{{12, 34}}, "main", {}, ty.f32(), {Return(Expr(1.0f))}, Func(Source{{12, 34}}, "main", {}, ty.f32(), {Return(Expr(1.0f))},
{Stage(ast::PipelineStage::kVertex)}, {Location(0)}); {Stage(ast::PipelineStage::kFragment)}, {Location(0)});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -500,5 +500,17 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateLocation) {
12:34 note: while analysing entry point main)"); 12:34 note: while analysing entry point main)");
} }
TEST_F(ResolverEntryPointValidationTest, VertexShaderMustReturnPosition) {
// [[stage(vertex)]]
// fn main() {}
Func(Source{{12, 34}}, "main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kVertex)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: a vertex shader must include the 'position' builtin "
"in its return type");
}
} // namespace } // namespace
} // namespace tint } // namespace tint

View File

@ -47,7 +47,6 @@ TEST_F(ResolverFunctionValidationTest, FunctionNamesMustBeUnique_fail) {
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
VoidFunctionEndWithoutReturnStatement_Pass) { VoidFunctionEndWithoutReturnStatement_Pass) {
// [[stage(vertex)]]
// fn func { var a:i32 = 2; } // fn func { var a:i32 = 2; }
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
@ -55,9 +54,6 @@ TEST_F(ResolverFunctionValidationTest,
ty.void_(), ty.void_(),
ast::StatementList{ ast::StatementList{
create<ast::VariableDeclStatement>(var), create<ast::VariableDeclStatement>(var),
},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
}); });
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -82,14 +78,10 @@ TEST_F(ResolverFunctionValidationTest, FunctionEndWithoutReturnStatement_Fail) {
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
VoidFunctionEndWithoutReturnStatementEmptyBody_Pass) { VoidFunctionEndWithoutReturnStatementEmptyBody_Pass) {
// [[stage(vertex)]]
// fn func {} // fn func {}
Func(Source{Source::Location{12, 34}}, "func", ast::VariableList{}, Func(Source{Source::Location{12, 34}}, "func", ast::VariableList{},
ty.void_(), ast::StatementList{}, ty.void_(), ast::StatementList{});
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -109,15 +101,11 @@ TEST_F(ResolverFunctionValidationTest,
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
FunctionTypeMustMatchReturnStatementType_Pass) { FunctionTypeMustMatchReturnStatementType_Pass) {
// [[stage(vertex)]]
// fn func { return; } // fn func { return; }
Func("func", ast::VariableList{}, ty.void_(), Func("func", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
}); });
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -148,10 +136,6 @@ TEST_F(ResolverFunctionValidationTest,
Expr(2.f)), Expr(2.f)),
}, },
ast::DecorationList{}); ast::DecorationList{});
Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -183,10 +167,6 @@ TEST_F(ResolverFunctionValidationTest,
Expr(2.f)), Expr(2.f)),
}, },
ast::DecorationList{}); ast::DecorationList{});
Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -202,10 +182,6 @@ TEST_F(ResolverFunctionValidationTest,
Expr(2u)), Expr(2u)),
}, },
ast::DecorationList{}); ast::DecorationList{});
Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),

View File

@ -521,7 +521,8 @@ bool Resolver::ValidateParameter(const ast::Variable* param) {
return ValidateVariable(param); return ValidateVariable(param);
} }
bool Resolver::ValidateFunction(const ast::Function* func) { bool Resolver::ValidateFunction(const ast::Function* func,
const FunctionInfo* info) {
if (symbol_to_function_.find(func->symbol()) != symbol_to_function_.end()) { if (symbol_to_function_.find(func->symbol()) != symbol_to_function_.end()) {
diagnostics_.add_error("v-0016", diagnostics_.add_error("v-0016",
"function names must be unique '" + "function names must be unique '" +
@ -564,7 +565,7 @@ bool Resolver::ValidateFunction(const ast::Function* func) {
} }
if (func->IsEntryPoint()) { if (func->IsEntryPoint()) {
if (!ValidateEntryPoint(func)) { if (!ValidateEntryPoint(func, info)) {
return false; return false;
} }
} }
@ -572,7 +573,8 @@ bool Resolver::ValidateFunction(const ast::Function* func) {
return true; return true;
} }
bool Resolver::ValidateEntryPoint(const ast::Function* func) { bool Resolver::ValidateEntryPoint(const ast::Function* func,
const FunctionInfo* info) {
auto stage_deco_count = 0; auto stage_deco_count = 0;
for (auto* deco : func->decorations()) { for (auto* deco : func->decorations()) {
if (deco->Is<ast::StageDecoration>()) { if (deco->Is<ast::StageDecoration>()) {
@ -750,9 +752,13 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func) {
} }
} }
if (!func->return_type()->Is<sem::Void>()) { // Clear IO sets after parameter validation. Builtin and location attributes
// in return types should be validated independently from those used in
// parameters.
builtins.clear(); builtins.clear();
locations.clear(); locations.clear();
if (!func->return_type()->Is<sem::Void>()) {
if (!validate_entry_point_decorations(func->return_type_decorations(), if (!validate_entry_point_decorations(func->return_type_decorations(),
func->return_type(), func->source(), func->return_type(), func->source(),
ParamOrRetType::kReturnType)) { ParamOrRetType::kReturnType)) {
@ -760,6 +766,28 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func) {
} }
} }
if (func->pipeline_stage() == ast::PipelineStage::kVertex &&
builtins.count(ast::Builtin::kPosition) == 0) {
// Check module-scope variables, as the SPIR-V sanitizer generates these.
bool found = false;
for (auto* var : info->referenced_module_vars) {
if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
var->declaration->decorations())) {
if (builtin->value() == ast::Builtin::kPosition) {
found = true;
break;
}
}
}
if (!found) {
diagnostics_.add_error(
"a vertex shader must include the 'position' builtin in its return "
"type",
func->source());
return false;
}
}
return true; return true;
} }
@ -863,7 +891,7 @@ bool Resolver::Function(ast::Function* func) {
Mark(deco); Mark(deco);
} }
if (!ValidateFunction(func)) { if (!ValidateFunction(func, func_info)) {
return false; return false;
} }

View File

@ -238,8 +238,8 @@ class Resolver {
// Each return true on success, false on failure. // Each return true on success, false on failure.
bool ValidateAssignment(const ast::AssignmentStatement* a); bool ValidateAssignment(const ast::AssignmentStatement* a);
bool ValidateBinary(ast::BinaryExpression* expr); bool ValidateBinary(ast::BinaryExpression* expr);
bool ValidateEntryPoint(const ast::Function* func); bool ValidateEntryPoint(const ast::Function* func, const FunctionInfo* info);
bool ValidateFunction(const ast::Function* func); bool ValidateFunction(const ast::Function* func, const FunctionInfo* info);
bool ValidateGlobalVariable(const VariableInfo* var); bool ValidateGlobalVariable(const VariableInfo* var);
bool ValidateMatrixConstructor(const sem::Matrix* matrix_type, bool ValidateMatrixConstructor(const sem::Matrix* matrix_type,
const ast::ExpressionList& values); const ast::ExpressionList& values);

View File

@ -1532,7 +1532,7 @@ TEST_F(ResolverTest, Function_EntryPoints_StageDecoration) {
create<ast::AssignmentStatement>(Expr("call_b"), Call("b")), create<ast::AssignmentStatement>(Expr("call_b"), Call("b")),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kCompute),
}); });
auto* ep_2 = auto* ep_2 =
@ -1541,7 +1541,7 @@ TEST_F(ResolverTest, Function_EntryPoints_StageDecoration) {
create<ast::AssignmentStatement>(Expr("call_c"), Call("c")), create<ast::AssignmentStatement>(Expr("call_c"), Call("c")),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kCompute),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -1620,7 +1620,7 @@ TEST_F(ResolverTest, Function_EntryPoints_LinearTime) {
create<ast::CallStatement>(Call(fn_b(0))), create<ast::CallStatement>(Call(fn_b(0))),
}, },
{ {
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kCompute),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();

View File

@ -65,11 +65,12 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointReturnType) {
} }
TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) {
auto* s = Structure( auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
"S", {Member("a", ty.f32(), {create<ast::LocationDecoration>(0)})});
Func("main", {Param("param", s)}, ty.void_(), {}, Func("main", {Param("param", s)}, ty.vec4<f32>(),
{create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); {Return(Construct(ty.vec4<f32>()))},
{Stage(ast::PipelineStage::kVertex)},
{Builtin(ast::Builtin::kPosition)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -81,10 +82,10 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderReturnType) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderReturnType) {
auto* s = Structure( auto* s = Structure(
"S", {Member("a", ty.f32(), {create<ast::LocationDecoration>(0)})}); "S", {Member("a", ty.f32(), {Builtin(ast::Builtin::kPosition)})});
Func("main", {}, s, {Return(Construct(s, Expr(0.f)))}, Func("main", {}, s, {Return(Construct(s, Expr(0.f)))},
{create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -142,13 +143,13 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsComputeShaderParam) {
TEST_F(ResolverPipelineStageUseTest, StructUsedMultipleStages) { TEST_F(ResolverPipelineStageUseTest, StructUsedMultipleStages) {
auto* s = Structure( auto* s = Structure(
"S", {Member("a", ty.f32(), {create<ast::LocationDecoration>(0)})}); "S", {Member("a", ty.f32(), {Builtin(ast::Builtin::kPosition)})});
Func("vert_main", {Param("param", s)}, s, {Return(Construct(s, Expr(0.f)))}, Func("vert_main", {Param("param", s)}, s, {Return(Construct(s, Expr(0.f)))},
{create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func("frag_main", {Param("param", s)}, ty.void_(), {}, Func("frag_main", {Param("param", s)}, ty.void_(), {},
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();

View File

@ -112,9 +112,7 @@ TEST_F(ResolverTypeValidationTest,
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f)); auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f));
Func("my_func", ast::VariableList{}, ty.void_(), {Decl(var)}, Func("my_func", ast::VariableList{}, ty.void_(), {Decl(var)});
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex)});
Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f)); Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f));
@ -277,9 +275,6 @@ TEST_F(ResolverTypeValidationTest,
ast::StatementList{ ast::StatementList{
create<ast::VariableDeclStatement>(Source{{13, 34}}, var1), create<ast::VariableDeclStatement>(Source{{13, 34}}, var1),
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
}); });
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -280,9 +280,6 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) {
create<ast::AssignmentStatement>(Source{Source::Location{12, 34}}, create<ast::AssignmentStatement>(Source{Source::Location{12, 34}},
Expr("global_var"), Expr(3.14f)), Expr("global_var"), Expr(3.14f)),
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
}); });
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -32,7 +32,7 @@ struct SB {
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var len : u32 = arrayLength(sb.arr); var len : u32 = arrayLength(sb.arr);
} }
@ -50,7 +50,7 @@ fn tint_symbol(buffer : SB, result : ptr<function, u32>)
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var tint_symbol_1 : u32 = 0u; var tint_symbol_1 : u32 = 0u;
tint_symbol(sb, tint_symbol_1); tint_symbol(sb, tint_symbol_1);
@ -74,7 +74,7 @@ struct SB {
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var a : u32 = arrayLength(sb.arr); var a : u32 = arrayLength(sb.arr);
var b : u32 = arrayLength(sb.arr); var b : u32 = arrayLength(sb.arr);
@ -94,7 +94,7 @@ fn tint_symbol(buffer : SB, result : ptr<function, u32>)
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var tint_symbol_1 : u32 = 0u; var tint_symbol_1 : u32 = 0u;
tint_symbol(sb, tint_symbol_1); tint_symbol(sb, tint_symbol_1);
@ -121,7 +121,7 @@ struct SB {
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var len : u32 = arrayLength(sb.arr); var len : u32 = arrayLength(sb.arr);
} }
@ -140,7 +140,7 @@ fn tint_symbol(buffer : SB, result : ptr<function, u32>)
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var tint_symbol_1 : u32 = 0u; var tint_symbol_1 : u32 = 0u;
tint_symbol(sb, tint_symbol_1); tint_symbol(sb, tint_symbol_1);
@ -164,7 +164,7 @@ struct SB {
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
if (true) { if (true) {
var len : u32 = arrayLength(sb.arr); var len : u32 = arrayLength(sb.arr);
@ -188,7 +188,7 @@ fn tint_symbol(buffer : SB, result : ptr<function, u32>)
var<storage> sb : [[access(read)]] SB; var<storage> sb : [[access(read)]] SB;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
if (true) { if (true) {
var tint_symbol_1 : u32 = 0u; var tint_symbol_1 : u32 = 0u;
@ -229,7 +229,7 @@ var<storage> sb1 : [[access(read)]] SB1;
var<storage> sb2 : [[access(read)]] SB2; var<storage> sb2 : [[access(read)]] SB2;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var len1 : u32 = arrayLength(sb1.arr1); var len1 : u32 = arrayLength(sb1.arr1);
var len2 : u32 = arrayLength(sb2.arr2); var len2 : u32 = arrayLength(sb2.arr2);
@ -260,7 +260,7 @@ var<storage> sb1 : [[access(read)]] SB1;
var<storage> sb2 : [[access(read)]] SB2; var<storage> sb2 : [[access(read)]] SB2;
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var tint_symbol_1 : u32 = 0u; var tint_symbol_1 : u32 = 0u;
tint_symbol(sb1, tint_symbol_1); tint_symbol(sb1, tint_symbol_1);

View File

@ -28,8 +28,9 @@ fn non_entry_a() {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() -> [[builtin(position)]] vec4<f32> {
var builtin_assignments_should_happen_before_this : f32; var builtin_assignments_should_happen_before_this : f32;
return vec4<f32>();
} }
fn non_entry_b() { fn non_entry_b() {
@ -43,42 +44,10 @@ fn non_entry_a() {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() -> [[builtin(position)]] vec4<f32> {
tint_pointsize = 1.0; tint_pointsize = 1.0;
var builtin_assignments_should_happen_before_this : f32; var builtin_assignments_should_happen_before_this : f32;
} return vec4<f32>();
fn non_entry_b() {
}
)";
auto got = Run<EmitVertexPointSize>(src);
EXPECT_EQ(expect, str(got));
}
TEST_F(EmitVertexPointSizeTest, VertexStageEmpty) {
auto* src = R"(
fn non_entry_a() {
}
[[stage(vertex)]]
fn entry() {
}
fn non_entry_b() {
}
)";
auto* expect = R"(
[[builtin(pointsize)]] var<out> tint_pointsize : f32;
fn non_entry_a() {
}
[[stage(vertex)]]
fn entry() {
tint_pointsize = 1.0;
} }
fn non_entry_b() { fn non_entry_b() {
@ -119,8 +88,9 @@ fn compute_entry() {
TEST_F(EmitVertexPointSizeTest, AttemptSymbolCollision) { TEST_F(EmitVertexPointSizeTest, AttemptSymbolCollision) {
auto* src = R"( auto* src = R"(
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() -> [[builtin(position)]] vec4<f32> {
var tint_pointsize : f32; var tint_pointsize : f32;
return vec4<f32>();
} }
)"; )";
@ -128,9 +98,10 @@ fn entry() {
[[builtin(pointsize)]] var<out> tint_pointsize_1 : f32; [[builtin(pointsize)]] var<out> tint_pointsize_1 : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() -> [[builtin(position)]] vec4<f32> {
tint_pointsize_1 = 1.0; tint_pointsize_1 = 1.0;
var tint_pointsize : f32; var tint_pointsize : f32;
return vec4<f32>();
} }
)"; )";

View File

@ -52,8 +52,9 @@ fn test(vert_idx : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry([[builtin(vertex_index)]] vert_idx : u32) { fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
test(vert_idx); test(vert_idx);
return vec4<f32>();
} }
)"; )";
@ -70,8 +71,9 @@ fn test(vert_idx : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry([[builtin(vertex_index)]] vert_idx : u32) { fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
test((vert_idx + tint_symbol_1.first_vertex_index)); test((vert_idx + tint_symbol_1.first_vertex_index));
return vec4<f32>();
} }
)"; )";
@ -97,8 +99,9 @@ fn test(inst_idx : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry([[builtin(instance_index)]] inst_idx : u32) { fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
test(inst_idx); test(inst_idx);
return vec4<f32>();
} }
)"; )";
@ -115,8 +118,9 @@ fn test(inst_idx : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry([[builtin(instance_index)]] inst_idx : u32) { fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
test((inst_idx + tint_symbol_1.first_instance_index)); test((inst_idx + tint_symbol_1.first_instance_index));
return vec4<f32>();
} }
)"; )";
@ -147,8 +151,9 @@ struct Inputs {
}; };
[[stage(vertex)]] [[stage(vertex)]]
fn entry(inputs : Inputs) { fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
test(inputs.instance_idx, inputs.vert_idx); test(inputs.instance_idx, inputs.vert_idx);
return vec4<f32>();
} }
)"; )";
@ -173,8 +178,9 @@ struct Inputs {
}; };
[[stage(vertex)]] [[stage(vertex)]]
fn entry(inputs : Inputs) { fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
test((inputs.instance_idx + tint_symbol_1.first_instance_index), (inputs.vert_idx + tint_symbol_1.first_vertex_index)); test((inputs.instance_idx + tint_symbol_1.first_instance_index), (inputs.vert_idx + tint_symbol_1.first_vertex_index));
return vec4<f32>();
} }
)"; )";
@ -204,8 +210,9 @@ fn func2(vert_idx : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry([[builtin(vertex_index)]] vert_idx : u32) { fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
func2(vert_idx); func2(vert_idx);
return vec4<f32>();
} }
)"; )";
@ -226,8 +233,9 @@ fn func2(vert_idx : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry([[builtin(vertex_index)]] vert_idx : u32) { fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
func2((vert_idx + tint_symbol_1.first_vertex_index)); func2((vert_idx + tint_symbol_1.first_vertex_index));
return vec4<f32>();
} }
)"; )";
@ -253,18 +261,21 @@ fn func(i : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry_a([[builtin(vertex_index)]] vert_idx : u32) { fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
func(vert_idx); func(vert_idx);
return vec4<f32>();
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) { fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
func(vert_idx + inst_idx); func(vert_idx + inst_idx);
return vec4<f32>();
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry_c([[builtin(instance_index)]] inst_idx : u32) { fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
func(inst_idx); func(inst_idx);
return vec4<f32>();
} }
)"; )";
@ -282,18 +293,21 @@ fn func(i : u32) -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry_a([[builtin(vertex_index)]] vert_idx : u32) { fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
func((vert_idx + tint_symbol_1.first_vertex_index)); func((vert_idx + tint_symbol_1.first_vertex_index));
return vec4<f32>();
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) { fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
func(((vert_idx + tint_symbol_1.first_vertex_index) + (inst_idx + tint_symbol_1.first_instance_index))); func(((vert_idx + tint_symbol_1.first_vertex_index) + (inst_idx + tint_symbol_1.first_instance_index)));
return vec4<f32>();
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry_c([[builtin(instance_index)]] inst_idx : u32) { fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
func((inst_idx + tint_symbol_1.first_instance_index)); func((inst_idx + tint_symbol_1.first_instance_index));
return vec4<f32>();
} }
)"; )";
@ -316,6 +330,8 @@ TEST_F(FirstIndexOffsetTest, OLD_BasicModuleVertexIndex) {
auto* src = R"( auto* src = R"(
[[builtin(vertex_index)]] var<in> vert_idx : u32; [[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 { fn test() -> u32 {
return vert_idx; return vert_idx;
} }
@ -323,6 +339,7 @@ fn test() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
test(); test();
pos = vec4<f32>();
} }
)"; )";
@ -336,6 +353,8 @@ struct tint_symbol {
[[builtin(vertex_index)]] var<in> vert_idx : u32; [[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 { fn test() -> u32 {
return (vert_idx + tint_symbol_1.first_vertex_index); return (vert_idx + tint_symbol_1.first_vertex_index);
} }
@ -343,6 +362,7 @@ fn test() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
test(); test();
pos = vec4<f32>();
} }
)"; )";
@ -363,6 +383,8 @@ TEST_F(FirstIndexOffsetTest, OLD_BasicModuleInstanceIndex) {
auto* src = R"( auto* src = R"(
[[builtin(instance_index)]] var<in> inst_idx : u32; [[builtin(instance_index)]] var<in> inst_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 { fn test() -> u32 {
return inst_idx; return inst_idx;
} }
@ -370,6 +392,7 @@ fn test() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
test(); test();
pos = vec4<f32>();
} }
)"; )";
@ -383,6 +406,8 @@ struct tint_symbol {
[[builtin(instance_index)]] var<in> inst_idx : u32; [[builtin(instance_index)]] var<in> inst_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 { fn test() -> u32 {
return (inst_idx + tint_symbol_1.first_instance_index); return (inst_idx + tint_symbol_1.first_instance_index);
} }
@ -390,6 +415,7 @@ fn test() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
test(); test();
pos = vec4<f32>();
} }
)"; )";
@ -410,6 +436,7 @@ TEST_F(FirstIndexOffsetTest, OLD_BasicModuleBothIndex) {
auto* src = R"( auto* src = R"(
[[builtin(instance_index)]] var<in> instance_idx : u32; [[builtin(instance_index)]] var<in> instance_idx : u32;
[[builtin(vertex_index)]] var<in> vert_idx : u32; [[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 { fn test() -> u32 {
return instance_idx + vert_idx; return instance_idx + vert_idx;
@ -418,6 +445,7 @@ fn test() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
test(); test();
pos = vec4<f32>();
} }
)"; )";
@ -434,6 +462,8 @@ struct tint_symbol {
[[builtin(vertex_index)]] var<in> vert_idx : u32; [[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 { fn test() -> u32 {
return ((instance_idx + tint_symbol_1.first_instance_index) + (vert_idx + tint_symbol_1.first_vertex_index)); return ((instance_idx + tint_symbol_1.first_instance_index) + (vert_idx + tint_symbol_1.first_vertex_index));
} }
@ -441,6 +471,7 @@ fn test() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
test(); test();
pos = vec4<f32>();
} }
)"; )";
@ -460,6 +491,7 @@ fn entry() {
TEST_F(FirstIndexOffsetTest, OLD_NestedCalls) { TEST_F(FirstIndexOffsetTest, OLD_NestedCalls) {
auto* src = R"( auto* src = R"(
[[builtin(vertex_index)]] var<in> vert_idx : u32; [[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn func1() -> u32 { fn func1() -> u32 {
return vert_idx; return vert_idx;
@ -472,6 +504,7 @@ fn func2() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
func2(); func2();
pos = vec4<f32>();
} }
)"; )";
@ -485,6 +518,8 @@ struct tint_symbol {
[[builtin(vertex_index)]] var<in> vert_idx : u32; [[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn func1() -> u32 { fn func1() -> u32 {
return (vert_idx + tint_symbol_1.first_vertex_index); return (vert_idx + tint_symbol_1.first_vertex_index);
} }
@ -496,6 +531,7 @@ fn func2() -> u32 {
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() {
func2(); func2();
pos = vec4<f32>();
} }
)"; )";

View File

@ -130,7 +130,7 @@ void Hlsl::AddEmptyEntryPoint(CloneContext& ctx) const {
ctx.dst->Func( ctx.dst->Func(
ctx.dst->Symbols().New("tint_unused_entry_point"), {}, ctx.dst->Symbols().New("tint_unused_entry_point"), {},
ctx.dst->ty.void_(), {}, ctx.dst->ty.void_(), {},
{ctx.dst->create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); {ctx.dst->create<ast::StageDecoration>(ast::PipelineStage::kCompute)});
} }
} // namespace transform } // namespace transform

View File

@ -24,7 +24,7 @@ using HlslTest = TransformTest;
TEST_F(HlslTest, PromoteArrayInitializerToConstVar_Basic) { TEST_F(HlslTest, PromoteArrayInitializerToConstVar_Basic) {
auto* src = R"( auto* src = R"(
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var f0 : f32 = 1.0; var f0 : f32 = 1.0;
var f1 : f32 = 2.0; var f1 : f32 = 2.0;
@ -35,7 +35,7 @@ fn main() {
)"; )";
auto* expect = R"( auto* expect = R"(
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var f0 : f32 = 1.0; var f0 : f32 = 1.0;
var f1 : f32 = 2.0; var f1 : f32 = 2.0;
@ -59,7 +59,7 @@ struct S {
c : vec3<f32>; c : vec3<f32>;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var x : f32 = S(1, 2.0, vec3<f32>()).b; var x : f32 = S(1, 2.0, vec3<f32>()).b;
} }
@ -72,7 +72,7 @@ struct S {
c : vec3<f32>; c : vec3<f32>;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
let tint_symbol : S = S(1, 2.0, vec3<f32>()); let tint_symbol : S = S(1, 2.0, vec3<f32>());
var x : f32 = tint_symbol.b; var x : f32 = tint_symbol.b;
@ -86,14 +86,14 @@ fn main() {
TEST_F(HlslTest, PromoteArrayInitializerToConstVar_ArrayInArray) { TEST_F(HlslTest, PromoteArrayInitializerToConstVar_ArrayInArray) {
auto* src = R"( auto* src = R"(
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var i : f32 = array<array<f32, 2>, 2>(array<f32, 2>(1.0, 2.0), array<f32, 2>(3.0, 4.0))[0][1]; var i : f32 = array<array<f32, 2>, 2>(array<f32, 2>(1.0, 2.0), array<f32, 2>(3.0, 4.0))[0][1];
} }
)"; )";
auto* expect = R"( auto* expect = R"(
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
let tint_symbol : array<f32, 2> = array<f32, 2>(1.0, 2.0); let tint_symbol : array<f32, 2> = array<f32, 2>(1.0, 2.0);
let tint_symbol_1 : array<f32, 2> = array<f32, 2>(3.0, 4.0); let tint_symbol_1 : array<f32, 2> = array<f32, 2>(3.0, 4.0);
@ -123,7 +123,7 @@ struct S3 {
a : S2; a : S2;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var x : i32 = S3(S2(1, S1(2), 3)).a.b.a; var x : i32 = S3(S2(1, S1(2), 3)).a.b.a;
} }
@ -144,7 +144,7 @@ struct S3 {
a : S2; a : S2;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
let tint_symbol : S1 = S1(2); let tint_symbol : S1 = S1(2);
let tint_symbol_1 : S2 = S2(1, tint_symbol, 3); let tint_symbol_1 : S2 = S2(1, tint_symbol, 3);
@ -168,7 +168,7 @@ struct S2 {
a : array<S1, 3>; a : array<S1, 3>;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var x : i32 = S2(array<S1, 3>(S1(1), S1(2), S1(3))).a[1].a; var x : i32 = S2(array<S1, 3>(S1(1), S1(2), S1(3))).a[1].a;
} }
@ -183,7 +183,7 @@ struct S2 {
a : array<S1, 3>; a : array<S1, 3>;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
let tint_symbol : S1 = S1(1); let tint_symbol : S1 = S1(1);
let tint_symbol_1 : S1 = S1(2); let tint_symbol_1 : S1 = S1(2);
@ -207,7 +207,7 @@ struct S {
c : i32; c : i32;
}; };
[[stage(vertex)]] [[stage(compute)]]
fn main() { fn main() {
var local_arr : array<f32, 4> = array<f32, 4>(0.0, 1.0, 2.0, 3.0); var local_arr : array<f32, 4> = array<f32, 4>(0.0, 1.0, 2.0, 3.0);
var local_str : S = S(1, 2.0, 3); var local_str : S = S(1, 2.0, 3);
@ -281,7 +281,7 @@ TEST_F(HlslTest, AddEmptyEntryPoint) {
auto* src = R"()"; auto* src = R"()";
auto* expect = R"( auto* expect = R"(
[[stage(vertex)]] [[stage(compute)]]
fn tint_unused_entry_point() { fn tint_unused_entry_point() {
} }
)"; )";

View File

@ -49,8 +49,9 @@ fn test() -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry() { fn entry() -> [[builtin(position)]] vec4<f32> {
test(); test();
return vec4<f32>();
} }
)"; )";
@ -62,8 +63,9 @@ fn tint_symbol_1() -> u32 {
} }
[[stage(vertex)]] [[stage(vertex)]]
fn tint_symbol_2() { fn tint_symbol_2() -> [[builtin(position)]] vec4<f32> {
tint_symbol_1(); tint_symbol_1();
return vec4<f32>();
} }
)"; )";

View File

@ -307,8 +307,8 @@ struct Interface {
[[location(1)]] value : f32; [[location(1)]] value : f32;
}; };
[[stage(vertex)]] [[stage(fragment)]]
fn vert_main(inputs : Interface) -> Interface { fn frag_main(inputs : Interface) -> Interface {
return inputs; return inputs;
} }
)"; )";
@ -326,8 +326,8 @@ fn tint_symbol_4(tint_symbol_2 : Interface) {
tint_symbol_3 = tint_symbol_2.value; tint_symbol_3 = tint_symbol_2.value;
} }
[[stage(vertex)]] [[stage(fragment)]]
fn vert_main() { fn frag_main() {
let tint_symbol_1 : Interface = Interface(tint_symbol); let tint_symbol_1 : Interface = Interface(tint_symbol);
tint_symbol_4(tint_symbol_1); tint_symbol_4(tint_symbol_1);
return; return;
@ -342,12 +342,13 @@ fn vert_main() {
TEST_F(SpirvTest, HandleEntryPointIOTypes_SharedStruct_DifferentShaders) { TEST_F(SpirvTest, HandleEntryPointIOTypes_SharedStruct_DifferentShaders) {
auto* src = R"( auto* src = R"(
struct Interface { struct Interface {
[[builtin(position)]] pos : vec4<f32>;
[[location(1)]] value : f32; [[location(1)]] value : f32;
}; };
[[stage(vertex)]] [[stage(vertex)]]
fn vert_main() -> Interface { fn vert_main() -> Interface {
return Interface(42.0); return Interface(vec4<f32>(), 42.0);
} }
[[stage(fragment)]] [[stage(fragment)]]
@ -358,27 +359,33 @@ fn frag_main(inputs : Interface) {
auto* expect = R"( auto* expect = R"(
struct Interface { struct Interface {
pos : vec4<f32>;
value : f32; value : f32;
}; };
[[location(1)]] var<out> tint_symbol_1 : f32; [[builtin(position)]] var<out> tint_symbol_1 : vec4<f32>;
fn tint_symbol_2(tint_symbol : Interface) { [[location(1)]] var<out> tint_symbol_2 : f32;
tint_symbol_1 = tint_symbol.value;
fn tint_symbol_3(tint_symbol : Interface) {
tint_symbol_1 = tint_symbol.pos;
tint_symbol_2 = tint_symbol.value;
} }
[[stage(vertex)]] [[stage(vertex)]]
fn vert_main() { fn vert_main() {
tint_symbol_2(Interface(42.0)); tint_symbol_3(Interface(vec4<f32>(), 42.0));
return; return;
} }
[[location(1)]] var<in> tint_symbol_3 : f32; [[builtin(position)]] var<in> tint_symbol_4 : vec4<f32>;
[[location(1)]] var<in> tint_symbol_5 : f32;
[[stage(fragment)]] [[stage(fragment)]]
fn frag_main() { fn frag_main() {
let tint_symbol_4 : Interface = Interface(tint_symbol_3); let tint_symbol_6 : Interface = Interface(tint_symbol_4, tint_symbol_5);
var x : f32 = tint_symbol_4.value; var x : f32 = tint_symbol_6.value;
} }
)"; )";

View File

@ -39,7 +39,9 @@ TEST_F(VertexPullingTest, Error_NoEntryPoint) {
TEST_F(VertexPullingTest, Error_InvalidEntryPoint) { TEST_F(VertexPullingTest, Error_InvalidEntryPoint) {
auto* src = R"( auto* src = R"(
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = "error: Vertex stage entry point not found"; auto* expect = "error: Vertex stage entry point not found";
@ -75,7 +77,9 @@ fn main() {}
TEST_F(VertexPullingTest, BasicModule) { TEST_F(VertexPullingTest, BasicModule) {
auto* src = R"( auto* src = R"(
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -85,10 +89,11 @@ struct TintVertexData {
}; };
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
} }
return vec4<f32>();
} }
)"; )";
@ -107,7 +112,9 @@ TEST_F(VertexPullingTest, OneAttribute) {
[[location(0)]] var<in> var_a : f32; [[location(0)]] var<in> var_a : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -123,12 +130,13 @@ struct TintVertexData {
var<private> var_a : f32; var<private> var_a : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_vertex_index * 4u) + 0u); tint_pulling_pos = ((tint_pulling_vertex_index * 4u) + 0u);
var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]); var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]);
} }
return vec4<f32>();
} }
)"; )";
@ -149,7 +157,9 @@ TEST_F(VertexPullingTest, OneInstancedAttribute) {
[[location(0)]] var<in> var_a : f32; [[location(0)]] var<in> var_a : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -165,12 +175,13 @@ struct TintVertexData {
var<private> var_a : f32; var<private> var_a : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_instance_index * 4u) + 0u); tint_pulling_pos = ((tint_pulling_instance_index * 4u) + 0u);
var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]); var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]);
} }
return vec4<f32>();
} }
)"; )";
@ -191,7 +202,9 @@ TEST_F(VertexPullingTest, OneAttributeDifferentOutputSet) {
[[location(0)]] var<in> var_a : f32; [[location(0)]] var<in> var_a : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -207,12 +220,13 @@ struct TintVertexData {
var<private> var_a : f32; var<private> var_a : f32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_vertex_index * 4u) + 0u); tint_pulling_pos = ((tint_pulling_vertex_index * 4u) + 0u);
var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]); var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]);
} }
return vec4<f32>();
} }
)"; )";
@ -238,7 +252,9 @@ TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex) {
[[builtin(instance_index)]] var<in> custom_instance_index : u32; [[builtin(instance_index)]] var<in> custom_instance_index : u32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -260,7 +276,7 @@ var<private> var_b : f32;
[[builtin(instance_index)]] var<in> custom_instance_index : u32; [[builtin(instance_index)]] var<in> custom_instance_index : u32;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
tint_pulling_pos = ((custom_vertex_index * 4u) + 0u); tint_pulling_pos = ((custom_vertex_index * 4u) + 0u);
@ -268,6 +284,7 @@ fn main() {
tint_pulling_pos = ((custom_instance_index * 4u) + 0u); tint_pulling_pos = ((custom_instance_index * 4u) + 0u);
var_b = bitcast<f32>(tint_pulling_vertex_buffer_1.tint_vertex_data[(tint_pulling_pos / 4u)]); var_b = bitcast<f32>(tint_pulling_vertex_buffer_1.tint_vertex_data[(tint_pulling_pos / 4u)]);
} }
return vec4<f32>();
} }
)"; )";
@ -299,7 +316,9 @@ TEST_F(VertexPullingTest, TwoAttributesSameBuffer) {
[[location(1)]] var<in> var_b : vec4<f32>; [[location(1)]] var<in> var_b : vec4<f32>;
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -317,7 +336,7 @@ var<private> var_a : f32;
var<private> var_b : vec4<f32>; var<private> var_b : vec4<f32>;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u); tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u);
@ -325,6 +344,7 @@ fn main() {
tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u); tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u);
var_b = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 0u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 4u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 8u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 12u) / 4u)])); var_b = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 0u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 4u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 8u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 12u) / 4u)]));
} }
return vec4<f32>();
} }
)"; )";
@ -349,7 +369,9 @@ TEST_F(VertexPullingTest, FloatVectorAttributes) {
[[location(2)]] var<in> var_c : vec4<f32>; [[location(2)]] var<in> var_c : vec4<f32>;
[[stage(vertex)]] [[stage(vertex)]]
fn main() {} fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)"; )";
auto* expect = R"( auto* expect = R"(
@ -373,7 +395,7 @@ var<private> var_b : vec3<f32>;
var<private> var_c : vec4<f32>; var<private> var_c : vec4<f32>;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos : u32; var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_vertex_index * 8u) + 0u); tint_pulling_pos = ((tint_pulling_vertex_index * 8u) + 0u);
@ -383,6 +405,7 @@ fn main() {
tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u); tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u);
var_c = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 0u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 4u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 8u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 12u) / 4u)])); var_c = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 0u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 4u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 8u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_2.tint_vertex_data[((tint_pulling_pos + 12u) / 4u)]));
} }
return vec4<f32>();
} }
)"; )";
@ -407,11 +430,12 @@ TEST_F(VertexPullingTest, AttemptSymbolCollision) {
[[location(1)]] var<in> var_b : vec4<f32>; [[location(1)]] var<in> var_b : vec4<f32>;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
var tint_pulling_vertex_index : i32; var tint_pulling_vertex_index : i32;
var tint_pulling_vertex_buffer_0 : i32; var tint_pulling_vertex_buffer_0 : i32;
var tint_vertex_data : i32; var tint_vertex_data : i32;
var tint_pulling_pos : i32; var tint_pulling_pos : i32;
return vec4<f32>();
} }
)"; )";
@ -430,7 +454,7 @@ var<private> var_a : f32;
var<private> var_b : vec4<f32>; var<private> var_b : vec4<f32>;
[[stage(vertex)]] [[stage(vertex)]]
fn main() { fn main() -> [[builtin(position)]] vec4<f32> {
{ {
var tint_pulling_pos_1 : u32; var tint_pulling_pos_1 : u32;
tint_pulling_pos_1 = ((tint_pulling_vertex_index_1 * 16u) + 0u); tint_pulling_pos_1 = ((tint_pulling_vertex_index_1 * 16u) + 0u);
@ -442,6 +466,7 @@ fn main() {
var tint_pulling_vertex_buffer_0 : i32; var tint_pulling_vertex_buffer_0 : i32;
var tint_vertex_data : i32; var tint_vertex_data : i32;
var tint_pulling_pos : i32; var tint_pulling_pos : i32;
return vec4<f32>();
} }
)"; )";

View File

@ -42,14 +42,14 @@ TEST_F(HlslGeneratorImplTest_EntryPoint,
create<ast::LocationDecoration>(1), create<ast::LocationDecoration>(1),
}); });
Func("vtx_main", ast::VariableList{}, ty.void_(), Func("vtx_main", ast::VariableList{}, ty.vec4<f32>(),
ast::StatementList{ ast::StatementList{
create<ast::AssignmentStatement>(Expr("foo"), Expr("foo")), Assign(Expr("foo"), Expr("foo")),
create<ast::AssignmentStatement>(Expr("bar"), Expr("bar")), Assign(Expr("bar"), Expr("bar")),
Return(Construct(ty.vec4<f32>())),
}, },
ast::DecorationList{ {Stage(ast::PipelineStage::kVertex)},
create<ast::StageDecoration>(ast::PipelineStage::kVertex), {Builtin(ast::Builtin::kPosition)});
});
std::unordered_set<Symbol> globals; std::unordered_set<Symbol> globals;
@ -85,14 +85,14 @@ TEST_F(HlslGeneratorImplTest_EntryPoint,
create<ast::LocationDecoration>(1), create<ast::LocationDecoration>(1),
}); });
Func("vtx_main", ast::VariableList{}, ty.void_(), Func("vtx_main", ast::VariableList{}, ty.vec4<f32>(),
ast::StatementList{ ast::StatementList{
create<ast::AssignmentStatement>(Expr("foo"), Expr("foo")), Assign(Expr("foo"), Expr("foo")),
create<ast::AssignmentStatement>(Expr("bar"), Expr("bar")), Assign(Expr("bar"), Expr("bar")),
Return(Construct(ty.vec4<f32>())),
}, },
ast::DecorationList{ {Stage(ast::PipelineStage::kVertex)},
create<ast::StageDecoration>(ast::PipelineStage::kVertex), {Builtin(ast::Builtin::kPosition)});
});
std::unordered_set<Symbol> globals; std::unordered_set<Symbol> globals;
@ -134,7 +134,7 @@ TEST_F(HlslGeneratorImplTest_EntryPoint,
create<ast::AssignmentStatement>(Expr("bar"), Expr("bar")), create<ast::AssignmentStatement>(Expr("bar"), Expr("bar")),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
std::unordered_set<Symbol> globals; std::unordered_set<Symbol> globals;

View File

@ -174,32 +174,39 @@ tint_symbol_2 frag_main(tint_symbol_1 tint_symbol) {
TEST_F(HlslGeneratorImplTest_Function, TEST_F(HlslGeneratorImplTest_Function,
Emit_Decoration_EntryPoint_SharedStruct_DifferentStages) { Emit_Decoration_EntryPoint_SharedStruct_DifferentStages) {
// struct Interface { // struct Interface {
// [[builtin(position)]] pos : vec4<f32>;
// [[location(1)]] col1 : f32; // [[location(1)]] col1 : f32;
// [[location(2)]] col2 : f32; // [[location(2)]] col2 : f32;
// }; // };
// fn vert_main() -> Interface { // fn vert_main() -> Interface {
// return Interface(0.4, 0.6); // return Interface(vec4<f32>(), 0.4, 0.6);
// } // }
// fn frag_main(colors : Interface) { // fn frag_main(inputs : Interface) {
// const r = colors.col1; // const r = inputs.col1;
// const g = colors.col2; // const g = inputs.col2;
// const p = inputs.pos;
// } // }
auto* interface_struct = Structure( auto* interface_struct = Structure(
"Interface", "Interface",
{Member("col1", ty.f32(), {create<ast::LocationDecoration>(1)}), {
Member("col2", ty.f32(), {create<ast::LocationDecoration>(2)})}); Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)}),
Member("col1", ty.f32(), {Location(1)}),
Member("col2", ty.f32(), {Location(2)}),
});
Func("vert_main", {}, interface_struct, Func("vert_main", {}, interface_struct,
{create<ast::ReturnStatement>( {Return(Construct(interface_struct, Construct(ty.vec4<f32>()),
Construct(interface_struct, Expr(0.5f), Expr(0.25f)))}, Expr(0.5f), Expr(0.25f)))},
{create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func("frag_main", {Param("colors", interface_struct)}, ty.void_(), Func("frag_main", {Param("inputs", interface_struct)}, ty.void_(),
{ {
WrapInStatement( WrapInStatement(
Const("r", ty.f32(), MemberAccessor(Expr("colors"), "col1"))), Const("r", ty.f32(), MemberAccessor(Expr("inputs"), "col1"))),
WrapInStatement( WrapInStatement(
Const("g", ty.f32(), MemberAccessor(Expr("colors"), "col2"))), Const("g", ty.f32(), MemberAccessor(Expr("inputs"), "col2"))),
WrapInStatement(Const("p", ty.vec4<f32>(),
MemberAccessor(Expr("inputs"), "pos"))),
}, },
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)}); {create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
@ -207,28 +214,32 @@ TEST_F(HlslGeneratorImplTest_Function,
ASSERT_TRUE(gen.Generate(out)) << gen.error(); ASSERT_TRUE(gen.Generate(out)) << gen.error();
EXPECT_EQ(result(), R"(struct Interface { EXPECT_EQ(result(), R"(struct Interface {
float4 pos;
float col1; float col1;
float col2; float col2;
}; };
struct tint_symbol { struct tint_symbol {
float col1 : TEXCOORD1; float col1 : TEXCOORD1;
float col2 : TEXCOORD2; float col2 : TEXCOORD2;
float4 pos : SV_Position;
}; };
struct tint_symbol_3 { struct tint_symbol_3 {
float col1 : TEXCOORD1; float col1 : TEXCOORD1;
float col2 : TEXCOORD2; float col2 : TEXCOORD2;
float4 pos : SV_Position;
}; };
tint_symbol vert_main() { tint_symbol vert_main() {
const Interface tint_symbol_1 = {0.5f, 0.25f}; const Interface tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f), 0.5f, 0.25f};
const tint_symbol tint_symbol_4 = {tint_symbol_1.col1, tint_symbol_1.col2}; const tint_symbol tint_symbol_4 = {tint_symbol_1.col1, tint_symbol_1.col2, tint_symbol_1.pos};
return tint_symbol_4; return tint_symbol_4;
} }
void frag_main(tint_symbol_3 tint_symbol_2) { void frag_main(tint_symbol_3 tint_symbol_2) {
const Interface colors = {tint_symbol_2.col1, tint_symbol_2.col2}; const Interface inputs = {tint_symbol_2.pos, tint_symbol_2.col1, tint_symbol_2.col2};
const float r = colors.col1; const float r = inputs.col1;
const float g = colors.col2; const float g = inputs.col2;
const float4 p = inputs.pos;
return; return;
} }

View File

@ -113,7 +113,7 @@ class HlslGeneratorImplTest_MemberAccessorBase : public BASE {
ProgramBuilder& b = *this; ProgramBuilder& b = *this;
b.Func("main", ast::VariableList{}, b.ty.void_(), statements, b.Func("main", ast::VariableList{}, b.ty.void_(), statements,
ast::DecorationList{ ast::DecorationList{
b.create<ast::StageDecoration>(ast::PipelineStage::kVertex), b.create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
} }
}; };

View File

@ -50,7 +50,7 @@ TEST_F(HlslSanitizerTest, ArrayLength) {
Call("arrayLength", MemberAccessor("sb", "arr")))), Call("arrayLength", MemberAccessor("sb", "arr")))),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();
@ -83,7 +83,7 @@ TEST_F(HlslSanitizerTest, PromoteArrayInitializerToConstVar) {
create<ast::VariableDeclStatement>(pos), create<ast::VariableDeclStatement>(pos),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();
@ -117,7 +117,7 @@ TEST_F(HlslSanitizerTest, PromoteStructInitializerToConstVar) {
create<ast::VariableDeclStatement>(pos), create<ast::VariableDeclStatement>(pos),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();

View File

@ -38,14 +38,14 @@ TEST_F(MslGeneratorImplTest, Emit_Function_EntryPointData_Vertex_Input) {
ast::DecorationList{create<ast::LocationDecoration>(1)}); ast::DecorationList{create<ast::LocationDecoration>(1)});
auto body = ast::StatementList{ auto body = ast::StatementList{
create<ast::AssignmentStatement>(Expr("foo"), Expr("foo")), Assign(Expr("foo"), Expr("foo")),
create<ast::AssignmentStatement>(Expr("bar"), Expr("bar")), Assign(Expr("bar"), Expr("bar")),
Return(Construct(ty.vec4<f32>())),
}; };
Func("vtx_main", ast::VariableList{}, ty.void_(), body, Func("vtx_main", ast::VariableList{}, ty.vec4<f32>(), body,
ast::DecorationList{ {Stage(ast::PipelineStage::kVertex)},
create<ast::StageDecoration>(ast::PipelineStage::kVertex), {Builtin(ast::Builtin::kPosition)});
});
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -75,14 +75,14 @@ TEST_F(MslGeneratorImplTest, Emit_Function_EntryPointData_Vertex_Output) {
ast::DecorationList{create<ast::LocationDecoration>(1)}); ast::DecorationList{create<ast::LocationDecoration>(1)});
auto body = ast::StatementList{ auto body = ast::StatementList{
create<ast::AssignmentStatement>(Expr("foo"), Expr("foo")), Assign(Expr("foo"), Expr("foo")),
create<ast::AssignmentStatement>(Expr("bar"), Expr("bar")), Assign(Expr("bar"), Expr("bar")),
Return(Construct(ty.vec4<f32>())),
}; };
Func("vtx_main", ast::VariableList{}, ty.void_(), body, Func("vtx_main", ast::VariableList{}, ty.vec4<f32>(), body,
ast::DecorationList{ {Stage(ast::PipelineStage::kVertex)},
create<ast::StageDecoration>(ast::PipelineStage::kVertex), {Builtin(ast::Builtin::kPosition)});
});
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -28,14 +28,14 @@ TEST_F(BuilderTest, Decoration_Stage) {
auto* func = auto* func =
Func("main", {}, ty.void_(), ast::StatementList{}, Func("main", {}, ty.void_(), ast::StatementList{},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
ASSERT_TRUE(b.GenerateFunction(func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
EXPECT_EQ(DumpInstructions(b.entry_points()), EXPECT_EQ(DumpInstructions(b.entry_points()),
R"(OpEntryPoint Vertex %3 "main" R"(OpEntryPoint Fragment %3 "main"
)"); )");
} }
@ -51,13 +51,24 @@ using Decoration_StageTest = TestParamHelper<FunctionStageData>;
TEST_P(Decoration_StageTest, Emit) { TEST_P(Decoration_StageTest, Emit) {
auto params = GetParam(); auto params = GetParam();
auto* func = Func("main", {}, ty.void_(), ast::StatementList{}, ast::Variable* var = nullptr;
ast::StatementList body;
if (params.stage == ast::PipelineStage::kVertex) {
var = Global("pos", ty.vec4<f32>(), ast::StorageClass::kOutput, nullptr,
ast::DecorationList{Builtin(ast::Builtin::kPosition)});
body.push_back(Assign("pos", Construct(ty.vec4<f32>())));
}
auto* func = Func("main", {}, ty.void_(), body,
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(params.stage), create<ast::StageDecoration>(params.stage),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
if (var) {
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
}
ASSERT_TRUE(b.GenerateFunction(func)) << b.error(); ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
auto preamble = b.entry_points(); auto preamble = b.entry_points();
@ -82,7 +93,7 @@ TEST_F(BuilderTest, Decoration_Stage_WithUnusedInterfaceIds) {
auto* func = auto* func =
Func("main", {}, ty.void_(), ast::StatementList{}, Func("main", {}, ty.void_(), ast::StatementList{},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
auto* v_in = Global("my_in", ty.f32(), ast::StorageClass::kInput); auto* v_in = Global("my_in", ty.f32(), ast::StorageClass::kInput);
@ -113,7 +124,7 @@ OpName %11 "main"
%9 = OpTypeFunction %10 %9 = OpTypeFunction %10
)"); )");
EXPECT_EQ(DumpInstructions(b.entry_points()), EXPECT_EQ(DumpInstructions(b.entry_points()),
R"(OpEntryPoint Vertex %11 "main" R"(OpEntryPoint Fragment %11 "main"
)"); )");
} }
@ -131,7 +142,7 @@ TEST_F(BuilderTest, Decoration_Stage_WithUsedInterfaceIds) {
// output multiple times. // output multiple times.
create<ast::AssignmentStatement>(Expr("my_out"), Expr("my_in"))}, create<ast::AssignmentStatement>(Expr("my_out"), Expr("my_in"))},
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -158,7 +169,7 @@ OpName %11 "main"
%9 = OpTypeFunction %10 %9 = OpTypeFunction %10
)"); )");
EXPECT_EQ(DumpInstructions(b.entry_points()), EXPECT_EQ(DumpInstructions(b.entry_points()),
R"(OpEntryPoint Vertex %11 "main" %4 %1 R"(OpEntryPoint Fragment %11 "main" %4 %1
)"); )");
} }

View File

@ -1261,7 +1261,7 @@ TEST_F(IntrinsicBuilderTest, Call_Modf) {
create<ast::CallStatement>(expr), create<ast::CallStatement>(expr),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1271,7 +1271,8 @@ TEST_F(IntrinsicBuilderTest, Call_Modf) {
auto* expect = R"(OpCapability Shader auto* expect = R"(OpCapability Shader
%11 = OpExtInstImport "GLSL.std.450" %11 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %3 "a_func" OpEntryPoint Fragment %3 "a_func"
OpExecutionMode %3 OriginUpperLeft
OpName %3 "a_func" OpName %3 "a_func"
OpName %5 "out" OpName %5 "out"
%2 = OpTypeVoid %2 = OpTypeVoid
@ -1304,7 +1305,7 @@ TEST_F(IntrinsicBuilderTest, Call_Frexp) {
create<ast::CallStatement>(expr), create<ast::CallStatement>(expr),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1314,7 +1315,8 @@ TEST_F(IntrinsicBuilderTest, Call_Frexp) {
auto* expect = R"(OpCapability Shader auto* expect = R"(OpCapability Shader
%13 = OpExtInstImport "GLSL.std.450" %13 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %3 "a_func" OpEntryPoint Fragment %3 "a_func"
OpExecutionMode %3 OriginUpperLeft
OpName %3 "a_func" OpName %3 "a_func"
OpName %5 "out" OpName %5 "out"
%2 = OpTypeVoid %2 = OpTypeVoid
@ -1393,7 +1395,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
create<ast::CallStatement>(expr), create<ast::CallStatement>(expr),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1443,7 +1445,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
create<ast::CallStatement>(expr), create<ast::CallStatement>(expr),
}, },
ast::DecorationList{ ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex), create<ast::StageDecoration>(ast::PipelineStage::kFragment),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();