tint/transform: Polyfill bit-shift with RHS modulo
Fixed: tint:1453 Fixed: tint:1543 Change-Id: Idb5af752d7a3bb9e181cc47430ad4ddfb707873d Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/108440 Auto-Submit: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
91e27f25f9
commit
02f04d914d
|
@ -614,7 +614,7 @@ Transform::ApplyResult BuiltinPolyfill::Apply(const Program* src,
|
||||||
|
|
||||||
auto& builtins = cfg->builtins;
|
auto& builtins = cfg->builtins;
|
||||||
|
|
||||||
utils::Hashmap<const sem::Builtin*, Symbol, 8> polyfills;
|
utils::Hashmap<const sem::Builtin*, Symbol, 8> builtin_polyfills;
|
||||||
|
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
CloneContext ctx{&b, src, /* auto_clone_symbols */ true};
|
CloneContext ctx{&b, src, /* auto_clone_symbols */ true};
|
||||||
|
@ -622,114 +622,137 @@ Transform::ApplyResult BuiltinPolyfill::Apply(const Program* src,
|
||||||
|
|
||||||
bool made_changes = false;
|
bool made_changes = false;
|
||||||
for (auto* node : src->ASTNodes().Objects()) {
|
for (auto* node : src->ASTNodes().Objects()) {
|
||||||
if (auto* call = src->Sem().Get<sem::Call>(node)) {
|
auto* expr = src->Sem().Get<sem::Expression>(node);
|
||||||
if (auto* builtin = call->Target()->As<sem::Builtin>()) {
|
if (!expr || expr->Stage() == sem::EvaluationStage::kConstant) {
|
||||||
if (call->Stage() == sem::EvaluationStage::kConstant) {
|
continue; // Don't polyfill @const expressions
|
||||||
continue; // Don't polyfill @const expressions
|
}
|
||||||
}
|
|
||||||
Symbol polyfill;
|
|
||||||
switch (builtin->Type()) {
|
|
||||||
case sem::BuiltinType::kAcosh:
|
|
||||||
if (builtins.acosh != Level::kNone) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.acosh(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kAsinh:
|
|
||||||
if (builtins.asinh) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.asinh(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kAtanh:
|
|
||||||
if (builtins.atanh != Level::kNone) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.atanh(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kClamp:
|
|
||||||
if (builtins.clamp_int) {
|
|
||||||
auto& sig = builtin->Signature();
|
|
||||||
if (sig.parameters[0]->Type()->is_integer_scalar_or_vector()) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.clampInteger(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kCountLeadingZeros:
|
|
||||||
if (builtins.count_leading_zeros) {
|
|
||||||
polyfill = polyfills.GetOrCreate(builtin, [&] {
|
|
||||||
return s.countLeadingZeros(builtin->ReturnType());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kCountTrailingZeros:
|
|
||||||
if (builtins.count_trailing_zeros) {
|
|
||||||
polyfill = polyfills.GetOrCreate(builtin, [&] {
|
|
||||||
return s.countTrailingZeros(builtin->ReturnType());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kExtractBits:
|
|
||||||
if (builtins.extract_bits != Level::kNone) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.extractBits(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kFirstLeadingBit:
|
|
||||||
if (builtins.first_leading_bit) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.firstLeadingBit(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kFirstTrailingBit:
|
|
||||||
if (builtins.first_trailing_bit) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.firstTrailingBit(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kInsertBits:
|
|
||||||
if (builtins.insert_bits != Level::kNone) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.insertBits(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kSaturate:
|
|
||||||
if (builtins.saturate) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.saturate(builtin->ReturnType()); });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kTextureSampleBaseClampToEdge:
|
|
||||||
if (builtins.texture_sample_base_clamp_to_edge_2d_f32) {
|
|
||||||
auto& sig = builtin->Signature();
|
|
||||||
auto* tex = sig.Parameter(sem::ParameterUsage::kTexture);
|
|
||||||
if (auto* stex = tex->Type()->As<sem::SampledTexture>()) {
|
|
||||||
if (stex->type()->Is<sem::F32>()) {
|
|
||||||
polyfill = polyfills.GetOrCreate(builtin, [&] {
|
|
||||||
return s.textureSampleBaseClampToEdge_2d_f32();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sem::BuiltinType::kQuantizeToF16:
|
|
||||||
if (builtins.quantize_to_vec_f16) {
|
|
||||||
if (auto* vec = builtin->ReturnType()->As<sem::Vector>()) {
|
|
||||||
polyfill = polyfills.GetOrCreate(
|
|
||||||
builtin, [&] { return s.quantizeToF16(vec); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if (auto* call = expr->As<sem::Call>()) {
|
||||||
break;
|
auto* builtin = call->Target()->As<sem::Builtin>();
|
||||||
}
|
if (!builtin) {
|
||||||
if (polyfill.IsValid()) {
|
continue;
|
||||||
auto* replacement = s.b.Call(polyfill, ctx.Clone(call->Declaration()->args));
|
}
|
||||||
ctx.Replace(call->Declaration(), replacement);
|
Symbol polyfill;
|
||||||
made_changes = true;
|
switch (builtin->Type()) {
|
||||||
}
|
case sem::BuiltinType::kAcosh:
|
||||||
|
if (builtins.acosh != Level::kNone) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.acosh(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kAsinh:
|
||||||
|
if (builtins.asinh) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.asinh(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kAtanh:
|
||||||
|
if (builtins.atanh != Level::kNone) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.atanh(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kClamp:
|
||||||
|
if (builtins.clamp_int) {
|
||||||
|
auto& sig = builtin->Signature();
|
||||||
|
if (sig.parameters[0]->Type()->is_integer_scalar_or_vector()) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.clampInteger(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kCountLeadingZeros:
|
||||||
|
if (builtins.count_leading_zeros) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.countLeadingZeros(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kCountTrailingZeros:
|
||||||
|
if (builtins.count_trailing_zeros) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.countTrailingZeros(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kExtractBits:
|
||||||
|
if (builtins.extract_bits != Level::kNone) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.extractBits(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kFirstLeadingBit:
|
||||||
|
if (builtins.first_leading_bit) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.firstLeadingBit(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kFirstTrailingBit:
|
||||||
|
if (builtins.first_trailing_bit) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.firstTrailingBit(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kInsertBits:
|
||||||
|
if (builtins.insert_bits != Level::kNone) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.insertBits(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kSaturate:
|
||||||
|
if (builtins.saturate) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.saturate(builtin->ReturnType()); });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kTextureSampleBaseClampToEdge:
|
||||||
|
if (builtins.texture_sample_base_clamp_to_edge_2d_f32) {
|
||||||
|
auto& sig = builtin->Signature();
|
||||||
|
auto* tex = sig.Parameter(sem::ParameterUsage::kTexture);
|
||||||
|
if (auto* stex = tex->Type()->As<sem::SampledTexture>()) {
|
||||||
|
if (stex->type()->Is<sem::F32>()) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(builtin, [&] {
|
||||||
|
return s.textureSampleBaseClampToEdge_2d_f32();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sem::BuiltinType::kQuantizeToF16:
|
||||||
|
if (builtins.quantize_to_vec_f16) {
|
||||||
|
if (auto* vec = builtin->ReturnType()->As<sem::Vector>()) {
|
||||||
|
polyfill = builtin_polyfills.GetOrCreate(
|
||||||
|
builtin, [&] { return s.quantizeToF16(vec); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polyfill.IsValid()) {
|
||||||
|
auto* replacement = s.b.Call(polyfill, ctx.Clone(call->Declaration()->args));
|
||||||
|
ctx.Replace(call->Declaration(), replacement);
|
||||||
|
made_changes = true;
|
||||||
|
}
|
||||||
|
} else if (auto* bin_op = node->As<ast::BinaryExpression>()) {
|
||||||
|
switch (bin_op->op) {
|
||||||
|
case ast::BinaryOp::kShiftLeft:
|
||||||
|
case ast::BinaryOp::kShiftRight:
|
||||||
|
if (builtins.bitshift_modulo) {
|
||||||
|
auto* lhs_ty = src->TypeOf(bin_op->lhs)->UnwrapRef();
|
||||||
|
auto* rhs_ty = src->TypeOf(bin_op->rhs)->UnwrapRef();
|
||||||
|
auto* lhs_el_ty = sem::Type::DeepestElementOf(lhs_ty);
|
||||||
|
const ast::Expression* mask = b.Expr(AInt(lhs_el_ty->Size() * 8 - 1));
|
||||||
|
if (rhs_ty->Is<sem::Vector>()) {
|
||||||
|
mask = b.Construct(CreateASTTypeFor(ctx, rhs_ty), mask);
|
||||||
|
}
|
||||||
|
auto* mod = b.And(ctx.Clone(bin_op->rhs), mask);
|
||||||
|
ctx.Replace(bin_op->rhs, mod);
|
||||||
|
made_changes = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ class BuiltinPolyfill final : public Castable<BuiltinPolyfill, Transform> {
|
||||||
bool asinh = false;
|
bool asinh = false;
|
||||||
/// What level should `atanh` be polyfilled?
|
/// What level should `atanh` be polyfilled?
|
||||||
Level atanh = Level::kNone;
|
Level atanh = Level::kNone;
|
||||||
|
/// Should the RHS of `<<` and `>>` be wrapped in a modulo bit-width of LHS?
|
||||||
|
bool bitshift_modulo = false;
|
||||||
/// Should `clamp()` be polyfilled for integer values (scalar or vector)?
|
/// Should `clamp()` be polyfilled for integer values (scalar or vector)?
|
||||||
bool clamp_int = false;
|
bool clamp_int = false;
|
||||||
/// Should `countLeadingZeros()` be polyfilled?
|
/// Should `countLeadingZeros()` be polyfilled?
|
||||||
|
@ -66,7 +68,7 @@ class BuiltinPolyfill final : public Castable<BuiltinPolyfill, Transform> {
|
||||||
/// Should `textureSampleBaseClampToEdge()` be polyfilled for texture_2d<f32> textures?
|
/// Should `textureSampleBaseClampToEdge()` be polyfilled for texture_2d<f32> textures?
|
||||||
bool texture_sample_base_clamp_to_edge_2d_f32 = false;
|
bool texture_sample_base_clamp_to_edge_2d_f32 = false;
|
||||||
/// Should the vector form of `quantizeToF16()` be polyfilled with a scalar implementation?
|
/// Should the vector form of `quantizeToF16()` be polyfilled with a scalar implementation?
|
||||||
/// See crbug.com/tint/1741
|
/// See crbug.com/tint/1741
|
||||||
bool quantize_to_vec_f16 = false;
|
bool quantize_to_vec_f16 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -398,6 +398,145 @@ fn f() {
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// bitshiftModulo
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
DataMap polyfillBitshiftModulo() {
|
||||||
|
BuiltinPolyfill::Builtins builtins;
|
||||||
|
builtins.bitshift_modulo = true;
|
||||||
|
DataMap data;
|
||||||
|
data.Add<BuiltinPolyfill::Config>(builtins);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, ShouldRunBitshiftModulo_shl_scalar) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = 1i << v;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
|
||||||
|
EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillBitshiftModulo()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, ShouldRunBitshiftModulo_shl_vector) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = vec3(1i) << vec3(v);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
|
||||||
|
EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillBitshiftModulo()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, ShouldRunBitshiftModulo_shr_scalar) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = 1i >> v;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
|
||||||
|
EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillBitshiftModulo()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, ShouldRunBitshiftModulo_shr_vector) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = vec3(1i) >> vec3(v);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
EXPECT_FALSE(ShouldRun<BuiltinPolyfill>(src));
|
||||||
|
EXPECT_TRUE(ShouldRun<BuiltinPolyfill>(src, polyfillBitshiftModulo()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, BitshiftModulo_shl_scalar) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = 1i << v;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = (1i << (v & 31));
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto got = Run<BuiltinPolyfill>(src, polyfillBitshiftModulo());
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, BitshiftModulo_shl_vector) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = vec3(1i) << vec3(v);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = (vec3(1i) << (vec3(v) & vec3<u32>(31)));
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto got = Run<BuiltinPolyfill>(src, polyfillBitshiftModulo());
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, BitshiftModulo_shr_scalar) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = 1i >> v;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = (1i >> (v & 31));
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto got = Run<BuiltinPolyfill>(src, polyfillBitshiftModulo());
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuiltinPolyfillTest, BitshiftModulo_shr_vector) {
|
||||||
|
auto* src = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = vec3(1i) >> vec3(v);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
fn f() {
|
||||||
|
let v = 15u;
|
||||||
|
let r = (vec3(1i) >> (vec3(v) & vec3<u32>(31)));
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto got = Run<BuiltinPolyfill>(src, polyfillBitshiftModulo());
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// clampInteger
|
// clampInteger
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -186,6 +186,7 @@ SanitizedResult Sanitize(const Program* in,
|
||||||
transform::BuiltinPolyfill::Builtins polyfills;
|
transform::BuiltinPolyfill::Builtins polyfills;
|
||||||
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
||||||
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
||||||
|
polyfills.bitshift_modulo = true;
|
||||||
polyfills.count_leading_zeros = true;
|
polyfills.count_leading_zeros = true;
|
||||||
polyfills.count_trailing_zeros = true;
|
polyfills.count_trailing_zeros = true;
|
||||||
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
|
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
|
||||||
|
|
|
@ -162,6 +162,7 @@ SanitizedResult Sanitize(const Program* in, const Options& options) {
|
||||||
polyfills.acosh = transform::BuiltinPolyfill::Level::kFull;
|
polyfills.acosh = transform::BuiltinPolyfill::Level::kFull;
|
||||||
polyfills.asinh = true;
|
polyfills.asinh = true;
|
||||||
polyfills.atanh = transform::BuiltinPolyfill::Level::kFull;
|
polyfills.atanh = transform::BuiltinPolyfill::Level::kFull;
|
||||||
|
polyfills.bitshift_modulo = true;
|
||||||
polyfills.clamp_int = true;
|
polyfills.clamp_int = true;
|
||||||
// TODO(crbug.com/tint/1449): Some of these can map to HLSL's `firstbitlow`
|
// TODO(crbug.com/tint/1449): Some of these can map to HLSL's `firstbitlow`
|
||||||
// and `firstbithigh`.
|
// and `firstbithigh`.
|
||||||
|
|
|
@ -171,6 +171,7 @@ SanitizedResult Sanitize(const Program* in, const Options& options) {
|
||||||
transform::BuiltinPolyfill::Builtins polyfills;
|
transform::BuiltinPolyfill::Builtins polyfills;
|
||||||
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
||||||
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
||||||
|
polyfills.bitshift_modulo = true; // crbug.com/tint/1543
|
||||||
polyfills.clamp_int = true;
|
polyfills.clamp_int = true;
|
||||||
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
|
polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
|
||||||
polyfills.first_leading_bit = true;
|
polyfills.first_leading_bit = true;
|
||||||
|
|
|
@ -52,6 +52,7 @@ SanitizedResult Sanitize(const Program* in, const Options& options) {
|
||||||
transform::BuiltinPolyfill::Builtins polyfills;
|
transform::BuiltinPolyfill::Builtins polyfills;
|
||||||
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
||||||
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
|
||||||
|
polyfills.bitshift_modulo = true;
|
||||||
polyfills.clamp_int = true;
|
polyfills.clamp_int = true;
|
||||||
polyfills.count_leading_zeros = true;
|
polyfills.count_leading_zeros = true;
|
||||||
polyfills.count_trailing_zeros = true;
|
polyfills.count_trailing_zeros = true;
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int a = 1;
|
const int a = 1;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const int r = (a << b);
|
const int r = (a << (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int a = 1;
|
const int a = 1;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const int r = (a << b);
|
const int r = (a << (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
int a = 1;
|
int a = 1;
|
||||||
uint b = 2u;
|
uint b = 2u;
|
||||||
int r = (a << b);
|
int r = (a << (b & 31u));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
int const a = 1;
|
int const a = 1;
|
||||||
uint const b = 2u;
|
uint const b = 2u;
|
||||||
int const r = as_type<int>((as_type<uint>(a) << b));
|
int const r = as_type<int>((as_type<uint>(a) << (b & 31u)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 10
|
; Bound: 12
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -14,8 +14,10 @@
|
||||||
%int_1 = OpConstant %int 1
|
%int_1 = OpConstant %int 1
|
||||||
%uint = OpTypeInt 32 0
|
%uint = OpTypeInt 32 0
|
||||||
%uint_2 = OpConstant %uint 2
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%9 = OpShiftLeftLogical %int %int_1 %uint_2
|
%10 = OpBitwiseAnd %uint %uint_2 %uint_31
|
||||||
|
%11 = OpShiftLeftLogical %int %int_1 %10
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint a = 1u;
|
const uint a = 1u;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const uint r = (a << b);
|
const uint r = (a << (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint a = 1u;
|
const uint a = 1u;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const uint r = (a << b);
|
const uint r = (a << (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
uint a = 1u;
|
uint a = 1u;
|
||||||
uint b = 2u;
|
uint b = 2u;
|
||||||
uint r = (a << b);
|
uint r = (a << (b & 31u));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
uint const a = 1u;
|
uint const a = 1u;
|
||||||
uint const b = 2u;
|
uint const b = 2u;
|
||||||
uint const r = (a << b);
|
uint const r = (a << (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 9
|
; Bound: 11
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -13,8 +13,10 @@
|
||||||
%uint = OpTypeInt 32 0
|
%uint = OpTypeInt 32 0
|
||||||
%uint_1 = OpConstant %uint 1
|
%uint_1 = OpConstant %uint 1
|
||||||
%uint_2 = OpConstant %uint 2
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%8 = OpShiftLeftLogical %uint %uint_1 %uint_2
|
%9 = OpBitwiseAnd %uint %uint_2 %uint_31
|
||||||
|
%10 = OpShiftLeftLogical %uint %uint_1 %9
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int3 a = int3(1, 2, 3);
|
const int3 a = int3(1, 2, 3);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const int3 r = (a << b);
|
const int3 r = (a << (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int3 a = int3(1, 2, 3);
|
const int3 a = int3(1, 2, 3);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const int3 r = (a << b);
|
const int3 r = (a << (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
ivec3 a = ivec3(1, 2, 3);
|
ivec3 a = ivec3(1, 2, 3);
|
||||||
uvec3 b = uvec3(4u, 5u, 6u);
|
uvec3 b = uvec3(4u, 5u, 6u);
|
||||||
ivec3 r = (a << b);
|
ivec3 r = (a << (b & uvec3(31u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
int3 const a = int3(1, 2, 3);
|
int3 const a = int3(1, 2, 3);
|
||||||
uint3 const b = uint3(4u, 5u, 6u);
|
uint3 const b = uint3(4u, 5u, 6u);
|
||||||
int3 const r = as_type<int3>((as_type<uint3>(a) << b));
|
int3 const r = as_type<int3>((as_type<uint3>(a) << (b & uint3(31u))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 18
|
; Bound: 21
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -22,8 +22,11 @@
|
||||||
%uint_5 = OpConstant %uint 5
|
%uint_5 = OpConstant %uint 5
|
||||||
%uint_6 = OpConstant %uint 6
|
%uint_6 = OpConstant %uint 6
|
||||||
%16 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
%16 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
|
%18 = OpConstantComposite %v3uint %uint_31 %uint_31 %uint_31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%17 = OpShiftLeftLogical %v3int %10 %16
|
%19 = OpBitwiseAnd %v3uint %16 %18
|
||||||
|
%20 = OpShiftLeftLogical %v3int %10 %19
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint3 a = uint3(1u, 2u, 3u);
|
const uint3 a = uint3(1u, 2u, 3u);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const uint3 r = (a << b);
|
const uint3 r = (a << (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint3 a = uint3(1u, 2u, 3u);
|
const uint3 a = uint3(1u, 2u, 3u);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const uint3 r = (a << b);
|
const uint3 r = (a << (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
uvec3 a = uvec3(1u, 2u, 3u);
|
uvec3 a = uvec3(1u, 2u, 3u);
|
||||||
uvec3 b = uvec3(4u, 5u, 6u);
|
uvec3 b = uvec3(4u, 5u, 6u);
|
||||||
uvec3 r = (a << b);
|
uvec3 r = (a << (b & uvec3(31u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
uint3 const a = uint3(1u, 2u, 3u);
|
uint3 const a = uint3(1u, 2u, 3u);
|
||||||
uint3 const b = uint3(4u, 5u, 6u);
|
uint3 const b = uint3(4u, 5u, 6u);
|
||||||
uint3 const r = (a << b);
|
uint3 const r = (a << (b & uint3(31u)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 16
|
; Bound: 19
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -20,8 +20,11 @@
|
||||||
%uint_5 = OpConstant %uint 5
|
%uint_5 = OpConstant %uint 5
|
||||||
%uint_6 = OpConstant %uint 6
|
%uint_6 = OpConstant %uint 6
|
||||||
%14 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
%14 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
|
%16 = OpConstantComposite %v3uint %uint_31 %uint_31 %uint_31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%15 = OpShiftLeftLogical %v3uint %10 %14
|
%17 = OpBitwiseAnd %v3uint %14 %16
|
||||||
|
%18 = OpShiftLeftLogical %v3uint %10 %17
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int a = 1;
|
const int a = 1;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const int r = (a >> b);
|
const int r = (a >> (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int a = 1;
|
const int a = 1;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const int r = (a >> b);
|
const int r = (a >> (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
int a = 1;
|
int a = 1;
|
||||||
uint b = 2u;
|
uint b = 2u;
|
||||||
int r = (a >> b);
|
int r = (a >> (b & 31u));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
int const a = 1;
|
int const a = 1;
|
||||||
uint const b = 2u;
|
uint const b = 2u;
|
||||||
int const r = (a >> b);
|
int const r = (a >> (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 10
|
; Bound: 12
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -14,8 +14,10 @@
|
||||||
%int_1 = OpConstant %int 1
|
%int_1 = OpConstant %int 1
|
||||||
%uint = OpTypeInt 32 0
|
%uint = OpTypeInt 32 0
|
||||||
%uint_2 = OpConstant %uint 2
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%9 = OpShiftRightArithmetic %int %int_1 %uint_2
|
%10 = OpBitwiseAnd %uint %uint_2 %uint_31
|
||||||
|
%11 = OpShiftRightArithmetic %int %int_1 %10
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint a = 1u;
|
const uint a = 1u;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const uint r = (a >> b);
|
const uint r = (a >> (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint a = 1u;
|
const uint a = 1u;
|
||||||
const uint b = 2u;
|
const uint b = 2u;
|
||||||
const uint r = (a >> b);
|
const uint r = (a >> (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
uint a = 1u;
|
uint a = 1u;
|
||||||
uint b = 2u;
|
uint b = 2u;
|
||||||
uint r = (a >> b);
|
uint r = (a >> (b & 31u));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
uint const a = 1u;
|
uint const a = 1u;
|
||||||
uint const b = 2u;
|
uint const b = 2u;
|
||||||
uint const r = (a >> b);
|
uint const r = (a >> (b & 31u));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 9
|
; Bound: 11
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -13,8 +13,10 @@
|
||||||
%uint = OpTypeInt 32 0
|
%uint = OpTypeInt 32 0
|
||||||
%uint_1 = OpConstant %uint 1
|
%uint_1 = OpConstant %uint 1
|
||||||
%uint_2 = OpConstant %uint 2
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%8 = OpShiftRightLogical %uint %uint_1 %uint_2
|
%9 = OpBitwiseAnd %uint %uint_2 %uint_31
|
||||||
|
%10 = OpShiftRightLogical %uint %uint_1 %9
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int3 a = int3(1, 2, 3);
|
const int3 a = int3(1, 2, 3);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const int3 r = (a >> b);
|
const int3 r = (a >> (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const int3 a = int3(1, 2, 3);
|
const int3 a = int3(1, 2, 3);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const int3 r = (a >> b);
|
const int3 r = (a >> (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
ivec3 a = ivec3(1, 2, 3);
|
ivec3 a = ivec3(1, 2, 3);
|
||||||
uvec3 b = uvec3(4u, 5u, 6u);
|
uvec3 b = uvec3(4u, 5u, 6u);
|
||||||
ivec3 r = (a >> b);
|
ivec3 r = (a >> (b & uvec3(31u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
int3 const a = int3(1, 2, 3);
|
int3 const a = int3(1, 2, 3);
|
||||||
uint3 const b = uint3(4u, 5u, 6u);
|
uint3 const b = uint3(4u, 5u, 6u);
|
||||||
int3 const r = (a >> b);
|
int3 const r = (a >> (b & uint3(31u)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 18
|
; Bound: 21
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -22,8 +22,11 @@
|
||||||
%uint_5 = OpConstant %uint 5
|
%uint_5 = OpConstant %uint 5
|
||||||
%uint_6 = OpConstant %uint 6
|
%uint_6 = OpConstant %uint 6
|
||||||
%16 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
%16 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
|
%18 = OpConstantComposite %v3uint %uint_31 %uint_31 %uint_31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%17 = OpShiftRightArithmetic %v3int %10 %16
|
%19 = OpBitwiseAnd %v3uint %16 %18
|
||||||
|
%20 = OpShiftRightArithmetic %v3int %10 %19
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint3 a = uint3(1u, 2u, 3u);
|
const uint3 a = uint3(1u, 2u, 3u);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const uint3 r = (a >> b);
|
const uint3 r = (a >> (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
void f() {
|
void f() {
|
||||||
const uint3 a = uint3(1u, 2u, 3u);
|
const uint3 a = uint3(1u, 2u, 3u);
|
||||||
const uint3 b = uint3(4u, 5u, 6u);
|
const uint3 b = uint3(4u, 5u, 6u);
|
||||||
const uint3 r = (a >> b);
|
const uint3 r = (a >> (b & (31u).xxx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void f() {
|
void f() {
|
||||||
uvec3 a = uvec3(1u, 2u, 3u);
|
uvec3 a = uvec3(1u, 2u, 3u);
|
||||||
uvec3 b = uvec3(4u, 5u, 6u);
|
uvec3 b = uvec3(4u, 5u, 6u);
|
||||||
uvec3 r = (a >> b);
|
uvec3 r = (a >> (b & uvec3(31u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
|
@ -4,7 +4,7 @@ using namespace metal;
|
||||||
kernel void f() {
|
kernel void f() {
|
||||||
uint3 const a = uint3(1u, 2u, 3u);
|
uint3 const a = uint3(1u, 2u, 3u);
|
||||||
uint3 const b = uint3(4u, 5u, 6u);
|
uint3 const b = uint3(4u, 5u, 6u);
|
||||||
uint3 const r = (a >> b);
|
uint3 const r = (a >> (b & uint3(31u)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; SPIR-V
|
; SPIR-V
|
||||||
; Version: 1.3
|
; Version: 1.3
|
||||||
; Generator: Google Tint Compiler; 0
|
; Generator: Google Tint Compiler; 0
|
||||||
; Bound: 16
|
; Bound: 19
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
|
@ -20,8 +20,11 @@
|
||||||
%uint_5 = OpConstant %uint 5
|
%uint_5 = OpConstant %uint 5
|
||||||
%uint_6 = OpConstant %uint 6
|
%uint_6 = OpConstant %uint 6
|
||||||
%14 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
%14 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6
|
||||||
|
%uint_31 = OpConstant %uint 31
|
||||||
|
%16 = OpConstantComposite %v3uint %uint_31 %uint_31 %uint_31
|
||||||
%f = OpFunction %void None %1
|
%f = OpFunction %void None %1
|
||||||
%4 = OpLabel
|
%4 = OpLabel
|
||||||
%15 = OpShiftRightLogical %v3uint %10 %14
|
%17 = OpBitwiseAnd %v3uint %14 %16
|
||||||
|
%18 = OpShiftRightLogical %v3uint %10 %17
|
||||||
OpReturn
|
OpReturn
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
|
|
Loading…
Reference in New Issue