tint: Add chromium_internal_relaxed_uniform_layout

This will be used by the PackedVec3 transform to avoid triggering
stricter layout validation rules for the uniform address space when
mutating types.

Bug: tint:1571
Change-Id: Ib15737fbe3cab4a8fbe453bcaf96ef2acc595921
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121601
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
James Price 2023-02-27 18:39:20 +00:00 committed by Dawn LUCI CQ
parent 806135658d
commit 0b3400c56e
8 changed files with 190 additions and 22 deletions

View File

@ -40,6 +40,9 @@ Extension ParseExtension(std::string_view str) {
if (str == "chromium_experimental_push_constant") {
return Extension::kChromiumExperimentalPushConstant;
}
if (str == "chromium_internal_relaxed_uniform_layout") {
return Extension::kChromiumInternalRelaxedUniformLayout;
}
if (str == "f16") {
return Extension::kF16;
}
@ -58,6 +61,8 @@ std::ostream& operator<<(std::ostream& out, Extension value) {
return out << "chromium_experimental_full_ptr_parameters";
case Extension::kChromiumExperimentalPushConstant:
return out << "chromium_experimental_push_constant";
case Extension::kChromiumInternalRelaxedUniformLayout:
return out << "chromium_internal_relaxed_uniform_layout";
case Extension::kF16:
return out << "f16";
}

View File

@ -37,6 +37,7 @@ enum class Extension {
kChromiumExperimentalDp4A,
kChromiumExperimentalFullPtrParameters,
kChromiumExperimentalPushConstant,
kChromiumInternalRelaxedUniformLayout,
kF16,
};
@ -51,11 +52,9 @@ std::ostream& operator<<(std::ostream& out, Extension value);
Extension ParseExtension(std::string_view str);
constexpr const char* kExtensionStrings[] = {
"chromium_disable_uniformity_analysis",
"chromium_experimental_dp4a",
"chromium_experimental_full_ptr_parameters",
"chromium_experimental_push_constant",
"f16",
"chromium_disable_uniformity_analysis", "chromium_experimental_dp4a",
"chromium_experimental_full_ptr_parameters", "chromium_experimental_push_constant",
"chromium_internal_relaxed_uniform_layout", "f16",
};
// A unique vector of extensions

View File

@ -59,13 +59,20 @@ void ExtensionParser(::benchmark::State& state) {
"chromium_exp9rimFntal_ush_constant",
"chrmium_experimental_push_constant",
"cOOromium_experiVeHtal_puh_conRRtant",
"y1",
"l77rrn6",
"4016",
"chromium_internl_relaxyd_uniform_layout",
"chromnnum_internrr77_Gelaxell_uniform_layout",
"chromium_intern4l_relaxe00_uniform_layout",
"chromium_internal_relaxed_uniform_layout",
"chrmoom_internal_relaxed_uniform_lyout",
"chroium_internal_rlaxed_uniform_layzzut",
"chromium_internaii_r11axed_uppifor_layout",
"f1XX",
"55199II",
"frSSHHa",
"f16",
"5",
"u16",
"f",
"U",
"jV3",
"",
};
for (auto _ : state) {
for (auto* str : kStrings) {

View File

@ -48,6 +48,7 @@ static constexpr Case kValidCases[] = {
{"chromium_experimental_full_ptr_parameters",
Extension::kChromiumExperimentalFullPtrParameters},
{"chromium_experimental_push_constant", Extension::kChromiumExperimentalPushConstant},
{"chromium_internal_relaxed_uniform_layout", Extension::kChromiumInternalRelaxedUniformLayout},
{"f16", Extension::kF16},
};
@ -64,9 +65,12 @@ static constexpr Case kInvalidCases[] = {
{"chvomium_experimental_push_constiint", Extension::kUndefined},
{"chromiu8WWexperimental_push_constant", Extension::kUndefined},
{"chromium_experiMental_push_costanxx", Extension::kUndefined},
{"fgg", Extension::kUndefined},
{"X", Extension::kUndefined},
{"316", Extension::kUndefined},
{"chromium_internal_relaxed_unXform_layugg", Extension::kUndefined},
{"chromiuu_iVterna_relxed_unifXrm_layout", Extension::kUndefined},
{"chromium_internal_relaxed_uni3orm_layout", Extension::kUndefined},
{"fE6", Extension::kUndefined},
{"fPTT", Extension::kUndefined},
{"dxx6", Extension::kUndefined},
};
using ExtensionParseTest = testing::TestWithParam<Case>;

View File

@ -70,6 +70,8 @@ enum extension {
// A Chromium-specific extension that enables passing of uniform, storage and workgroup
// address-spaced pointers as parameters, as well as pointers into sub-objects.
chromium_experimental_full_ptr_parameters
// A Chromium-specific extension that relaxes memory layout requirements for uniform storage.
chromium_internal_relaxed_uniform_layout
}
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class

View File

@ -62,7 +62,7 @@ TEST_F(EnableDirectiveTest, InvalidIdentifier) {
// Error when unknown extension found
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@ -76,7 +76,7 @@ TEST_F(EnableDirectiveTest, InvalidIdentifierSuggest) {
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Did you mean 'f16'?
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@ -124,7 +124,7 @@ TEST_F(EnableDirectiveTest, InvalidTokens) {
p->translation_unit();
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@ -135,7 +135,7 @@ Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_
p->translation_unit();
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);
@ -147,7 +147,7 @@ Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), R"(1:8: expected extension
Did you mean 'f16'?
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'f16')");
Possible values: 'chromium_disable_uniformity_analysis', 'chromium_experimental_dp4a', 'chromium_experimental_full_ptr_parameters', 'chromium_experimental_push_constant', 'chromium_internal_relaxed_uniform_layout', 'f16')");
auto program = p->program();
auto& ast = program.AST();
EXPECT_EQ(ast.Enables().Length(), 0u);

View File

@ -603,5 +603,150 @@ TEST_F(ResolverAddressSpaceLayoutValidationTest, PushConstant_Aligned) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverAddressSpaceLayoutValidationTest, RelaxedUniformLayout_StructMemberOffset_Struct) {
// enable chromium_internal_relaxed_uniform_layout;
//
// struct Inner {
// scalar : i32;
// };
//
// struct Outer {
// scalar : f32;
// inner : Inner;
// };
//
// @group(0) @binding(0)
// var<uniform> a : Outer;
Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
Structure(Source{{12, 34}}, "Inner",
utils::Vector{
Member("scalar", ty.i32()),
});
Structure(Source{{34, 56}}, "Outer",
utils::Vector{
Member("scalar", ty.f32()),
Member(Source{{56, 78}}, "inner", ty("Inner")),
});
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), builtin::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverAddressSpaceLayoutValidationTest, RelaxedUniformLayout_StructMemberOffset_Array) {
// enable chromium_internal_relaxed_uniform_layout;
//
// type Inner = @stride(16) array<f32, 10u>;
//
// struct Outer {
// scalar : f32;
// inner : Inner;
// };
//
// @group(0) @binding(0)
// var<uniform> a : Outer;
Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
Alias("Inner", ty.array<f32, 10>(utils::Vector{Stride(16)}));
Structure(Source{{12, 34}}, "Outer",
utils::Vector{
Member("scalar", ty.f32()),
Member(Source{{56, 78}}, "inner", ty("Inner")),
});
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), builtin::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverAddressSpaceLayoutValidationTest, RelaxedUniformLayout_MemberOffsetNotMutipleOf16) {
// enable chromium_internal_relaxed_uniform_layout;
//
// struct Inner {
// @align(1) @size(5) scalar : i32;
// };
//
// struct Outer {
// inner : Inner;
// scalar : i32;
// };
//
// @group(0) @binding(0)
// var<uniform> a : Outer;
Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
Structure(Source{{12, 34}}, "Inner",
utils::Vector{
Member("scalar", ty.i32(), utils::Vector{MemberAlign(1_i), MemberSize(5_a)}),
});
Structure(Source{{34, 56}}, "Outer",
utils::Vector{
Member(Source{{56, 78}}, "inner", ty("Inner")),
Member(Source{{78, 90}}, "scalar", ty.i32()),
});
GlobalVar(Source{{22, 24}}, "a", ty("Outer"), builtin::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverAddressSpaceLayoutValidationTest, RelaxedUniformLayout_ArrayStride_Scalar) {
// enable chromium_internal_relaxed_uniform_layout;
//
// struct Outer {
// arr : array<f32, 10u>;
// };
//
// @group(0) @binding(0)
// var<uniform> a : Outer;
Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
Structure(Source{{12, 34}}, "Outer",
utils::Vector{
Member("arr", ty.array<f32, 10>()),
});
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), builtin::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverAddressSpaceLayoutValidationTest, RelaxedUniformLayout_ArrayStride_Vech) {
// enable f16;
// enable chromium_internal_relaxed_uniform_layout;
//
// struct Outer {
// arr : array<vec3<f16>, 10u>;
// };
//
// @group(0) @binding(0)
// var<uniform> a : Outer;
Enable(builtin::Extension::kF16);
Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
Structure(Source{{12, 34}}, "Outer",
utils::Vector{
Member("arr", ty.array(ty.vec3<f16>(), 10_u)),
});
GlobalVar(Source{{78, 90}}, "a", ty("Outer"), builtin::AddressSpace::kUniform, Group(0_a),
Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
} // namespace
} // namespace tint::resolver

