mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 16:37:08 +00:00
Implement atomicSub intrinsic
Polyfill this for HLSL using an atomic add with the operand negated. Fixed: tint:1130 Change-Id: Ifa32d58973f1b48593ec0f6320f47f4358a5a3a9 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/62760 Auto-Submit: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
committed by
Tint LUCI CQ
parent
a96dce9c89
commit
f9d19719fd
File diff suppressed because it is too large
Load Diff
@@ -537,6 +537,7 @@ fn textureLoad(texture: texture_external, coords: vec2<i32>) -> vec4<f32>
|
||||
[[stage("fragment", "compute")]] fn atomicLoad<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>) -> T
|
||||
[[stage("fragment", "compute")]] fn atomicStore<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T)
|
||||
[[stage("fragment", "compute")]] fn atomicAdd<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
|
||||
[[stage("fragment", "compute")]] fn atomicSub<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
|
||||
[[stage("fragment", "compute")]] fn atomicMax<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
|
||||
[[stage("fragment", "compute")]] fn atomicMin<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
|
||||
[[stage("fragment", "compute")]] fn atomicAnd<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T) -> T
|
||||
|
||||
@@ -91,6 +91,7 @@ bool IsAtomicIntrinsic(IntrinsicType i) {
|
||||
return i == sem::IntrinsicType::kAtomicLoad ||
|
||||
i == sem::IntrinsicType::kAtomicStore ||
|
||||
i == sem::IntrinsicType::kAtomicAdd ||
|
||||
i == sem::IntrinsicType::kAtomicSub ||
|
||||
i == sem::IntrinsicType::kAtomicMax ||
|
||||
i == sem::IntrinsicType::kAtomicMin ||
|
||||
i == sem::IntrinsicType::kAtomicAnd ||
|
||||
|
||||
@@ -303,6 +303,9 @@ IntrinsicType ParseIntrinsicType(const std::string& name) {
|
||||
if (name == "atomicAdd") {
|
||||
return IntrinsicType::kAtomicAdd;
|
||||
}
|
||||
if (name == "atomicSub") {
|
||||
return IntrinsicType::kAtomicSub;
|
||||
}
|
||||
if (name == "atomicMax") {
|
||||
return IntrinsicType::kAtomicMax;
|
||||
}
|
||||
@@ -513,6 +516,8 @@ const char* str(IntrinsicType i) {
|
||||
return "atomicStore";
|
||||
case IntrinsicType::kAtomicAdd:
|
||||
return "atomicAdd";
|
||||
case IntrinsicType::kAtomicSub:
|
||||
return "atomicSub";
|
||||
case IntrinsicType::kAtomicMax:
|
||||
return "atomicMax";
|
||||
case IntrinsicType::kAtomicMin:
|
||||
|
||||
@@ -125,6 +125,7 @@ enum class IntrinsicType {
|
||||
kAtomicLoad,
|
||||
kAtomicStore,
|
||||
kAtomicAdd,
|
||||
kAtomicSub,
|
||||
kAtomicMax,
|
||||
kAtomicMin,
|
||||
kAtomicAnd,
|
||||
|
||||
@@ -238,6 +238,9 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicAdd;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicSub;
|
||||
break;
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicMax;
|
||||
break;
|
||||
@@ -723,6 +726,9 @@ std::string DecomposeMemoryAccess::Intrinsic::InternalName() const {
|
||||
case Op::kAtomicAdd:
|
||||
ss << "intrinsic_atomic_add_";
|
||||
break;
|
||||
case Op::kAtomicSub:
|
||||
ss << "intrinsic_atomic_sub_";
|
||||
break;
|
||||
case Op::kAtomicMax:
|
||||
ss << "intrinsic_atomic_max_";
|
||||
break;
|
||||
|
||||
@@ -46,6 +46,7 @@ class DecomposeMemoryAccess
|
||||
kAtomicLoad,
|
||||
kAtomicStore,
|
||||
kAtomicAdd,
|
||||
kAtomicSub,
|
||||
kAtomicMax,
|
||||
kAtomicMin,
|
||||
kAtomicAnd,
|
||||
|
||||
@@ -1237,6 +1237,7 @@ fn main() {
|
||||
atomicStore(&sb.a, 123);
|
||||
ignore(atomicLoad(&sb.a));
|
||||
ignore(atomicAdd(&sb.a, 123));
|
||||
ignore(atomicSub(&sb.a, 123));
|
||||
ignore(atomicMax(&sb.a, 123));
|
||||
ignore(atomicMin(&sb.a, 123));
|
||||
ignore(atomicAnd(&sb.a, 123));
|
||||
@@ -1248,6 +1249,7 @@ fn main() {
|
||||
atomicStore(&sb.b, 123u);
|
||||
ignore(atomicLoad(&sb.b));
|
||||
ignore(atomicAdd(&sb.b, 123u));
|
||||
ignore(atomicSub(&sb.b, 123u));
|
||||
ignore(atomicMax(&sb.b, 123u));
|
||||
ignore(atomicMin(&sb.b, 123u));
|
||||
ignore(atomicAnd(&sb.b, 123u));
|
||||
@@ -1277,56 +1279,62 @@ fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_pa
|
||||
[[internal(intrinsic_atomic_add_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_max_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_sub_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_min_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_max_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_and_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_min_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_or_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_and_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_xor_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_or_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_exchange_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_xor_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_exchange_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
|
||||
|
||||
[[internal(intrinsic_atomic_compare_exchange_weak_storage_i32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
|
||||
fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
|
||||
|
||||
[[internal(intrinsic_atomic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32)
|
||||
fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32)
|
||||
|
||||
[[internal(intrinsic_atomic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> u32
|
||||
fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_add_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_max_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_min_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_sub_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_and_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_max_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_or_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_min_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_xor_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_and_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_exchange_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
[[internal(intrinsic_atomic_or_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_xor_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_exchange_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
|
||||
|
||||
[[internal(intrinsic_atomic_compare_exchange_weak_storage_u32), internal(disable_validation__function_has_no_body)]]
|
||||
fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
|
||||
fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
|
||||
|
||||
[[stage(compute), workgroup_size(1)]]
|
||||
fn main() {
|
||||
@@ -1339,17 +1347,19 @@ fn main() {
|
||||
ignore(tint_symbol_6(sb, 16u, 123));
|
||||
ignore(tint_symbol_7(sb, 16u, 123));
|
||||
ignore(tint_symbol_8(sb, 16u, 123));
|
||||
ignore(tint_symbol_9(sb, 16u, 123, 345));
|
||||
tint_symbol_10(sb, 20u, 123u);
|
||||
ignore(tint_symbol_11(sb, 20u));
|
||||
ignore(tint_symbol_12(sb, 20u, 123u));
|
||||
ignore(tint_symbol_9(sb, 16u, 123));
|
||||
ignore(tint_symbol_10(sb, 16u, 123, 345));
|
||||
tint_symbol_11(sb, 20u, 123u);
|
||||
ignore(tint_symbol_12(sb, 20u));
|
||||
ignore(tint_symbol_13(sb, 20u, 123u));
|
||||
ignore(tint_symbol_14(sb, 20u, 123u));
|
||||
ignore(tint_symbol_15(sb, 20u, 123u));
|
||||
ignore(tint_symbol_16(sb, 20u, 123u));
|
||||
ignore(tint_symbol_17(sb, 20u, 123u));
|
||||
ignore(tint_symbol_18(sb, 20u, 123u));
|
||||
ignore(tint_symbol_19(sb, 20u, 123u, 345u));
|
||||
ignore(tint_symbol_19(sb, 20u, 123u));
|
||||
ignore(tint_symbol_20(sb, 20u, 123u));
|
||||
ignore(tint_symbol_21(sb, 20u, 123u, 345u));
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -1373,6 +1383,7 @@ fn main() {
|
||||
atomicStore(&(w.a), 123);
|
||||
ignore(atomicLoad(&(w.a)));
|
||||
ignore(atomicAdd(&(w.a), 123));
|
||||
ignore(atomicSub(&(w.a), 123));
|
||||
ignore(atomicMax(&(w.a), 123));
|
||||
ignore(atomicMin(&(w.a), 123));
|
||||
ignore(atomicAnd(&(w.a), 123));
|
||||
@@ -1383,6 +1394,7 @@ fn main() {
|
||||
atomicStore(&(w.b), 123u);
|
||||
ignore(atomicLoad(&(w.b)));
|
||||
ignore(atomicAdd(&(w.b), 123u));
|
||||
ignore(atomicSub(&(w.b), 123u));
|
||||
ignore(atomicMax(&(w.b), 123u));
|
||||
ignore(atomicMin(&(w.b), 123u));
|
||||
ignore(atomicAnd(&(w.b), 123u));
|
||||
|
||||
@@ -869,6 +869,7 @@ bool GeneratorImpl::EmitStorageBufferAccess(
|
||||
case Op::kAtomicLoad:
|
||||
case Op::kAtomicStore:
|
||||
case Op::kAtomicAdd:
|
||||
case Op::kAtomicSub:
|
||||
case Op::kAtomicMax:
|
||||
case Op::kAtomicMin:
|
||||
case Op::kAtomicAnd:
|
||||
@@ -930,7 +931,14 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
||||
}
|
||||
l << " = 0;";
|
||||
}
|
||||
line(&buf) << "buffer." << hlsl << "(offset, value, original_value);";
|
||||
{
|
||||
auto l = line(&buf);
|
||||
l << "buffer." << hlsl << "(offset, ";
|
||||
if (intrinsic->op == Op::kAtomicSub) {
|
||||
l << "-";
|
||||
}
|
||||
l << "value, original_value);";
|
||||
}
|
||||
line(&buf) << "return original_value;";
|
||||
return name;
|
||||
};
|
||||
@@ -939,6 +947,10 @@ bool GeneratorImpl::EmitStorageAtomicCall(
|
||||
case Op::kAtomicAdd:
|
||||
return rmw("atomicAdd", "InterlockedAdd");
|
||||
|
||||
case Op::kAtomicSub:
|
||||
// Use add with the operand negated.
|
||||
return rmw("atomicSub", "InterlockedAdd");
|
||||
|
||||
case Op::kAtomicMax:
|
||||
return rmw("atomicMax", "InterlockedMax");
|
||||
|
||||
@@ -1130,6 +1142,10 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
||||
if (i > 0) {
|
||||
pre << ", ";
|
||||
}
|
||||
if (i == 1 && intrinsic->Type() == sem::IntrinsicType::kAtomicSub) {
|
||||
// Sub uses InterlockedAdd with the operand negated.
|
||||
pre << "-";
|
||||
}
|
||||
if (!EmitExpression(pre, arg)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1240,6 +1256,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
|
||||
}
|
||||
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
return call("InterlockedAdd");
|
||||
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
|
||||
@@ -634,6 +634,9 @@ bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
|
||||
case sem::IntrinsicType::kAtomicAdd:
|
||||
return call("atomic_fetch_add_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
return call("atomic_fetch_sub_explicit", true);
|
||||
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
return call("atomic_fetch_max_explicit", true);
|
||||
|
||||
|
||||
@@ -3151,6 +3151,15 @@ bool Builder::GenerateAtomicIntrinsic(ast::CallExpression* call,
|
||||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicSub:
|
||||
return push_function_inst(spv::Op::OpAtomicISub, {
|
||||
result_type,
|
||||
result_id,
|
||||
pointer,
|
||||
memory,
|
||||
semantics,
|
||||
value,
|
||||
});
|
||||
case sem::IntrinsicType::kAtomicMax:
|
||||
return push_function_inst(
|
||||
is_value_signed() ? spv::Op::OpAtomicSMax : spv::Op::OpAtomicUMax,
|
||||
|
||||
Reference in New Issue
Block a user