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 {
|
namespace tint::ast {
|
||||||
|
|
||||||
Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
|
Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
|
||||||
|
if (name == "chromium_experimental_dp4a") {
|
||||||
|
return Enable::ExtensionKind::kChromiumExperimentalDP4a;
|
||||||
|
}
|
||||||
|
|
||||||
// The reserved internal extension name for testing
|
// The reserved internal extension name for testing
|
||||||
if (name == "InternalExtensionForTesting") {
|
if (name == "InternalExtensionForTesting") {
|
||||||
return Enable::ExtensionKind::kInternalExtensionForTesting;
|
return Enable::ExtensionKind::kInternalExtensionForTesting;
|
||||||
|
@ -32,6 +36,8 @@ Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
|
||||||
|
|
||||||
std::string Enable::KindToName(ExtensionKind kind) {
|
std::string Enable::KindToName(ExtensionKind kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
case ExtensionKind::kChromiumExperimentalDP4a:
|
||||||
|
return "chromium_experimental_dp4a";
|
||||||
// The reserved internal extension for testing
|
// The reserved internal extension for testing
|
||||||
case ExtensionKind::kInternalExtensionForTesting:
|
case ExtensionKind::kInternalExtensionForTesting:
|
||||||
return "InternalExtensionForTesting";
|
return "InternalExtensionForTesting";
|
||||||
|
|
|
@ -32,6 +32,11 @@ class Enable : public Castable<Enable, Node> {
|
||||||
public:
|
public:
|
||||||
/// The enum class identifing each supported WGSL extension
|
/// The enum class identifing each supported WGSL extension
|
||||||
enum class ExtensionKind {
|
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
|
/// An internal reserved extension for test, named
|
||||||
/// "InternalExtensionForTesting"
|
/// "InternalExtensionForTesting"
|
||||||
kInternalExtensionForTesting = -2,
|
kInternalExtensionForTesting = -2,
|
||||||
|
|
|
@ -300,6 +300,8 @@ fn determinant<N: num>(mat<N, N, f32>) -> f32
|
||||||
fn distance(f32, f32) -> f32
|
fn distance(f32, f32) -> f32
|
||||||
fn distance<N: num>(vec<N, f32>, vec<N, 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 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(f32) -> f32
|
||||||
[[stage("fragment")]] fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>
|
[[stage("fragment")]] fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>
|
||||||
[[stage("fragment")]] fn dpdxCoarse(f32) -> f32
|
[[stage("fragment")]] fn dpdxCoarse(f32) -> f32
|
||||||
|
|
|
@ -371,5 +371,71 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
|
|
||||||
} // namespace texture_constexpr_args
|
} // 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
|
||||||
} // namespace tint::resolver
|
} // 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);
|
current_function_->AddDirectlyCalledBuiltin(builtin);
|
||||||
|
|
||||||
|
if (!validator_.RequiredExtensionForBuiltinFunction(call, builder_->AST().Extensions())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsTextureBuiltin(builtin_type)) {
|
if (IsTextureBuiltin(builtin_type)) {
|
||||||
if (!validator_.TextureBuiltinFunction(call)) {
|
if (!validator_.TextureBuiltinFunction(call)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -1517,6 +1517,28 @@ bool Validator::TextureBuiltinFunction(const sem::Call* call) const {
|
||||||
check_arg_is_constexpr(sem::ParameterUsage::kComponent, 0, 3);
|
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 {
|
bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_statement) const {
|
||||||
auto* decl = call->Declaration();
|
auto* decl = call->Declaration();
|
||||||
auto* target = call->Target()->As<sem::Function>();
|
auto* target = call->Target()->As<sem::Function>();
|
||||||
|
|
|
@ -373,6 +373,13 @@ class Validator {
|
||||||
/// @returns true on success, false otherwise
|
/// @returns true on success, false otherwise
|
||||||
bool TextureBuiltinFunction(const sem::Call* call) const;
|
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
|
/// Validates there are no duplicate attributes
|
||||||
/// @param attributes the list of attributes to validate
|
/// @param attributes the list of attributes to validate
|
||||||
/// @returns true on success, false otherwise.
|
/// @returns true on success, false otherwise.
|
||||||
|
|
|
@ -145,6 +145,16 @@ bool Builtin::HasSideEffects() const {
|
||||||
return false;
|
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
|
} // namespace tint::sem
|
||||||
|
|
||||||
//! @endcond
|
//! @endcond
|
||||||
|
|
|
@ -134,6 +134,10 @@ class Builtin final : public Castable<Builtin, CallTarget> {
|
||||||
/// one of its inputs)
|
/// one of its inputs)
|
||||||
bool HasSideEffects() const;
|
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:
|
private:
|
||||||
const BuiltinType type_;
|
const BuiltinType type_;
|
||||||
const PipelineStageSet supported_stages_;
|
const PipelineStageSet supported_stages_;
|
||||||
|
|
|
@ -56,6 +56,8 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
BuiltinData{"determinant", BuiltinType::kDeterminant},
|
BuiltinData{"determinant", BuiltinType::kDeterminant},
|
||||||
BuiltinData{"distance", BuiltinType::kDistance},
|
BuiltinData{"distance", BuiltinType::kDistance},
|
||||||
BuiltinData{"dot", BuiltinType::kDot},
|
BuiltinData{"dot", BuiltinType::kDot},
|
||||||
|
BuiltinData{"dot4I8Packed", BuiltinType::kDot4I8Packed},
|
||||||
|
BuiltinData{"dot4U8Packed", BuiltinType::kDot4U8Packed},
|
||||||
BuiltinData{"dpdx", BuiltinType::kDpdx},
|
BuiltinData{"dpdx", BuiltinType::kDpdx},
|
||||||
BuiltinData{"dpdxCoarse", BuiltinType::kDpdxCoarse},
|
BuiltinData{"dpdxCoarse", BuiltinType::kDpdxCoarse},
|
||||||
BuiltinData{"dpdxFine", BuiltinType::kDpdxFine},
|
BuiltinData{"dpdxFine", BuiltinType::kDpdxFine},
|
||||||
|
|
|
@ -89,6 +89,12 @@ BuiltinType ParseBuiltinType(const std::string& name) {
|
||||||
if (name == "dot") {
|
if (name == "dot") {
|
||||||
return BuiltinType::kDot;
|
return BuiltinType::kDot;
|
||||||
}
|
}
|
||||||
|
if (name == "dot4I8Packed") {
|
||||||
|
return BuiltinType::kDot4I8Packed;
|
||||||
|
}
|
||||||
|
if (name == "dot4U8Packed") {
|
||||||
|
return BuiltinType::kDot4U8Packed;
|
||||||
|
}
|
||||||
if (name == "dpdx") {
|
if (name == "dpdx") {
|
||||||
return BuiltinType::kDpdx;
|
return BuiltinType::kDpdx;
|
||||||
}
|
}
|
||||||
|
@ -391,6 +397,10 @@ const char* str(BuiltinType i) {
|
||||||
return "distance";
|
return "distance";
|
||||||
case BuiltinType::kDot:
|
case BuiltinType::kDot:
|
||||||
return "dot";
|
return "dot";
|
||||||
|
case BuiltinType::kDot4I8Packed:
|
||||||
|
return "dot4I8Packed";
|
||||||
|
case BuiltinType::kDot4U8Packed:
|
||||||
|
return "dot4U8Packed";
|
||||||
case BuiltinType::kDpdx:
|
case BuiltinType::kDpdx:
|
||||||
return "dpdx";
|
return "dpdx";
|
||||||
case BuiltinType::kDpdxCoarse:
|
case BuiltinType::kDpdxCoarse:
|
||||||
|
|
|
@ -53,6 +53,8 @@ enum class BuiltinType {
|
||||||
kDeterminant,
|
kDeterminant,
|
||||||
kDistance,
|
kDistance,
|
||||||
kDot,
|
kDot,
|
||||||
|
kDot4I8Packed,
|
||||||
|
kDot4U8Packed,
|
||||||
kDpdx,
|
kDpdx,
|
||||||
kDpdxCoarse,
|
kDpdxCoarse,
|
||||||
kDpdxFine,
|
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 -}}
|
{{- range .Sem.Builtins -}}
|
||||||
{{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from builtins.def */}}
|
{{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from intrinsics.def */}}
|
||||||
{{- if not (eq .Name "smoothStep") }}
|
{{- /* 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 .Overloads -}}
|
||||||
{{- range Permute . -}}
|
{{- range Permute . -}}
|
||||||
{{- /* Generate a ./gen/<function>/<permuataion-hash>.wgsl file using
|
{{- /* Generate a ./gen/<function>/<permuataion-hash>.wgsl file using
|
||||||
|
|
Loading…
Reference in New Issue