intrinsics: Add missing select() overload

WGSL supports select() with vectors, where the condition is a
scalar. To support this in SPIR-V versions older than 1.4, we need to
splat the condition operand to a vector of the same size as the
objects.

Fixed: tint:933
Change-Id: I571af46e74cd7bb24093524ccfed25a3ed612676
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56340
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price
2021-06-29 08:45:34 +00:00
committed by Tint LUCI CQ
parent c7aa21e265
commit 077fe64b11
64 changed files with 4789 additions and 2463 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -359,6 +359,7 @@ fn reverseBits<N: num, T: iu32>(vec<N, T>) -> vec<N, T>
fn round(f32) -> f32
fn round<N: num>(vec<N, f32>) -> vec<N, f32>
fn select<T: scalar>(T, T, bool) -> T
fn select<T: scalar, N: num>(vec<N, T>, vec<N, T>, bool) -> vec<N, T>
fn select<N: num, T: scalar>(vec<N, T>, vec<N, T>, vec<N, bool>) -> vec<N, T>
fn sign(f32) -> f32
fn sign<N: num>(vec<N, f32>) -> vec<N, f32>

View File

@@ -468,8 +468,9 @@ TEST_F(ResolverIntrinsicTest, Select_Error_NoParams) {
EXPECT_EQ(r()->error(),
R"(error: no matching call to select()
2 candidate functions:
3 candidate functions:
select(T, T, bool) -> T where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is f32, i32, u32 or bool
)");
}
@@ -483,8 +484,9 @@ TEST_F(ResolverIntrinsicTest, Select_Error_SelectorInt) {
EXPECT_EQ(r()->error(),
R"(error: no matching call to select(i32, i32, i32)
2 candidate functions:
3 candidate functions:
select(T, T, bool) -> T where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is f32, i32, u32 or bool
)");
}
@@ -500,8 +502,9 @@ TEST_F(ResolverIntrinsicTest, Select_Error_Matrix) {
EXPECT_EQ(r()->error(),
R"(error: no matching call to select(mat2x2<f32>, mat2x2<f32>, bool)
2 candidate functions:
3 candidate functions:
select(T, T, bool) -> T where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is f32, i32, u32 or bool
)");
}
@@ -515,8 +518,9 @@ TEST_F(ResolverIntrinsicTest, Select_Error_MismatchTypes) {
EXPECT_EQ(r()->error(),
R"(error: no matching call to select(f32, vec2<f32>, bool)
2 candidate functions:
3 candidate functions:
select(T, T, bool) -> T where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is f32, i32, u32 or bool
)");
}
@@ -531,8 +535,9 @@ TEST_F(ResolverIntrinsicTest, Select_Error_MismatchVectorSize) {
EXPECT_EQ(r()->error(),
R"(error: no matching call to select(vec2<f32>, vec3<f32>, bool)
2 candidate functions:
3 candidate functions:
select(T, T, bool) -> T where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is f32, i32, u32 or bool
select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is f32, i32, u32 or bool
)");
}

View File

@@ -2441,6 +2441,23 @@ uint32_t Builder::GenerateIntrinsic(ast::CallExpression* call,
if (!cond_id || !true_id || !false_id) {
return 0;
}
// If the condition is scalar but the objects are vectors, we need to
// splat the condition into a vector of the same size.
// TODO(jrprice): If we're targeting SPIR-V 1.4, we don't need to do this.
auto* result_vector_type = intrinsic->ReturnType()->As<sem::Vector>();
if (result_vector_type && intrinsic->Parameters()[2].type->is_scalar()) {
sem::Bool bool_type;
sem::Vector bool_vec_type(&bool_type, result_vector_type->size());
if (!GenerateTypeIfNeeded(&bool_vec_type)) {
return 0;
}
cond_id = GenerateSplat(cond_id, &bool_vec_type);
if (cond_id == 0) {
return 0;
}
}
if (!push_function_inst(
spv::Op::OpSelect,
{Operand::Int(result_type_id), result, Operand::Int(cond_id),