writer/hlsl: Implement atomics

Storage buffers are emitted as `ByteAddressBuffer`s in HLSL, so we have to jump through hoops to support atomic ops on storage buffer atomics.
Workgroup atomics are far more conventional, but very little code can be shared between these two code paths.

Bug: tint:892
Change-Id: If10ea866e3b67a093e87aca689d34065fd49b705
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54651
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton 2021-06-18 18:56:13 +00:00 committed by Ben Clayton
parent 0a32a724f4
commit e6d171ac66
68 changed files with 1819 additions and 830 deletions

View File

@ -88,6 +88,19 @@ bool IsBarrierIntrinsic(IntrinsicType i) {
i == IntrinsicType::kStorageBarrier; i == IntrinsicType::kStorageBarrier;
} }
bool IsAtomicIntrinsic(IntrinsicType i) {
return i == sem::IntrinsicType::kAtomicLoad ||
i == sem::IntrinsicType::kAtomicStore ||
i == sem::IntrinsicType::kAtomicAdd ||
i == sem::IntrinsicType::kAtomicMax ||
i == sem::IntrinsicType::kAtomicMin ||
i == sem::IntrinsicType::kAtomicAnd ||
i == sem::IntrinsicType::kAtomicOr ||
i == sem::IntrinsicType::kAtomicXor ||
i == sem::IntrinsicType::kAtomicExchange ||
i == sem::IntrinsicType::kAtomicCompareExchangeWeak;
}
Intrinsic::Intrinsic(IntrinsicType type, Intrinsic::Intrinsic(IntrinsicType type,
sem::Type* return_type, sem::Type* return_type,
const ParameterList& parameters, const ParameterList& parameters,
@ -136,5 +149,9 @@ bool Intrinsic::IsBarrier() const {
return IsBarrierIntrinsic(type_); return IsBarrierIntrinsic(type_);
} }
bool Intrinsic::IsAtomic() const {
return IsAtomicIntrinsic(type_);
}
} // namespace sem } // namespace sem
} // namespace tint } // namespace tint

View File

