writer/msl: Implement atomics

Common logic between the HLSL, WGSL and MSL writers has been moved into
the TextGenerator base class.

Fixed: tint:892
Change-Id: I0f469516947fe64817ce6251e436da74e5e176e8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56068
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-06-29 11:53:15 +00:00 committed by Tint LUCI CQ
parent 4b7af8d2c9
commit f2ec7f38e5
59 changed files with 783 additions and 634 deletions

View File

@ -669,6 +669,7 @@ if(${TINT_BUILD_TESTS})
utils/unique_vector_test.cc utils/unique_vector_test.cc
writer/append_vector_test.cc writer/append_vector_test.cc
writer/float_to_string_test.cc writer/float_to_string_test.cc
writer/text_generator_test.cc
) )
if(${TINT_BUILD_SPV_READER}) if(${TINT_BUILD_SPV_READER})

View File

@ -61,7 +61,7 @@ TEST_F(ResolverAtomicValidationTest, Local) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: cannot declare an atomic var in a function scope"); "12:34 error: atomic var requires workgroup storage");
} }
TEST_F(ResolverAtomicValidationTest, NoAtomicExpr) { TEST_F(ResolverAtomicValidationTest, NoAtomicExpr) {

View File

@ -909,22 +909,14 @@ bool Resolver::ValidateVariable(const VariableInfo* info) {
// https://gpuweb.github.io/gpuweb/wgsl/#atomic-types // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types
// Atomic types may only be instantiated by variables in the workgroup storage // Atomic types may only be instantiated by variables in the workgroup storage
// class or by storage buffer variables with a read_write access mode. // class or by storage buffer variables with a read_write access mode.
if (info->type->UnwrapRef()->Is<sem::Atomic>()) { if (info->type->UnwrapRef()->Is<sem::Atomic>() &&
if (info->kind != VariableKind::kGlobal) { info->storage_class != ast::StorageClass::kWorkgroup) {
// Neither storage nor workgroup storage classes can be used in function
// scopes.
AddError("cannot declare an atomic var in a function scope",
info->declaration->type()->source());
return false;
}
if (info->storage_class != ast::StorageClass::kWorkgroup) {
// Storage buffers require a structure, so just check for workgroup // Storage buffers require a structure, so just check for workgroup
// storage here. // storage here.
AddError("atomic var requires workgroup storage", AddError("atomic var requires workgroup storage",
info->declaration->type()->source()); info->declaration->type()->source());
return false; return false;
} }
}
return true; return true;
} }

View File

@ -104,8 +104,7 @@ std::ostream& operator<<(std::ostream& s, const RegisterAndSpace& rs) {
} // namespace } // namespace
GeneratorImpl::GeneratorImpl(const Program* program) GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
: builder_(ProgramBuilder::Wrap(program)) {}
GeneratorImpl::~GeneratorImpl() = default; GeneratorImpl::~GeneratorImpl() = default;
@ -165,10 +164,6 @@ bool GeneratorImpl::Generate() {
return true; return true;
} }
std::string GeneratorImpl::generate_name(const std::string& prefix) {
return builder_.Symbols().NameFor(builder_.Symbols().New(prefix));
}
bool GeneratorImpl::EmitArrayAccessor(std::ostream& out, bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
ast::ArrayAccessorExpression* expr) { ast::ArrayAccessorExpression* expr) {
if (!EmitExpression(out, expr->array())) { if (!EmitExpression(out, expr->array())) {
@ -222,7 +217,7 @@ bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) { bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
if (expr->op() == ast::BinaryOp::kLogicalAnd || if (expr->op() == ast::BinaryOp::kLogicalAnd ||
expr->op() == ast::BinaryOp::kLogicalOr) { expr->op() == ast::BinaryOp::kLogicalOr) {
auto name = generate_name(kTempNamePrefix); auto name = UniqueIdentifier(kTempNamePrefix);
{ {
auto pre = line(); auto pre = line();
@ -505,7 +500,7 @@ bool GeneratorImpl::EmitUniformBufferAccess(
const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) { const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) {
const auto& params = expr->params(); const auto& params = expr->params();
std::string scalar_offset = generate_name("scalar_offset"); std::string scalar_offset = UniqueIdentifier("scalar_offset");
{ {
auto pre = line(); auto pre = line();
pre << "const int " << scalar_offset << " = ("; pre << "const int " << scalar_offset << " = (";
@ -534,7 +529,7 @@ bool GeneratorImpl::EmitUniformBufferAccess(
}; };
// Has a minimum alignment of 8 bytes, so is either .xy or .zw // Has a minimum alignment of 8 bytes, so is either .xy or .zw
auto load_vec2 = [&] { auto load_vec2 = [&] {
std::string ubo_load = generate_name("ubo_load"); std::string ubo_load = UniqueIdentifier("ubo_load");
{ {
auto pre = line(); auto pre = line();
@ -744,7 +739,7 @@ bool GeneratorImpl::EmitStorageAtomicCall(
transform::DecomposeMemoryAccess::Intrinsic::Op op) { transform::DecomposeMemoryAccess::Intrinsic::Op op) {
using Op = transform::DecomposeMemoryAccess::Intrinsic::Op; using Op = transform::DecomposeMemoryAccess::Intrinsic::Op;
std::string result = generate_name("atomic_result"); std::string result = UniqueIdentifier("atomic_result");
auto* result_ty = TypeOf(expr); auto* result_ty = TypeOf(expr);
if (!result_ty->Is<sem::Void>()) { if (!result_ty->Is<sem::Void>()) {
@ -849,7 +844,7 @@ bool GeneratorImpl::EmitStorageAtomicCall(
auto* compare_value = expr->params()[2]; auto* compare_value = expr->params()[2];
auto* value = expr->params()[3]; auto* value = expr->params()[3];
std::string compare = generate_name("atomic_compare_value"); std::string compare = UniqueIdentifier("atomic_compare_value");
{ // T atomic_compare_value = compare_value; { // T atomic_compare_value = compare_value;
auto pre = line(); auto pre = line();
if (!EmitTypeAndName(pre, TypeOf(compare_value), if (!EmitTypeAndName(pre, TypeOf(compare_value),
@ -924,7 +919,7 @@ bool GeneratorImpl::EmitStorageAtomicCall(
bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out, bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
ast::CallExpression* expr, ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Intrinsic* intrinsic) {
std::string result = generate_name("atomic_result"); std::string result = UniqueIdentifier("atomic_result");
if (!intrinsic->ReturnType()->Is<sem::Void>()) { if (!intrinsic->ReturnType()->Is<sem::Void>()) {
auto pre = line(); auto pre = line();
@ -1018,7 +1013,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out,
auto* compare_value = expr->params()[1]; auto* compare_value = expr->params()[1];
auto* value = expr->params()[2]; auto* value = expr->params()[2];
std::string compare = generate_name("atomic_compare_value"); std::string compare = UniqueIdentifier("atomic_compare_value");
{ // T compare_value = <compare_value>; { // T compare_value = <compare_value>;
auto pre = line(); auto pre = line();
@ -1130,8 +1125,8 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
// Exponent is an integer, which HLSL does not have an overload for. // Exponent is an integer, which HLSL does not have an overload for.
// We need to cast from a float. // We need to cast from a float.
auto float_exp = generate_name(kTempNamePrefix); auto float_exp = UniqueIdentifier(kTempNamePrefix);
auto significand = generate_name(kTempNamePrefix); auto significand = UniqueIdentifier(kTempNamePrefix);
line() << "float" << width << " " << float_exp << ";"; line() << "float" << width << " " << float_exp << ";";
{ {
auto pre = line(); auto pre = line();
@ -1173,8 +1168,8 @@ bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
constexpr auto* kMinNormalExponent = "0x0080000"; constexpr auto* kMinNormalExponent = "0x0080000";
constexpr auto* kMaxNormalExponent = "0x7f00000"; constexpr auto* kMaxNormalExponent = "0x7f00000";
auto exponent = generate_name("tint_isnormal_exponent"); auto exponent = UniqueIdentifier("tint_isnormal_exponent");
auto clamped = generate_name("tint_isnormal_clamped"); auto clamped = UniqueIdentifier("tint_isnormal_clamped");
{ {
auto pre = line(); auto pre = line();
@ -1196,7 +1191,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
ast::CallExpression* expr, ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Intrinsic* intrinsic) {
auto* param = expr->params()[0]; auto* param = expr->params()[0];
auto tmp_name = generate_name(kTempNamePrefix); auto tmp_name = UniqueIdentifier(kTempNamePrefix);
std::ostringstream expr_out; std::ostringstream expr_out;
if (!EmitExpression(expr_out, param)) { if (!EmitExpression(expr_out, param)) {
return false; return false;
@ -1261,7 +1256,7 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
ast::CallExpression* expr, ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Intrinsic* intrinsic) {
auto* param = expr->params()[0]; auto* param = expr->params()[0];
auto tmp_name = generate_name(kTempNamePrefix); auto tmp_name = UniqueIdentifier(kTempNamePrefix);
std::ostringstream expr_out; std::ostringstream expr_out;
if (!EmitExpression(expr_out, param)) { if (!EmitExpression(expr_out, param)) {
return false; return false;
@ -1282,7 +1277,7 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
switch (intrinsic->Type()) { switch (intrinsic->Type()) {
case sem::IntrinsicType::kUnpack4x8snorm: case sem::IntrinsicType::kUnpack4x8snorm:
case sem::IntrinsicType::kUnpack2x16snorm: { case sem::IntrinsicType::kUnpack2x16snorm: {
auto tmp_name2 = generate_name(kTempNamePrefix); auto tmp_name2 = UniqueIdentifier(kTempNamePrefix);
line() << "int " << tmp_name2 << " = int(" << expr_out.str() << ");"; line() << "int " << tmp_name2 << " = int(" << expr_out.str() << ");";
{ // Perform sign extension on the converted values. { // Perform sign extension on the converted values.
auto pre = line(); auto pre = line();
@ -1302,7 +1297,7 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
} }
case sem::IntrinsicType::kUnpack4x8unorm: case sem::IntrinsicType::kUnpack4x8unorm:
case sem::IntrinsicType::kUnpack2x16unorm: { case sem::IntrinsicType::kUnpack2x16unorm: {
auto tmp_name2 = generate_name(kTempNamePrefix); auto tmp_name2 = UniqueIdentifier(kTempNamePrefix);
line() << "uint " << tmp_name2 << " = " << expr_out.str() << ";"; line() << "uint " << tmp_name2 << " = " << expr_out.str() << ";";
{ {
auto pre = line(); auto pre = line();
@ -1492,7 +1487,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
} }
// Declare a variable to hold the queried texture info // Declare a variable to hold the queried texture info
auto dims = generate_name(kTempNamePrefix); auto dims = UniqueIdentifier(kTempNamePrefix);
if (num_dimensions == 1) { if (num_dimensions == 1) {
line() << "int " << dims << ";"; line() << "int " << dims << ";";
} else { } else {

View File

@ -361,11 +361,6 @@ class GeneratorImpl : public TextGenerator {
ast::InterpolationType type, ast::InterpolationType type,
ast::InterpolationSampling sampling) const; ast::InterpolationSampling sampling) const;
/// Generate a unique name
/// @param prefix the name prefix
/// @returns a unique name
std::string generate_name(const std::string& prefix);
private: private:
enum class VarType { kIn, kOut }; enum class VarType { kIn, kOut };
@ -376,25 +371,6 @@ class GeneratorImpl : public TextGenerator {
std::string get_buffer_name(ast::Expression* expr); std::string get_buffer_name(ast::Expression* expr);
/// @returns the resolved type of the ast::Expression `expr`
/// @param expr the expression
sem::Type* TypeOf(ast::Expression* expr) const {
return builder_.TypeOf(expr);
}
/// @returns the resolved type of the ast::Type `type`
/// @param type the type
const sem::Type* TypeOf(const ast::Type* type) const {
return builder_.TypeOf(type);
}
/// @returns the resolved type of the ast::TypeDecl `type_decl`
/// @param type_decl the type
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const {
return builder_.TypeOf(type_decl);
}
ProgramBuilder builder_;
std::function<bool()> emit_continuing_; std::function<bool()> emit_continuing_;
std::unordered_map<const sem::Struct*, std::string> structure_builders_; std::unordered_map<const sem::Struct*, std::string> structure_builders_;
}; };

View File

@ -43,24 +43,6 @@ TEST_F(HlslGeneratorImplTest, Generate) {
)"); )");
} }
TEST_F(HlslGeneratorImplTest, InputStructName) {
GeneratorImpl& gen = Build();
ASSERT_EQ(gen.generate_name("func_main_in"), "func_main_in");
}
TEST_F(HlslGeneratorImplTest, InputStructName_ConflictWithExisting) {
Symbols().Register("func_main_out_1");
Symbols().Register("func_main_out_2");
GeneratorImpl& gen = Build();
ASSERT_EQ(gen.generate_name("func_main_out"), "func_main_out");
ASSERT_EQ(gen.generate_name("func_main_out"), "func_main_out_3");
ASSERT_EQ(gen.generate_name("func_main_out"), "func_main_out_4");
ASSERT_EQ(gen.generate_name("func_main_out"), "func_main_out_5");
}
struct HlslBuiltinData { struct HlslBuiltinData {
ast::Builtin builtin; ast::Builtin builtin;
const char* attribute_name; const char* attribute_name;

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "src/writer/msl/generator.h" #include "src/writer/msl/generator.h"
#include "src/writer/msl/generator_impl.h"
namespace tint { namespace tint {
namespace writer { namespace writer {

View File

@ -18,13 +18,14 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "src/writer/msl/generator_impl.h"
#include "src/writer/text.h" #include "src/writer/text.h"
namespace tint { namespace tint {
namespace writer { namespace writer {
namespace msl { namespace msl {
class GeneratorImpl;
/// Class to generate MSL source /// Class to generate MSL source
class Generator : public Text { class Generator : public Text {
public: public:
@ -46,6 +47,9 @@ class Generator : public Text {
std::string error() const; std::string error() const;
private: private:
Generator(const Generator&) = delete;
Generator& operator=(const Generator&) = delete;
std::unique_ptr<GeneratorImpl> impl_; std::unique_ptr<GeneratorImpl> impl_;
}; };

View File

@ -33,6 +33,7 @@
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
#include "src/ast/void.h" #include "src/ast/void.h"
#include "src/sem/array.h" #include "src/sem/array.h"
#include "src/sem/atomic_type.h"
#include "src/sem/bool_type.h" #include "src/sem/bool_type.h"
#include "src/sem/call.h" #include "src/sem/call.h"
#include "src/sem/depth_texture_type.h" #include "src/sem/depth_texture_type.h"
@ -71,8 +72,7 @@ bool last_is_break_or_fallthrough(const ast::BlockStatement* stmts) {
} // namespace } // namespace
GeneratorImpl::GeneratorImpl(const Program* program) GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
: TextGenerator(), program_(program) {}
GeneratorImpl::~GeneratorImpl() = default; GeneratorImpl::~GeneratorImpl() = default;
@ -359,6 +359,9 @@ bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out, bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
ast::CallExpression* expr, ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Intrinsic* intrinsic) {
if (intrinsic->IsAtomic()) {
return EmitAtomicCall(out, expr, intrinsic);
}
if (intrinsic->IsTexture()) { if (intrinsic->IsTexture()) {
return EmitTextureCall(out, expr, intrinsic); return EmitTextureCall(out, expr, intrinsic);
} }
@ -422,6 +425,111 @@ bool GeneratorImpl::EmitIntrinsicCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) {
auto call = [&](const char* name) {
out << name;
{
ScopedParen sp(out);
for (size_t i = 0; i < expr->params().size(); i++) {
auto* arg = expr->params()[i];
if (i > 0) {
out << ", ";
}
if (!EmitExpression(out, arg)) {
return false;
}
}
out << ", memory_order_relaxed";
}
return true;
};
switch (intrinsic->Type()) {
case sem::IntrinsicType::kAtomicLoad:
return call("atomic_load_explicit");
case sem::IntrinsicType::kAtomicStore:
return call("atomic_store_explicit");
case sem::IntrinsicType::kAtomicAdd:
return call("atomic_fetch_add_explicit");
case sem::IntrinsicType::kAtomicMax:
return call("atomic_fetch_max_explicit");
case sem::IntrinsicType::kAtomicMin:
return call("atomic_fetch_min_explicit");
case sem::IntrinsicType::kAtomicAnd:
return call("atomic_fetch_and_explicit");
case sem::IntrinsicType::kAtomicOr:
return call("atomic_fetch_or_explicit");
case sem::IntrinsicType::kAtomicXor:
return call("atomic_fetch_xor_explicit");
case sem::IntrinsicType::kAtomicExchange:
return call("atomic_exchange_explicit");
case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
auto* target = expr->params()[0];
auto* compare_value = expr->params()[1];
auto* value = expr->params()[2];
auto prev_value = UniqueIdentifier("prev_value");
auto matched = UniqueIdentifier("matched");
{ // prev_value = <compare_value>;
auto pre = line();
if (!EmitType(pre, TypeOf(value), "")) {
return false;
}
pre << " " << prev_value << " = ";
if (!EmitExpression(pre, compare_value)) {
return false;
}
pre << ";";
}
{ // bool matched = atomic_compare_exchange_weak_explicit(
// target, &got, <value>, memory_order_relaxed, memory_order_relaxed)
auto pre = line();
pre << "bool " << matched << " = atomic_compare_exchange_weak_explicit";
{
ScopedParen sp(pre);
if (!EmitExpression(pre, target)) {
return false;
}
pre << ", &" << prev_value << ", ";
if (!EmitExpression(pre, value)) {
return false;
}
pre << ", memory_order_relaxed, memory_order_relaxed";
}
pre << ";";
}
{ // [u]int2(got, matched)
if (!EmitType(out, TypeOf(expr), "")) {
return false;
}
out << "(" << prev_value << ", " << matched << ")";
}
return true;
}
default:
break;
}
TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported atomic intrinsic: " << intrinsic->Type();
return false;
}
bool GeneratorImpl::EmitTextureCall(std::ostream& out, bool GeneratorImpl::EmitTextureCall(std::ostream& out,
ast::CallExpression* expr, ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) { const sem::Intrinsic* intrinsic) {
@ -1550,6 +1658,20 @@ bool GeneratorImpl::EmitSwitch(ast::SwitchStatement* stmt) {
bool GeneratorImpl::EmitType(std::ostream& out, bool GeneratorImpl::EmitType(std::ostream& out,
const sem::Type* type, const sem::Type* type,
const std::string& name) { const std::string& name) {
if (auto* atomic = type->As<sem::Atomic>()) {
if (atomic->Type()->Is<sem::I32>()) {
out << "atomic_int";
return true;
}
if (atomic->Type()->Is<sem::U32>()) {
out << "atomic_uint";
return true;
}
TINT_ICE(Writer, diagnostics_)
<< "unhandled atomic type " << atomic->Type()->type_name();
return false;
}
if (auto* ary = type->As<sem::Array>()) { if (auto* ary = type->As<sem::Array>()) {
const sem::Type* base_type = ary; const sem::Type* base_type = ary;
std::vector<uint32_t> sizes; std::vector<uint32_t> sizes;
@ -1570,18 +1692,33 @@ bool GeneratorImpl::EmitType(std::ostream& out,
for (uint32_t size : sizes) { for (uint32_t size : sizes) {
out << "[" << size << "]"; out << "[" << size << "]";
} }
} else if (type->Is<sem::Bool>()) { return true;
}
if (type->Is<sem::Bool>()) {
out << "bool"; out << "bool";
} else if (type->Is<sem::F32>()) { return true;
}
if (type->Is<sem::F32>()) {
out << "float"; out << "float";
} else if (type->Is<sem::I32>()) { return true;
}
if (type->Is<sem::I32>()) {
out << "int"; out << "int";
} else if (auto* mat = type->As<sem::Matrix>()) { return true;
}
if (auto* mat = type->As<sem::Matrix>()) {
if (!EmitType(out, mat->type(), "")) { if (!EmitType(out, mat->type(), "")) {
return false; return false;
} }
out << mat->columns() << "x" << mat->rows(); out << mat->columns() << "x" << mat->rows();
} else if (auto* ptr = type->As<sem::Pointer>()) { return true;
}
if (auto* ptr = type->As<sem::Pointer>()) {
switch (ptr->StorageClass()) { switch (ptr->StorageClass()) {
case ast::StorageClass::kFunction: case ast::StorageClass::kFunction:
case ast::StorageClass::kPrivate: case ast::StorageClass::kPrivate:
@ -1611,13 +1748,22 @@ bool GeneratorImpl::EmitType(std::ostream& out,
} }
out << "* " << name; out << "* " << name;
} }
} else if (type->Is<sem::Sampler>()) { return true;
}
if (type->Is<sem::Sampler>()) {
out << "sampler"; out << "sampler";
} else if (auto* str = type->As<sem::Struct>()) { return true;
}
if (auto* str = type->As<sem::Struct>()) {
// The struct type emits as just the name. The declaration would be emitted // The struct type emits as just the name. The declaration would be emitted
// as part of emitting the declared types. // as part of emitting the declared types.
out << program_->Symbols().NameFor(str->Declaration()->name()); out << program_->Symbols().NameFor(str->Declaration()->name());
} else if (auto* tex = type->As<sem::Texture>()) { return true;
}
if (auto* tex = type->As<sem::Texture>()) {
if (tex->Is<sem::DepthTexture>()) { if (tex->Is<sem::DepthTexture>()) {
out << "depth"; out << "depth";
} else { } else {
@ -1684,25 +1830,32 @@ bool GeneratorImpl::EmitType(std::ostream& out,
return false; return false;
} }
out << ">"; out << ">";
return true;
}
} else if (type->Is<sem::U32>()) { if (type->Is<sem::U32>()) {
out << "uint"; out << "uint";
} else if (auto* vec = type->As<sem::Vector>()) { return true;
}
if (auto* vec = type->As<sem::Vector>()) {
if (!EmitType(out, vec->type(), "")) { if (!EmitType(out, vec->type(), "")) {
return false; return false;
} }
out << vec->size(); out << vec->size();
} else if (type->Is<sem::Void>()) { return true;
}
if (type->Is<sem::Void>()) {
out << "void"; out << "void";
} else { return true;
}
diagnostics_.add_error(diag::System::Writer, diagnostics_.add_error(diag::System::Writer,
"unknown type in EmitType: " + type->type_name()); "unknown type in EmitType: " + type->type_name());
return false; return false;
} }
return true;
}
bool GeneratorImpl::EmitPackedType(std::ostream& out, bool GeneratorImpl::EmitPackedType(std::ostream& out,
const sem::Type* type, const sem::Type* type,
const std::string& name) { const std::string& name) {
@ -2039,6 +2192,10 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(
return SizeAndAlign{str->Size(), str->Align()}; return SizeAndAlign{str->Size(), str->Align()};
} }
if (auto* atomic = ty->As<sem::Atomic>()) {
return MslPackedTypeSizeAndAlign(atomic->Type());
}
TINT_UNREACHABLE(Writer, diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "Unhandled type " << ty->TypeInfo().name; << "Unhandled type " << ty->TypeInfo().name;
return {}; return {};

View File

@ -104,6 +104,15 @@ class GeneratorImpl : public TextGenerator {
bool EmitIntrinsicCall(std::ostream& out, bool EmitIntrinsicCall(std::ostream& out,
ast::CallExpression* expr, ast::CallExpression* expr,
const sem::Intrinsic* intrinsic); const sem::Intrinsic* intrinsic);
/// Handles generating a call to an atomic function (`atomicAdd`,
/// `atomicMax`, etc)
/// @param out the output of the expression stream
/// @param expr the call expression
/// @param intrinsic the semantic information for the atomic intrinsic
/// @returns true if the call expression is emitted
bool EmitAtomicCall(std::ostream& out,
ast::CallExpression* expr,
const sem::Intrinsic* intrinsic);
/// Handles generating a call to a texture function (`textureSample`, /// Handles generating a call to a texture function (`textureSample`,
/// `textureSampleGrad`, etc) /// `textureSampleGrad`, etc)
/// @param out the output of the expression stream /// @param out the output of the expression stream
@ -263,24 +272,6 @@ class GeneratorImpl : public TextGenerator {
ast::InterpolationSampling sampling) const; ast::InterpolationSampling sampling) const;
private: private:
/// @returns the resolved type of the ast::Expression `expr`
/// @param expr the expression
sem::Type* TypeOf(ast::Expression* expr) const {
return program_->TypeOf(expr);
}
/// @returns the resolved type of the ast::Type `type`
/// @param type the type
const sem::Type* TypeOf(const ast::Type* type) const {
return program_->TypeOf(type);
}
/// @returns the resolved type of the ast::TypeDecl `type_decl`
/// @param type_decl the type declaration
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const {
return program_->TypeOf(type_decl);
}
// A pair of byte size and alignment `uint32_t`s. // A pair of byte size and alignment `uint32_t`s.
struct SizeAndAlign { struct SizeAndAlign {
uint32_t size; uint32_t size;
@ -291,7 +282,6 @@ class GeneratorImpl : public TextGenerator {
/// type. /// type.
SizeAndAlign MslPackedTypeSizeAndAlign(const sem::Type* ty); SizeAndAlign MslPackedTypeSizeAndAlign(const sem::Type* ty);
const Program* program_ = nullptr;
std::function<bool()> emit_continuing_; std::function<bool()> emit_continuing_;
}; };

View File

@ -14,10 +14,13 @@
#include "src/writer/text_generator.h" #include "src/writer/text_generator.h"
#include <limits>
namespace tint { namespace tint {
namespace writer { namespace writer {
TextGenerator::TextGenerator() = default; TextGenerator::TextGenerator(const Program* program)
: program_(program), builder_(ProgramBuilder::Wrap(program)) {}
TextGenerator::~TextGenerator() = default; TextGenerator::~TextGenerator() = default;
@ -31,6 +34,10 @@ void TextGenerator::make_indent(std::ostream& out) const {
} }
} }
std::string TextGenerator::UniqueIdentifier(const std::string& prefix) {
return builder_.Symbols().NameFor(builder_.Symbols().New(prefix));
}
TextGenerator::LineWriter::LineWriter(TextGenerator* generator) TextGenerator::LineWriter::LineWriter(TextGenerator* generator)
: gen(generator) {} : gen(generator) {}

View File

@ -20,6 +20,7 @@
#include <utility> #include <utility>
#include "src/diagnostic/diagnostic.h" #include "src/diagnostic/diagnostic.h"
#include "src/program_builder.h"
namespace tint { namespace tint {
namespace writer { namespace writer {
@ -28,7 +29,8 @@ namespace writer {
class TextGenerator { class TextGenerator {
public: public:
/// Constructor /// Constructor
TextGenerator(); /// @param program the program used by the generator
explicit TextGenerator(const Program* program);
~TextGenerator(); ~TextGenerator();
/// Increment the emitter indent level /// Increment the emitter indent level
@ -58,6 +60,11 @@ class TextGenerator {
/// @returns the error /// @returns the error
std::string error() const { return diagnostics_.str(); } std::string error() const { return diagnostics_.str(); }
/// @return a new, unique identifier with the given prefix.
/// @param prefix optional prefix to apply to the generated identifier. If
/// empty "tint" will be used.
std::string UniqueIdentifier(const std::string& prefix = "");
protected: protected:
/// LineWriter is a helper that acts as a string buffer, who's content is /// LineWriter is a helper that acts as a string buffer, who's content is
/// emitted to the TextGenerator as a single line on destruction. /// emitted to the TextGenerator as a single line on destruction.
@ -122,9 +129,31 @@ class TextGenerator {
TextGenerator* gen; TextGenerator* gen;
}; };
/// @returns the resolved type of the ast::Expression `expr`
/// @param expr the expression
sem::Type* TypeOf(ast::Expression* expr) const {
return builder_.TypeOf(expr);
}
/// @returns the resolved type of the ast::Type `type`
/// @param type the type
const sem::Type* TypeOf(const ast::Type* type) const {
return builder_.TypeOf(type);
}
/// @returns the resolved type of the ast::TypeDecl `type_decl`
/// @param type_decl the type
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const {
return builder_.TypeOf(type_decl);
}
/// @returns a new LineWriter, used for buffering and writing a line to out_ /// @returns a new LineWriter, used for buffering and writing a line to out_
LineWriter line() { return LineWriter(this); } LineWriter line() { return LineWriter(this); }
/// The program
Program const* const program_;
/// A ProgramBuilder that thinly wraps program_
ProgramBuilder builder_;
/// The text output stream /// The text output stream
std::ostringstream out_; std::ostringstream out_;
/// Diagnostics generated by the generator /// Diagnostics generated by the generator

View File

@ -0,0 +1,48 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/writer/text_generator.h"
#include "gtest/gtest.h"
namespace tint {
namespace writer {
namespace {
TEST(TextGeneratorTest, UniqueIdentifier) {
Program program(ProgramBuilder{});
TextGenerator gen(&program);
ASSERT_EQ(gen.UniqueIdentifier("ident"), "ident");
ASSERT_EQ(gen.UniqueIdentifier("ident"), "ident_1");
}
TEST(TextGeneratorTest, UniqueIdentifier_ConflictWithExisting) {
ProgramBuilder builder;
builder.Symbols().Register("ident_1");
builder.Symbols().Register("ident_2");
Program program(std::move(builder));
TextGenerator gen(&program);
ASSERT_EQ(gen.UniqueIdentifier("ident"), "ident");
ASSERT_EQ(gen.UniqueIdentifier("ident"), "ident_3");
ASSERT_EQ(gen.UniqueIdentifier("ident"), "ident_4");
ASSERT_EQ(gen.UniqueIdentifier("ident"), "ident_5");
}
} // namespace
} // namespace writer
} // namespace tint

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "src/writer/wgsl/generator.h" #include "src/writer/wgsl/generator.h"
#include "src/writer/wgsl/generator_impl.h"
namespace tint { namespace tint {
namespace writer { namespace writer {

View File

@ -19,12 +19,13 @@
#include <string> #include <string>
#include "src/writer/text.h" #include "src/writer/text.h"
#include "src/writer/wgsl/generator_impl.h"
namespace tint { namespace tint {
namespace writer { namespace writer {
namespace wgsl { namespace wgsl {
class GeneratorImpl;
/// Class to generate WGSL source /// Class to generate WGSL source
class Generator : public Text { class Generator : public Text {
public: public:
@ -46,6 +47,9 @@ class Generator : public Text {
std::string error() const; std::string error() const;
private: private:
Generator(const Generator&) = delete;
Generator& operator=(const Generator&) = delete;
std::unique_ptr<GeneratorImpl> impl_; std::unique_ptr<GeneratorImpl> impl_;
}; };

View File

@ -15,7 +15,6 @@
#include "src/writer/wgsl/generator_impl.h" #include "src/writer/wgsl/generator_impl.h"
#include <algorithm> #include <algorithm>
#include <limits>
#include "src/ast/access.h" #include "src/ast/access.h"
#include "src/ast/alias.h" #include "src/ast/alias.h"
@ -60,8 +59,7 @@ namespace tint {
namespace writer { namespace writer {
namespace wgsl { namespace wgsl {
GeneratorImpl::GeneratorImpl(const Program* program) GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
: TextGenerator(), program_(program) {}
GeneratorImpl::~GeneratorImpl() = default; GeneratorImpl::~GeneratorImpl() = default;
@ -1059,24 +1057,6 @@ bool GeneratorImpl::EmitSwitch(ast::SwitchStatement* stmt) {
return true; return true;
} }
std::string GeneratorImpl::UniqueIdentifier(const std::string& suffix) {
auto const limit =
std::numeric_limits<decltype(next_unique_identifier_suffix)>::max();
while (next_unique_identifier_suffix < limit) {
auto ident = "tint_" + std::to_string(next_unique_identifier_suffix);
if (!suffix.empty()) {
ident += "_" + suffix;
}
next_unique_identifier_suffix++;
if (!program_->Symbols().Get(ident).IsValid()) {
return ident;
}
}
diagnostics_.add_error(diag::System::Writer,
"Unable to generate a unique WGSL identifier");
return "<invalid-ident>";
}
} // namespace wgsl } // namespace wgsl
} // namespace writer } // namespace writer
} // namespace tint } // namespace tint

View File

@ -194,13 +194,6 @@ class GeneratorImpl : public TextGenerator {
/// @param decos the decoration list /// @param decos the decoration list
/// @returns true if the decorations were emitted /// @returns true if the decorations were emitted
bool EmitDecorations(const ast::DecorationList& decos); bool EmitDecorations(const ast::DecorationList& decos);
private:
/// @return a new, unique, valid WGSL identifier with the given suffix.
std::string UniqueIdentifier(const std::string& suffix = "");
Program const* const program_;
uint32_t next_unique_identifier_suffix = 0;
}; };
} // namespace wgsl } // namespace wgsl

View File

@ -141,10 +141,10 @@ TEST_F(WgslGeneratorImplTest, EmitType_StructOffsetDecl) {
ASSERT_TRUE(gen.EmitStructType(s)) << gen.error(); ASSERT_TRUE(gen.EmitStructType(s)) << gen.error();
EXPECT_EQ(gen.result(), R"(struct S { EXPECT_EQ(gen.result(), R"(struct S {
[[size(8)]] [[size(8)]]
tint_0_padding : u32; padding : u32;
a : i32; a : i32;
[[size(4)]] [[size(4)]]
tint_1_padding : u32; padding_1 : u32;
b : f32; b : f32;
}; };
)"); )");
@ -162,10 +162,10 @@ TEST_F(WgslGeneratorImplTest, EmitType_StructOffsetDecl_WithSymbolCollisions) {
ASSERT_TRUE(gen.EmitStructType(s)) << gen.error(); ASSERT_TRUE(gen.EmitStructType(s)) << gen.error();
EXPECT_EQ(gen.result(), R"(struct S { EXPECT_EQ(gen.result(), R"(struct S {
[[size(8)]] [[size(8)]]
tint_1_padding : u32; padding : u32;
tint_0_padding : i32; tint_0_padding : i32;
[[size(4)]] [[size(4)]]
tint_3_padding : u32; padding_1 : u32;
tint_2_padding : f32; tint_2_padding : f32;
}; };
)"); )");

View File

@ -305,6 +305,7 @@ tint_unittests_source_set("tint_unittests_core_src") {
"../src/utils/unique_vector_test.cc", "../src/utils/unique_vector_test.cc",
"../src/writer/append_vector_test.cc", "../src/writer/append_vector_test.cc",
"../src/writer/float_to_string_test.cc", "../src/writer/float_to_string_test.cc",
"../src/writer/text_generator_test.cc",
] ]
deps = [ deps = [

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicAdd_794055(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicAdd_794055(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicAdd(&(*(tint_symbol)), 1); int res = atomic_fetch_add_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicAdd_794055(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicAdd_794055(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicAdd_8a199a(device SB_RW& sb_rw) {
uint res = atomic_fetch_add_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicAdd_8a199a() {
var res : u32 = atomicAdd(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicAdd_8a199a(sb_rw);
atomicAdd_8a199a(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicAdd_8a199a(sb_rw);
atomicAdd_8a199a(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicAdd_d32fe4(device SB_RW& sb_rw) {
int res = atomic_fetch_add_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicAdd_d32fe4() {
var res : i32 = atomicAdd(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicAdd_d32fe4(sb_rw);
atomicAdd_d32fe4(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicAdd_d32fe4(sb_rw);
atomicAdd_d32fe4(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicAdd_d5db1d(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicAdd(&(*(tint_symbol)), 1u); uint res = atomic_fetch_add_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicAdd_d5db1d(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicAdd_d5db1d(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicAnd_152966(device SB_RW& sb_rw) {
int res = atomic_fetch_and_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicAnd_152966() {
var res : i32 = atomicAnd(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicAnd_152966(sb_rw);
atomicAnd_152966(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicAnd_152966(sb_rw);
atomicAnd_152966(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicAnd_34edd3(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicAnd_34edd3(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicAnd(&(*(tint_symbol)), 1u); uint res = atomic_fetch_and_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicAnd_34edd3(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicAnd_34edd3(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicAnd_45a819(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicAnd_45a819(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicAnd(&(*(tint_symbol)), 1); int res = atomic_fetch_and_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicAnd_45a819(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicAnd_45a819(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicAnd_85a8d9(device SB_RW& sb_rw) {
uint res = atomic_fetch_and_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicAnd_85a8d9() {
var res : u32 = atomicAnd(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicAnd_85a8d9(sb_rw);
atomicAnd_85a8d9(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicAnd_85a8d9(sb_rw);
atomicAnd_85a8d9(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,25 +1,23 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicCompareExchangeWeak_12871c(device SB_RW& sb_rw) {
int prev_value = 1;
fn atomicCompareExchangeWeak_12871c() { bool matched = atomic_compare_exchange_weak_explicit(&(sb_rw.arg_0), &prev_value, 1, memory_order_relaxed, memory_order_relaxed);
var res : vec2<i32> = atomicCompareExchangeWeak(&(sb_rw.arg_0), 1, 1); int2 res = int2(prev_value, matched);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicCompareExchangeWeak_12871c(sb_rw);
atomicCompareExchangeWeak_12871c(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicCompareExchangeWeak_12871c(sb_rw);
atomicCompareExchangeWeak_12871c(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,25 +1,23 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicCompareExchangeWeak_6673da(device SB_RW& sb_rw) {
uint prev_value = 1u;
fn atomicCompareExchangeWeak_6673da() { bool matched = atomic_compare_exchange_weak_explicit(&(sb_rw.arg_0), &prev_value, 1u, memory_order_relaxed, memory_order_relaxed);
var res : vec2<u32> = atomicCompareExchangeWeak(&(sb_rw.arg_0), 1u, 1u); uint2 res = uint2(prev_value, matched);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicCompareExchangeWeak_6673da(sb_rw);
atomicCompareExchangeWeak_6673da(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicCompareExchangeWeak_6673da(sb_rw);
atomicCompareExchangeWeak_6673da(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,14 +1,19 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicCompareExchangeWeak_89ea3b(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicCompareExchangeWeak_89ea3b(threadgroup atomic_int* const tint_symbol_1) {
var res : vec2<i32> = atomicCompareExchangeWeak(&(*(tint_symbol)), 1, 1); int prev_value = 1;
bool matched = atomic_compare_exchange_weak_explicit(&(*(tint_symbol_1)), &prev_value, 1, memory_order_relaxed, memory_order_relaxed);
int2 res = int2(prev_value, matched);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicCompareExchangeWeak_89ea3b(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicCompareExchangeWeak_89ea3b(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,19 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicCompareExchangeWeak_b2ab2c(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicCompareExchangeWeak_b2ab2c(threadgroup atomic_uint* const tint_symbol_1) {
var res : vec2<u32> = atomicCompareExchangeWeak(&(*(tint_symbol)), 1u, 1u); uint prev_value = 1u;
bool matched = atomic_compare_exchange_weak_explicit(&(*(tint_symbol_1)), &prev_value, 1u, memory_order_relaxed, memory_order_relaxed);
uint2 res = uint2(prev_value, matched);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicCompareExchangeWeak_b2ab2c(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicCompareExchangeWeak_b2ab2c(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicExchange_0a5dca(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicExchange_0a5dca(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicExchange(&(*(tint_symbol)), 1u); uint res = atomic_exchange_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicExchange_0a5dca(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicExchange_0a5dca(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicExchange_d59712(device SB_RW& sb_rw) {
uint res = atomic_exchange_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicExchange_d59712() {
var res : u32 = atomicExchange(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicExchange_d59712(sb_rw);
atomicExchange_d59712(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicExchange_d59712(sb_rw);
atomicExchange_d59712(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicExchange_e114ba(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicExchange_e114ba(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicExchange(&(*(tint_symbol)), 1); int res = atomic_exchange_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicExchange_e114ba(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicExchange_e114ba(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicExchange_f2e22f(device SB_RW& sb_rw) {
int res = atomic_exchange_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicExchange_f2e22f() {
var res : i32 = atomicExchange(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicExchange_f2e22f(sb_rw);
atomicExchange_f2e22f(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicExchange_f2e22f(sb_rw);
atomicExchange_f2e22f(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicLoad_0806ad(device SB_RW& sb_rw) {
int res = atomic_load_explicit(&(sb_rw.arg_0), memory_order_relaxed);
fn atomicLoad_0806ad() {
var res : i32 = atomicLoad(&(sb_rw.arg_0));
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicLoad_0806ad(sb_rw);
atomicLoad_0806ad(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicLoad_0806ad(sb_rw);
atomicLoad_0806ad(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicLoad_361bf1(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicLoad_361bf1(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicLoad(&(*(tint_symbol))); uint res = atomic_load_explicit(&(*(tint_symbol_1)), memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicLoad_361bf1(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicLoad_361bf1(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicLoad_afcc03(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicLoad_afcc03(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicLoad(&(*(tint_symbol))); int res = atomic_load_explicit(&(*(tint_symbol_1)), memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicLoad_afcc03(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicLoad_afcc03(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicLoad_fe6cc3(device SB_RW& sb_rw) {
uint res = atomic_load_explicit(&(sb_rw.arg_0), memory_order_relaxed);
fn atomicLoad_fe6cc3() {
var res : u32 = atomicLoad(&(sb_rw.arg_0));
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicLoad_fe6cc3(sb_rw);
atomicLoad_fe6cc3(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicLoad_fe6cc3(sb_rw);
atomicLoad_fe6cc3(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicMax_51b9be(device SB_RW& sb_rw) {
uint res = atomic_fetch_max_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicMax_51b9be() {
var res : u32 = atomicMax(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicMax_51b9be(sb_rw);
atomicMax_51b9be(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicMax_51b9be(sb_rw);
atomicMax_51b9be(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicMax_92aa72(device SB_RW& sb_rw) {
int res = atomic_fetch_max_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicMax_92aa72() {
var res : i32 = atomicMax(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicMax_92aa72(sb_rw);
atomicMax_92aa72(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicMax_92aa72(sb_rw);
atomicMax_92aa72(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicMax_a89cc3(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicMax_a89cc3(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicMax(&(*(tint_symbol)), 1); int res = atomic_fetch_max_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicMax_a89cc3(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicMax_a89cc3(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicMax_beccfc(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicMax_beccfc(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicMax(&(*(tint_symbol)), 1u); uint res = atomic_fetch_max_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicMax_beccfc(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicMax_beccfc(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicMin_278235(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicMin_278235(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicMin(&(*(tint_symbol)), 1); int res = atomic_fetch_min_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicMin_278235(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicMin_278235(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicMin_69d383(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicMin_69d383(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicMin(&(*(tint_symbol)), 1u); uint res = atomic_fetch_min_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicMin_69d383(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicMin_69d383(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicMin_8e38dc(device SB_RW& sb_rw) {
int res = atomic_fetch_min_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicMin_8e38dc() {
var res : i32 = atomicMin(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicMin_8e38dc(sb_rw);
atomicMin_8e38dc(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicMin_8e38dc(sb_rw);
atomicMin_8e38dc(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicMin_c67a74(device SB_RW& sb_rw) {
uint res = atomic_fetch_min_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicMin_c67a74() {
var res : u32 = atomicMin(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicMin_c67a74(sb_rw);
atomicMin_c67a74(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicMin_c67a74(sb_rw);
atomicMin_c67a74(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicOr_5e3d61(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicOr_5e3d61(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicOr(&(*(tint_symbol)), 1u); uint res = atomic_fetch_or_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicOr_5e3d61(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicOr_5e3d61(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicOr_5e95d4(device SB_RW& sb_rw) {
uint res = atomic_fetch_or_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicOr_5e95d4() {
var res : u32 = atomicOr(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicOr_5e95d4(sb_rw);
atomicOr_5e95d4(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicOr_5e95d4(sb_rw);
atomicOr_5e95d4(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicOr_8d96a0(device SB_RW& sb_rw) {
int res = atomic_fetch_or_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicOr_8d96a0() {
var res : i32 = atomicOr(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicOr_8d96a0(sb_rw);
atomicOr_8d96a0(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicOr_8d96a0(sb_rw);
atomicOr_8d96a0(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicOr_d09248(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicOr_d09248(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicOr(&(*(tint_symbol)), 1); int res = atomic_fetch_or_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicOr_d09248(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicOr_d09248(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicStore_726882(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicStore_726882(threadgroup atomic_uint* const tint_symbol_1) {
atomicStore(&(*(tint_symbol)), 1u); atomic_store_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicStore_726882(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicStore_726882(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicStore_8bea94(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicStore_8bea94(threadgroup atomic_int* const tint_symbol_1) {
atomicStore(&(*(tint_symbol)), 1); atomic_store_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicStore_8bea94(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicStore_8bea94(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicStore_cdc29e(device SB_RW& sb_rw) {
atomic_store_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicStore_cdc29e() {
atomicStore(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicStore_cdc29e(sb_rw);
atomicStore_cdc29e(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicStore_cdc29e(sb_rw);
atomicStore_cdc29e(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicStore_d1e9a6(device SB_RW& sb_rw) {
atomic_store_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicStore_d1e9a6() {
atomicStore(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicStore_d1e9a6(sb_rw);
atomicStore_d1e9a6(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicStore_d1e9a6(sb_rw);
atomicStore_d1e9a6(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<u32>; /* 0x0000 */ atomic_uint arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicXor_54510e(device SB_RW& sb_rw) {
uint res = atomic_fetch_xor_explicit(&(sb_rw.arg_0), 1u, memory_order_relaxed);
fn atomicXor_54510e() {
var res : u32 = atomicXor(&(sb_rw.arg_0), 1u);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicXor_54510e(sb_rw);
atomicXor_54510e(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicXor_54510e(sb_rw);
atomicXor_54510e(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__u32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicXor_75dc95(tint_symbol : ptr<workgroup, atomic<i32>>) { void atomicXor_75dc95(threadgroup atomic_int* const tint_symbol_1) {
var res : i32 = atomicXor(&(*(tint_symbol)), 1); int res = atomic_fetch_xor_explicit(&(*(tint_symbol_1)), 1, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_int tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>; if ((local_invocation_index == 0u)) {
atomicXor_75dc95(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), int(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicXor_75dc95(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope

View File

@ -1,25 +1,21 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
[[block]]
struct SB_RW { struct SB_RW {
arg_0 : atomic<i32>; /* 0x0000 */ atomic_int arg_0;
}; };
[[group(0), binding(0)]] var<storage, read_write> sb_rw : SB_RW; void atomicXor_c1b78c(device SB_RW& sb_rw) {
int res = atomic_fetch_xor_explicit(&(sb_rw.arg_0), 1, memory_order_relaxed);
fn atomicXor_c1b78c() {
var res : i32 = atomicXor(&(sb_rw.arg_0), 1);
} }
[[stage(fragment)]] fragment void fragment_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn fragment_main() { atomicXor_c1b78c(sb_rw);
atomicXor_c1b78c(); return;
} }
[[stage(compute)]] kernel void compute_main(device SB_RW& sb_rw [[buffer(0)]]) {
fn compute_main() { atomicXor_c1b78c(sb_rw);
atomicXor_c1b78c(); return;
} }
Failed to generate: error: unknown type in EmitType: __atomic__i32

View File

@ -1,14 +1,17 @@
SKIP: FAILED #include <metal_stdlib>
using namespace metal;
fn atomicXor_c8e6be(tint_symbol : ptr<workgroup, atomic<u32>>) { void atomicXor_c8e6be(threadgroup atomic_uint* const tint_symbol_1) {
var res : u32 = atomicXor(&(*(tint_symbol)), 1u); uint res = atomic_fetch_xor_explicit(&(*(tint_symbol_1)), 1u, memory_order_relaxed);
} }
[[stage(compute)]] kernel void compute_main(uint local_invocation_index [[thread_index_in_threadgroup]]) {
fn compute_main() { threadgroup atomic_uint tint_symbol_2;
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>; if ((local_invocation_index == 0u)) {
atomicXor_c8e6be(&(tint_symbol_1)); atomic_store_explicit(&(tint_symbol_2), uint(), memory_order_relaxed);
}
threadgroup_barrier(mem_flags::mem_threadgroup);
atomicXor_c8e6be(&(tint_symbol_2));
return;
} }
error: cannot declare an atomic var in a function scope