tint: Support dot4I8Packed and dot4U8Packed in sem
This patch adds the support of dot4I8Packed and dot4U8Packed in semantics under the extension "chromium_experimental_dp4a". Bug: tint:1497 Test: tint_unittests Change-Id: I659172fcb8953ba13b49664c6c9ad75724ff5957 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/88962 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
4b6d3f4346
commit
6c9e475211
|
@ -22,6 +22,10 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::Enable);
|
|||
namespace tint::ast {
|
||||
|
||||
Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
|
||||
if (name == "chromium_experimental_dp4a") {
|
||||
return Enable::ExtensionKind::kChromiumExperimentalDP4a;
|
||||
}
|
||||
|
||||
// The reserved internal extension name for testing
|
||||
if (name == "InternalExtensionForTesting") {
|
||||
return Enable::ExtensionKind::kInternalExtensionForTesting;
|
||||
|
@ -32,6 +36,8 @@ Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
|
|||
|
||||
std::string Enable::KindToName(ExtensionKind kind) {
|
||||
switch (kind) {
|
||||
case ExtensionKind::kChromiumExperimentalDP4a:
|
||||
return "chromium_experimental_dp4a";
|
||||
// The reserved internal extension for testing
|
||||
case ExtensionKind::kInternalExtensionForTesting:
|
||||
return "InternalExtensionForTesting";
|
||||
|
|
|
@ -32,6 +32,11 @@ class Enable : public Castable<Enable, Node> {
|
|||
public:
|
||||
/// The enum class identifing each supported WGSL extension
|
||||
enum class ExtensionKind {
|
||||
/// An extension for the experimental feature
|
||||
/// "chromium_experimental_dp4a".
|
||||
/// See crbug.com/tint/1497 for more details
|
||||
kChromiumExperimentalDP4a,
|
||||
|
||||
/// An internal reserved extension for test, named
|
||||
/// "InternalExtensionForTesting"
|
||||
kInternalExtensionForTesting = -2,
|
||||
|
|
|
@ -300,6 +300,8 @@ fn determinant<N: num>(mat<N, N, f32>) -> f32
|
|||
fn distance(f32, f32) -> f32
|
||||
fn distance<N: num>(vec<N, f32>, vec<N, f32>) -> f32
|
||||
fn dot<N: num, T: fiu32>(vec<N, T>, vec<N, T>) -> T
|
||||
fn dot4I8Packed(u32, u32) -> i32
|
||||
fn dot4U8Packed(u32, u32) -> u32
|
||||
[[stage("fragment")]] fn dpdx(f32) -> f32
|
||||
[[stage("fragment")]] fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>
|
||||
[[stage("fragment")]] fn dpdxCoarse(f32) -> f32
|
||||
|
|
|
@ -371,5 +371,71 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
|
||||
} // namespace texture_constexpr_args
|
||||
|
||||
// TODO(crbug.com/tint/1497): Update or remove ResolverDP4aExtensionValidationTest when the
|
||||
// experimental extension chromium_experimental_dp4a is not needed.
|
||||
using ResolverDP4aExtensionValidationTest = ResolverTest;
|
||||
|
||||
TEST_F(ResolverDP4aExtensionValidationTest, Dot4I8PackedWithExtension) {
|
||||
// enable chromium_experimental_dp4a;
|
||||
// fn func { return dot4I8Packed(1u, 2u); }
|
||||
auto* ext =
|
||||
create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
|
||||
"chromium_experimental_dp4a");
|
||||
AST().AddEnable(ext);
|
||||
|
||||
Func("func", {}, ty.i32(),
|
||||
{
|
||||
Return(Call(Source{Source::Location{12, 34}}, "dot4I8Packed",
|
||||
ast::ExpressionList{Expr(1_u), Expr(2_u)})),
|
||||
});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve());
|
||||
}
|
||||
|
||||
TEST_F(ResolverDP4aExtensionValidationTest, Dot4I8PackedWithoutExtension) {
|
||||
// fn func { return dot4I8Packed(1u, 2u); }
|
||||
Func("func", {}, ty.i32(),
|
||||
{
|
||||
Return(Call(Source{Source::Location{12, 34}}, "dot4I8Packed",
|
||||
ast::ExpressionList{Expr(1_u), Expr(2_u)})),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: cannot call built-in function 'dot4I8Packed' without extension chromium_experimental_dp4a)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverDP4aExtensionValidationTest, Dot4U8PackedWithExtension) {
|
||||
// enable chromium_experimental_dp4a;
|
||||
// fn func { return dot4U8Packed(1u, 2u); }
|
||||
auto* ext =
|
||||
create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
|
||||
"chromium_experimental_dp4a");
|
||||
AST().AddEnable(ext);
|
||||
|
||||
Func("func", {}, ty.u32(),
|
||||
{
|
||||
Return(Call(Source{Source::Location{12, 34}}, "dot4U8Packed",
|
||||
ast::ExpressionList{Expr(1_u), Expr(2_u)})),
|
||||
});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve());
|
||||
}
|
||||
|
||||
TEST_F(ResolverDP4aExtensionValidationTest, Dot4U8PackedWithoutExtension) {
|
||||
// fn func { return dot4U8Packed(1u, 2u); }
|
||||
Func("func", {}, ty.u32(),
|
||||
{
|
||||
Return(Call(Source{Source::Location{12, 34}}, "dot4U8Packed",
|
||||
ast::ExpressionList{Expr(1_u), Expr(2_u)})),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: cannot call built-in function 'dot4U8Packed' without extension chromium_experimental_dp4a)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::resolver
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1309,6 +1309,10 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
|
||||
current_function_->AddDirectlyCalledBuiltin(builtin);
|
||||
|
||||
if (!validator_.RequiredExtensionForBuiltinFunction(call, builder_->AST().Extensions())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsTextureBuiltin(builtin_type)) {
|
||||
if (!validator_.TextureBuiltinFunction(call)) {
|
||||
return nullptr;
|
||||
|
|
|
@ -1517,6 +1517,28 @@ bool Validator::TextureBuiltinFunction(const sem::Call* call) const {
|
|||
check_arg_is_constexpr(sem::ParameterUsage::kComponent, 0, 3);
|
||||
}
|
||||
|
||||
bool Validator::RequiredExtensionForBuiltinFunction(const sem::Call* call,
|
||||
const ast::ExtensionSet& extensionSet) const {
|
||||
const auto* builtin = call->Target()->As<sem::Builtin>();
|
||||
if (!builtin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto extension = builtin->RequiredExtension();
|
||||
if (extension == ast::Enable::ExtensionKind::kNotAnExtension) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (extensionSet.find(extension) == extensionSet.cend()) {
|
||||
AddError("cannot call built-in function '" + std::string(builtin->str()) +
|
||||
"' without extension " + ast::Enable::KindToName(extension),
|
||||
call->Declaration()->source);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_statement) const {
|
||||
auto* decl = call->Declaration();
|
||||
auto* target = call->Target()->As<sem::Function>();
|
||||
|
|
|
@ -373,6 +373,13 @@ class Validator {
|
|||
/// @returns true on success, false otherwise
|
||||
bool TextureBuiltinFunction(const sem::Call* call) const;
|
||||
|
||||
/// Validates an optional builtin function and its required extension.
|
||||
/// @param call the builtin call to validate
|
||||
/// @param extensionSet all the extensions declared in current module
|
||||
/// @returns true on success, false otherwise
|
||||
bool RequiredExtensionForBuiltinFunction(const sem::Call* call,
|
||||
const ast::ExtensionSet& extensionSet) const;
|
||||
|
||||
/// Validates there are no duplicate attributes
|
||||
/// @param attributes the list of attributes to validate
|
||||
/// @returns true on success, false otherwise.
|
||||
|
|
|
@ -145,6 +145,16 @@ bool Builtin::HasSideEffects() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
ast::Enable::ExtensionKind Builtin::RequiredExtension() const {
|
||||
switch (type_) {
|
||||
case sem::BuiltinType::kDot4I8Packed:
|
||||
case sem::BuiltinType::kDot4U8Packed:
|
||||
return ast::Enable::ExtensionKind::kChromiumExperimentalDP4a;
|
||||
default:
|
||||
return ast::Enable::ExtensionKind::kNotAnExtension;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tint::sem
|
||||
|
||||
//! @endcond
|
||||
|
|
|
@ -134,6 +134,10 @@ class Builtin final : public Castable<Builtin, CallTarget> {
|
|||
/// one of its inputs)
|
||||
bool HasSideEffects() const;
|
||||
|
||||
/// @returns the required extension of this builtin function. Returns
|
||||
/// ast::Enable::ExtensionKind::kNotAnExtension if no extension is required.
|
||||
ast::Enable::ExtensionKind RequiredExtension() const;
|
||||
|
||||
private:
|
||||
const BuiltinType type_;
|
||||
const PipelineStageSet supported_stages_;
|
||||
|
|
|
@ -56,6 +56,8 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
BuiltinData{"determinant", BuiltinType::kDeterminant},
|
||||
BuiltinData{"distance", BuiltinType::kDistance},
|
||||
BuiltinData{"dot", BuiltinType::kDot},
|
||||
BuiltinData{"dot4I8Packed", BuiltinType::kDot4I8Packed},
|
||||
BuiltinData{"dot4U8Packed", BuiltinType::kDot4U8Packed},
|
||||
BuiltinData{"dpdx", BuiltinType::kDpdx},
|
||||
BuiltinData{"dpdxCoarse", BuiltinType::kDpdxCoarse},
|
||||
BuiltinData{"dpdxFine", BuiltinType::kDpdxFine},
|
||||
|
|
|
@ -89,6 +89,12 @@ BuiltinType ParseBuiltinType(const std::string& name) {
|
|||
if (name == "dot") {
|
||||
return BuiltinType::kDot;
|
||||
}
|
||||
if (name == "dot4I8Packed") {
|
||||
return BuiltinType::kDot4I8Packed;
|
||||
}
|
||||
if (name == "dot4U8Packed") {
|
||||
return BuiltinType::kDot4U8Packed;
|
||||
}
|
||||
if (name == "dpdx") {
|
||||
return BuiltinType::kDpdx;
|
||||
}
|
||||
|
@ -391,6 +397,10 @@ const char* str(BuiltinType i) {
|
|||
return "distance";
|
||||
case BuiltinType::kDot:
|
||||
return "dot";
|
||||
case BuiltinType::kDot4I8Packed:
|
||||
return "dot4I8Packed";
|
||||
case BuiltinType::kDot4U8Packed:
|
||||
return "dot4U8Packed";
|
||||
case BuiltinType::kDpdx:
|
||||
return "dpdx";
|
||||
case BuiltinType::kDpdxCoarse:
|
||||
|
|
|
@ -53,6 +53,8 @@ enum class BuiltinType {
|
|||
kDeterminant,
|
||||
kDistance,
|
||||
kDot,
|
||||
kDot4I8Packed,
|
||||
kDot4U8Packed,
|
||||
kDpdx,
|
||||
kDpdxCoarse,
|
||||
kDpdxFine,
|
||||
|
|
|
@ -9,10 +9,11 @@ See:
|
|||
--------------------------------------------------------------------------------
|
||||
*/ -}}
|
||||
|
||||
{{- /* For each permutation of each overload of each builtin... */ -}}
|
||||
{{- /* For each permutation of each overload of each function... */ -}}
|
||||
{{- range .Sem.Builtins -}}
|
||||
{{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from builtins.def */}}
|
||||
{{- if not (eq .Name "smoothStep") }}
|
||||
{{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from intrinsics.def */}}
|
||||
{{- /* TODO(crbug.com/tint/1536): Remove the bodge below after we support [[extension("extension_name")]] in intrinsics.def */}}
|
||||
{{- if not (or (eq .Name "smoothStep") (eq .Name "dot4I8Packed") (eq .Name "dot4U8Packed"))}}
|
||||
{{- range .Overloads -}}
|
||||
{{- range Permute . -}}
|
||||
{{- /* Generate a ./gen/<function>/<permuataion-hash>.wgsl file using
|
||||
|
|
Loading…
Reference in New Issue