mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-03 19:55:56 +00:00
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:
parent
4b7af8d2c9
commit
f2ec7f38e5
@ -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})
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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,23 +1830,30 @@ 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,
|
||||||
@ -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 {};
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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) {}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
48
src/writer/text_generator_test.cc
Normal file
48
src/writer/text_generator_test.cc
Normal 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
|
@ -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 {
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
)");
|
)");
|
||||||
|
@ -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 = [
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user