Implement data packing intrinsics

* Fix how the HLSL writer determines how to use a RWByteAddressBuffer
* Fix how the HLSL writer decides the register space for a storage
  variable
* Fix inference of hlsl format in the tint executable
* Add support for data packing intrinsics
  * type determination
  * validation
  * writers
  * spirv reader

Bug: tint:340, tint:473, tint:474
Change-Id: I45dc8fd7c6f9abc7d30f617c7e3d713d7965b76e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40342
Commit-Queue: Alan Baker <alanbaker@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
Alan Baker
2021-02-04 16:17:49 +00:00
committed by Commit Bot service account
parent fbd47c752e
commit c63e1c0791
16 changed files with 706 additions and 130 deletions

View File

@@ -1632,4 +1632,136 @@ INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
::testing::Values(std::make_tuple("all", 1),
std::make_tuple("any", 1)));
using DataPacking4x8 = ValidatorBuiltinsTestWithParams<std::string>;
TEST_P(DataPacking4x8, Float_Vec4) {
auto name = GetParam();
auto* builtin = Call(name, vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(DataPacking4x8, Float_Vec2) {
auto name = GetParam();
auto* builtin = Call(name, vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect vector size for " + name + ". Requires 4 elements");
}
TEST_P(DataPacking4x8, Int_Vec4) {
auto name = GetParam();
auto* builtin = Call(name, vec4<int>(1, 1, 1, 1));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect type for " + name + ". Requires float vector value");
}
TEST_P(DataPacking4x8, Float_Scalar) {
auto name = GetParam();
auto* builtin = Call(name, Expr(1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect type for " + name + ". Requires float vector value");
}
TEST_P(DataPacking4x8, TooFewParams) {
auto name = GetParam();
auto* builtin = Call(name);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect number of parameters for " + name + " expected 1 got 0");
}
TEST_P(DataPacking4x8, TooManyParams) {
auto name = GetParam();
auto* builtin = Call(name, vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect number of parameters for " + name + " expected 1 got 2");
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
DataPacking4x8,
::testing::Values("pack4x8snorm", "pack4x8unorm"));
using DataPacking2x16 = ValidatorBuiltinsTestWithParams<std::string>;
TEST_P(DataPacking2x16, Float_Vec4) {
auto name = GetParam();
auto* builtin = Call(name, vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect vector size for " + name + ". Requires 2 elements");
}
TEST_P(DataPacking2x16, Float_Vec2) {
auto name = GetParam();
auto* builtin = Call(name, vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(DataPacking2x16, Int_Vec4) {
auto name = GetParam();
auto* builtin = Call(name, vec4<int>(1, 1, 1, 1));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect type for " + name + ". Requires float vector value");
}
TEST_P(DataPacking2x16, Float_Scalar) {
auto name = GetParam();
auto* builtin = Call(name, Expr(1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect type for " + name + ". Requires float vector value");
}
TEST_P(DataPacking2x16, TooFewParams) {
auto name = GetParam();
auto* builtin = Call(name);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect number of parameters for " + name + " expected 1 got 0");
}
TEST_P(DataPacking2x16, TooManyParams) {
auto name = GetParam();
auto* builtin = Call(name, vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.ValidateCallExpr(builtin));
EXPECT_EQ(v.error(),
"incorrect number of parameters for " + name + " expected 1 got 2");
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
DataPacking2x16,
::testing::Values("pack2x16snorm",
"pack2x16unorm",
"pack2x16float"));
} // namespace tint

View File

@@ -153,6 +153,16 @@ constexpr const IntrinsicData kIntrinsicData[] = {
true},
{semantic::Intrinsic::kNormalize, 1, IntrinsicDataType::kFloatVector, 0,
true},
{semantic::Intrinsic::kPack4x8Snorm, 1, IntrinsicDataType::kFloatVector, 4,
false},
{semantic::Intrinsic::kPack4x8Unorm, 1, IntrinsicDataType::kFloatVector, 4,
false},
{semantic::Intrinsic::kPack2x16Snorm, 1, IntrinsicDataType::kFloatVector, 2,
false},
{semantic::Intrinsic::kPack2x16Unorm, 1, IntrinsicDataType::kFloatVector, 2,
false},
{semantic::Intrinsic::kPack2x16Float, 1, IntrinsicDataType::kFloatVector, 2,
false},
{semantic::Intrinsic::kPow, 2, IntrinsicDataType::kFloatScalarOrVector, 0,
true},
{semantic::Intrinsic::kReflect, 2, IntrinsicDataType::kFloatScalarOrVector,
@@ -845,6 +855,15 @@ bool ValidatorImpl::ValidateCallExpr(const ast::CallExpression* expr) {
}
}
if (semantic::intrinsic::IsDataPackingIntrinsic(data->intrinsic)) {
if (!program_->TypeOf(expr)->Is<type::U32>()) {
add_error(expr->source(),
"incorrect type for " + builtin +
". Result type must be an unsigned int scalar");
return false;
}
}
if (data->intrinsic == semantic::Intrinsic::kLength ||
data->intrinsic == semantic::Intrinsic::kDistance ||
data->intrinsic == semantic::Intrinsic::kDeterminant) {