View File

@ -467,7 +467,9 @@ bool Validator::AddressSpaceLayout(const type::Type* store_ty,
}
// Validate that member is at a valid byte offset
if (m->Offset() % required_align != 0) {
if (m->Offset() % required_align != 0 &&
!enabled_extensions_.Contains(
builtin::Extension::kChromiumInternalRelaxedUniformLayout)) {
AddError("the offset of a struct member of type '" +
m->Type()->UnwrapRef()->FriendlyName(symbols_) +
"' in address space '" + utils::ToString(address_space) +
@ -493,7 +495,9 @@ bool Validator::AddressSpaceLayout(const type::Type* store_ty,
auto* const prev_member = (i == 0) ? nullptr : str->Members()[i - 1];
if (prev_member && is_uniform_struct(prev_member->Type())) {
const uint32_t prev_to_curr_offset = m->Offset() - prev_member->Offset();
if (prev_to_curr_offset % 16 != 0) {
if (prev_to_curr_offset % 16 != 0 &&
!enabled_extensions_.Contains(
builtin::Extension::kChromiumInternalRelaxedUniformLayout)) {
AddError(
"uniform storage requires that the number of bytes between the "
"start of the previous member of type struct and the current "
@ -526,7 +530,9 @@ bool Validator::AddressSpaceLayout(const type::Type* store_ty,
return false;
}
if (address_space == builtin::AddressSpace::kUniform) {
if (address_space == builtin::AddressSpace::kUniform &&
!enabled_extensions_.Contains(
builtin::Extension::kChromiumInternalRelaxedUniformLayout)) {
// We already validated that this array member is itself aligned to 16 bytes above, so
// we only need to validate that stride is a multiple of 16 bytes.
if (arr->Stride() % 16 != 0) {