@ -69,6 +69,11 @@ bool IsDataUnpackingIntrinsic(IntrinsicType i);
/// @returns true if the given `i` is a barrier intrinsic /// @returns true if the given `i` is a barrier intrinsic
bool IsBarrierIntrinsic(IntrinsicType i); bool IsBarrierIntrinsic(IntrinsicType i);
/// Determines if the given `i` is a atomic intrinsic
/// @param i the intrinsic
/// @returns true if the given `i` is a atomic intrinsic
bool IsAtomicIntrinsic(IntrinsicType i);
/// Intrinsic holds the semantic information for an intrinsic function. /// Intrinsic holds the semantic information for an intrinsic function.
class Intrinsic : public Castable<Intrinsic, CallTarget> { class Intrinsic : public Castable<Intrinsic, CallTarget> {
public: public:
@ -129,6 +134,9 @@ class Intrinsic : public Castable<Intrinsic, CallTarget> {
/// @returns true if intrinsic is a barrier intrinsic /// @returns true if intrinsic is a barrier intrinsic
bool IsBarrier() const; bool IsBarrier() const;
/// @returns true if intrinsic is a atomic intrinsic
bool IsAtomic() const;
private: private:
IntrinsicType const type_; IntrinsicType const type_;
PipelineStageSet const supported_stages_; PipelineStageSet const supported_stages_;

View File

@ -25,8 +25,10 @@
#include "src/ast/disable_validation_decoration.h" #include "src/ast/disable_validation_decoration.h"
#include "src/ast/scalar_constructor_expression.h" #include "src/ast/scalar_constructor_expression.h"
#include "src/ast/type_name.h" #include "src/ast/type_name.h"
#include "src/ast/unary_op.h"
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/sem/array.h" #include "src/sem/array.h"
#include "src/sem/atomic_type.h"
#include "src/sem/call.h" #include "src/sem/call.h"
#include "src/sem/member_accessor_expression.h" #include "src/sem/member_accessor_expression.h"
#include "src/sem/reference_type.h" #include "src/sem/reference_type.h"
@ -175,16 +177,31 @@ std::unique_ptr<Offset> Mul(LHS&& lhs_, RHS&& rhs_) {
return out; return out;
} }
/// TypePair is a pair of types that can be used as a unordered map or set key. /// LoadStoreKey is the unordered map key to a load or store intrinsic.
struct TypePair { struct LoadStoreKey {
sem::Type const* first; sem::Type const* buf_ty; // buffer type
sem::Type const* second; sem::Type const* el_ty; // element type
bool operator==(const TypePair& rhs) const { bool operator==(const LoadStoreKey& rhs) const {
return first == rhs.first && second == rhs.second; return buf_ty == rhs.buf_ty && el_ty == rhs.el_ty;
} }
struct Hasher { struct Hasher {
inline std::size_t operator()(const TypePair& u) const { inline std::size_t operator()(const LoadStoreKey& u) const {
return utils::Hash(u.first, u.second); return utils::Hash(u.buf_ty, u.el_ty);
}
};
};
/// AtomicKey is the unordered map key to an atomic intrinsic.
struct AtomicKey {
sem::Type const* buf_ty; // buffer type
sem::Type const* el_ty; // element type
sem::IntrinsicType const op; // atomic op
bool operator==(const AtomicKey& rhs) const {
return buf_ty == rhs.buf_ty && el_ty == rhs.el_ty && op == rhs.op;
}
struct Hasher {
inline std::size_t operator()(const AtomicKey& u) const {
return utils::Hash(u.buf_ty, u.el_ty, u.op);
} }
}; };
}; };
@ -200,122 +217,145 @@ uint32_t MatrixColumnStride(const sem::Matrix* mat) {
return ScalarSize(mat->type()) * ((mat->rows() == 2) ? 2 : 4); return ScalarSize(mat->type()) * ((mat->rows() == 2) ? 2 : 4);
} }
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied bool IntrinsicDataTypeFor(const sem::Type* ty,
/// to a stub function to load the type `ty`. DecomposeStorageAccess::Intrinsic::DataType& out) {
DecomposeStorageAccess::Intrinsic* IntrinsicLoadFor(ProgramBuilder* builder,
const sem::Type* ty) {
using Intrinsic = DecomposeStorageAccess::Intrinsic;
auto intrinsic = [builder](Intrinsic::Type type) {
return builder->ASTNodes().Create<Intrinsic>(builder->ID(), type);
};
if (ty->Is<sem::I32>()) { if (ty->Is<sem::I32>()) {
return intrinsic(Intrinsic::kLoadI32); out = DecomposeStorageAccess::Intrinsic::DataType::kI32;
return true;
} }
if (ty->Is<sem::U32>()) { if (ty->Is<sem::U32>()) {
return intrinsic(Intrinsic::kLoadU32); out = DecomposeStorageAccess::Intrinsic::DataType::kU32;
return true;
} }
if (ty->Is<sem::F32>()) { if (ty->Is<sem::F32>()) {
return intrinsic(Intrinsic::kLoadF32); out = DecomposeStorageAccess::Intrinsic::DataType::kF32;
return true;
} }
if (auto* vec = ty->As<sem::Vector>()) { if (auto* vec = ty->As<sem::Vector>()) {
switch (vec->size()) { switch (vec->size()) {
case 2: case 2:
if (vec->type()->Is<sem::I32>()) { if (vec->type()->Is<sem::I32>()) {
return intrinsic(Intrinsic::kLoadVec2I32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec2I32;
return true;
} }
if (vec->type()->Is<sem::U32>()) { if (vec->type()->Is<sem::U32>()) {
return intrinsic(Intrinsic::kLoadVec2U32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec2U32;
return true;
} }
if (vec->type()->Is<sem::F32>()) { if (vec->type()->Is<sem::F32>()) {
return intrinsic(Intrinsic::kLoadVec2F32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec2F32;
return true;
} }
break; break;
case 3: case 3:
if (vec->type()->Is<sem::I32>()) { if (vec->type()->Is<sem::I32>()) {
return intrinsic(Intrinsic::kLoadVec3I32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec3I32;
return true;
} }
if (vec->type()->Is<sem::U32>()) { if (vec->type()->Is<sem::U32>()) {
return intrinsic(Intrinsic::kLoadVec3U32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec3U32;
return true;
} }
if (vec->type()->Is<sem::F32>()) { if (vec->type()->Is<sem::F32>()) {
return intrinsic(Intrinsic::kLoadVec3F32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec3F32;
return true;
} }
break; break;
case 4: case 4:
if (vec->type()->Is<sem::I32>()) { if (vec->type()->Is<sem::I32>()) {
return intrinsic(Intrinsic::kLoadVec4I32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec4I32;
return true;
} }
if (vec->type()->Is<sem::U32>()) { if (vec->type()->Is<sem::U32>()) {
return intrinsic(Intrinsic::kLoadVec4U32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec4U32;
return true;
} }
if (vec->type()->Is<sem::F32>()) { if (vec->type()->Is<sem::F32>()) {
return intrinsic(Intrinsic::kLoadVec4F32); out = DecomposeStorageAccess::Intrinsic::DataType::kVec4F32;
return true;
} }
break; break;
} }
return false;
} }
return nullptr;
return false;
}
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
/// to a stub function to load the type `ty`.
DecomposeStorageAccess::Intrinsic* IntrinsicLoadFor(ProgramBuilder* builder,
const sem::Type* ty) {
DecomposeStorageAccess::Intrinsic::DataType type;
if (!IntrinsicDataTypeFor(ty, type)) {
return nullptr;
}
return builder->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
builder->ID(), DecomposeStorageAccess::Intrinsic::Op::kLoad, type);
} }
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied /// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
/// to a stub function to store the type `ty`. /// to a stub function to store the type `ty`.
DecomposeStorageAccess::Intrinsic* IntrinsicStoreFor(ProgramBuilder* builder, DecomposeStorageAccess::Intrinsic* IntrinsicStoreFor(ProgramBuilder* builder,
const sem::Type* ty) { const sem::Type* ty) {
using Intrinsic = DecomposeStorageAccess::Intrinsic; DecomposeStorageAccess::Intrinsic::DataType type;
if (!IntrinsicDataTypeFor(ty, type)) {
return nullptr;
}
return builder->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
builder->ID(), DecomposeStorageAccess::Intrinsic::Op::kStore, type);
}
auto intrinsic = [builder](Intrinsic::Type type) { /// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
return builder->ASTNodes().Create<Intrinsic>(builder->ID(), type); /// to a stub function for the atomic op and the type `ty`.
}; DecomposeStorageAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
sem::IntrinsicType ity,
const sem::Type* ty) {
auto op = DecomposeStorageAccess::Intrinsic::Op::kAtomicLoad;
switch (ity) {
case sem::IntrinsicType::kAtomicLoad:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicLoad;
break;
case sem::IntrinsicType::kAtomicStore:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicStore;
break;
case sem::IntrinsicType::kAtomicAdd:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicAdd;
break;
case sem::IntrinsicType::kAtomicMax:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicMax;
break;
case sem::IntrinsicType::kAtomicMin:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicMin;
break;
case sem::IntrinsicType::kAtomicAnd:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicAnd;
break;
case sem::IntrinsicType::kAtomicOr:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicOr;
break;
case sem::IntrinsicType::kAtomicXor:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicXor;
break;
case sem::IntrinsicType::kAtomicExchange:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicExchange;
break;
case sem::IntrinsicType::kAtomicCompareExchangeWeak:
op = DecomposeStorageAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
break;
default:
TINT_ICE(builder->Diagnostics())
<< "invalid IntrinsicType for DecomposeStorageAccess::Intrinsic: "
<< ty->type_name();
break;
}
if (ty->Is<sem::I32>()) { DecomposeStorageAccess::Intrinsic::DataType type;
return intrinsic(Intrinsic::kStoreI32); if (!IntrinsicDataTypeFor(ty, type)) {
return nullptr;
} }
if (ty->Is<sem::U32>()) { return builder->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
return intrinsic(Intrinsic::kStoreU32); builder->ID(), op, type);
}
if (ty->Is<sem::F32>()) {
return intrinsic(Intrinsic::kStoreF32);
}
if (auto* vec = ty->As<sem::Vector>()) {
switch (vec->size()) {
case 2:
if (vec->type()->Is<sem::I32>()) {
return intrinsic(Intrinsic::kStoreVec2U32);
}
if (vec->type()->Is<sem::U32>()) {
return intrinsic(Intrinsic::kStoreVec2F32);
}
if (vec->type()->Is<sem::F32>()) {
return intrinsic(Intrinsic::kStoreVec2I32);
}
break;
case 3:
if (vec->type()->Is<sem::I32>()) {
return intrinsic(Intrinsic::kStoreVec3U32);
}
if (vec->type()->Is<sem::U32>()) {
return intrinsic(Intrinsic::kStoreVec3F32);
}
if (vec->type()->Is<sem::F32>()) {
return intrinsic(Intrinsic::kStoreVec3I32);
}
break;
case 4:
if (vec->type()->Is<sem::I32>()) {
return intrinsic(Intrinsic::kStoreVec4U32);
}
if (vec->type()->Is<sem::U32>()) {
return intrinsic(Intrinsic::kStoreVec4F32);
}
if (vec->type()->Is<sem::F32>()) {
return intrinsic(Intrinsic::kStoreVec4I32);
}
break;
}
}
return nullptr;
} }
/// Inserts `node` before `insert_after` in the global declarations of /// Inserts `node` before `insert_after` in the global declarations of
@ -374,9 +414,11 @@ struct DecomposeStorageAccess::State {
/// The visited order of AST expressions (superset of #accesses) /// The visited order of AST expressions (superset of #accesses)
std::vector<ast::Expression*> expression_order; std::vector<ast::Expression*> expression_order;
/// [buffer-type, element-type] -> load function name /// [buffer-type, element-type] -> load function name
std::unordered_map<TypePair, Symbol, TypePair::Hasher> load_funcs; std::unordered_map<LoadStoreKey, Symbol, LoadStoreKey::Hasher> load_funcs;
/// [buffer-type, element-type] -> store function name /// [buffer-type, element-type] -> store function name
std::unordered_map<TypePair, Symbol, TypePair::Hasher> store_funcs; std::unordered_map<LoadStoreKey, Symbol, LoadStoreKey::Hasher> store_funcs;
/// [buffer-type, element-type, atomic-op] -> load function name
std::unordered_map<AtomicKey, Symbol, AtomicKey::Hasher> atomic_funcs;
/// List of storage buffer writes /// List of storage buffer writes
std::vector<Store> stores; std::vector<Store> stores;
@ -419,7 +461,7 @@ struct DecomposeStorageAccess::State {
const sem::Type* buf_ty, const sem::Type* buf_ty,
const sem::Type* el_ty, const sem::Type* el_ty,
const sem::VariableUser* var_user) { const sem::VariableUser* var_user) {
return utils::GetOrCreate(load_funcs, TypePair{buf_ty, el_ty}, [&] { return utils::GetOrCreate(load_funcs, LoadStoreKey{buf_ty, el_ty}, [&] {
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty); auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
ast::VariableList params = { ast::VariableList params = {
@ -495,7 +537,7 @@ struct DecomposeStorageAccess::State {
const sem::Type* buf_ty, const sem::Type* buf_ty,
const sem::Type* el_ty, const sem::Type* el_ty,
const sem::VariableUser* var_user) { const sem::VariableUser* var_user) {
return utils::GetOrCreate(store_funcs, TypePair{buf_ty, el_ty}, [&] { return utils::GetOrCreate(store_funcs, LoadStoreKey{buf_ty, el_ty}, [&] {
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty); auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty); auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
ast::VariableList params{ ast::VariableList params{
@ -560,69 +602,161 @@ struct DecomposeStorageAccess::State {
return func->symbol(); return func->symbol();
}); });
} }
/// AtomicFunc() returns a symbol to an intrinsic function that performs an
/// atomic operation from a storage buffer of type `buf_ty`. The function has
/// the signature:
// `fn atomic_op(buf : buf_ty, offset : u32, ...) -> T`
/// @param ctx the CloneContext
/// @param insert_after the user-declared type to insert the function after
/// @param buf_ty the storage buffer type
/// @param el_ty the storage buffer element type
/// @param intrinsic the atomic intrinsic
/// @param var_user the variable user
/// @return the name of the function that performs the load
Symbol AtomicFunc(CloneContext& ctx,
const ast::TypeDecl* insert_after,
const sem::Type* buf_ty,
const sem::Type* el_ty,
const sem::Intrinsic* intrinsic,
const sem::VariableUser* var_user) {
auto op = intrinsic->Type();
return utils::GetOrCreate(atomic_funcs, AtomicKey{buf_ty, el_ty, op}, [&] {
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
// The first parameter to all WGSL atomics is the expression to the
// atomic. This is replaced with two parameters: the buffer and offset.
ast::VariableList params = {
// Note: The buffer parameter requires the kStorage StorageClass in
// order for HLSL to emit this as a ByteAddressBuffer.
ctx.dst->create<ast::Variable>(
ctx.dst->Sym("buffer"), ast::StorageClass::kStorage,
var_user->Variable()->Access(), buf_ast_ty, true, nullptr,
ast::DecorationList{}),
ctx.dst->Param("offset", ctx.dst->ty.u32()),
};
// Other parameters are copied as-is:
for (size_t i = 1; i < intrinsic->Parameters().size(); i++) {
auto& param = intrinsic->Parameters()[i];
auto* ty = CreateASTTypeFor(&ctx, param.type);
params.emplace_back(ctx.dst->Param("param_" + std::to_string(i), ty));
}
auto* atomic = IntrinsicAtomicFor(ctx.dst, op, el_ty);
if (atomic == nullptr) {
TINT_ICE(ctx.dst->Diagnostics())
<< "IntrinsicAtomicFor() returned nullptr for op " << op
<< " and type " << el_ty->type_name();
}
auto* ret_ty = CreateASTTypeFor(&ctx, intrinsic->ReturnType());
auto* func = ctx.dst->create<ast::Function>(
ctx.dst->Sym(), params, ret_ty, nullptr,
ast::DecorationList{
atomic,
ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
ctx.dst->ID(), ast::DisabledValidation::kFunctionHasNoBody),
},
ast::DecorationList{});
InsertGlobal(ctx, insert_after, func);
return func->symbol();
});
}
}; };
DecomposeStorageAccess::Intrinsic::Intrinsic(ProgramID program_id, Type ty) DecomposeStorageAccess::Intrinsic::Intrinsic(ProgramID program_id,
: Base(program_id), type(ty) {} Op o,
DataType ty)
: Base(program_id), op(o), type(ty) {}
DecomposeStorageAccess::Intrinsic::~Intrinsic() = default; DecomposeStorageAccess::Intrinsic::~Intrinsic() = default;
std::string DecomposeStorageAccess::Intrinsic::InternalName() const { std::string DecomposeStorageAccess::Intrinsic::InternalName() const {
switch (type) { std::stringstream ss;
case kLoadU32: switch (op) {
return "intrinsic_load_u32"; case Op::kLoad:
case kLoadF32: ss << "intrinsic_load_";
return "intrinsic_load_f32"; break;
case kLoadI32: case Op::kStore:
return "intrinsic_load_i32"; ss << "intrinsic_store_";
case kLoadVec2U32: break;
return "intrinsic_load_vec2_u32"; case Op::kAtomicLoad:
case kLoadVec2F32: ss << "intrinsic_atomic_load_";
return "intrinsic_load_vec2_f32"; break;
case kLoadVec2I32: case Op::kAtomicStore:
return "intrinsic_load_vec2_i32"; ss << "intrinsic_atomic_store_";
case kLoadVec3U32: break;
return "intrinsic_load_vec3_u32"; case Op::kAtomicAdd:
case kLoadVec3F32: ss << "intrinsic_atomic_add_";
return "intrinsic_load_vec3_f32"; break;
case kLoadVec3I32: case Op::kAtomicMax:
return "intrinsic_load_vec3_i32"; ss << "intrinsic_atomic_max_";
case kLoadVec4U32: break;
return "intrinsic_load_vec4_u32"; case Op::kAtomicMin:
case kLoadVec4F32: ss << "intrinsic_atomic_min_";
return "intrinsic_load_vec4_f32"; break;
case kLoadVec4I32: case Op::kAtomicAnd:
return "intrinsic_load_vec4_i32"; ss << "intrinsic_atomic_and_";
case kStoreU32: break;
return "intrinsic_store_u32"; case Op::kAtomicOr:
case kStoreF32: ss << "intrinsic_atomic_or_";
return "intrinsic_store_f32"; break;
case kStoreI32: case Op::kAtomicXor:
return "intrinsic_store_i32"; ss << "intrinsic_atomic_xor_";
case kStoreVec2U32: break;
return "intrinsic_store_vec2_u32"; case Op::kAtomicExchange:
case kStoreVec2F32: ss << "intrinsic_atomic_exchange_";
return "intrinsic_store_vec2_f32"; break;
case kStoreVec2I32: case Op::kAtomicCompareExchangeWeak:
return "intrinsic_store_vec2_i32"; ss << "intrinsic_atomic_compare_exchange_weak_";
case kStoreVec3U32: break;
return "intrinsic_store_vec3_u32";
case kStoreVec3F32:
return "intrinsic_store_vec3_f32";
case kStoreVec3I32:
return "intrinsic_store_vec3_i32";
case kStoreVec4U32:
return "intrinsic_store_vec4_u32";
case kStoreVec4F32:
return "intrinsic_store_vec4_f32";
case kStoreVec4I32:
return "intrinsic_store_vec4_i32";
} }
return ""; switch (type) {
case DataType::kU32:
ss << "u32";
break;
case DataType::kF32:
ss << "f32";
break;
case DataType::kI32:
ss << "i32";
break;
case DataType::kVec2U32:
ss << "vec2_u32";
break;
case DataType::kVec2F32:
ss << "vec2_f32";
break;
case DataType::kVec2I32:
ss << "vec2_i32";
break;
case DataType::kVec3U32:
ss << "vec3_u32";
break;
case DataType::kVec3F32:
ss << "vec3_f32";
break;
case DataType::kVec3I32:
ss << "vec3_i32";
break;
case DataType::kVec4U32:
ss << "vec4_u32";
break;
case DataType::kVec4F32:
ss << "vec4_f32";
break;
case DataType::kVec4I32:
ss << "vec4_i32";
break;
}
return ss.str();
} }
DecomposeStorageAccess::Intrinsic* DecomposeStorageAccess::Intrinsic::Clone( DecomposeStorageAccess::Intrinsic* DecomposeStorageAccess::Intrinsic::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
return ctx->dst->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>( return ctx->dst->ASTNodes().Create<DecomposeStorageAccess::Intrinsic>(
ctx->dst->ID(), type); ctx->dst->ID(), op, type);
} }
DecomposeStorageAccess::DecomposeStorageAccess() = default; DecomposeStorageAccess::DecomposeStorageAccess() = default;
@ -728,6 +862,18 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
} }
} }
if (auto* op = node->As<ast::UnaryOpExpression>()) {
if (op->op() == ast::UnaryOp::kAddressOf) {
// &X
if (auto access = state.TakeAccess(op->expr())) {
// HLSL does not support pointers, so just take the access from the
// reference and place it on the pointer.
state.AddAccess(op, std::move(access));
continue;
}
}
}
if (auto* assign = node->As<ast::AssignmentStatement>()) { if (auto* assign = node->As<ast::AssignmentStatement>()) {
// X = Y // X = Y
// Move the LHS access to a store. // Move the LHS access to a store.
@ -741,16 +887,31 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) { if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) { if (intrinsic->Type() == sem::IntrinsicType::kArrayLength) {
// arrayLength(X) // arrayLength(X)
// Don't convert X into a load, this actually requires the real // Don't convert X into a load, this intrinsic actually requires the
// reference. // real pointer.
auto* arg = call_expr->params()[0]; state.TakeAccess(call_expr->params()[0]);
}
if (intrinsic->IsAtomic()) {
if (auto access = state.TakeAccess(call_expr->params()[0])) {
// atomic___(X)
// TODO(crbug.com/tint/806): Once the deprecated arrayLength() auto* buf = access.var->Declaration();
// overload is removed, this can safely assume a pointer arg. auto* offset = access.offset->Build(ctx);
if (auto* address_of = arg->As<ast::UnaryOpExpression>()) { auto* buf_ty = access.var->Type()->UnwrapRef();
arg = address_of->expr(); auto* el_ty = access.type->UnwrapRef()->As<sem::Atomic>()->Type();
auto* insert_after = TypeDeclOf(access.var->Type());
Symbol func =
state.AtomicFunc(ctx, insert_after, buf_ty, el_ty, intrinsic,
access.var->As<sem::VariableUser>());
ast::ExpressionList args{ctx.Clone(buf), offset};
for (size_t i = 1; i < call_expr->params().size(); i++) {
auto* arg = call_expr->params()[i];
args.emplace_back(ctx.Clone(arg));
}
ctx.Replace(call_expr, ctx.dst->Call(func, args));
} }
state.TakeAccess(arg);
} }
} }
} }

View File

@ -28,7 +28,8 @@ class CloneContext;
namespace transform { namespace transform {
/// DecomposeStorageAccess is a transform used to replace storage buffer /// DecomposeStorageAccess is a transform used to replace storage buffer
/// accesses with a combination of load / store functions on primitive types. /// accesses with a combination of load, store or atomic functions on primitive
/// types.
class DecomposeStorageAccess : public Transform { class DecomposeStorageAccess : public Transform {
public: public:
/// Intrinsic is an InternalDecoration that's used to decorate a stub function /// Intrinsic is an InternalDecoration that's used to decorate a stub function
@ -37,38 +38,43 @@ class DecomposeStorageAccess : public Transform {
/// with a possible cast. /// with a possible cast.
class Intrinsic : public Castable<Intrinsic, ast::InternalDecoration> { class Intrinsic : public Castable<Intrinsic, ast::InternalDecoration> {
public: public:
/// Storage access intrinsic type /// Intrinsic op
enum Type { enum class Op {
kLoadU32, // `[RW]ByteAddressBuffer.Load()` kLoad,
kLoadF32, // `asfloat([RW]ByteAddressBuffer.Load())` kStore,
kLoadI32, // `asint([RW]ByteAddressBuffer.Load())` kAtomicLoad,
kLoadVec2U32, // `[RW]ByteAddressBuffer.Load2()` kAtomicStore,
kLoadVec2F32, // `asfloat([RW]ByteAddressBuffer.Load2())` kAtomicAdd,
kLoadVec2I32, // `asint([RW]ByteAddressBuffer.Load2())` kAtomicMax,
kLoadVec3U32, // `[RW]ByteAddressBuffer.Load3()` kAtomicMin,
kLoadVec3F32, // `asfloat([RW]ByteAddressBuffer.Load3())` kAtomicAnd,
kLoadVec3I32, // `asint([RW]ByteAddressBuffer.Load3())` kAtomicOr,
kLoadVec4U32, // `[RW]ByteAddressBuffer.Load4()` kAtomicXor,
kLoadVec4F32, // `asfloat([RW]ByteAddressBuffer.Load4())` kAtomicExchange,
kLoadVec4I32, // `asint([RW]ByteAddressBuffer.Load4())` kAtomicCompareExchangeWeak,
kStoreU32, // `RWByteAddressBuffer.Store()` };
kStoreF32, // `asfloat(RWByteAddressBuffer.Store())`
kStoreI32, // `asint(RWByteAddressBuffer.Store())` /// Intrinsic data type
kStoreVec2U32, // `RWByteAddressBuffer.Store2()` enum class DataType {
kStoreVec2F32, // `asfloat(RWByteAddressBuffer.Store2())` kU32,
kStoreVec2I32, // `asint(RWByteAddressBuffer.Store2())` kF32,
kStoreVec3U32, // `RWByteAddressBuffer.Store3()` kI32,
kStoreVec3F32, // `asfloat(RWByteAddressBuffer.Store3())` kVec2U32,
kStoreVec3I32, // `asint(RWByteAddressBuffer.Store3())` kVec2F32,
kStoreVec4U32, // `RWByteAddressBuffer.Store4()` kVec2I32,
kStoreVec4F32, // `asfloat(RWByteAddressBuffer.Store4())` kVec3U32,
kStoreVec4I32, // `asint(RWByteAddressBuffer.Store4())` kVec3F32,
kVec3I32,
kVec4U32,
kVec4F32,
kVec4I32,
}; };
/// Constructor /// Constructor
/// @param program_id the identifier of the program that owns this node /// @param program_id the identifier of the program that owns this node
/// @param ty the type of the intrinsic /// @param o the op of the intrinsic
Intrinsic(ProgramID program_id, Type ty); /// @param ty the data type of the intrinsic
Intrinsic(ProgramID program_id, Op o, DataType ty);
/// Destructor /// Destructor
~Intrinsic() override; ~Intrinsic() override;
@ -81,8 +87,11 @@ class DecomposeStorageAccess : public Transform {
/// @return the newly cloned object /// @return the newly cloned object
Intrinsic* Clone(CloneContext* ctx) const override; Intrinsic* Clone(CloneContext* ctx) const override;
/// The op of the intrinsic
Op const op;
/// The type of the intrinsic /// The type of the intrinsic
Type const type; DataType const type;
}; };
/// Constructor /// Constructor

View File

@ -309,31 +309,31 @@ fn tint_symbol_1(buffer : SB, offset : u32, value : u32)
[[internal(intrinsic_store_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_2(buffer : SB, offset : u32, value : f32) fn tint_symbol_2(buffer : SB, offset : u32, value : f32)
[[internal(intrinsic_store_vec2_u32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec2_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>) fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>)
[[internal(intrinsic_store_vec2_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec2_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>) fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>)
[[internal(intrinsic_store_vec2_i32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec2_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>) fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>)
[[internal(intrinsic_store_vec3_u32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec3_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>) fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>)
[[internal(intrinsic_store_vec3_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec3_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>) fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>)
[[internal(intrinsic_store_vec3_i32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec3_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>) fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>)
[[internal(intrinsic_store_vec4_u32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec4_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>) fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>)
[[internal(intrinsic_store_vec4_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec4_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>) fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>)
[[internal(intrinsic_store_vec4_i32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec4_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>) fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>)
fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) { fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) {
@ -657,31 +657,31 @@ fn tint_symbol_1(buffer : SB, offset : u32, value : u32)
[[internal(intrinsic_store_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_2(buffer : SB, offset : u32, value : f32) fn tint_symbol_2(buffer : SB, offset : u32, value : f32)
[[internal(intrinsic_store_vec2_u32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec2_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>) fn tint_symbol_3(buffer : SB, offset : u32, value : vec2<i32>)
[[internal(intrinsic_store_vec2_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec2_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>) fn tint_symbol_4(buffer : SB, offset : u32, value : vec2<u32>)
[[internal(intrinsic_store_vec2_i32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec2_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>) fn tint_symbol_5(buffer : SB, offset : u32, value : vec2<f32>)
[[internal(intrinsic_store_vec3_u32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec3_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>) fn tint_symbol_6(buffer : SB, offset : u32, value : vec3<i32>)
[[internal(intrinsic_store_vec3_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec3_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>) fn tint_symbol_7(buffer : SB, offset : u32, value : vec3<u32>)
[[internal(intrinsic_store_vec3_i32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec3_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>) fn tint_symbol_8(buffer : SB, offset : u32, value : vec3<f32>)
[[internal(intrinsic_store_vec4_u32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec4_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>) fn tint_symbol_9(buffer : SB, offset : u32, value : vec4<i32>)
[[internal(intrinsic_store_vec4_f32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec4_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>) fn tint_symbol_10(buffer : SB, offset : u32, value : vec4<u32>)
[[internal(intrinsic_store_vec4_i32), internal(disable_validation__function_has_no_body)]] [[internal(intrinsic_store_vec4_f32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>) fn tint_symbol_11(buffer : SB, offset : u32, value : vec4<f32>)
fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) { fn tint_symbol_12(buffer : SB, offset : u32, value : mat2x2<f32>) {
@ -1011,6 +1011,185 @@ fn main() {
EXPECT_EQ(expect, str(got)); EXPECT_EQ(expect, str(got));
} }
TEST_F(DecomposeStorageAccessTest, StorageBufferAtomics) {
auto* src = R"(
[[block]]
struct SB {
padding : vec4<f32>;
a : atomic<i32>;
b : atomic<u32>;
};
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
[[stage(compute)]]
fn main() {
atomicStore(&sb.a, 123);
ignore(atomicLoad(&sb.a));
ignore(atomicAdd(&sb.a, 123));
ignore(atomicMax(&sb.a, 123));
ignore(atomicMin(&sb.a, 123));
ignore(atomicAnd(&sb.a, 123));
ignore(atomicOr(&sb.a, 123));
ignore(atomicXor(&sb.a, 123));
ignore(atomicExchange(&sb.a, 123));
ignore(atomicCompareExchangeWeak(&sb.a, 123, 345));
atomicStore(&sb.b, 123u);
ignore(atomicLoad(&sb.b));
ignore(atomicAdd(&sb.b, 123u));
ignore(atomicMax(&sb.b, 123u));
ignore(atomicMin(&sb.b, 123u));
ignore(atomicAnd(&sb.b, 123u));
ignore(atomicOr(&sb.b, 123u));
ignore(atomicXor(&sb.b, 123u));
ignore(atomicExchange(&sb.b, 123u));
ignore(atomicCompareExchangeWeak(&sb.b, 123u, 345u));
}
)";
auto* expect = R"(
[[block]]
struct SB {
padding : vec4<f32>;
a : atomic<i32>;
b : atomic<u32>;
};
[[internal(intrinsic_atomic_store_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol(buffer : SB, offset : u32, param_1 : i32)
[[internal(intrinsic_atomic_load_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_1(buffer : SB, offset : u32) -> i32
[[internal(intrinsic_atomic_add_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_2(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_max_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_3(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_min_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_4(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_and_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_5(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_or_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_6(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_xor_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_7(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_exchange_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_8(buffer : SB, offset : u32, param_1 : i32) -> i32
[[internal(intrinsic_atomic_compare_exchange_weak_i32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_9(buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
[[internal(intrinsic_atomic_store_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_10(buffer : SB, offset : u32, param_1 : u32)
[[internal(intrinsic_atomic_load_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_11(buffer : SB, offset : u32) -> u32
[[internal(intrinsic_atomic_add_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_12(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_max_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_13(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_min_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_14(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_and_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_15(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_or_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_16(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_xor_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_17(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_exchange_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_18(buffer : SB, offset : u32, param_1 : u32) -> u32
[[internal(intrinsic_atomic_compare_exchange_weak_u32), internal(disable_validation__function_has_no_body)]]
fn tint_symbol_19(buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
[[group(0), binding(0)]] var<storage, read_write> sb : SB;
[[stage(compute)]]
fn main() {
tint_symbol(sb, 16u, 123);
ignore(tint_symbol_1(sb, 16u));
ignore(tint_symbol_2(sb, 16u, 123));
ignore(tint_symbol_3(sb, 16u, 123));
ignore(tint_symbol_4(sb, 16u, 123));
ignore(tint_symbol_5(sb, 16u, 123));
ignore(tint_symbol_6(sb, 16u, 123));
ignore(tint_symbol_7(sb, 16u, 123));
ignore(tint_symbol_8(sb, 16u, 123));
ignore(tint_symbol_9(sb, 16u, 123, 345));
tint_symbol_10(sb, 20u, 123u);
ignore(tint_symbol_11(sb, 20u));
ignore(tint_symbol_12(sb, 20u, 123u));
ignore(tint_symbol_13(sb, 20u, 123u));
ignore(tint_symbol_14(sb, 20u, 123u));
ignore(tint_symbol_15(sb, 20u, 123u));
ignore(tint_symbol_16(sb, 20u, 123u));
ignore(tint_symbol_17(sb, 20u, 123u));
ignore(tint_symbol_18(sb, 20u, 123u));
ignore(tint_symbol_19(sb, 20u, 123u, 345u));
}
)";
auto got = Run<DecomposeStorageAccess>(src);
EXPECT_EQ(expect, str(got));
}
TEST_F(DecomposeStorageAccessTest, WorkgroupBufferAtomics) {
auto* src = R"(
struct S {
padding : vec4<f32>;
a : atomic<i32>;
b : atomic<u32>;
};
var<workgroup> w : S;
[[stage(compute)]]
fn main() {
atomicStore(&(w.a), 123);
ignore(atomicLoad(&(w.a)));
ignore(atomicAdd(&(w.a), 123));
ignore(atomicMax(&(w.a), 123));
ignore(atomicMin(&(w.a), 123));
ignore(atomicAnd(&(w.a), 123));
ignore(atomicOr(&(w.a), 123));
ignore(atomicXor(&(w.a), 123));
ignore(atomicExchange(&(w.a), 123));
ignore(atomicCompareExchangeWeak(&(w.a), 123, 345));
atomicStore(&(w.b), 123u);
ignore(atomicLoad(&(w.b)));
ignore(atomicAdd(&(w.b), 123u));
ignore(atomicMax(&(w.b), 123u));
ignore(atomicMin(&(w.b), 123u));
ignore(atomicAnd(&(w.b), 123u));
ignore(atomicOr(&(w.b), 123u));
ignore(atomicXor(&(w.b), 123u));
ignore(atomicExchange(&(w.b), 123u));
ignore(atomicCompareExchangeWeak(&(w.b), 123u, 345u));
}
)";
auto* expect = src;
auto got = Run<DecomposeStorageAccess>(src);
EXPECT_EQ(expect, str(got));
}
} // namespace } // namespace
} // namespace transform } // namespace transform
} // namespace tint } // namespace tint

View File

@ -17,6 +17,7 @@
#include <algorithm> #include <algorithm>
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/sem/atomic_type.h"
#include "src/sem/reference_type.h" #include "src/sem/reference_type.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Data); TINT_INSTANTIATE_TYPEINFO(tint::transform::Data);
@ -111,6 +112,9 @@ ast::Type* Transform::CreateASTTypeFor(CloneContext* ctx, const sem::Type* ty) {
if (auto* s = ty->As<sem::Reference>()) { if (auto* s = ty->As<sem::Reference>()) {
return CreateASTTypeFor(ctx, s->StoreType()); return CreateASTTypeFor(ctx, s->StoreType());
} }
if (auto* a = ty->As<sem::Atomic>()) {
return ctx->dst->create<ast::Atomic>(CreateASTTypeFor(ctx, a->Type()));
}
if (auto* t = ty->As<sem::DepthTexture>()) { if (auto* t = ty->As<sem::DepthTexture>()) {
return ctx->dst->create<ast::DepthTexture>(t->dim()); return ctx->dst->create<ast::DepthTexture>(t->dim());
} }

View File

@ -25,6 +25,7 @@
#include "src/ast/override_decoration.h" #include "src/ast/override_decoration.h"
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
#include "src/sem/array.h" #include "src/sem/array.h"
#include "src/sem/atomic_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"
#include "src/sem/function.h" #include "src/sem/function.h"
@ -35,7 +36,6 @@
#include "src/sem/struct.h" #include "src/sem/struct.h"
#include "src/sem/variable.h" #include "src/sem/variable.h"
#include "src/transform/calculate_array_length.h" #include "src/transform/calculate_array_length.h"
#include "src/transform/decompose_storage_access.h"
#include "src/utils/scoped_assignment.h" #include "src/utils/scoped_assignment.h"
#include "src/writer/append_vector.h" #include "src/writer/append_vector.h"
#include "src/writer/float_to_string.h" #include "src/writer/float_to_string.h"
@ -431,99 +431,7 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
if (auto* intrinsic = if (auto* intrinsic =
ast::GetDecoration<transform::DecomposeStorageAccess::Intrinsic>( ast::GetDecoration<transform::DecomposeStorageAccess::Intrinsic>(
func->Declaration()->decorations())) { func->Declaration()->decorations())) {
auto load = [&](const char* cast, int n) { return EmitDecomposeStorageAccessIntrinsic(pre, out, expr, intrinsic);
if (cast) {
out << cast << "(";
}
if (!EmitExpression(pre, out, params[0])) { // buffer
return false;
}
out << ".Load";
if (n > 1) {
out << n;
}
ScopedParen sp(out);
if (!EmitExpression(pre, out, params[1])) { // offset
return false;
}
if (cast) {
out << ")";
}
return true;
};
auto store = [&](int n) {
if (!EmitExpression(pre, out, params[0])) { // buffer
return false;
}
out << ".Store";
if (n > 1) {
out << n;
}
ScopedParen sp1(out);
if (!EmitExpression(pre, out, params[1])) { // offset
return false;
}
out << ", asuint";
ScopedParen sp2(out);
if (!EmitExpression(pre, out, params[2])) { // value
return false;
}
return true;
};
switch (intrinsic->type) {
case transform::DecomposeStorageAccess::Intrinsic::kLoadU32:
return load(nullptr, 1);
case transform::DecomposeStorageAccess::Intrinsic::kLoadF32:
return load("asfloat", 1);
case transform::DecomposeStorageAccess::Intrinsic::kLoadI32:
return load("asint", 1);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec2U32:
return load(nullptr, 2);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec2F32:
return load("asfloat", 2);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec2I32:
return load("asint", 2);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec3U32:
return load(nullptr, 3);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec3F32:
return load("asfloat", 3);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec3I32:
return load("asint", 3);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec4U32:
return load(nullptr, 4);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec4F32:
return load("asfloat", 4);
case transform::DecomposeStorageAccess::Intrinsic::kLoadVec4I32:
return load("asint", 4);
case transform::DecomposeStorageAccess::Intrinsic::kStoreU32:
return store(1);
case transform::DecomposeStorageAccess::Intrinsic::kStoreF32:
return store(1);
case transform::DecomposeStorageAccess::Intrinsic::kStoreI32:
return store(1);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec2U32:
return store(2);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec2F32:
return store(2);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec2I32:
return store(2);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec3U32:
return store(3);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec3F32:
return store(3);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec3I32:
return store(3);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec4U32:
return store(4);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec4F32:
return store(4);
case transform::DecomposeStorageAccess::Intrinsic::kStoreVec4I32:
return store(4);
}
TINT_UNIMPLEMENTED(diagnostics_) << static_cast<int>(intrinsic->type);
return false;
} }
} }
@ -544,6 +452,8 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
return EmitDataUnpackingCall(pre, out, expr, intrinsic); return EmitDataUnpackingCall(pre, out, expr, intrinsic);
} else if (intrinsic->IsBarrier()) { } else if (intrinsic->IsBarrier()) {
return EmitBarrierCall(pre, out, intrinsic); return EmitBarrierCall(pre, out, intrinsic);
} else if (intrinsic->IsAtomic()) {
return EmitWorkgroupAtomicCall(pre, out, expr, intrinsic);
} }
auto name = generate_builtin_name(intrinsic); auto name = generate_builtin_name(intrinsic);
if (name.empty()) { if (name.empty()) {
@ -597,6 +507,486 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
return true; return true;
} }
bool GeneratorImpl::EmitDecomposeStorageAccessIntrinsic(
std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,
const transform::DecomposeStorageAccess::Intrinsic* intrinsic) {
const auto& params = expr->params();
using Op = transform::DecomposeStorageAccess::Intrinsic::Op;
using DataType = transform::DecomposeStorageAccess::Intrinsic::DataType;
switch (intrinsic->op) {
case Op::kLoad: {
auto load = [&](const char* cast, int n) {
if (cast) {
out << cast << "(";
}
if (!EmitExpression(pre, out, params[0])) { // buffer
return false;
}
out << ".Load";
if (n > 1) {
out << n;
}
ScopedParen sp(out);
if (!EmitExpression(pre, out, params[1])) { // offset
return false;
}
if (cast) {
out << ")";
}
return true;
};
switch (intrinsic->type) {
case DataType::kU32:
return load(nullptr, 1);
case DataType::kF32:
return load("asfloat", 1);
case DataType::kI32:
return load("asint", 1);
case DataType::kVec2U32:
return load(nullptr, 2);
case DataType::kVec2F32:
return load("asfloat", 2);
case DataType::kVec2I32:
return load("asint", 2);
case DataType::kVec3U32:
return load(nullptr, 3);
case DataType::kVec3F32:
return load("asfloat", 3);
case DataType::kVec3I32:
return load("asint", 3);
case DataType::kVec4U32:
return load(nullptr, 4);
case DataType::kVec4F32:
return load("asfloat", 4);
case DataType::kVec4I32:
return load("asint", 4);
}
TINT_UNREACHABLE(diagnostics_)
<< "unsupported DecomposeStorageAccess::Intrinsic::DataType: "
<< static_cast<int>(intrinsic->type);
return false;
}
case Op::kStore: {
auto store = [&](int n) {
if (!EmitExpression(pre, out, params[0])) { // buffer
return false;
}
out << ".Store";
if (n > 1) {
out << n;
}
ScopedParen sp1(out);
if (!EmitExpression(pre, out, params[1])) { // offset
return false;
}
out << ", asuint";
ScopedParen sp2(out);
if (!EmitExpression(pre, out, params[2])) { // value
return false;
}
return true;
};
switch (intrinsic->type) {
case DataType::kU32:
return store(1);
case DataType::kF32:
return store(1);
case DataType::kI32:
return store(1);
case DataType::kVec2U32:
return store(2);
case DataType::kVec2F32:
return store(2);
case DataType::kVec2I32:
return store(2);
case DataType::kVec3U32:
return store(3);
case DataType::kVec3F32:
return store(3);
case DataType::kVec3I32:
return store(3);
case DataType::kVec4U32:
return store(4);
case DataType::kVec4F32:
return store(4);
case DataType::kVec4I32:
return store(4);
}
TINT_UNREACHABLE(diagnostics_)
<< "unsupported DecomposeStorageAccess::Intrinsic::DataType: "
<< static_cast<int>(intrinsic->type);
return false;
}
case Op::kAtomicLoad:
case Op::kAtomicStore:
case Op::kAtomicAdd:
case Op::kAtomicMax:
case Op::kAtomicMin:
case Op::kAtomicAnd:
case Op::kAtomicOr:
case Op::kAtomicXor:
case Op::kAtomicExchange:
case Op::kAtomicCompareExchangeWeak:
return EmitStorageAtomicCall(pre, out, expr, intrinsic->op);
}
TINT_UNREACHABLE(diagnostics_)
<< "unsupported DecomposeStorageAccess::Intrinsic::Op: "
<< static_cast<int>(intrinsic->op);
return false;
}
bool GeneratorImpl::EmitStorageAtomicCall(
std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,
transform::DecomposeStorageAccess::Intrinsic::Op op) {
using Op = transform::DecomposeStorageAccess::Intrinsic::Op;
std::stringstream ss;
std::string result = generate_name("atomic_result");
auto* result_ty = TypeOf(expr);
if (!result_ty->Is<sem::Void>()) {
if (!EmitType(ss, TypeOf(expr), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) {
return false;
}
ss << " " << result << " = ";
if (!EmitZeroValue(ss, result_ty)) {
return false;
}
make_indent(ss << ";" << std::endl);
}
auto* buffer = expr->params()[0];
auto* offset = expr->params()[1];
switch (op) {
case Op::kAtomicLoad: {
// HLSL does not have an InterlockedLoad, so we emulate it with
// InterlockedOr using 0 as the OR value
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedOr";
{
ScopedParen sp(ss);
if (!EmitExpression(pre, ss, offset)) {
return false;
}
ss << ", 0, " << result;
}
make_indent(ss << ";" << std::endl);
pre << ss.str();
out << result;
return true;
}
case Op::kAtomicStore: {
// HLSL does not have an InterlockedStore, so we emulate it with
// InterlockedExchange and discard the returned value
auto* value = expr->params()[2];
auto* value_ty = TypeOf(value);
if (!EmitType(pre, value_ty, ast::StorageClass::kNone,
ast::Access::kUndefined, "")) {
return false;
}
pre << " " << result << " = ";
if (!EmitZeroValue(pre, value_ty)) {
return false;
}
make_indent(pre << ";" << std::endl);
if (!EmitExpression(pre, out, buffer)) {
return false;
}
out << ".InterlockedExchange";
{
ScopedParen sp(out);
if (!EmitExpression(pre, out, offset)) {
return false;
}
out << ", ";
if (!EmitExpression(pre, out, value)) {
return false;
}
out << ", " << result;
}
return true;
}
case Op::kAtomicCompareExchangeWeak: {
auto* compare_value = expr->params()[2];
auto* value = expr->params()[3];
std::string compare = generate_name("atomic_compare_value");
if (!EmitType(ss, TypeOf(compare_value), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) {
return false;
}
ss << " " << compare << " = ";
if (!EmitExpression(pre, ss, compare_value)) {
return false;
}
make_indent(ss << ";" << std::endl);
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedCompareExchange";
{
ScopedParen sp(ss);
if (!EmitExpression(pre, ss, offset)) {
return false;
}
ss << ", " << compare << ", ";
if (!EmitExpression(pre, ss, value)) {
return false;
}
ss << ", " << result << ".x";
}
make_indent(ss << ";" << std::endl);
ss << result << ".y = " << result << ".x == " << compare;
make_indent(ss << ";" << std::endl);
pre << ss.str();
out << result;
return true;
}
case Op::kAtomicAdd:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedAdd";
break;
case Op::kAtomicMax:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedMax";
break;
case Op::kAtomicMin:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedMin";
break;
case Op::kAtomicAnd:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedAnd";
break;
case Op::kAtomicOr:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedOr";
break;
case Op::kAtomicXor:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedXor";
break;
case Op::kAtomicExchange:
if (!EmitExpression(pre, ss, buffer)) {
return false;
}
ss << ".InterlockedExchange";
break;
default:
TINT_UNREACHABLE(diagnostics_)
<< "unsupported atomic DecomposeStorageAccess::Intrinsic::Op: "
<< static_cast<int>(op);
return false;
}
{
ScopedParen sp(ss);
if (!EmitExpression(pre, ss, offset)) {
return false;
}
for (size_t i = 1; i < expr->params().size() - 1; i++) {
auto* arg = expr->params()[i];
ss << ", ";
if (!EmitExpression(pre, ss, arg)) {
return false;
}
}
ss << ", " << result;
}
make_indent(ss << ";" << std::endl);
pre << ss.str();
out << result;
return true;
}
bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) {
std::stringstream ss;
std::string result = generate_name("atomic_result");
if (!intrinsic->ReturnType()->Is<sem::Void>()) {
if (!EmitType(ss, intrinsic->ReturnType(), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) {
return false;
}
ss << " " << result << " = ";
if (!EmitZeroValue(ss, intrinsic->ReturnType())) {
return false;
}
make_indent(ss << ";" << std::endl);
}
switch (intrinsic->Type()) {
case sem::IntrinsicType::kAtomicLoad: {
// HLSL does not have an InterlockedLoad, so we emulate it with
// InterlockedOr using 0 as the OR value
ss << "InterlockedOr";
{
ScopedParen sp(ss);
if (!EmitExpression(pre, ss, expr->params()[0])) {
return false;
}
ss << ", 0, " << result;
}
make_indent(ss << ";" << std::endl);
pre << ss.str();
out << result;
return true;
}
case sem::IntrinsicType::kAtomicStore: {
// HLSL does not have an InterlockedStore, so we emulate it with
// InterlockedExchange and discard the returned value
auto* value_ty = intrinsic->Parameters()[1].type;
if (!EmitType(pre, value_ty, ast::StorageClass::kNone,
ast::Access::kUndefined, "")) {
return false;
}
pre << " " << result << " = ";
if (!EmitZeroValue(pre, value_ty)) {
return false;
}
make_indent(pre << ";" << std::endl);
out << "InterlockedExchange";
{
ScopedParen sp(out);
if (!EmitExpression(pre, out, expr->params()[0])) {
return false;
}
out << ", ";
if (!EmitExpression(pre, out, expr->params()[1])) {
return false;
}
out << ", " << result;
}
return true;
}
case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
auto* dest = expr->params()[0];
auto* compare_value = expr->params()[1];
auto* value = expr->params()[2];
std::string compare = generate_name("atomic_compare_value");
if (!EmitType(ss, TypeOf(compare_value), ast::StorageClass::kNone,
ast::Access::kUndefined, "")) {
return false;
}
ss << " " << compare << " = ";
if (!EmitExpression(pre, ss, compare_value)) {
return false;
}
make_indent(ss << ";" << std::endl);
ss << "InterlockedCompareExchange";
{
ScopedParen sp(ss);
if (!EmitExpression(pre, ss, dest)) {
return false;
}
ss << ", " << compare << ", ";
if (!EmitExpression(pre, ss, value)) {
return false;
}
ss << ", " << result << ".x";
}
make_indent(ss << ";" << std::endl);
ss << result << ".y = " << result << ".x == " << compare;
make_indent(ss << ";" << std::endl);
pre << ss.str();
out << result;
return true;
}
case sem::IntrinsicType::kAtomicAdd:
ss << "InterlockedAdd";
break;
case sem::IntrinsicType::kAtomicMax:
ss << "InterlockedMax";
break;
case sem::IntrinsicType::kAtomicMin:
ss << "InterlockedMin";
break;
case sem::IntrinsicType::kAtomicAnd:
ss << "InterlockedAnd";
break;
case sem::IntrinsicType::kAtomicOr:
ss << "InterlockedOr";
break;
case sem::IntrinsicType::kAtomicXor:
ss << "InterlockedXor";
break;
case sem::IntrinsicType::kAtomicExchange:
ss << "InterlockedExchange";
break;
default:
TINT_UNREACHABLE(diagnostics_)
<< "unsupported atomic intrinsic: " << intrinsic->Type();
return false;
}
{
ScopedParen sp(ss);
for (size_t i = 0; i < expr->params().size(); i++) {
auto* arg = expr->params()[i];
if (i > 0) {
ss << ", ";
}
if (!EmitExpression(pre, ss, arg)) {
return false;
}
}
ss << ", " << result;
}
make_indent(ss << ";" << std::endl);
pre << ss.str();
out << result;
return true;
}
bool GeneratorImpl::EmitSelectCall(std::ostream& pre, bool GeneratorImpl::EmitSelectCall(std::ostream& pre,
std::ostream& out, std::ostream& out,
ast::CallExpression* expr) { ast::CallExpression* expr) {
@ -1153,11 +1543,10 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
} }
return true; return true;
} // namespace hlsl }
std::string GeneratorImpl::generate_builtin_name( std::string GeneratorImpl::generate_builtin_name(
const sem::Intrinsic* intrinsic) { const sem::Intrinsic* intrinsic) {
std::string out;
switch (intrinsic->Type()) { switch (intrinsic->Type()) {
case sem::IntrinsicType::kAbs: case sem::IntrinsicType::kAbs:
case sem::IntrinsicType::kAcos: case sem::IntrinsicType::kAcos:
@ -1198,71 +1587,51 @@ std::string GeneratorImpl::generate_builtin_name(
case sem::IntrinsicType::kTanh: case sem::IntrinsicType::kTanh:
case sem::IntrinsicType::kTranspose: case sem::IntrinsicType::kTranspose:
case sem::IntrinsicType::kTrunc: case sem::IntrinsicType::kTrunc:
out = intrinsic->str(); return intrinsic->str();
break;
case sem::IntrinsicType::kCountOneBits: case sem::IntrinsicType::kCountOneBits:
out = "countbits"; return "countbits";
break;
case sem::IntrinsicType::kDpdx: case sem::IntrinsicType::kDpdx:
out = "ddx"; return "ddx";
break;
case sem::IntrinsicType::kDpdxCoarse: case sem::IntrinsicType::kDpdxCoarse:
out = "ddx_coarse"; return "ddx_coarse";
break;
case sem::IntrinsicType::kDpdxFine: case sem::IntrinsicType::kDpdxFine:
out = "ddx_fine"; return "ddx_fine";
break;
case sem::IntrinsicType::kDpdy: case sem::IntrinsicType::kDpdy:
out = "ddy"; return "ddy";
break;
case sem::IntrinsicType::kDpdyCoarse: case sem::IntrinsicType::kDpdyCoarse:
out = "ddy_coarse"; return "ddy_coarse";
break;
case sem::IntrinsicType::kDpdyFine: case sem::IntrinsicType::kDpdyFine:
out = "ddy_fine"; return "ddy_fine";
break;
case sem::IntrinsicType::kFaceForward: case sem::IntrinsicType::kFaceForward:
out = "faceforward"; return "faceforward";
break;
case sem::IntrinsicType::kFract: case sem::IntrinsicType::kFract:
out = "frac"; return "frac";
break;
case sem::IntrinsicType::kFma: case sem::IntrinsicType::kFma:
out = "mad"; return "mad";
break;
case sem::IntrinsicType::kFwidth: case sem::IntrinsicType::kFwidth:
case sem::IntrinsicType::kFwidthCoarse: case sem::IntrinsicType::kFwidthCoarse:
case sem::IntrinsicType::kFwidthFine: case sem::IntrinsicType::kFwidthFine:
out = "fwidth"; return "fwidth";
break;
case sem::IntrinsicType::kInverseSqrt: case sem::IntrinsicType::kInverseSqrt:
out = "rsqrt"; return "rsqrt";
break;
case sem::IntrinsicType::kIsFinite: case sem::IntrinsicType::kIsFinite:
out = "isfinite"; return "isfinite";
break;
case sem::IntrinsicType::kIsInf: case sem::IntrinsicType::kIsInf:
out = "isinf"; return "isinf";
break;
case sem::IntrinsicType::kIsNan: case sem::IntrinsicType::kIsNan:
out = "isnan"; return "isnan";
break;
case sem::IntrinsicType::kMix: case sem::IntrinsicType::kMix:
out = "lerp"; return "lerp";
break;
case sem::IntrinsicType::kReverseBits: case sem::IntrinsicType::kReverseBits:
out = "reversebits"; return "reversebits";
break;
case sem::IntrinsicType::kSmoothStep: case sem::IntrinsicType::kSmoothStep:
out = "smoothstep"; return "smoothstep";
break;
default: default:
diagnostics_.add_error("Unknown builtin method: " + diagnostics_.add_error("Unknown builtin method: " +
std::string(intrinsic->str())); std::string(intrinsic->str()));
return "";
} }
return out; return "";
} }
bool GeneratorImpl::EmitCase(std::ostream& out, ast::CaseStatement* stmt) { bool GeneratorImpl::EmitCase(std::ostream& out, ast::CaseStatement* stmt) {
@ -2237,6 +2606,10 @@ bool GeneratorImpl::EmitType(std::ostream& out,
} }
out << ", " << size << ">"; out << ", " << size << ">";
} }
} else if (auto* atomic = type->As<sem::Atomic>()) {
if (!EmitType(out, atomic->Type(), storage_class, access, name)) {
return false;
}
} else if (type->Is<sem::Void>()) { } else if (type->Is<sem::Void>()) {
out << "void"; out << "void";
} else { } else {

View File

@ -32,6 +32,7 @@
#include "src/ast/unary_op_expression.h" #include "src/ast/unary_op_expression.h"
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/scope_stack.h" #include "src/scope_stack.h"
#include "src/transform/decompose_storage_access.h"
#include "src/writer/text_generator.h" #include "src/writer/text_generator.h"
namespace tint { namespace tint {
@ -115,6 +116,18 @@ class GeneratorImpl : public TextGenerator {
bool EmitCall(std::ostream& pre, bool EmitCall(std::ostream& pre,
std::ostream& out, std::ostream& out,
ast::CallExpression* expr); ast::CallExpression* expr);
/// Handles generating a call expression to a
/// transform::DecomposeStorageAccess::Intrinsic
/// @param pre the preamble for the expression stream
/// @param out the output of the expression stream
/// @param expr the call expression
/// @param intrinsic the transform::DecomposeStorageAccess::Intrinsic
/// @returns true if the call expression is emitted
bool EmitDecomposeStorageAccessIntrinsic(
std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,
const transform::DecomposeStorageAccess::Intrinsic* intrinsic);
/// Handles generating a barrier intrinsic call /// Handles generating a barrier intrinsic call
/// @param pre the preamble for the expression stream /// @param pre the preamble for the expression stream
/// @param out the output of the expression stream /// @param out the output of the expression stream
@ -123,6 +136,27 @@ class GeneratorImpl : public TextGenerator {
bool EmitBarrierCall(std::ostream& pre, bool EmitBarrierCall(std::ostream& pre,
std::ostream& out, std::ostream& out,
const sem::Intrinsic* intrinsic); const sem::Intrinsic* intrinsic);
/// Handles generating an atomic intrinsic call for a storage buffer variable
/// @param pre the preamble for the expression stream
/// @param out the output of the expression stream
/// @param expr the call expression
/// @param op the atomic op
/// @returns true if the call expression is emitted
bool EmitStorageAtomicCall(
std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,
transform::DecomposeStorageAccess::Intrinsic::Op op);
/// Handles generating an atomic intrinsic call for a workgroup variable
/// @param pre the preamble for the expression stream
/// @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 EmitWorkgroupAtomicCall(std::ostream& pre,
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 pre the preamble for the expression stream /// @param pre the preamble for the expression stream

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicAdd_794055() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedAdd(arg_0, 1, atomic_result);
fn atomicAdd_794055() { int res = atomic_result;
var res : i32 = atomicAdd(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicAdd_794055(); atomicAdd_794055();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicAdd_794055(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicAdd(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicAdd_794055(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicAdd_8a199a() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedAdd(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicAdd_8a199a();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicAdd_8a199a();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicAdd_d32fe4() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedAdd(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicAdd_d32fe4();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicAdd_d32fe4();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicAdd_d5db1d() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedAdd(arg_0, 1u, atomic_result);
fn atomicAdd_d5db1d() { uint res = atomic_result;
var res : u32 = atomicAdd(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicAdd_d5db1d(); atomicAdd_d5db1d();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicAdd_d5db1d(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicAdd(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicAdd_d5db1d(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicAnd_152966() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedAnd(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicAnd_152966();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicAnd_152966();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicAnd_34edd3() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedAnd(arg_0, 1u, atomic_result);
fn atomicAnd_34edd3() { uint res = atomic_result;
var res : u32 = atomicAnd(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicAnd_34edd3(); atomicAnd_34edd3();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicAnd_34edd3(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicAnd(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicAnd_34edd3(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicAnd_45a819() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedAnd(arg_0, 1, atomic_result);
fn atomicAnd_45a819() { int res = atomic_result;
var res : i32 = atomicAnd(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicAnd_45a819(); atomicAnd_45a819();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicAnd_45a819(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicAnd(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicAnd_45a819(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicAnd_85a8d9() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedAnd(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicAnd_85a8d9();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicAnd_85a8d9();
return;
}

View File

@ -1,10 +1,20 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicCompareExchangeWeak_12871c() {
******************************************************************** int2 atomic_result = int2(0, 0);
* The tint shader compiler has encountered an unexpected error. * int atomic_compare_value = 1;
* * sb_rw.InterlockedCompareExchange(0u, atomic_compare_value, 1, atomic_result.x);
* Please help us fix this issue by submitting a bug report at * atomic_result.y = atomic_result.x == atomic_compare_value;
* crbug.com/tint with the source program that triggered the bug. * int2 res = atomic_result;
******************************************************************** }
void fragment_main() {
atomicCompareExchangeWeak_12871c();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicCompareExchangeWeak_12871c();
return;
}

View File

@ -1,10 +1,20 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicCompareExchangeWeak_6673da() {
******************************************************************** uint2 atomic_result = uint2(0u, 0u);
* The tint shader compiler has encountered an unexpected error. * uint atomic_compare_value = 1u;
* * sb_rw.InterlockedCompareExchange(0u, atomic_compare_value, 1u, atomic_result.x);
* Please help us fix this issue by submitting a bug report at * atomic_result.y = atomic_result.x == atomic_compare_value;
* crbug.com/tint with the source program that triggered the bug. * uint2 res = atomic_result;
******************************************************************** }
void fragment_main() {
atomicCompareExchangeWeak_6673da();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicCompareExchangeWeak_6673da();
return;
}

View File

@ -1,15 +1,15 @@
SKIP: FAILED groupshared int arg_0;
void atomicCompareExchangeWeak_89ea3b() {
var<workgroup> arg_0 : atomic<i32>; int2 atomic_result = int2(0, 0);
int atomic_compare_value = 1;
fn atomicCompareExchangeWeak_89ea3b() { InterlockedCompareExchange(arg_0, atomic_compare_value, 1, atomic_result.x);
var res : vec2<i32> = atomicCompareExchangeWeak(&(arg_0), 1, 1); atomic_result.y = atomic_result.x == atomic_compare_value;
int2 res = atomic_result;
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicCompareExchangeWeak_89ea3b(); atomicCompareExchangeWeak_89ea3b();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicCompareExchangeWeak_89ea3b(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : vec2<i32> = atomicCompareExchangeWeak(&(*(tint_symbol)), 1, 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicCompareExchangeWeak_89ea3b(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,15 @@
SKIP: FAILED groupshared uint arg_0;
void atomicCompareExchangeWeak_b2ab2c() {
var<workgroup> arg_0 : atomic<u32>; uint2 atomic_result = uint2(0u, 0u);
uint atomic_compare_value = 1u;
fn atomicCompareExchangeWeak_b2ab2c() { InterlockedCompareExchange(arg_0, atomic_compare_value, 1u, atomic_result.x);
var res : vec2<u32> = atomicCompareExchangeWeak(&(arg_0), 1u, 1u); atomic_result.y = atomic_result.x == atomic_compare_value;
uint2 res = atomic_result;
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicCompareExchangeWeak_b2ab2c(); atomicCompareExchangeWeak_b2ab2c();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicCompareExchangeWeak_b2ab2c(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : vec2<u32> = atomicCompareExchangeWeak(&(*(tint_symbol)), 1u, 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicCompareExchangeWeak_b2ab2c(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicExchange_0a5dca() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedExchange(arg_0, 1u, atomic_result);
fn atomicExchange_0a5dca() { uint res = atomic_result;
var res : u32 = atomicExchange(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicExchange_0a5dca(); atomicExchange_0a5dca();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicExchange_0a5dca(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicExchange(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicExchange_0a5dca(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicExchange_d59712() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedExchange(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicExchange_d59712();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicExchange_d59712();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicExchange_e114ba() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedExchange(arg_0, 1, atomic_result);
fn atomicExchange_e114ba() { int res = atomic_result;
var res : i32 = atomicExchange(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicExchange_e114ba(); atomicExchange_e114ba();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicExchange_e114ba(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicExchange(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicExchange_e114ba(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicExchange_f2e22f() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedExchange(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicExchange_f2e22f();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicExchange_f2e22f();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicLoad_0806ad() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedOr(0u, 0, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicLoad_0806ad();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicLoad_0806ad();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicLoad_361bf1() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedOr(arg_0, 0, atomic_result);
fn atomicLoad_361bf1() { uint res = atomic_result;
var res : u32 = atomicLoad(&(arg_0));
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicLoad_361bf1(); atomicLoad_361bf1();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicLoad_361bf1(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicLoad(&(*(tint_symbol)));
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicLoad_361bf1(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicLoad_afcc03() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedOr(arg_0, 0, atomic_result);
fn atomicLoad_afcc03() { int res = atomic_result;
var res : i32 = atomicLoad(&(arg_0));
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicLoad_afcc03(); atomicLoad_afcc03();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicLoad_afcc03(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicLoad(&(*(tint_symbol)));
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicLoad_afcc03(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicLoad_fe6cc3() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedOr(0u, 0, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicLoad_fe6cc3();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicLoad_fe6cc3();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicMax_51b9be() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedMax(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicMax_51b9be();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicMax_51b9be();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicMax_92aa72() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedMax(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicMax_92aa72();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicMax_92aa72();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicMax_a89cc3() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedMax(arg_0, 1, atomic_result);
fn atomicMax_a89cc3() { int res = atomic_result;
var res : i32 = atomicMax(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicMax_a89cc3(); atomicMax_a89cc3();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicMax_a89cc3(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicMax(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicMax_a89cc3(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicMax_beccfc() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedMax(arg_0, 1u, atomic_result);
fn atomicMax_beccfc() { uint res = atomic_result;
var res : u32 = atomicMax(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicMax_beccfc(); atomicMax_beccfc();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicMax_beccfc(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicMax(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicMax_beccfc(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicMin_278235() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedMin(arg_0, 1, atomic_result);
fn atomicMin_278235() { int res = atomic_result;
var res : i32 = atomicMin(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicMin_278235(); atomicMin_278235();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicMin_278235(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicMin(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicMin_278235(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicMin_69d383() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedMin(arg_0, 1u, atomic_result);
fn atomicMin_69d383() { uint res = atomic_result;
var res : u32 = atomicMin(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicMin_69d383(); atomicMin_69d383();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicMin_69d383(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicMin(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicMin_69d383(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicMin_8e38dc() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedMin(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicMin_8e38dc();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicMin_8e38dc();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicMin_c67a74() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedMin(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicMin_c67a74();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicMin_c67a74();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicOr_5e3d61() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedOr(arg_0, 1u, atomic_result);
fn atomicOr_5e3d61() { uint res = atomic_result;
var res : u32 = atomicOr(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicOr_5e3d61(); atomicOr_5e3d61();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicOr_5e3d61(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicOr(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicOr_5e3d61(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicOr_5e95d4() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedOr(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicOr_5e95d4();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicOr_5e95d4();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicOr_8d96a0() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedOr(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicOr_8d96a0();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicOr_8d96a0();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicOr_d09248() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedOr(arg_0, 1, atomic_result);
fn atomicOr_d09248() { int res = atomic_result;
var res : i32 = atomicOr(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicOr_d09248(); atomicOr_d09248();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicOr_d09248(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicOr(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicOr_d09248(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,12 @@
SKIP: FAILED groupshared uint arg_0;
void atomicStore_726882() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedExchange(arg_0, 1u, atomic_result);
fn atomicStore_726882() {
atomicStore(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicStore_726882(); atomicStore_726882();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicStore_726882(tint_symbol : ptr<workgroup, atomic<u32>>) {
atomicStore(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicStore_726882(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,15 +1,12 @@
SKIP: FAILED groupshared int arg_0;
void atomicStore_8bea94() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedExchange(arg_0, 1, atomic_result);
fn atomicStore_8bea94() {
atomicStore(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicStore_8bea94(); atomicStore_8bea94();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicStore_8bea94(tint_symbol : ptr<workgroup, atomic<i32>>) {
atomicStore(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicStore_8bea94(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,17 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicStore_cdc29e() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedExchange(0u, 1u, atomic_result);
* * }
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicStore_cdc29e();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicStore_cdc29e();
return;
}

View File

@ -1,10 +1,17 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicStore_d1e9a6() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedExchange(0u, 1, atomic_result);
* * }
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicStore_d1e9a6();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicStore_d1e9a6();
return;
}

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicXor_54510e() {
******************************************************************** uint atomic_result = 0u;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedXor(0u, 0u, atomic_result);
* * uint res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicXor_54510e();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicXor_54510e();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared int arg_0;
void atomicXor_75dc95() {
var<workgroup> arg_0 : atomic<i32>; int atomic_result = 0;
InterlockedXor(arg_0, 1, atomic_result);
fn atomicXor_75dc95() { int res = atomic_result;
var res : i32 = atomicXor(&(arg_0), 1);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicXor_75dc95(); atomicXor_75dc95();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicXor_75dc95(tint_symbol : ptr<workgroup, atomic<i32>>) {
var res : i32 = atomicXor(&(*(tint_symbol)), 1);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<i32>;
atomicXor_75dc95(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope

View File

@ -1,10 +1,18 @@
SKIP: FAILED RWByteAddressBuffer sb_rw : register(u0, space0);
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic void atomicXor_c1b78c() {
******************************************************************** int atomic_result = 0;
* The tint shader compiler has encountered an unexpected error. * sb_rw.InterlockedXor(0u, 0u, atomic_result);
* * int res = atomic_result;
* Please help us fix this issue by submitting a bug report at * }
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
void fragment_main() {
atomicXor_c1b78c();
return;
}
[numthreads(1, 1, 1)]
void compute_main() {
atomicXor_c1b78c();
return;
}

View File

@ -1,15 +1,13 @@
SKIP: FAILED groupshared uint arg_0;
void atomicXor_c8e6be() {
var<workgroup> arg_0 : atomic<u32>; uint atomic_result = 0u;
InterlockedXor(arg_0, 1u, atomic_result);
fn atomicXor_c8e6be() { uint res = atomic_result;
var res : u32 = atomicXor(&(arg_0), 1u);
} }
[[stage(compute)]] [numthreads(1, 1, 1)]
fn compute_main() { void compute_main() {
atomicXor_c8e6be(); atomicXor_c8e6be();
return;
} }
Failed to generate: error: unknown type in EmitType

View File

@ -1,10 +1,14 @@
SKIP: FAILED SKIP: FAILED
../src/transform/transform.cc:133 internal compiler error: TINT_UNREACHABLE Unhandled type: tint::sem::Atomic
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
fn atomicXor_c8e6be(tint_symbol : ptr<workgroup, atomic<u32>>) {
var res : u32 = atomicXor(&(*(tint_symbol)), 1u);
}
[[stage(compute)]]
fn compute_main() {
[[internal(disable_validation__function_var_storage_class)]] var<workgroup> tint_symbol_1 : atomic<u32>;
atomicXor_c8e6be(&(tint_symbol_1));
}
error: cannot declare an atomic var in a function scope